Merge branch 'master' into joh/outline

This commit is contained in:
Johannes Rieken
2018-05-14 09:18:57 +02:00
195 changed files with 6042 additions and 1251 deletions

View File

@@ -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) {

View File

@@ -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(/\/\*\*+[ ]?@/)) {

View File

@@ -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) || [];
}

View 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;
}

View File

@@ -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);

View File

@@ -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', {

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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));
}
}
}
}

View File

@@ -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 {

View File

@@ -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';
}

View File

@@ -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 {

View File

@@ -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>;
}

View File

@@ -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.

View File

@@ -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');
}

View File

@@ -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);

View File

@@ -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;