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 0ccb11af814c..b0c7ecbeb957 100644 --- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart +++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart @@ -11,7 +11,6 @@ import 'package:analysis_server/src/services/search/search_engine.dart' show SearchMatch; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:analyzer/src/util/performance/operation_performance.dart'; import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart'; @@ -66,15 +65,6 @@ class ReferencesHandler OperationPerformanceImpl performance) async { final node = NodeLocator(offset).searchWithin(result.unit); var element = server.getElementOfNode(node); - if (element is LibraryImportElement) { - element = element.prefix?.element; - } - if (element is FieldFormalParameterElement) { - element = element.field; - } - if (element is PropertyAccessorElement) { - element = element.variable; - } if (element == null) { return success(null); } @@ -84,7 +74,7 @@ class ReferencesHandler final results = await performance.runAsync( "computer.compute", (childPerformance) => - computer.compute(element!, false, performance: childPerformance)); + computer.compute(element, false, performance: childPerformance)); Location? toLocation(SearchMatch result) { final file = session.getFile(result.file); diff --git a/pkg/analysis_server/test/lsp/references_test.dart b/pkg/analysis_server/test/lsp/references_test.dart index d8a7c4357cd3..d2ae77e1d472 100644 --- a/pkg/analysis_server/test/lsp/references_test.dart +++ b/pkg/analysis_server/test/lsp/references_test.dart @@ -3,9 +3,11 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analysis_server/lsp_protocol/protocol.dart'; +import 'package:analyzer/src/test_utilities/test_code_format.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; +import '../utils/test_code_extensions.dart'; import 'server_abstract.dart'; void main() { @@ -17,171 +19,145 @@ void main() { @reflectiveTest class ReferencesTest extends AbstractLspAnalysisServerTest { Future test_acrossFiles_includeDeclaration() async { - final mainContents = ''' - import 'referenced.dart'; + final otherContent = ''' +import 'main.dart'; - void f() { - [[foo]](); - } - '''; - - final referencedContents = ''' - /// Ensure the function is on a line that - /// does not exist in the mainContents file - /// to ensure we're translating offsets to line/col - /// using the correct file's LineInfo - /// ... - /// ... - /// ... - /// ... - /// ... - [[^foo]]() {} - '''; - - final referencedFileUri = - Uri.file(join(projectFolderPath, 'lib', 'referenced.dart')); - - await initialize(); - await openFile(mainFileUri, withoutMarkers(mainContents)); - await openFile(referencedFileUri, withoutMarkers(referencedContents)); - final res = await getReferences( - referencedFileUri, - positionFromMarker(referencedContents), +void f() { + [!foo!](); +} +'''; + + final mainContent = ''' +/// Ensure the function is on a line that +/// does not exist in the mainContents file +/// to ensure we're translating offsets to line/col +/// using the correct file's LineInfo +/// ... +/// ... +/// ... +/// ... +/// ... +[!^foo!]() {} +'''; + + await _checkRanges( + mainContent, + otherContent: otherContent, includeDeclarations: true, ); - - // Ensure both the reference and the declaration are included. - expect(res, hasLength(2)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(mainContents)))); - expect( - res, - contains(Location( - uri: referencedFileUri, - range: rangeFromMarkers(referencedContents)))); } Future test_acrossFiles_withoutDeclaration() async { - final mainContents = ''' - import 'referenced.dart'; + final otherContent = ''' +import 'main.dart'; - void f() { - [[foo]](); - } - '''; - - final referencedContents = ''' - /// Ensure the function is on a line that - /// does not exist in the mainContents file - /// to ensure we're translating offsets to line/col - /// using the correct file's LineInfo - /// ... - /// ... - /// ... - /// ... - /// ... - ^foo() {} - '''; - - final referencedFileUri = - Uri.file(join(projectFolderPath, 'lib', 'referenced.dart')); +void f() { + [!foo!](); +} +'''; + + final mainContent = ''' +/// Ensure the function is on a line that +/// does not exist in the mainContents file +/// to ensure we're translating offsets to line/col +/// using the correct file's LineInfo +/// ... +/// ... +/// ... +/// ... +/// ... +^foo() {} +'''; + + await _checkRanges( + mainContent, + otherContent: otherContent, + includeDeclarations: false, + ); + } - await initialize(); - await openFile(mainFileUri, withoutMarkers(mainContents)); - await openFile(referencedFileUri, withoutMarkers(referencedContents)); - final res = await getReferences( - referencedFileUri, positionFromMarker(referencedContents)); + Future test_field() async { + // References on the field should find both the initializing formal and the + // reference to the getter. + final content = ''' +class AAA { + final String? aa^a; + const AAA({this./*[0*/aaa/*0]*/}); +} + +final a = AAA(aaa: '')./*[1*/aaa/*1]*/; +'''; - expect(res, hasLength(1)); - var loc = res.single; - expect(loc.range, equals(rangeFromMarkers(mainContents))); - expect(loc.uri, equals(mainFileUri)); + await _checkRanges(content); } Future test_function_startOfParameterList() async { - final contents = ''' - foo^() { - [[foo]](); - } - '''; + final content = ''' +foo^() { + [!foo!](); +} +'''; - await initialize(); - await openFile(mainFileUri, withoutMarkers(contents)); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), - ); + await _checkRanges(content); } Future test_function_startOfTypeParameterList() async { - final contents = ''' - foo^() { - [[foo]](); - } - '''; + final content = ''' +foo^() { + [!foo!](); +} +'''; - await initialize(); - await openFile(mainFileUri, withoutMarkers(contents)); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), - ); + await _checkRanges(content); + } + + Future test_import_prefix() async { + final content = ''' +imp^ort 'dart:async' as async; + +/*[0*/async./*0]*/Future? f() {} +/*[1*/async./*1]*/Future? g() {} +'''; + + await _checkRanges(content); + } + + Future test_initializingFormals() async { + // References on "this.aaa" should only find the matching named argument. + final content = ''' +class AAA { + final String? aaa; + const AAA({this.aa^a}); +} + +final a = AAA([!aaa!]: '').aaa; +'''; + + await _checkRanges(content); } Future test_method_startOfParameterList() async { - final contents = ''' - class A { - foo^() { - [[foo]](); - } - } - '''; + final content = ''' +class A { + foo^() { + [!foo!](); + } +} +'''; - await initialize(); - await openFile(mainFileUri, withoutMarkers(contents)); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), - ); + await _checkRanges(content); } Future test_method_startOfTypeParameterList() async { - final contents = ''' - class A { - foo^() { - [[foo]](); - } - } - '''; + final content = ''' +class A { + foo^() { + [!foo!](); + } +} +'''; - await initialize(); - await openFile(mainFileUri, withoutMarkers(contents)); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), - ); + await _checkRanges(content); } Future test_nonDartFile() async { @@ -193,42 +169,63 @@ class ReferencesTest extends AbstractLspAnalysisServerTest { } Future test_singleFile_withoutDeclaration() async { - final contents = ''' - f^oo() { - [[foo]](); - } - '''; + final content = ''' +f^oo() { + [!foo!](); +} +'''; - await initialize(); - await openFile(mainFileUri, withoutMarkers(contents)); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), - ); + await _checkRanges(content, includeDeclarations: false); } Future test_unopenFile() async { - final contents = ''' + final code = TestCode.parse(''' f^oo() { - [[foo]](); + [!foo!](); } - '''; + '''); + + newFile(mainFilePath, code.code); + await initialize(); + final res = await getReferences(mainFileUri, code.position.position); + + final expected = [ + for (final range in code.ranges) + Location(uri: mainFileUri, range: range.range), + ]; + + expect(res, unorderedEquals(expected)); + } + + Future _checkRanges( + String mainContent, { + String? otherContent, + bool includeDeclarations = false, + }) async { + final mainCode = TestCode.parse(mainContent); + final otherCode = + otherContent != null ? TestCode.parse(otherContent) : null; + final otherFileUri = Uri.file(join(projectFolderPath, 'lib', 'other.dart')); - newFile(mainFilePath, withoutMarkers(contents)); await initialize(); - final res = await getReferences(mainFileUri, positionFromMarker(contents)); - - expect(res, hasLength(1)); - expect( - res, - contains( - Location(uri: mainFileUri, range: rangeFromMarkers(contents)), - ), + await openFile(mainFileUri, mainCode.code); + if (otherCode != null) { + await openFile(otherFileUri, otherCode.code); + } + final res = await getReferences( + mainFileUri, + mainCode.position.position, + includeDeclarations: includeDeclarations, ); + + final expected = [ + for (final range in mainCode.ranges) + Location(uri: mainFileUri, range: range.range), + if (otherCode != null) + for (final range in otherCode.ranges) + Location(uri: otherFileUri, range: range.range), + ]; + + expect(res, unorderedEquals(expected)); } }