mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 10:38:59 +01:00
Merge branch 'master' into joh/outline
This commit is contained in:
@@ -8,7 +8,7 @@ import { CancellationTokenSource, Disposable, TextDocument, TextDocumentChangeEv
|
||||
import * as Proto from '../protocol';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import { Delayer } from '../utils/async';
|
||||
import { disposeAll } from '../utils/dipose';
|
||||
import { disposeAll } from '../utils/dispose';
|
||||
import * as languageModeIds from '../utils/languageModeIds';
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ export default class BufferSyncSupport {
|
||||
const token = new CancellationTokenSource();
|
||||
|
||||
const getErr = this.pendingGetErr = {
|
||||
request: this.client.execute('geterr', args, token.token)
|
||||
request: this.client.executeAsync('geterr', args, token.token)
|
||||
.then(undefined, () => { })
|
||||
.then(() => {
|
||||
if (this.pendingGetErr === getErr) {
|
||||
|
||||
@@ -136,6 +136,8 @@ class MyCompletionItem extends vscode.CompletionItem {
|
||||
return vscode.CompletionItemKind.File;
|
||||
case PConst.Kind.directory:
|
||||
return vscode.CompletionItemKind.Folder;
|
||||
case PConst.Kind.string:
|
||||
return vscode.CompletionItemKind.Constant;
|
||||
}
|
||||
return vscode.CompletionItemKind.Property;
|
||||
}
|
||||
@@ -290,7 +292,7 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
|
||||
...typeConverters.Position.toFileLocationRequestArgs(file, position),
|
||||
includeExternalModuleExports: completionConfiguration.autoImportSuggestions,
|
||||
includeInsertTextCompletions: true,
|
||||
triggerCharacter: context.triggerCharacter ? (context.triggerCharacter === '.' ? undefined : context.triggerCharacter) : undefined
|
||||
triggerCharacter: context.triggerCharacter as Proto.CompletionsTriggerCharacter
|
||||
};
|
||||
|
||||
let msg: Proto.CompletionEntry[] | undefined = undefined;
|
||||
@@ -469,7 +471,7 @@ export default class TypeScriptCompletionItemProvider implements vscode.Completi
|
||||
}
|
||||
}
|
||||
|
||||
if (context.triggerCharacter === '@') {
|
||||
if (context.triggerCharacter === '@' && !this.client.apiVersion.has290Features()) {
|
||||
// make sure we are in something that looks like the start of a jsdoc comment
|
||||
const pre = line.text.slice(0, position.character);
|
||||
if (!pre.match(/^\s*\*[ ]?@/) && !pre.match(/\/\*\*+[ ]?@/)) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
class DiagnosticSet {
|
||||
export class DiagnosticSet {
|
||||
private _map: ObjectMap<vscode.Diagnostic[]> = Object.create(null);
|
||||
|
||||
public set(
|
||||
@@ -90,11 +90,11 @@ export class DiagnosticsManager {
|
||||
public diagnosticsReceived(
|
||||
kind: DiagnosticKind,
|
||||
file: vscode.Uri,
|
||||
syntaxDiagnostics: vscode.Diagnostic[]
|
||||
diagnostics: vscode.Diagnostic[]
|
||||
): void {
|
||||
const diagnostics = this._diagnostics.get(kind);
|
||||
if (diagnostics) {
|
||||
diagnostics.set(file, syntaxDiagnostics);
|
||||
const collection = this._diagnostics.get(kind);
|
||||
if (collection) {
|
||||
collection.set(file, diagnostics);
|
||||
this.updateCurrentDiagnostics(file);
|
||||
}
|
||||
}
|
||||
@@ -112,15 +112,22 @@ export class DiagnosticsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const allDiagnostics: vscode.Diagnostic[] = [];
|
||||
allDiagnostics.push(...this._diagnostics.get(DiagnosticKind.Syntax)!.get(file));
|
||||
allDiagnostics.push(...this._diagnostics.get(DiagnosticKind.Semantic)!.get(file));
|
||||
if (this._enableSuggestions) {
|
||||
allDiagnostics.push(...this._diagnostics.get(DiagnosticKind.Suggestion)!.get(file));
|
||||
}
|
||||
const allDiagnostics = [
|
||||
...this._diagnostics.get(DiagnosticKind.Syntax)!.get(file),
|
||||
...this._diagnostics.get(DiagnosticKind.Semantic)!.get(file),
|
||||
...this.getSuggestionDiagnostics(file),
|
||||
];
|
||||
this._currentDiagnostics.set(file, allDiagnostics);
|
||||
}
|
||||
|
||||
private getSuggestionDiagnostics(file: vscode.Uri) {
|
||||
if (!this._enableSuggestions) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this._diagnostics.get(DiagnosticKind.Suggestion)!.get(file);
|
||||
}
|
||||
|
||||
public getDiagnostics(file: vscode.Uri): vscode.Diagnostic[] {
|
||||
return this._currentDiagnostics.get(file) || [];
|
||||
}
|
||||
|
||||
@@ -88,10 +88,10 @@ export default class FileConfigurationManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const args = {
|
||||
const args: Proto.ConfigureRequestArguments = {
|
||||
file,
|
||||
...currentOptions
|
||||
} as Proto.ConfigureRequestArguments;
|
||||
};
|
||||
await this.client.execute('configure', args, token);
|
||||
this.formatOptions[key] = currentOptions;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as Proto from '../protocol';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import { Command, CommandManager } from '../utils/commandManager';
|
||||
import * as typeconverts from '../utils/typeConverters';
|
||||
import FileConfigurationManager from './fileConfigurationManager';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -48,7 +49,8 @@ class OrganizeImportsCommand implements Command {
|
||||
export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvider {
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
commandManager: CommandManager
|
||||
commandManager: CommandManager,
|
||||
private readonly fileConfigManager: FileConfigurationManager,
|
||||
) {
|
||||
commandManager.register(new OrganizeImportsCommand(client));
|
||||
}
|
||||
@@ -61,7 +63,7 @@ export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvi
|
||||
document: vscode.TextDocument,
|
||||
_range: vscode.Range,
|
||||
_context: vscode.CodeActionContext,
|
||||
_token: vscode.CancellationToken
|
||||
token: vscode.CancellationToken
|
||||
): vscode.CodeAction[] {
|
||||
if (!this.client.apiVersion.has280Features()) {
|
||||
return [];
|
||||
@@ -72,6 +74,8 @@ export class OrganizeImportsCodeActionProvider implements vscode.CodeActionProvi
|
||||
return [];
|
||||
}
|
||||
|
||||
this.fileConfigManager.ensureConfigurationForDocument(document, token);
|
||||
|
||||
const action = new vscode.CodeAction(
|
||||
localize('oraganizeImportsAction.title', "Organize Imports"),
|
||||
vscode.CodeActionKind.SourceOrganizeImports);
|
||||
|
||||
@@ -33,7 +33,10 @@ class ApplyCodeActionCommand implements Command {
|
||||
if (action.fixName) {
|
||||
/* __GDPR__
|
||||
"quickFix.execute" : {
|
||||
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
|
||||
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.logTelemetry('quickFix.execute', {
|
||||
@@ -64,8 +67,11 @@ class ApplyFixAllCodeAction implements Command {
|
||||
|
||||
if (tsAction.fixName) {
|
||||
/* __GDPR__
|
||||
"quickFix.execute" : {
|
||||
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
|
||||
"quickFixAll.execute" : {
|
||||
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.logTelemetry('quickFixAll.execute', {
|
||||
|
||||
@@ -102,7 +102,7 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv
|
||||
|
||||
public async provideCodeActions(
|
||||
document: vscode.TextDocument,
|
||||
_range: vscode.Range,
|
||||
rangeOrSelection: vscode.Range | vscode.Selection,
|
||||
context: vscode.CodeActionContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.CodeAction[]> {
|
||||
@@ -114,22 +114,16 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!vscode.window.activeTextEditor) {
|
||||
if (!(rangeOrSelection instanceof vscode.Selection) || rangeOrSelection.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
const file = this.client.normalizePath(document.uri);
|
||||
if (!file || editor.document.uri.fsPath !== document.uri.fsPath) {
|
||||
if (!file) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (editor.selection.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const range = editor.selection;
|
||||
const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(file, range);
|
||||
const args: Proto.GetApplicableRefactorsRequestArgs = typeConverters.Range.toFileRangeRequestArgs(file, rangeOrSelection);
|
||||
try {
|
||||
const response = await this.client.execute('getApplicableRefactors', args, token);
|
||||
if (!response || !response.body) {
|
||||
@@ -143,7 +137,7 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv
|
||||
codeAction.command = {
|
||||
title: info.description,
|
||||
command: SelectRefactorCommand.ID,
|
||||
arguments: [document, file, info, range]
|
||||
arguments: [document, file, info, rangeOrSelection]
|
||||
};
|
||||
actions.push(codeAction);
|
||||
} else {
|
||||
@@ -152,7 +146,7 @@ export default class TypeScriptRefactorProvider implements vscode.CodeActionProv
|
||||
codeAction.command = {
|
||||
title: action.description,
|
||||
command: ApplyRefactoringCommand.ID,
|
||||
arguments: [document, file, info.name, action.name, range]
|
||||
arguments: [document, file, info.name, action.name, rangeOrSelection]
|
||||
};
|
||||
actions.push(codeAction);
|
||||
}
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ReferenceProvider, Location, TextDocument, Position, CancellationToken } from 'vscode';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
|
||||
export default class TypeScriptReferenceSupport implements ReferenceProvider {
|
||||
export default class TypeScriptReferenceSupport implements vscode.ReferenceProvider {
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient) { }
|
||||
|
||||
public async provideReferences(
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
options: { includeDeclaration: boolean },
|
||||
token: CancellationToken
|
||||
): Promise<Location[]> {
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
options: vscode.ReferenceContext,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.Location[]> {
|
||||
const filepath = this.client.normalizePath(document.uri);
|
||||
if (!filepath) {
|
||||
return [];
|
||||
@@ -29,7 +29,7 @@ export default class TypeScriptReferenceSupport implements ReferenceProvider {
|
||||
if (!msg.body) {
|
||||
return [];
|
||||
}
|
||||
const result: Location[] = [];
|
||||
const result: vscode.Location[] = [];
|
||||
const has203Features = this.client.apiVersion.has203Features();
|
||||
for (const ref of msg.body.refs) {
|
||||
if (!options.includeDeclaration && has203Features && ref.isDefinition) {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { DiagnosticSet } from './diagnostics';
|
||||
|
||||
|
||||
export class UnusedHighlighter {
|
||||
|
||||
private readonly _decorationType: vscode.TextEditorDecorationType;
|
||||
|
||||
private readonly _diagnostics = new DiagnosticSet();
|
||||
private _validate: boolean = true;
|
||||
|
||||
constructor(
|
||||
) {
|
||||
this._decorationType = vscode.window.createTextEditorDecorationType({
|
||||
opacity: '0.7'
|
||||
});
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this._decorationType.dispose();
|
||||
}
|
||||
|
||||
public reInitialize(): void {
|
||||
this._diagnostics.clear();
|
||||
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
editor.setDecorations(this._decorationType, []);
|
||||
}
|
||||
}
|
||||
|
||||
public set validate(value: boolean) {
|
||||
if (this._validate === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._validate = value;
|
||||
if (!value) {
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
editor.setDecorations(this._decorationType, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public diagnosticsReceived(
|
||||
file: vscode.Uri,
|
||||
diagnostics: vscode.Diagnostic[]
|
||||
): void {
|
||||
// Undocumented flag to enable
|
||||
if (!vscode.workspace.getConfiguration('typescript').get('showUnused.experimentalFade')) {
|
||||
return;
|
||||
}
|
||||
this._diagnostics.set(file, diagnostics);
|
||||
this._updateCurrentHighlights(file);
|
||||
}
|
||||
|
||||
private _updateCurrentHighlights(file: vscode.Uri) {
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
if (editor.document.uri.fsPath !== file.fsPath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const diagnostics = this._diagnostics.get(editor.document.uri);
|
||||
if (diagnostics) {
|
||||
editor.setDecorations(this._decorationType, diagnostics.map(x => x.range));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,9 @@ import { LanguageDescription } from './utils/languageDescription';
|
||||
import * as fileSchemes from './utils/fileSchemes';
|
||||
import { CachedNavTreeResponse } from './features/baseCodeLensProvider';
|
||||
import { memoize } from './utils/memoize';
|
||||
import { disposeAll } from './utils/dipose';
|
||||
import { disposeAll } from './utils/dispose';
|
||||
import TelemetryReporter from './utils/telemetry';
|
||||
import { UnusedHighlighter } from './features/unusedHighlighter';
|
||||
|
||||
const validateSetting = 'validate.enable';
|
||||
const suggestionSetting = 'suggestionActions.enabled';
|
||||
@@ -29,6 +30,7 @@ const foldingSetting = 'typescript.experimental.syntaxFolding';
|
||||
export default class LanguageProvider {
|
||||
private readonly diagnosticsManager: DiagnosticsManager;
|
||||
private readonly bufferSyncSupport: BufferSyncSupport;
|
||||
private readonly ununsedHighlighter: UnusedHighlighter;
|
||||
private readonly fileConfigurationManager: FileConfigurationManager;
|
||||
|
||||
private readonly toUpdateOnConfigurationChanged: ({ updateConfiguration: () => void })[] = [];
|
||||
@@ -56,6 +58,7 @@ export default class LanguageProvider {
|
||||
}, this._validate);
|
||||
|
||||
this.diagnosticsManager = new DiagnosticsManager(description.diagnosticOwner);
|
||||
this.ununsedHighlighter = new UnusedHighlighter();
|
||||
|
||||
workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables);
|
||||
this.configurationChanged();
|
||||
@@ -170,7 +173,7 @@ export default class LanguageProvider {
|
||||
}
|
||||
|
||||
private configurationChanged(): void {
|
||||
const config = workspace.getConfiguration(this.id);
|
||||
const config = workspace.getConfiguration(this.id, null);
|
||||
this.updateValidate(config.get(validateSetting, true));
|
||||
this.updateSuggestionDiagnostics(config.get(suggestionSetting, true));
|
||||
|
||||
@@ -226,6 +229,7 @@ export default class LanguageProvider {
|
||||
|
||||
public reInitialize(): void {
|
||||
this.diagnosticsManager.reInitialize();
|
||||
this.ununsedHighlighter.reInitialize();
|
||||
this.bufferSyncSupport.reOpenDocuments();
|
||||
this.bufferSyncSupport.requestAllDiagnostics();
|
||||
this.fileConfigurationManager.reset();
|
||||
@@ -249,7 +253,7 @@ export default class LanguageProvider {
|
||||
}
|
||||
|
||||
if (this.client.apiVersion.has280Features()) {
|
||||
const organizeImportsProvider = new (await import('./features/organizeImports')).OrganizeImportsCodeActionProvider(this.client, this.commandManager);
|
||||
const organizeImportsProvider = new (await import('./features/organizeImports')).OrganizeImportsCodeActionProvider(this.client, this.commandManager, this.fileConfigurationManager);
|
||||
this.versionDependentDisposables.push(languages.registerCodeActionsProvider(selector, organizeImportsProvider, organizeImportsProvider.metadata));
|
||||
}
|
||||
}
|
||||
@@ -258,8 +262,13 @@ export default class LanguageProvider {
|
||||
this.bufferSyncSupport.requestAllDiagnostics();
|
||||
}
|
||||
|
||||
public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, syntaxDiagnostics: Diagnostic[]): void {
|
||||
this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, syntaxDiagnostics);
|
||||
public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, diagnostics: (Diagnostic & { reportUnnecessary: any })[]): void {
|
||||
const config = workspace.getConfiguration(this.id);
|
||||
const reportUnnecessary = config.get<boolean>('showUnused.enabled', true);
|
||||
if (diagnosticsKind === DiagnosticKind.Suggestion) {
|
||||
this.ununsedHighlighter.diagnosticsReceived(file, diagnostics.filter(diag => diag.reportUnnecessary));
|
||||
}
|
||||
this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, diagnostics.filter(diag => diag.reportUnnecessary ? reportUnnecessary : true));
|
||||
}
|
||||
|
||||
public configFileDiagnosticsReceived(file: Uri, diagnostics: Diagnostic[]): void {
|
||||
|
||||
@@ -31,6 +31,7 @@ export class Kind {
|
||||
public static readonly type = 'type';
|
||||
public static readonly variable = 'var';
|
||||
public static readonly warning = 'warning';
|
||||
public static readonly string = 'string';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import * as typeConverters from './utils/typeConverters';
|
||||
import { CommandManager } from './utils/commandManager';
|
||||
import { LanguageDescription } from './utils/languageDescription';
|
||||
import LogDirectoryProvider from './utils/logDirectoryProvider';
|
||||
import { disposeAll } from './utils/dipose';
|
||||
import { disposeAll } from './utils/dispose';
|
||||
import { DiagnosticKind } from './features/diagnostics';
|
||||
|
||||
// Style check diagnostics that can be reported as warnings
|
||||
@@ -146,8 +146,9 @@ export default class TypeScriptServiceClientHost {
|
||||
}
|
||||
|
||||
private configurationChanged(): void {
|
||||
const config = workspace.getConfiguration('typescript');
|
||||
this.reportStyleCheckAsWarnings = config.get('reportStyleChecksAsWarnings', true);
|
||||
const typescriptConfig = workspace.getConfiguration('typescript');
|
||||
|
||||
this.reportStyleCheckAsWarnings = typescriptConfig.get('reportStyleChecksAsWarnings', true);
|
||||
}
|
||||
|
||||
private async findLanguage(resource: Uri): Promise<LanguageProvider | undefined> {
|
||||
@@ -239,11 +240,14 @@ export default class TypeScriptServiceClientHost {
|
||||
});
|
||||
}
|
||||
|
||||
private createMarkerDatas(diagnostics: Proto.Diagnostic[], source: string): Diagnostic[] {
|
||||
private createMarkerDatas(
|
||||
diagnostics: Proto.Diagnostic[],
|
||||
source: string
|
||||
): (Diagnostic & { reportUnnecessary: any })[] {
|
||||
return diagnostics.map(tsDiag => this.tsDiagnosticToVsDiagnostic(tsDiag, source));
|
||||
}
|
||||
|
||||
private tsDiagnosticToVsDiagnostic(diagnostic: Proto.Diagnostic, source: string) {
|
||||
private tsDiagnosticToVsDiagnostic(diagnostic: Proto.Diagnostic, source: string): Diagnostic & { reportUnnecessary: any } {
|
||||
const { start, end, text } = diagnostic;
|
||||
const range = new Range(typeConverters.Position.fromLocation(start), typeConverters.Position.fromLocation(end));
|
||||
const converted = new Diagnostic(range, text);
|
||||
@@ -252,7 +256,8 @@ export default class TypeScriptServiceClientHost {
|
||||
if (diagnostic.code) {
|
||||
converted.code = diagnostic.code;
|
||||
}
|
||||
return converted;
|
||||
(converted as Diagnostic & { reportUnnecessary: any }).reportUnnecessary = diagnostic.reportsUnnecessary;
|
||||
return converted as Diagnostic & { reportUnnecessary: any };
|
||||
}
|
||||
|
||||
private getDiagnosticSeverity(diagnostic: Proto.Diagnostic): DiagnosticSeverity {
|
||||
|
||||
@@ -30,7 +30,6 @@ export interface ITypeScriptServiceClient {
|
||||
execute(command: 'open', args: Proto.OpenRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command: 'close', args: Proto.FileRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command: 'change', args: Proto.ChangeRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command: 'geterr', args: Proto.GeterrRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
|
||||
execute(command: 'quickinfo', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.QuickInfoResponse>;
|
||||
execute(command: 'completions', args: Proto.CompletionsRequestArgs, token?: CancellationToken): Promise<Proto.CompletionsResponse>;
|
||||
execute(command: 'completionEntryDetails', args: Proto.CompletionDetailsRequestArgs, token?: CancellationToken): Promise<Proto.CompletionDetailsResponse>;
|
||||
@@ -60,4 +59,6 @@ export interface ITypeScriptServiceClient {
|
||||
execute(command: 'organizeImports', args: Proto.OrganizeImportsRequestArgs, token?: CancellationToken): Promise<Proto.OrganizeImportsResponse>;
|
||||
execute(command: 'getOutliningSpans', args: Proto.FileRequestArgs, token: CancellationToken): Promise<Proto.OutliningSpansResponse>;
|
||||
execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise<any>;
|
||||
|
||||
executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: CancellationToken): Promise<any>;
|
||||
}
|
||||
@@ -28,37 +28,45 @@ import { TypeScriptVersionPicker } from './utils/versionPicker';
|
||||
import * as fileSchemes from './utils/fileSchemes';
|
||||
import { inferredProjectConfig } from './utils/tsconfig';
|
||||
import LogDirectoryProvider from './utils/logDirectoryProvider';
|
||||
import { disposeAll } from './utils/dipose';
|
||||
import { disposeAll } from './utils/dispose';
|
||||
import { DiagnosticKind } from './features/diagnostics';
|
||||
import { TypeScriptPluginPathsProvider } from './utils/pluginPathsProvider';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
interface CallbackItem {
|
||||
c: (value: any) => void;
|
||||
e: (err: any) => void;
|
||||
start: number;
|
||||
readonly c: (value: any) => void;
|
||||
readonly e: (err: any) => void;
|
||||
readonly start: number;
|
||||
}
|
||||
|
||||
class CallbackMap {
|
||||
private readonly callbacks: Map<number, CallbackItem> = new Map();
|
||||
private readonly asyncCallbacks: Map<number, CallbackItem> = new Map();
|
||||
public pendingResponses: number = 0;
|
||||
|
||||
public destroy(e: any): void {
|
||||
for (const callback of this.callbacks.values()) {
|
||||
callback.e(e);
|
||||
}
|
||||
for (const callback of this.asyncCallbacks.values()) {
|
||||
callback.e(e);
|
||||
}
|
||||
this.callbacks.clear();
|
||||
this.pendingResponses = 0;
|
||||
}
|
||||
|
||||
public add(seq: number, callback: CallbackItem) {
|
||||
this.callbacks.set(seq, callback);
|
||||
++this.pendingResponses;
|
||||
public add(seq: number, callback: CallbackItem, isAsync: boolean) {
|
||||
if (isAsync) {
|
||||
this.asyncCallbacks.set(seq, callback);
|
||||
} else {
|
||||
this.callbacks.set(seq, callback);
|
||||
++this.pendingResponses;
|
||||
}
|
||||
}
|
||||
|
||||
public fetch(seq: number): CallbackItem | undefined {
|
||||
const callback = this.callbacks.get(seq);
|
||||
const callback = this.callbacks.get(seq) || this.asyncCallbacks.get(seq);
|
||||
this.delete(seq);
|
||||
return callback;
|
||||
}
|
||||
@@ -66,13 +74,16 @@ class CallbackMap {
|
||||
private delete(seq: number) {
|
||||
if (this.callbacks.delete(seq)) {
|
||||
--this.pendingResponses;
|
||||
} else {
|
||||
this.asyncCallbacks.delete(seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface RequestItem {
|
||||
request: Proto.Request;
|
||||
readonly request: Proto.Request;
|
||||
callbacks: CallbackItem | null;
|
||||
readonly isAsync: boolean;
|
||||
}
|
||||
|
||||
class RequestQueue {
|
||||
@@ -383,7 +394,11 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
this.error('Starting TSServer failed with error.', err);
|
||||
window.showErrorMessage(localize('serverCouldNotBeStarted', 'TypeScript language server couldn\'t be started. Error message is: {0}', err.message || err));
|
||||
/* __GDPR__
|
||||
"error" : {}
|
||||
"error" : {
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('error');
|
||||
this.resetClientVersion();
|
||||
@@ -401,7 +416,11 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
this.error(`TSServer log file: ${this.tsServerLogFile}`);
|
||||
}
|
||||
/* __GDPR__
|
||||
"tsserver.error" : {}
|
||||
"tsserver.error" : {
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.error');
|
||||
this.serviceExited(false);
|
||||
@@ -413,7 +432,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
this.error(`TSServer exited with code: ${code}`);
|
||||
/* __GDPR__
|
||||
"tsserver.exitWithCode" : {
|
||||
"code" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }
|
||||
"code" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.exitWithCode', { code: code });
|
||||
@@ -567,7 +589,11 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
id: MessageAction.reportIssue
|
||||
});
|
||||
/* __GDPR__
|
||||
"serviceExited" : {}
|
||||
"serviceExited" : {
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('serviceExited');
|
||||
this.resetClientVersion();
|
||||
@@ -657,6 +683,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: CancellationToken): Promise<any> {
|
||||
return this.executeImpl(command, args, { isAsync: true, token, expectsResult: true });
|
||||
}
|
||||
|
||||
public execute(command: string, args: any, expectsResultOrToken?: boolean | CancellationToken): Promise<any> {
|
||||
let token: CancellationToken | undefined = undefined;
|
||||
let expectsResult = true;
|
||||
@@ -665,19 +695,23 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
} else {
|
||||
token = expectsResultOrToken;
|
||||
}
|
||||
return this.executeImpl(command, args, { isAsync: false, token, expectsResult });
|
||||
}
|
||||
|
||||
private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: CancellationToken, expectsResult: boolean }): Promise<any> {
|
||||
const request = this.requestQueue.createRequest(command, args);
|
||||
const requestInfo: RequestItem = {
|
||||
request: request,
|
||||
callbacks: null
|
||||
callbacks: null,
|
||||
isAsync: executeInfo.isAsync
|
||||
};
|
||||
let result: Promise<any>;
|
||||
if (expectsResult) {
|
||||
if (executeInfo.expectsResult) {
|
||||
let wasCancelled = false;
|
||||
result = new Promise<any>((resolve, reject) => {
|
||||
requestInfo.callbacks = { c: resolve, e: reject, start: Date.now() };
|
||||
if (token) {
|
||||
token.onCancellationRequested(() => {
|
||||
if (executeInfo.token) {
|
||||
executeInfo.token.onCancellationRequested(() => {
|
||||
wasCancelled = true;
|
||||
this.tryCancelRequest(request.seq);
|
||||
});
|
||||
@@ -736,7 +770,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
const serverRequest = requestItem.request;
|
||||
this.tracer.traceRequest(serverRequest, !!requestItem.callbacks, this.requestQueue.length);
|
||||
if (requestItem.callbacks) {
|
||||
this.callbacks.add(serverRequest.seq, requestItem.callbacks);
|
||||
this.callbacks.add(serverRequest.seq, requestItem.callbacks, requestItem.isAsync);
|
||||
}
|
||||
this.service()
|
||||
.then((childProcess) => {
|
||||
@@ -805,8 +839,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
private dispatchEvent(event: Proto.Event) {
|
||||
switch (event.event) {
|
||||
case 'requestCompleted':
|
||||
const p = this.callbacks.fetch((event as Proto.RequestCompletedEvent).body.request_seq);
|
||||
const seq = (event as Proto.RequestCompletedEvent).body.request_seq;
|
||||
const p = this.callbacks.fetch(seq);
|
||||
if (p) {
|
||||
this.tracer.traceRequestCompleted('requestCompleted', seq, p.start);
|
||||
p.c(undefined);
|
||||
}
|
||||
break;
|
||||
@@ -897,7 +933,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
|
||||
"typingsInstalled" : {
|
||||
"installedPackages" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"installSuccess": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"typingsInstallerVersion": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
"typingsInstallerVersion": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
// __GDPR__COMMENT__: Other events are defined by TypeScript.
|
||||
|
||||
@@ -57,7 +57,11 @@ class ExcludeHintItem {
|
||||
this._item.color = '#A5DF3B';
|
||||
this._item.show();
|
||||
/* __GDPR__
|
||||
"js.hintProjectExcludes" : {}
|
||||
"js.hintProjectExcludes" : {
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.logTelemetry('js.hintProjectExcludes');
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@ export default class TelemetryReporter {
|
||||
if (!properties) {
|
||||
properties = {};
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"TypeScriptCommonProperties" : {
|
||||
"version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
properties['version'] = this.clientVersionDelegate();
|
||||
|
||||
reporter.sendTelemetryEvent(eventName, properties);
|
||||
|
||||
@@ -74,6 +74,13 @@ export default class Tracer {
|
||||
this.logTrace(`Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - startTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data);
|
||||
}
|
||||
|
||||
public traceRequestCompleted(command: string, request_seq: number, startTime: number): any {
|
||||
if (this.trace === Trace.Off) {
|
||||
return;
|
||||
}
|
||||
this.logTrace(`Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`);
|
||||
}
|
||||
|
||||
public traceEvent(event: Proto.Event): void {
|
||||
if (this.trace === Trace.Off) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user