diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart index 6a9f19787e5a..c9f01422fd6a 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart @@ -64,7 +64,8 @@ class ReferencesHandler ReferenceParams params, ResolvedUnitResult unit, OperationPerformanceImpl performance) async { - final node = NodeLocator(offset).searchWithin(result.unit); + var node = NodeLocator(offset).searchWithin(result.unit); + node = _getReferenceTargetNode(node); var element = server.getElementOfNode(node); if (element == null) { return success(null); @@ -104,4 +105,24 @@ class ReferencesHandler return success(referenceResults); } + + /// Gets the nearest node that should be used for finding references. + /// + /// This is usually the same node but allows some adjustments such as + /// considering the offset between a type name and type arguments as part + /// of the type. + AstNode? _getReferenceTargetNode(AstNode? node) { + // Consider the angle brackets for type arguments part of the leading type, + // otherwise we don't navigate in the common situation of having the type + // name selected, where VS Code provides the end of the selection as the + // position to search. + // + // In `A^` node will be `TypeParameterList` and we will not find any + // references. + if (node is TypeParameterList) { + node = node.parent; + } + + return node; + } } diff --git a/pkg/analysis_server/test/lsp/references_test.dart b/pkg/analysis_server/test/lsp/references_test.dart index c745ebac72ee..2a404b663da6 100644 --- a/pkg/analysis_server/test/lsp/references_test.dart +++ b/pkg/analysis_server/test/lsp/references_test.dart @@ -178,6 +178,26 @@ f^oo() { await _checkRanges(content, includeDeclarations: false); } + Future test_type() async { + final content = ''' +class A^aa {} + +[!Aaa!]? a; +'''; + + await _checkRanges(content); + } + + Future test_type_generic_end() async { + final content = ''' +class Aaa^ {} + +[!Aaa!]? a; +'''; + + await _checkRanges(content); + } + Future test_unopenFile() async { final code = TestCode.parse(''' f^oo() {