Fix wrong script info used to resolve line/offset for call hierarchy items (#36559)

This commit is contained in:
Ron Buckton
2020-01-31 14:41:25 -08:00
committed by GitHub
parent 01af3aa483
commit 9a357c19f3
5 changed files with 110 additions and 29 deletions

View File

@@ -2164,15 +2164,18 @@ namespace ts.server {
return result;
}
private toProtocolCallHierarchyItem(item: CallHierarchyItem, scriptInfo?: ScriptInfo): protocol.CallHierarchyItem {
private getScriptInfoFromProjectService(file: string) {
const normalizedFile = toNormalizedPath(file);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(normalizedFile);
if (!scriptInfo) {
const file = toNormalizedPath(item.file);
scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
if (!scriptInfo) {
this.projectService.logErrorForScriptInfoNotFound(file);
return Errors.ThrowNoProject();
}
this.projectService.logErrorForScriptInfoNotFound(normalizedFile);
return Errors.ThrowNoProject();
}
return scriptInfo;
}
private toProtocolCallHierarchyItem(item: CallHierarchyItem): protocol.CallHierarchyItem {
const scriptInfo = this.getScriptInfoFromProjectService(item.file);
return {
name: item.name,
kind: item.kind,
@@ -2182,7 +2185,8 @@ namespace ts.server {
};
}
private toProtocolCallHierarchyIncomingCall(incomingCall: CallHierarchyIncomingCall, scriptInfo: ScriptInfo): protocol.CallHierarchyIncomingCall {
private toProtocolCallHierarchyIncomingCall(incomingCall: CallHierarchyIncomingCall): protocol.CallHierarchyIncomingCall {
const scriptInfo = this.getScriptInfoFromProjectService(incomingCall.from.file);
return {
from: this.toProtocolCallHierarchyItem(incomingCall.from),
fromSpans: incomingCall.fromSpans.map(fromSpan => toProtocolTextSpan(fromSpan, scriptInfo))
@@ -2202,29 +2206,21 @@ namespace ts.server {
if (scriptInfo) {
const position = this.getPosition(args, scriptInfo);
const result = project.getLanguageService().prepareCallHierarchy(file, position);
return result && mapOneOrMany(result, item => this.toProtocolCallHierarchyItem(item, scriptInfo));
return result && mapOneOrMany(result, item => this.toProtocolCallHierarchyItem(item));
}
return undefined;
}
private provideCallHierarchyIncomingCalls(args: protocol.FileLocationRequestArgs): protocol.CallHierarchyIncomingCall[] {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
if (!scriptInfo) {
this.projectService.logErrorForScriptInfoNotFound(file);
return Errors.ThrowNoProject();
}
const scriptInfo = this.getScriptInfoFromProjectService(file);
const incomingCalls = project.getLanguageService().provideCallHierarchyIncomingCalls(file, this.getPosition(args, scriptInfo));
return incomingCalls.map(call => this.toProtocolCallHierarchyIncomingCall(call, scriptInfo));
return incomingCalls.map(call => this.toProtocolCallHierarchyIncomingCall(call));
}
private provideCallHierarchyOutgoingCalls(args: protocol.FileLocationRequestArgs): protocol.CallHierarchyOutgoingCall[] {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
if (!scriptInfo) {
this.projectService.logErrorForScriptInfoNotFound(file);
return Errors.ThrowNoProject();
}
const scriptInfo = this.getScriptInfoFromProjectService(file);
const outgoingCalls = project.getLanguageService().provideCallHierarchyOutgoingCalls(file, this.getPosition(args, scriptInfo));
return outgoingCalls.map(call => this.toProtocolCallHierarchyOutgoingCall(call, scriptInfo));
}

View File

@@ -260,16 +260,18 @@ namespace ts.CallHierarchy {
range: TextRange;
}
function convertEntryToCallSite(entry: FindAllReferences.Entry, _originalNode: Node, typeChecker: TypeChecker): CallSite | undefined {
function convertEntryToCallSite(entry: FindAllReferences.Entry): CallSite | undefined {
if (entry.kind === FindAllReferences.EntryKind.Node) {
if (isCallOrNewExpressionTarget(entry.node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isTaggedTemplateTag(entry.node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isDecoratorTarget(entry.node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isJsxOpeningLikeElementTagName(entry.node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isRightSideOfPropertyAccess(entry.node)
|| isArgumentExpressionOfElementAccess(entry.node)) {
const ancestor = findAncestor(entry.node, isValidCallHierarchyDeclaration) || entry.node.getSourceFile();
return { declaration: firstOrOnly(findImplementationOrAllInitialDeclarations(typeChecker, ancestor)), range: createTextRangeFromNode(entry.node, entry.node.getSourceFile()) };
const { node } = entry;
if (isCallOrNewExpressionTarget(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isTaggedTemplateTag(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isDecoratorTarget(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isJsxOpeningLikeElementTagName(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
|| isRightSideOfPropertyAccess(node)
|| isArgumentExpressionOfElementAccess(node)) {
const sourceFile = node.getSourceFile();
const ancestor = findAncestor(node, isValidCallHierarchyDeclaration) || sourceFile;
return { declaration: ancestor, range: createTextRangeFromNode(node, sourceFile) };
}
}
}