Skip to content

Fix incoming call hierarchy ranges - #11455

Open
Bill Schnurr (bschnurr) wants to merge 1 commit into
microsoft:mainfrom
bschnurr:pr11444-redo
Open

Fix incoming call hierarchy ranges#11455
Bill Schnurr (bschnurr) wants to merge 1 commit into
microsoft:mainfrom
bschnurr:pr11444-redo

Conversation

@bschnurr

Copy link
Copy Markdown
Member

Summary

Redo of #11444 on current upstream main, with regression coverage added.

This fixes incorrect callHierarchy/incomingCalls item ranges for function callers and ensures incoming call hierarchy also resolves when the request position lands on a Function node rather than only a Name node.

Changes

Production fixes

  • In callHierarchyProvider.ts, incoming call items for function callers now use:

    • range: the full function range
    • selectionRange: the function name range
  • In referencesProvider.ts, getDeclarationForPosition now handles ParseNodeType.Function by resolving through node.d.name.

Tests

Added regression coverage for incoming call hierarchy:

  • showcallhierarchy.incomingCalls.function.fourslash.ts
    • verifies full caller range
    • verifies name-only selectionRange
    • verifies lookup when the request starts on a Function node

Updated adjacent incoming-call expectation:

  • showcallhierarchy.incomingCalls.aliasedFunction.fourslash.ts
    • now expects the full caller function range

Extended the shared fourslash incoming-call assertion to support optional selectionRange checks.

Validation

Ran the call hierarchy fourslash slice:

  • npx jest src/tests/fourSlashRunner.test.ts -t "showcallhierarchy" --runInBand --forceExit

Result:

  • 6 passed

Ran the full fourslash runner:

  • npx jest src/tests/fourSlashRunner.test.ts --runInBand --forceExit

Result:

  • 251 passed

@github-actions

This comment has been minimized.

return this.getDeclarationForNode(program, fileUri, node, reporter, useCase, token);
}

if (node.nodeType === ParseNodeType.Function) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot generated:
Broader behavioral scope than documented. getDeclarationForPosition is also called by renameProvider.ts and reportReferences. This change means Rename and Find All References now resolve from the def keyword position (previously returned undefined). This is likely a net improvement, but worth noting in the PR description and considering additional test coverage for rename-from-def scenarios.

[verified]

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot generated:
Magic numbers in expandPositionRange are fragile. The offsets (4, 10) encode "def " (4 chars) and "(): func()" (10 chars). Any future edit to the test Python (renaming, adding type annotations) silently breaks these without a compile error. Consider using a named range [|...|] wrapping the full function definition for the range assertion. This matches the robustness guidance in the test instructions.

[verified]

@bschnurr

Copy link
Copy Markdown
Member Author

/benchmark

@rchiodo

Rich Chiodo (rchiodo) commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR.

expectedSelectionRange.filter((e) => this._deepEqual(a.from.selectionRange, e)).length,
1
);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning · Non-blocking recommendation

selectionRange is optional per expected item, but once any item supplies it this loop requires every actual item to match one of the supplied ranges. Match each actual call against one complete expected item and check selectionRange only when that matched expectation provides it; a mixed specified/unspecified test would confirm the failure.

[verified]

@rchiodo

Copy link
Copy Markdown
Collaborator

Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) added the review-auto:approved Automated review: no blocking findings (approval posted). label Aug 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

sympy (https://github.com/sympy/sympy)
-   .../projects/sympy/sympy/solvers/bivariate.py:135:15 - error: Operator "-" not supported for "None" (reportOptionalOperand)
-   .../projects/sympy/sympy/solvers/bivariate.py:139:17 - error: Operator "-" not supported for type "Basic | Unknown" (reportOperatorIssue)
-   .../projects/sympy/sympy/solvers/bivariate.py:144:23 - error: Operator "-" not supported for "None" (reportOptionalOperand)
-   .../projects/sympy/sympy/solvers/deutils.py:234:14 - error: Operator "not in" not supported for types "str" and "Unknown | int"
-     Operator "not in" not supported for types "str" and "int" (reportOperatorIssue)
-   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:176:44 - error: Cannot access attribute "expand" for class "Basic"
-     Attribute "expand" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:423:38 - error: Argument of type "Unknown | Expr | Literal[0]" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:423:38 - error: Argument of type "int | Expr" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
-     Type "Unknown | Expr | Literal[0]" is not assignable to type "Expr"
+     Type "int | Expr" is not assignable to type "Expr"
-       "Literal[0]" is not assignable to "Expr" (reportArgumentType)
+       "int" is not assignable to "Expr" (reportArgumentType)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:504:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:505:19 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:506:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:569:42 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+     Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:569:50 - error: Operator "*" not supported for types "Expr" and "Unknown | Basic"
+     Operator "*" not supported for types "Expr" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:725:42 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:735:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:736:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:737:19 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:814:47 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:841:26 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:842:22 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:36 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+     Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:42 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:51 - error: Operator "*" not supported for types "int" and "Unknown | Basic"
+     Operator "*" not supported for types "int" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:57 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:843:66 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:845:53 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:854:18 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:856:22 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:865:22 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:865:36 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:867:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:868:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:869:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:870:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:871:27 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:872:27 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:876:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:877:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:878:24 - error: Operator "**" not supported for types "Unknown | Basic" and "Literal[2]"
+     Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:879:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:880:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:881:24 - error: Operator "*" not supported for types "Unknown | Basic" and "Unknown | Basic"
+     Operator "*" not supported for types "Basic" and "Basic" (reportOperatorIssue)
+   .../projects/sympy/sympy/solvers/diophantine/diophantine.py:888:37 - error: Operator "*" not supported for types "int" and "Unknown | None"
+     Operator "*" not supported for types "int" and "None" (reportOperatorIssue)

... (truncated 599 lines) ...

@github-actions

Copy link
Copy Markdown
Contributor

Type checker benchmark

🟢 No performance regressions detected.

Regression threshold: 20.0%
Variance guard: >1.0s time and >100.0 MB memory

Package Checker Files checked Time Time delta Peak memory Memory delta Status
ansible pyright 583 22.133s +2.2% 1075.7 MB -3.2% 🟢 Pass
click pyright 17 3.023s +4.0% 360.0 MB -0.3% 🟢 Pass
homeassistant pyright 9850 160.983s +1.7% 6180.5 MB -0.2% 🟢 Pass
numpy pyright 356 41.695s -4.0% 1826.5 MB -1.3% 🟢 Pass
pandas pyright 1459 958.585s -3.1% 4442.7 MB +0.2% 🟢 Pass
pytest pyright 243 12.189s -3.1% 914.3 MB -1.8% 🟢 Pass
requests pyright 19 2.260s -1.7% 345.3 MB -0.5% 🟢 Pass
torch pyright 2400 148.540s -3.4% 5022.1 MB +2.7% 🟢 Pass
transformers pyright 2901 126.935s -5.7% 5245.5 MB +2.3% 🟢 Pass

Pyright stats

Package Parsed/bound Checked Find Read Tokenize Parse Imports Bind Check Cycles
ansible 989 583 0.040s 0.110s 0.430s 0.840s 0.260s 1.040s 18.790s 0.000s
click 111 17 0.000s 0.010s 0.130s 0.230s 0.040s 0.270s 2.040s 0.000s
homeassistant 11138 9850 0.430s 1.020s 3.110s 5.230s 2.420s 7.410s 137.670s 0.000s
numpy 603 356 0.010s 0.070s 0.400s 0.720s 0.240s 0.900s 38.710s 0.000s
pandas 1895 1459 0.070s 0.290s 1.530s 2.540s 0.350s 3.010s 949.370s 0.000s
pytest 542 243 0.020s 0.040s 0.370s 0.480s 0.120s 0.690s 10.000s 0.000s
requests 168 19 0.000s 0.010s 0.110s 0.200s 0.050s 0.250s 1.320s 0.000s
torch 3076 2400 0.140s 0.450s 2.360s 3.440s 0.660s 4.530s 135.450s 0.000s
transformers 3534 2901 0.130s 0.440s 2.740s 3.880s 1.030s 10.160s 111.890s 0.000s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants