Skip to content

Commit

Permalink
Pickup all TSConfigs in Workspace for TSC Build Task (#27306)
Browse files Browse the repository at this point in the history
Follow up on #26079

Allows us to pick up all tsconfig files in a workspace for the build tasks
  • Loading branch information
mjbvz committed May 26, 2017
1 parent 3700493 commit 770206a
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 21 deletions.
51 changes: 30 additions & 21 deletions extensions/typescript/src/features/taskProvider.ts
Expand Up @@ -11,6 +11,7 @@ import * as vscode from 'vscode';

import * as Proto from '../protocol';
import TypeScriptServiceClient from '../typescriptServiceClient';
import TsConfigProvider from "../utils/tsconfigProvider";


const exists = (file: string): Promise<boolean> =>
Expand All @@ -21,32 +22,47 @@ const exists = (file: string): Promise<boolean> =>
});

export default class TypeScriptTaskProvider implements vscode.TaskProvider {
private readonly tsconfigProvider: TsConfigProvider;

public constructor(
private readonly lazyClient: () => TypeScriptServiceClient
) { }
) {
this.tsconfigProvider = new TsConfigProvider();
}

dispose() {
this.tsconfigProvider.dispose();
}

async provideTasks(token: vscode.CancellationToken): Promise<vscode.Task[]> {
public async provideTasks(token: vscode.CancellationToken): Promise<vscode.Task[]> {
const rootPath = vscode.workspace.rootPath;
if (!rootPath) {
return [];
}

const projects = (await this.getConfigForActiveFile(token)).concat(await this.getConfigsForWorkspace());
const command = await this.getCommand();
const projects = await this.getAllTsConfigs(token);

return projects
.filter((x, i) => projects.indexOf(x) === i)
.map(configFile => {
const configFileName = path.relative(rootPath, configFile);
const buildTask = new vscode.ShellTask(`tsc: build ${configFileName}`, `${command} -p ${configFile}`, '$tsc');
buildTask.group = vscode.TaskGroup.Build;
return buildTask;
});
return projects.map(configFile => {
const configFileName = path.relative(rootPath, configFile);
const buildTask = new vscode.ShellTask(`tsc: build ${configFileName}`, `${command} -p ${configFile}`, '$tsc');
buildTask.group = vscode.TaskGroup.Build;
return buildTask;
});
}

private async getAllTsConfigs(token: vscode.CancellationToken): Promise<string[]> {
const out: string[] = [];
const configs = (await this.getTsConfigForActiveFile(token)).concat(await this.getTsConfigsInWorkspace());
for (const config of configs) {
if (await exists(config)) {
out.push(config);
}
}
return out;
}

private async getConfigForActiveFile(token: vscode.CancellationToken): Promise<string[]> {
private async getTsConfigForActiveFile(token: vscode.CancellationToken): Promise<string[]> {
const editor = vscode.window.activeTextEditor;
if (editor) {
if (path.basename(editor.document.fileName).match(/^tsconfig\.(.\.)?json$/)) {
Expand Down Expand Up @@ -75,15 +91,8 @@ export default class TypeScriptTaskProvider implements vscode.TaskProvider {
return [];
}

private async getConfigsForWorkspace(): Promise<string[]> {
if (!vscode.workspace.rootPath) {
return [];
}
const rootTsConfig = path.join(vscode.workspace.rootPath, 'tsconfig.json');
if (!await exists(rootTsConfig)) {
return [];
}
return [rootTsConfig];
private async getTsConfigsInWorkspace(): Promise<string[]> {
return Array.from(await this.tsconfigProvider.getConfigsForWorkspace());
}

private async getCommand(): Promise<string> {
Expand Down
58 changes: 58 additions & 0 deletions extensions/typescript/src/utils/tsconfigProvider.ts
@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';

export default class TsConfigProvider extends vscode.Disposable {
private readonly tsconfigs = new Set<string>();

private activated: boolean = false;
private disposables: vscode.Disposable[] = [];

constructor() {
super(() => this.dispose());
}

dispose(): void {
this.disposables.forEach(d => d.dispose());
}

public async getConfigsForWorkspace(): Promise<Iterable<string>> {
if (!vscode.workspace.rootPath) {
return [];
}
await this.ensureActivated();
return this.tsconfigs;
}

private async ensureActivated() {
if (this.activated) {
return this;
}
this.activated = true;

for (const config of await TsConfigProvider.loadWorkspaceTsconfigs()) {
this.tsconfigs.add(config.fsPath);
}

const configFileWatcher = vscode.workspace.createFileSystemWatcher('**/tsconfig*.json');
this.disposables.push(configFileWatcher);
configFileWatcher.onDidCreate(this.handleProjectCreate, this, this.disposables);
configFileWatcher.onDidDelete(this.handleProjectDelete, this, this.disposables);

return this;
}

private static loadWorkspaceTsconfigs() {
return vscode.workspace.findFiles('**/tsconfig*.json', '**/node_modules/**');
}

private handleProjectCreate(e: vscode.Uri) {
this.tsconfigs.add(e.fsPath);
}

private handleProjectDelete(e: vscode.Uri) {
this.tsconfigs.delete(e.fsPath);
}
}

0 comments on commit 770206a

Please sign in to comment.