Open config file when configure excludes status bar item is clicked. Fixes #21215

This commit is contained in:
Matt Bierner 2017-06-06 17:52:58 -07:00
parent 7968d90989
commit a5c9a7c58c
6 changed files with 65 additions and 59 deletions

View file

@ -11,8 +11,8 @@ import * as vscode from 'vscode';
import * as Proto from '../protocol';
import TypeScriptServiceClient from '../typescriptServiceClient';
import TsConfigProvider from "../utils/tsconfigProvider";
import TsConfigProvider from '../utils/tsconfigProvider';
import { isImplicitProjectConfigFile } from '../utils/tsconfig';
const exists = (file: string): Promise<boolean> =>
new Promise<boolean>((resolve, _reject) => {
@ -89,7 +89,7 @@ class TscTaskProvider implements vscode.TaskProvider {
}
const { configFileName } = res.body;
if (configFileName && configFileName.indexOf('/dev/null/') !== 0) {
if (configFileName && !isImplicitProjectConfigFile(configFileName)) {
return [configFileName];
}
return [];

View file

@ -8,7 +8,7 @@
* https://github.com/Microsoft/TypeScript-Sublime-Plugin/blob/master/TypeScript%20Indent.tmPreferences
* ------------------------------------------------------------------------------------------ */
import { env, languages, commands, workspace, window, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, Disposable, Uri, MessageItem, TextEditor, DiagnosticSeverity, TextDocument, SnippetString } from 'vscode';
import { env, languages, commands, workspace, window, ExtensionContext, Memento, IndentAction, Diagnostic, DiagnosticCollection, Range, Disposable, Uri, MessageItem, TextEditor, DiagnosticSeverity, TextDocument } from 'vscode';
// This must be the first statement otherwise modules might got loaded with
// the wrong locale.
@ -48,7 +48,8 @@ import ImplementationCodeLensProvider from './features/implementationsCodeLensPr
import * as ProjectStatus from './utils/projectStatus';
import TypingsStatus, { AtaProgressReporter } from './utils/typingsStatus';
import VersionStatus from './utils/versionStatus';
import { getContributedTypeScriptServerPlugins, TypeScriptServerPlugin } from "./utils/plugins";
import { getContributedTypeScriptServerPlugins, TypeScriptServerPlugin } from './utils/plugins';
import { openOrCreateConfigFile, isImplicitProjectConfigFile } from './utils/tsconfig';
interface LanguageDescription {
id: string;
@ -560,7 +561,7 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
}
const { configFileName } = res.body;
if (configFileName && configFileName.indexOf('/dev/null/') !== 0) {
if (configFileName && !isImplicitProjectConfigFile(configFileName)) {
return workspace.openTextDocument(configFileName)
.then(doc =>
window.showTextDocument(doc, window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined));
@ -581,22 +582,7 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
}).then(selected => {
switch (selected && selected.id) {
case ProjectConfigAction.CreateConfig:
const configFile = Uri.file(path.join(rootPath, isTypeScriptProject ? 'tsconfig.json' : 'jsconfig.json'));
const col = window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined;
return workspace.openTextDocument(configFile)
.then(doc => {
return window.showTextDocument(doc, col);
}, _ => {
return workspace.openTextDocument(configFile.with({ scheme: 'untitled' }))
.then(doc => window.showTextDocument(doc, col))
.then(editor => {
if (editor.document.getText().length === 0) {
return editor.insertSnippet(new SnippetString('{\n\t$0\n}'))
.then(_ => editor);
}
return editor;
});
});
return openOrCreateConfigFile(isTypeScriptProject);
case ProjectConfigAction.LearnMore:
if (isTypeScriptProject) {

View file

@ -990,7 +990,7 @@ export default class TypeScriptServiceClient implements ITypescriptServiceClient
} else if (event.event === 'configFileDiag') {
this.host.configFileDiagnosticsReceived(event as Proto.ConfigFileDiagnosticEvent);
} else if (event.event === 'telemetry') {
let telemetryData = (event as Proto.TelemetryEvent).body;
const telemetryData = (event as Proto.TelemetryEvent).body;
this.dispatchTelemetryEvent(telemetryData);
} else if (event.event === 'projectLanguageServiceState') {
const data = (event as Proto.ProjectLanguageServiceStateEvent).body;

View file

@ -6,18 +6,15 @@
import * as vscode from 'vscode';
import { ITypescriptServiceClient } from '../typescriptService';
import { loadMessageBundle } from 'vscode-nls';
import { dirname, join } from 'path';
import { dirname } from 'path';
import { openOrCreateConfigFile, isImplicitProjectConfigFile } from './tsconfig';
const localize = loadMessageBundle();
const selector = ['javascript', 'javascriptreact'];
interface Option extends vscode.MessageItem {
execute(): void;
}
interface Hint {
message: string;
options: Option[];
}
interface ProjectHintedMap {
@ -45,29 +42,11 @@ class ExcludeHintItem {
this._item.hide();
}
public show(configFileName: string, largeRoots: string, onExecute: () => void) {
public show(largeRoots: string) {
this._currentHint = {
message: largeRoots.length > 0
? localize('hintExclude', "To enable project-wide JavaScript/TypeScript language features, exclude folders with many files, like: {0}", largeRoots)
: localize('hintExclude.generic', "To enable project-wide JavaScript/TypeScript language features, exclude large folders with source files that you do not work on."),
options: [{
title: localize('open', "Configure Excludes"),
execute: () => {
this._client.logTelemetry('js.hintProjectExcludes.accepted');
onExecute();
this._item.hide();
let configFileUri: vscode.Uri;
if (vscode.workspace.rootPath && dirname(configFileName).indexOf(vscode.workspace.rootPath) === 0) {
configFileUri = vscode.Uri.file(configFileName);
} else {
configFileUri = vscode.Uri.parse('untitled://' + join(vscode.workspace.rootPath || '', 'jsconfig.json'));
}
return vscode.workspace.openTextDocument(configFileName)
.then(vscode.window.showTextDocument);
}
}]
: localize('hintExclude.generic', "To enable project-wide JavaScript/TypeScript language features, exclude large folders with source files that you do not work on.")
};
this._item.tooltip = this._currentHint.message;
this._item.text = localize('large.label', "Configure Excludes");
@ -120,9 +99,8 @@ function createLargeProjectMonitorForProject(item: ExcludeHintItem, client: ITyp
if (fileNames.length > fileLimit || res.body.languageServiceDisabled) {
let largeRoots = computeLargeRoots(configFileName, fileNames).map(f => `'/${f}/'`).join(', ');
item.show(configFileName, largeRoots, () => {
projectHinted[configFileName] = true;
});
item.show(largeRoots);
projectHinted[configFileName] = true;
} else {
item.hide();
}
@ -147,7 +125,17 @@ function createLargeProjectMonitorFromTypeScript(item: ExcludeHintItem, client:
if (body.languageServiceEnabled) {
item.hide();
} else {
item.show(body.projectName, '', () => { });
const configFileName = body.projectName;
if (configFileName) {
if (!isImplicitProjectConfigFile(configFileName)) {
vscode.workspace.openTextDocument(configFileName)
.then(vscode.window.showTextDocument);
} else {
openOrCreateConfigFile(configFileName.match(/tsconfig\.?.*\.json/) !== null);
}
}
item.show('');
}
});
}
@ -157,12 +145,8 @@ export function create(client: ITypescriptServiceClient, isOpen: (path: string)
let item = new ExcludeHintItem(client);
toDispose.push(vscode.commands.registerCommand('js.projectStatus.command', () => {
let { message, options } = item.getCurrentHint();
return vscode.window.showInformationMessage(message, ...options).then(selection => {
if (selection) {
return selection.execute();
}
});
let { message } = item.getCurrentHint();
return vscode.window.showInformationMessage(message);
}));
if (client.apiVersion.has213Features()) {

View file

@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* 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';
import * as path from 'path';
export function isImplicitProjectConfigFile(configFileName: string) {
return configFileName.indexOf('/dev/null/') === 0;
}
export function openOrCreateConfigFile(
isTypeScriptProject: boolean
): Thenable<vscode.TextEditor | null> {
if (!vscode.workspace.rootPath) {
return Promise.resolve(null);
}
const configFile = vscode.Uri.file(path.join(vscode.workspace.rootPath, isTypeScriptProject ? 'tsconfig.json' : 'jsconfig.json'));
const col = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
return vscode.workspace.openTextDocument(configFile)
.then(doc => {
return vscode.window.showTextDocument(doc, col);
}, _ => {
return vscode.workspace.openTextDocument(configFile.with({ scheme: 'untitled' }))
.then(doc => vscode.window.showTextDocument(doc, col))
.then(editor => {
if (editor.document.getText().length === 0) {
return editor.insertSnippet(new vscode.SnippetString('{\n\t$0\n}'))
.then(_ => editor);
}
return editor;
});
});
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import stream = require('stream');
import * as stream from 'stream';
const DefaultSize: number = 8192;
const ContentLength: string = 'Content-Length: ';