diff --git a/packages/pyright-internal/src/languageService/callHierarchyProvider.ts b/packages/pyright-internal/src/languageService/callHierarchyProvider.ts index 75ec9aeb08a4..11749b30b177 100644 --- a/packages/pyright-internal/src/languageService/callHierarchyProvider.ts +++ b/packages/pyright-internal/src/languageService/callHierarchyProvider.ts @@ -589,6 +589,12 @@ class FindIncomingCallTreeWalker extends ParseTreeWalker { }; } else { const functionRange = convertOffsetsToRange( + executionNode.start, + executionNode.start + executionNode.length, + this._parseResults.tokenizerOutput.lines + ); + + const functionSelectionRange = convertOffsetsToRange( executionNode.d.name.start, executionNode.d.name.start + executionNode.d.name.length, this._parseResults.tokenizerOutput.lines @@ -599,7 +605,7 @@ class FindIncomingCallTreeWalker extends ParseTreeWalker { kind: SymbolKind.Function, uri: convertUriToLspUriString(this._program.fileSystem, this._fileUri), range: functionRange, - selectionRange: functionRange, + selectionRange: functionSelectionRange, }; } diff --git a/packages/pyright-internal/src/languageService/referencesProvider.ts b/packages/pyright-internal/src/languageService/referencesProvider.ts index eb3ba2c49f39..11283d4a9d4c 100644 --- a/packages/pyright-internal/src/languageService/referencesProvider.ts +++ b/packages/pyright-internal/src/languageService/referencesProvider.ts @@ -403,6 +403,10 @@ export class ReferencesProvider { return this.getDeclarationForNode(program, fileUri, node, reporter, useCase, token); } + if (node.nodeType === ParseNodeType.Function) { + return this.getDeclarationForNode(program, fileUri, node.d.name, reporter, useCase, token); + } + // For other node types, there are no references to be found. return undefined; } diff --git a/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.aliasedFunction.fourslash.ts b/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.aliasedFunction.fourslash.ts index 2cf73f55fc36..3bd68b93ef14 100644 --- a/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.aliasedFunction.fourslash.ts +++ b/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.aliasedFunction.fourslash.ts @@ -10,8 +10,7 @@ //// //// def callByName(): //// func() -//// def [|callByAlias|](): -//// /*marker2*/foobar() +//// def [|/*callByAliasRange*/callByAlias|](): /*marker2*/foobar() // @filename: consume2.py //// from declare import func as foobar @@ -20,10 +19,15 @@ //// func() { - const ranges = helper.getRanges(); - const itemList = ranges.map((range) => { - return { filePath: range.fileName, range: helper.convertPositionRange(range), name: 'callByAlias' }; - }); + const callByAliasRange = helper.getPositionRange('callByAliasRange'); + const itemList = [ + { + filePath: helper.getMappedFilePath('consume.py'), + range: helper.expandPositionRange(callByAliasRange, 4, 12), + selectionRange: callByAliasRange, + name: 'callByAlias', + }, + ]; helper.verifyShowCallHierarchyGetIncomingCalls({ marker1: { diff --git a/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.function.fourslash.ts b/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.function.fourslash.ts index 89663e941b71..e338c51e3f46 100644 --- a/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.function.fourslash.ts +++ b/packages/pyright-internal/src/tests/fourslash/showcallhierarchy.incomingCalls.function.fourslash.ts @@ -1,32 +1,35 @@ /// // @filename: declare.py -//// def /*marker1*/func(): +//// /*marker3*/def /*marker1*/func(): //// return 1 // @filename: consume.py //// from declare import func -//// from declare import /*marker2*/func as foobar //// -//// def [|callByName|](): -//// /*marker3*/func() -//// def callByAlias(): -//// foobar() +//// def [|/*callByNameSelection*/callByName|](): /*marker2*/func() // @filename: consume2.py //// from declare import func //// -//// def [|callByName2|](): -//// func() +//// def [|/*callByName2Selection*/callByName2|](): func() { - const ranges = helper.getRanges(); - const references = ranges.map((range) => { - return { path: range.fileName, range: helper.convertPositionRange(range) }; - }); + const callByNameSelectionRange = helper.getPositionRange('callByNameSelection'); + const callByName2SelectionRange = helper.getPositionRange('callByName2Selection'); const itemList = [ - { filePath: references[0].path, range: references[0].range, name: 'callByName' }, - { filePath: references[1].path, range: references[1].range, name: 'callByName2' }, + { + filePath: helper.getMappedFilePath('consume.py'), + range: helper.expandPositionRange(callByNameSelectionRange, 4, 10), + selectionRange: callByNameSelectionRange, + name: 'callByName', + }, + { + filePath: helper.getMappedFilePath('consume2.py'), + range: helper.expandPositionRange(callByName2SelectionRange, 4, 10), + selectionRange: callByName2SelectionRange, + name: 'callByName2', + }, ]; helper.verifyShowCallHierarchyGetIncomingCalls({ diff --git a/packages/pyright-internal/src/tests/fourslash/typings/fourslash.d.ts b/packages/pyright-internal/src/tests/fourslash/typings/fourslash.d.ts index e1f456c871ab..292dc0dc967e 100644 --- a/packages/pyright-internal/src/tests/fourslash/typings/fourslash.d.ts +++ b/packages/pyright-internal/src/tests/fourslash/typings/fourslash.d.ts @@ -67,6 +67,7 @@ declare namespace _ { filePath: string; name: string; range: PositionRange; + selectionRange?: PositionRange; } interface TextRange { diff --git a/packages/pyright-internal/src/tests/harness/fourslash/testState.ts b/packages/pyright-internal/src/tests/harness/fourslash/testState.ts index 9b434a076e49..d0377f89ed5b 100644 --- a/packages/pyright-internal/src/tests/harness/fourslash/testState.ts +++ b/packages/pyright-internal/src/tests/harness/fourslash/testState.ts @@ -1272,6 +1272,9 @@ export class TestState { const expectedFilePath = map[name].items.map((x) => x.filePath); const expectedRange = map[name].items.map((x) => x.range); const expectedName = map[name].items.map((x) => x.name); + const expectedSelectionRange = map[name].items + .map((x) => x.selectionRange) + .filter((x): x is PositionRange => x !== undefined); const position = this.convertOffsetToPosition(fileName, marker.position); const actual = new CallHierarchyProvider( @@ -1289,6 +1292,12 @@ export class TestState { for (const a of actual) { assert.strictEqual(expectedRange?.filter((e) => this._deepEqual(a.from.range, e)).length, 1); assert.strictEqual(expectedName?.filter((e) => this._deepEqual(a.from.name, e)).length, 1); + if (expectedSelectionRange.length > 0) { + assert.strictEqual( + expectedSelectionRange.filter((e) => this._deepEqual(a.from.selectionRange, e)).length, + 1 + ); + } assert.ok( expectedFilePath?.filter((e) => this._deepEqual(a.from.uri, Uri.file(e, this.serviceProvider).toString())