From 33ad5917a340d80f9f086285b53cd5e98aa334fc Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Mon, 24 Oct 2022 13:09:55 +0200 Subject: [PATCH] Move LSIF to TS 4.8.4 --- src/compiler/checker.ts | 31 +++++++++++++++++++++++++++ src/compiler/types.ts | 15 +++++++++++++ src/harness/client.ts | 11 ++++++++-- src/harness/harnessLanguageService.ts | 10 +++++---- src/services/services.ts | 21 +++++++++++------- src/services/shims.ts | 31 ++++++++++++++++----------- src/services/types.ts | 2 ++ 7 files changed, 95 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8381f6898077f..025c91f504d93 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -395,6 +395,9 @@ namespace ts { // extra cost of calling `getParseTreeNode` when calling these functions from inside the // checker. const checker: TypeChecker = { + setSymbolChainCache: (cache: SymbolChainCache | undefined): void => { + nodeBuilder.setSymbolChainCache(cache); + }, getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"), getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"), getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount, @@ -4901,7 +4904,9 @@ namespace ts { } function createNodeBuilder() { + let symbolChainCache: SymbolChainCache | undefined; return { + setSymbolChainCache: (cache: SymbolChainCache | undefined): void => { symbolChainCache = cache }, typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)), indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => @@ -4942,6 +4947,7 @@ namespace ts { readFile: host.readFile ? (fileName => host.readFile!(fileName)) : undefined, } : undefined }, encounteredError: false, + cache: symbolChainCache, reportedDiagnostic: false, visitedTypes: undefined, symbolDepth: undefined, @@ -6146,6 +6152,30 @@ namespace ts { /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { + let key: SymbolChainCacheKey | undefined; + let result: Symbol[] | undefined; + if (context.cache) { + key = { + symbol, + enclosingDeclaration: context.enclosingDeclaration, + flags: context.flags, + meaning: meaning, + yieldModuleSymbol: yieldModuleSymbol, + endOfChain: endOfChain + } + result = context.cache.lookup(key); + if (result) { + return result; + } + } + result = doGetSymbolChain(symbol, meaning, endOfChain); + if (result && key && context.cache) { + context.cache.cache(key, result); + } + return result; + } + + function doGetSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); let parentSpecifiers: (string | undefined)[]; if (!accessibleSymbolChain || @@ -8423,6 +8453,7 @@ namespace ts { enclosingDeclaration: Node | undefined; flags: NodeBuilderFlags; tracker: SymbolTracker; + cache: SymbolChainCache | undefined; // State encounteredError: boolean; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e7aa743008d69..e7c128bcdc50c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4359,7 +4359,22 @@ namespace ts { readonly redirectTargetsMap: RedirectTargetsMap; } + export interface SymbolChainCacheKey { + symbol: Symbol; + enclosingDeclaration?: Node; + flags: NodeBuilderFlags; + meaning: SymbolFlags; + yieldModuleSymbol?: boolean; + endOfChain: boolean; + } + + export interface SymbolChainCache { + lookup(key: SymbolChainCacheKey): Symbol[] | undefined; + cache(key: SymbolChainCacheKey, value: Symbol[]): void; + } + export interface TypeChecker { + setSymbolChainCache(cache: SymbolChainCache | undefined): void; getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type; /* @internal */ getTypeOfSymbol(symbol: Symbol): Type; getDeclaredTypeOfSymbol(symbol: Symbol): Type; diff --git a/src/harness/client.ts b/src/harness/client.ts index fd3fce41df634..f09d62e104ddd 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -170,7 +170,11 @@ namespace ts.server { return { line, character: offset }; } - getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { + getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; + getQuickInfoAtPosition(node: ts.Node, sourceFile?: ts.SourceFile): QuickInfo; + getQuickInfoAtPosition(arg0: string | ts.Node, arg1: number | ts.SourceFile | undefined): QuickInfo { + const fileName = typeof arg0 === "string" ? arg0 : arg1 !== undefined ? (arg1 as ts.SourceFile).fileName : arg0.getSourceFile().fileName; + const position = typeof arg0 === "string" ? arg1 as number : arg0.getStart(arg1 as ts.SourceFile); const args = this.createFileLocationRequestArgs(fileName, position); const request = this.processRequest(CommandNames.Quickinfo, args); @@ -632,7 +636,10 @@ namespace ts.server { })); } - getOutliningSpans(file: string): OutliningSpan[] { + getOutliningSpans(file: string): OutliningSpan[]; + getOutliningSpans(sourceFile: ts.SourceFile): OutliningSpan[]; + getOutliningSpans(arg0: string | ts.SourceFile): OutliningSpan[] { + const file = typeof arg0 === "string" ? arg0 : arg0.fileName; const request = this.processRequest(CommandNames.GetOutliningSpans, { file }); const response = this.processResponse(request); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 3497d9acf5bc8..3c70ed7612deb 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -499,8 +499,10 @@ namespace Harness.LanguageService { getCompletionEntrySymbol(): ts.Symbol { throw new Error("getCompletionEntrySymbol not implemented across the shim layer."); } - getQuickInfoAtPosition(fileName: string, position: number): ts.QuickInfo { - return unwrapJSONCallResult(this.shim.getQuickInfoAtPosition(fileName, position)); + getQuickInfoAtPosition(filename: string, position: number): ts.QuickInfo | undefined; + getQuickInfoAtPosition(node: ts.Node, sourceFile: ts.SourceFile | undefined): ts.QuickInfo | undefined; + getQuickInfoAtPosition(arg0: string | ts.Node, arg1: number | ts.SourceFile | undefined): ts.QuickInfo | undefined { + return unwrapJSONCallResult(this.shim.getQuickInfoAtPosition(arg0 as any, arg1 as any)); } getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): ts.TextSpan { return unwrapJSONCallResult(this.shim.getNameOrDottedNameSpan(fileName, startPos, endPos)); @@ -556,8 +558,8 @@ namespace Harness.LanguageService { getNavigationTree(fileName: string): ts.NavigationTree { return unwrapJSONCallResult(this.shim.getNavigationTree(fileName)); } - getOutliningSpans(fileName: string): ts.OutliningSpan[] { - return unwrapJSONCallResult(this.shim.getOutliningSpans(fileName)); + getOutliningSpans(arg0: string | ts.SourceFile): ts.OutliningSpan[] { + return unwrapJSONCallResult(this.shim.getOutliningSpans(arg0 as any)); } getTodoComments(fileName: string, descriptors: ts.TodoCommentDescriptor[]): ts.TodoComment[] { return unwrapJSONCallResult(this.shim.getTodoComments(fileName, JSON.stringify(descriptors))); diff --git a/src/services/services.ts b/src/services/services.ts index ecd7eae9530c9..3494a95ba0a7c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1675,11 +1675,14 @@ namespace ts { return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source }, host, preferences); } - function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined { - synchronizeHostData(); - - const sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); + function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; + function getQuickInfoAtPosition(node: ts.Node, sourceFile?: ts.SourceFile): QuickInfo | undefined; + function getQuickInfoAtPosition(arg0: string | ts.Node, arg1: number | ts.SourceFile | undefined): QuickInfo | undefined { + synchronizeHostData(); + + const sourceFile: ts.SourceFile = typeof arg0 === 'string' ? getValidSourceFile(arg0) : (arg1 !== undefined) ? arg1 as ts.SourceFile : arg0.getSourceFile(); + const node: ts.Node = typeof arg0 === 'string' ? getTouchingPropertyName(sourceFile, arg1 as number) : arg0; + const position: number = typeof arg1 === 'number' ? arg1 : node.getStart(sourceFile, false); if (node === sourceFile) { // Avoid giving quickInfo for the sourceFile as a whole. return undefined; @@ -1979,9 +1982,11 @@ namespace ts { return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } - function getOutliningSpans(fileName: string): OutliningSpan[] { - // doesn't use compiler - no need to synchronize with host - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + function getOutliningSpans(fileName: string): OutliningSpan[]; + function getOutliningSpans(sourceFile: ts.SourceFile): OutliningSpan[]; + function getOutliningSpans(arg0: string | ts.SourceFile): OutliningSpan[] { + // doesn't use compiler - no need to synchronize with host + const sourceFile = typeof arg0 === 'string' ? syntaxTreeCache.getCurrentSourceFile(arg0) : arg0; return OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } diff --git a/src/services/shims.ts b/src/services/shims.ts index 6d313b695ce67..b415db87cd6e1 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -764,12 +764,16 @@ namespace ts { * Computes a string representation of the type at the requested position * in the active file. */ - public getQuickInfoAtPosition(fileName: string, position: number): string { - return this.forwardJSONCall( - `getQuickInfoAtPosition('${fileName}', ${position})`, - () => this.languageService.getQuickInfoAtPosition(fileName, position) - ); - } + public getQuickInfoAtPosition(fileName: string, position: number): string; + public getQuickInfoAtPosition(node: ts.Node, sourceFile: ts.SourceFile | undefined): string; + public getQuickInfoAtPosition(arg0: string | ts.Node, arg1: number | ts.SourceFile | undefined): string { + const fileName = typeof arg0 === "string" ? arg0 : arg1 !== undefined ? (arg1 as ts.SourceFile).fileName : arg0.getSourceFile().fileName; + const position = typeof arg0 === "string" ? arg1 as number : arg0.getStart(arg1 as ts.SourceFile); + return this.forwardJSONCall( + `getQuickInfoAtPosition('${fileName}', ${position})`, + () => this.languageService.getQuickInfoAtPosition(arg0 as any, arg1 as any) + ); + } /// NAMEORDOTTEDNAMESPAN @@ -1032,12 +1036,15 @@ namespace ts { ); } - public getOutliningSpans(fileName: string): string { - return this.forwardJSONCall( - `getOutliningSpans('${fileName}')`, - () => this.languageService.getOutliningSpans(fileName) - ); - } + public getOutliningSpans(fileName: string): string; + public getOutliningSpans(sourceFile: ts.SourceFile): string; + public getOutliningSpans(arg0: string | ts.SourceFile): string { + let fileName = typeof arg0 === "string" ? arg0 : arg0.fileName; + return this.forwardJSONCall( + `getOutliningSpans('${fileName}')`, + () => this.languageService.getOutliningSpans(arg0 as any) + ); + } public getTodoComments(fileName: string, descriptors: string): string { return this.forwardJSONCall( diff --git a/src/services/types.ts b/src/services/types.ts index ff3d2ed56bcb4..ca5a6faae63b3 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -460,6 +460,7 @@ namespace ts { * @param position A zero-based index of the character where you want the quick info */ getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; + getQuickInfoAtPosition(node: ts.Node, sourceFile?: ts.SourceFile): QuickInfo | undefined; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; @@ -505,6 +506,7 @@ namespace ts { provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences | undefined): InlayHint[] getOutliningSpans(fileName: string): OutliningSpan[]; + getOutliningSpans(sourceFile: ts.SourceFile): OutliningSpan[]; getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number;