mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 01:29:04 +01:00
Merge branch 'master' into aeschli/ts-sem
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
import API from '../utils/api';
|
||||
import { VersionDependentRegistration } from '../utils/dependentRegistration';
|
||||
import * as Proto from '../protocol';
|
||||
import * as path from 'path';
|
||||
import * as PConst from '../protocol.const';
|
||||
|
||||
class TypeScriptCallHierarchySupport implements vscode.CallHierarchyProvider {
|
||||
public static readonly minVersion = API.v380;
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient) { }
|
||||
|
||||
public async prepareCallHierarchy(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.CallHierarchyItem | vscode.CallHierarchyItem[] | undefined> {
|
||||
const filepath = this.client.toOpenedFilePath(document);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position);
|
||||
const response = await this.client.execute('prepareCallHierarchy', args, token);
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Array.isArray(response.body)
|
||||
? response.body.map(fromProtocolCallHierarchyItem)
|
||||
: fromProtocolCallHierarchyItem(response.body);
|
||||
}
|
||||
|
||||
public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
|
||||
const filepath = this.client.toPath(item.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const args = typeConverters.Position.toFileLocationRequestArgs(filepath, item.selectionRange.start);
|
||||
const response = await this.client.execute('provideCallHierarchyIncomingCalls', args, token);
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return response.body.map(fromProtocolCallHierchyIncomingCall);
|
||||
}
|
||||
|
||||
public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
|
||||
const filepath = this.client.toPath(item.uri);
|
||||
if (!filepath) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const args = typeConverters.Position.toFileLocationRequestArgs(filepath, item.selectionRange.start);
|
||||
const response = await this.client.execute('provideCallHierarchyOutgoingCalls', args, token);
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return response.body.map(fromProtocolCallHierchyOutgoingCall);
|
||||
}
|
||||
}
|
||||
|
||||
function isSourceFileItem(item: Proto.CallHierarchyItem) {
|
||||
return item.kind === PConst.Kind.script || item.kind === PConst.Kind.module && item.selectionSpan.start.line === 0 && item.selectionSpan.start.offset === 0;
|
||||
}
|
||||
|
||||
function fromProtocolCallHierarchyItem(item: Proto.CallHierarchyItem): vscode.CallHierarchyItem {
|
||||
const useFileName = isSourceFileItem(item);
|
||||
const name = useFileName ? path.basename(item.file) : item.name;
|
||||
const detail = useFileName ? vscode.workspace.asRelativePath(path.dirname(item.file)) : '';
|
||||
return new vscode.CallHierarchyItem(
|
||||
typeConverters.SymbolKind.fromProtocolScriptElementKind(item.kind),
|
||||
name,
|
||||
detail,
|
||||
vscode.Uri.file(item.file),
|
||||
typeConverters.Range.fromTextSpan(item.span),
|
||||
typeConverters.Range.fromTextSpan(item.selectionSpan)
|
||||
);
|
||||
}
|
||||
|
||||
function fromProtocolCallHierchyIncomingCall(item: Proto.CallHierarchyIncomingCall): vscode.CallHierarchyIncomingCall {
|
||||
return new vscode.CallHierarchyIncomingCall(
|
||||
fromProtocolCallHierarchyItem(item.from),
|
||||
item.fromSpans.map(typeConverters.Range.fromTextSpan)
|
||||
);
|
||||
}
|
||||
|
||||
function fromProtocolCallHierchyOutgoingCall(item: Proto.CallHierarchyOutgoingCall): vscode.CallHierarchyOutgoingCall {
|
||||
return new vscode.CallHierarchyOutgoingCall(
|
||||
fromProtocolCallHierarchyItem(item.to),
|
||||
item.fromSpans.map(typeConverters.Range.fromTextSpan)
|
||||
);
|
||||
}
|
||||
|
||||
export function register(
|
||||
selector: vscode.DocumentSelector,
|
||||
client: ITypeScriptServiceClient
|
||||
) {
|
||||
return new VersionDependentRegistration(client, TypeScriptCallHierarchySupport.minVersion,
|
||||
() => vscode.languages.registerCallHierarchyProvider(selector,
|
||||
new TypeScriptCallHierarchySupport(client)));
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import { ConfigurationDependentRegistration } from '../utils/dependentRegistrati
|
||||
import { memoize } from '../utils/memoize';
|
||||
import * as Previewer from '../utils/previewer';
|
||||
import { snippetForFunctionCall } from '../utils/snippetForFunctionCall';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
import TypingsStatus from '../utils/typingsStatus';
|
||||
import FileConfigurationManager from './fileConfigurationManager';
|
||||
@@ -405,15 +405,17 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
|
||||
"duration" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"type" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"count" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"updateGraphDurationMs" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.telemetryReporter.logTelemetry('completions.execute', {
|
||||
duration: duration + '',
|
||||
type: response ? response.type : 'unknown',
|
||||
count: (response && response.type === 'response' && response.body ? response.body.entries.length : 0) + ''
|
||||
duration: duration,
|
||||
type: response?.type ?? 'unknown',
|
||||
count: response?.type === 'response' && response.body ? response.body.entries.length : 0,
|
||||
updateGraphDurationMs: response?.type === 'response' ? response.performanceData?.updateGraphDurationMs : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Command, CommandManager } from '../utils/commandManager';
|
||||
import { VersionDependentRegistration } from '../utils/dependentRegistration';
|
||||
import * as typeconverts from '../utils/typeConverters';
|
||||
import FileConfigurationManager from './fileConfigurationManager';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import { nulToken } from '../utils/cancellation';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -12,7 +12,7 @@ import { nulToken } from '../utils/cancellation';
|
||||
import { applyCodeActionCommands, getEditForCodeAction } from '../utils/codeAction';
|
||||
import { Command, CommandManager } from '../utils/commandManager';
|
||||
import { memoize } from '../utils/memoize';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
import { DiagnosticsManager } from './diagnostics';
|
||||
import FileConfigurationManager from './fileConfigurationManager';
|
||||
|
||||
@@ -11,7 +11,7 @@ import API from '../utils/api';
|
||||
import { nulToken } from '../utils/cancellation';
|
||||
import { Command, CommandManager } from '../utils/commandManager';
|
||||
import { VersionDependentRegistration } from '../utils/dependentRegistration';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import * as typeConverters from '../utils/typeConverters';
|
||||
import FormattingOptionsManager from './fileConfigurationManager';
|
||||
import * as fileSchemes from '../utils/fileSchemes';
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Disposable } from './utils/dispose';
|
||||
import * as fileSchemes from './utils/fileSchemes';
|
||||
import { LanguageDescription } from './utils/languageDescription';
|
||||
import { memoize } from './utils/memoize';
|
||||
import TelemetryReporter from './utils/telemetry';
|
||||
import { TelemetryReporter } from './utils/telemetry';
|
||||
import TypingsStatus from './utils/typingsStatus';
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ export default class LanguageProvider extends Disposable {
|
||||
import('./features/tagClosing').then(provider => this._register(provider.register(selector, this.description.id, this.client))),
|
||||
import('./features/typeDefinitions').then(provider => this._register(provider.register(selector, this.client))),
|
||||
import('./features/semanticColoring').then(provider => this._register(provider.register(selector, this.client))),
|
||||
import('./features/callHierarchy').then(provider => this._register(provider.register(selector, this.client))),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ export class Kind {
|
||||
public static readonly warning = 'warning';
|
||||
public static readonly string = 'string';
|
||||
public static readonly parameter = 'parameter';
|
||||
public static readonly typeParameter = 'type parameter';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +1,61 @@
|
||||
import * as Proto from 'typescript/lib/protocol';
|
||||
export = Proto;
|
||||
|
||||
declare module "typescript/lib/protocol" {
|
||||
// TODO: Remove this hardcoded type once we update to TS 3.8+ that brings in the proper types
|
||||
interface Response {
|
||||
performanceData?: {
|
||||
updateGraphDurationMs?: number;
|
||||
}
|
||||
}
|
||||
|
||||
const enum CommandTypes {
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
|
||||
}
|
||||
|
||||
interface CallHierarchyItem {
|
||||
name: string;
|
||||
kind: ScriptElementKind;
|
||||
file: string;
|
||||
span: TextSpan;
|
||||
selectionSpan: TextSpan;
|
||||
}
|
||||
|
||||
interface CallHierarchyIncomingCall {
|
||||
from: CallHierarchyItem;
|
||||
fromSpans: TextSpan[];
|
||||
}
|
||||
|
||||
interface CallHierarchyOutgoingCall {
|
||||
to: CallHierarchyItem;
|
||||
fromSpans: TextSpan[];
|
||||
}
|
||||
|
||||
interface PrepareCallHierarchyRequest extends FileLocationRequest {
|
||||
command: CommandTypes.PrepareCallHierarchy;
|
||||
}
|
||||
|
||||
interface PrepareCallHierarchyResponse extends Response {
|
||||
readonly body: CallHierarchyItem | CallHierarchyItem[];
|
||||
}
|
||||
|
||||
interface ProvideCallHierarchyIncomingCallsRequest extends FileLocationRequest {
|
||||
command: CommandTypes.ProvideCallHierarchyIncomingCalls;
|
||||
kind: ScriptElementKind;
|
||||
}
|
||||
|
||||
interface ProvideCallHierarchyIncomingCallsResponse extends Response {
|
||||
readonly body: CallHierarchyIncomingCall[];
|
||||
}
|
||||
|
||||
interface ProvideCallHierarchyOutgoingCallsRequest extends FileLocationRequest {
|
||||
command: CommandTypes.ProvideCallHierarchyOutgoingCalls;
|
||||
kind: ScriptElementKind;
|
||||
}
|
||||
|
||||
interface ProvideCallHierarchyOutgoingCallsResponse extends Response {
|
||||
readonly body: CallHierarchyOutgoingCall[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as stream from 'stream';
|
||||
import { PipeRequestCanceller, TsServerProcess, ProcessBasedTsServer } from '../tsServer/server';
|
||||
import { nulToken } from '../utils/cancellation';
|
||||
import Logger from '../utils/logger';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import Tracer from '../utils/tracer';
|
||||
import * as Proto from '../protocol';
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as vscode from 'vscode';
|
||||
import * as Proto from '../protocol';
|
||||
import { ServerResponse, TypeScriptRequests } from '../typescriptService';
|
||||
import { Disposable } from '../utils/dispose';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import Tracer from '../utils/tracer';
|
||||
import { TypeScriptVersion } from '../utils/versionProvider';
|
||||
import { Reader } from '../utils/wireProtocol';
|
||||
|
||||
@@ -15,7 +15,7 @@ import LogDirectoryProvider from '../utils/logDirectoryProvider';
|
||||
import Logger from '../utils/logger';
|
||||
import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider';
|
||||
import { PluginManager } from '../utils/plugins';
|
||||
import TelemetryReporter from '../utils/telemetry';
|
||||
import { TelemetryReporter } from '../utils/telemetry';
|
||||
import Tracer from '../utils/tracer';
|
||||
import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider';
|
||||
import { ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerProcess, TsServerDelegate } from './server';
|
||||
|
||||
@@ -58,6 +58,9 @@ interface StandardTsServerRequests {
|
||||
'signatureHelp': [Proto.SignatureHelpRequestArgs, Proto.SignatureHelpResponse];
|
||||
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse];
|
||||
'updateOpen': [Proto.UpdateOpenRequestArgs, Proto.Response];
|
||||
'prepareCallHierarchy': [Proto.FileLocationRequestArgs, Proto.PrepareCallHierarchyResponse];
|
||||
'provideCallHierarchyIncomingCalls': [Proto.FileLocationRequestArgs, Proto.ProvideCallHierarchyIncomingCallsResponse];
|
||||
'provideCallHierarchyOutgoingCalls': [Proto.FileLocationRequestArgs, Proto.ProvideCallHierarchyOutgoingCallsResponse];
|
||||
}
|
||||
|
||||
interface NoResponseTsServerRequests {
|
||||
|
||||
@@ -22,7 +22,7 @@ import LogDirectoryProvider from './utils/logDirectoryProvider';
|
||||
import Logger from './utils/logger';
|
||||
import { TypeScriptPluginPathsProvider } from './utils/pluginPathsProvider';
|
||||
import { PluginManager } from './utils/plugins';
|
||||
import TelemetryReporter, { VSCodeTelemetryReporter } from './utils/telemetry';
|
||||
import { TelemetryReporter, VSCodeTelemetryReporter, TelemetryProperties } from './utils/telemetry';
|
||||
import Tracer from './utils/tracer';
|
||||
import { inferredProjectCompilerOptions } from './utils/tsconfig';
|
||||
import { TypeScriptVersionPicker } from './utils/versionPicker';
|
||||
@@ -271,7 +271,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
this.logger.error(message, data);
|
||||
}
|
||||
|
||||
private logTelemetry(eventName: string, properties?: { readonly [prop: string]: string }) {
|
||||
private logTelemetry(eventName: string, properties?: TelemetryProperties) {
|
||||
this.telemetryReporter.logTelemetry(eventName, properties);
|
||||
}
|
||||
|
||||
@@ -711,7 +711,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}",
|
||||
"${TypeScriptRequestErrorProperties}"
|
||||
]
|
||||
],
|
||||
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('fatalError', { command, ...(error instanceof TypeScriptServerError ? error.telemetry : {}) });
|
||||
|
||||
@@ -31,6 +31,7 @@ export default class API {
|
||||
public static readonly v340 = API.fromSimpleString('3.4.0');
|
||||
public static readonly v345 = API.fromSimpleString('3.4.5');
|
||||
public static readonly v350 = API.fromSimpleString('3.5.0');
|
||||
public static readonly v380 = API.fromSimpleString('3.8.0');
|
||||
|
||||
public static fromVersionString(versionString: string): API {
|
||||
let version = semver.valid(versionString);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { loadMessageBundle } from 'vscode-nls';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
import TelemetryReporter from './telemetry';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
import { isImplicitProjectConfigFile, openOrCreateConfigFile } from './tsconfig';
|
||||
|
||||
const localize = loadMessageBundle();
|
||||
|
||||
@@ -13,8 +13,12 @@ interface PackageInfo {
|
||||
readonly aiKey: string;
|
||||
}
|
||||
|
||||
export default interface TelemetryReporter {
|
||||
logTelemetry(eventName: string, properties?: { readonly [prop: string]: string }): void;
|
||||
export interface TelemetryProperties {
|
||||
readonly [prop: string]: string | number | undefined;
|
||||
}
|
||||
|
||||
export interface TelemetryReporter {
|
||||
logTelemetry(eventName: string, properties?: TelemetryProperties): void;
|
||||
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,18 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as Proto from '../protocol';
|
||||
import * as PConst from '../protocol.const';
|
||||
import { ITypeScriptServiceClient } from '../typescriptService';
|
||||
|
||||
export namespace Range {
|
||||
export const fromTextSpan = (span: Proto.TextSpan): vscode.Range =>
|
||||
fromLocations(span.start, span.end);
|
||||
|
||||
export const toTextSpan = (range: vscode.Range): Proto.TextSpan => ({
|
||||
start: Position.toLocation(range.start),
|
||||
end: Position.toLocation(range.end)
|
||||
});
|
||||
|
||||
export const fromLocations = (start: Proto.Location, end: Proto.Location): vscode.Range =>
|
||||
new vscode.Range(
|
||||
Math.max(0, start.line - 1), Math.max(start.offset - 1, 0),
|
||||
@@ -90,3 +96,33 @@ export namespace WorkspaceEdit {
|
||||
return workspaceEdit;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace SymbolKind {
|
||||
export function fromProtocolScriptElementKind(kind: Proto.ScriptElementKind) {
|
||||
switch (kind) {
|
||||
case PConst.Kind.module: return vscode.SymbolKind.Module;
|
||||
case PConst.Kind.class: return vscode.SymbolKind.Class;
|
||||
case PConst.Kind.enum: return vscode.SymbolKind.Enum;
|
||||
case PConst.Kind.enumMember: return vscode.SymbolKind.EnumMember;
|
||||
case PConst.Kind.interface: return vscode.SymbolKind.Interface;
|
||||
case PConst.Kind.indexSignature: return vscode.SymbolKind.Method;
|
||||
case PConst.Kind.callSignature: return vscode.SymbolKind.Method;
|
||||
case PConst.Kind.memberFunction: return vscode.SymbolKind.Method;
|
||||
case PConst.Kind.memberVariable: return vscode.SymbolKind.Property;
|
||||
case PConst.Kind.memberGetAccessor: return vscode.SymbolKind.Property;
|
||||
case PConst.Kind.memberSetAccessor: return vscode.SymbolKind.Property;
|
||||
case PConst.Kind.variable: return vscode.SymbolKind.Variable;
|
||||
case PConst.Kind.let: return vscode.SymbolKind.Variable;
|
||||
case PConst.Kind.const: return vscode.SymbolKind.Variable;
|
||||
case PConst.Kind.localVariable: return vscode.SymbolKind.Variable;
|
||||
case PConst.Kind.alias: return vscode.SymbolKind.Variable;
|
||||
case PConst.Kind.function: return vscode.SymbolKind.Function;
|
||||
case PConst.Kind.localFunction: return vscode.SymbolKind.Function;
|
||||
case PConst.Kind.constructSignature: return vscode.SymbolKind.Constructor;
|
||||
case PConst.Kind.constructorImplementation: return vscode.SymbolKind.Constructor;
|
||||
case PConst.Kind.typeParameter: return vscode.SymbolKind.TypeParameter;
|
||||
case PConst.Kind.string: return vscode.SymbolKind.String;
|
||||
default: return vscode.SymbolKind.Variable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user