| // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp; | 
 | import 'package:analysis_server/src/analysis_server.dart'; | 
 | import 'package:analysis_server/src/legacy_analysis_server.dart'; | 
 | import 'package:analyzer/src/test_utilities/test_code_format.dart'; | 
 | import 'package:analyzer_plugin/protocol/protocol_common.dart'; | 
 | import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; | 
 | import 'package:analyzer_testing/experiments/experiments.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() { | 
 |   defineReflectiveSuite(() { | 
 |     defineReflectiveTests(DefinitionTest); | 
 |   }); | 
 | } | 
 |  | 
 | @reflectiveTest | 
 | class DefinitionTest extends AbstractLspAnalysisServerTest { | 
 |   @override | 
 |   AnalysisServerOptions get serverOptions => | 
 |       AnalysisServerOptions() | 
 |         ..enabledExperiments = [ | 
 |           ...super.serverOptions.enabledExperiments, | 
 |           ...experimentsForTests, | 
 |         ]; | 
 |  | 
 |   Future<void> test_acrossFiles() async { | 
 |     var mainContents = ''' | 
 | import 'referenced.dart'; | 
 |  | 
 | void f() { | 
 |   fo^o(); | 
 | } | 
 | '''; | 
 |  | 
 |     var 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!]() {} | 
 | '''; | 
 |  | 
 |     var referencedFilePath = join(projectFolderPath, 'lib', 'referenced.dart'); | 
 |     var referencedFileUri = toUri(referencedFilePath); | 
 |  | 
 |     var mainCode = TestCode.parse(mainContents); | 
 |     var referencedCode = TestCode.parse(referencedContents); | 
 |  | 
 |     newFile(mainFilePath, mainCode.code); | 
 |     newFile(referencedFilePath, referencedCode.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocation( | 
 |       mainFileUri, | 
 |       mainCode.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.range, equals(referencedCode.range.range)); | 
 |     expect(loc.uri, equals(referencedFileUri)); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_class() async { | 
 |     var contents = ''' | 
 | class [!^A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_constructorNamed() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   A.[!^named!]() {} | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_constructorNamed_typeName() async { | 
 |     var contents = ''' | 
 | class [!A!] { | 
 |   ^A.named() {} | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_defaultConstructor() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   [!^A!]() {} | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_function() async { | 
 |     var contents = ''' | 
 | void [!^f!]() {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_importPrefix() async { | 
 |     var contents = ''' | 
 | import 'dart:math' as [!^math!]; | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_atDeclaration_method() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   void [!^f!]() {} | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_closure_parameter() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | void f(void Function(int) _) {} | 
 |  | 
 | void g() => f((/*[0*/variable/*0]*/) { | 
 |   print(/*[1*/^variable/*1]*/); | 
 | }); | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.first; | 
 |     expect(loc.originSelectionRange, equals(code.ranges.last.range)); | 
 |     expect(loc.targetRange, equals(code.ranges.first.range)); | 
 |     expect(loc.targetSelectionRange, equals(code.ranges.first.range)); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_adjacentReference() async { | 
 |     /// Computing Dart navigation locates a node at the provided offset then | 
 |     /// returns all navigation regions inside it. This test ensures we filter | 
 |     /// out any regions that are in the same target node (the comment) but do | 
 |     /// not span the requested offset. | 
 |     var contents = ''' | 
 | /// Te^st | 
 | /// | 
 | /// References [String]. | 
 | void f() {} | 
 | '''; | 
 |     var code = TestCode.parse(contents); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocation( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(0)); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_enumMember_qualified() async { | 
 |     var contents = ''' | 
 | /// [A.o^ne]. | 
 | enum A { | 
 |   [!one!], | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_extensionMember() async { | 
 |     var contents = ''' | 
 | /// [myFi^eld] | 
 | extension on String { | 
 |   String get [!myField!] => ''; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_extensionMember_qualified() async { | 
 |     var contents = ''' | 
 | /// [StringExtension.myFi^eld] | 
 | extension StringExtension on String { | 
 |   String get [!myField!] => ''; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_importPrefix() async { | 
 |     var contents = ''' | 
 | /// This is a comment for [^math] | 
 | import 'dart:math' as [!math!]; | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_instanceMember_qualified() async { | 
 |     var contents = ''' | 
 | /// [A.myFi^eld]. | 
 | class A { | 
 |   final String [!myField!] = ''; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_instanceMember_qualified_inherited() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   final String [!myField!] = ''; | 
 | } | 
 | /// [B.myFi^eld]. | 
 | class B extends A {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_namedConstructor_qualified() async { | 
 |     var contents = ''' | 
 | /// [A.nam^ed]. | 
 | class A { | 
 |   A.[!named!](); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_comment_staticMember_qualified() async { | 
 |     var contents = ''' | 
 | /// [A.myStaticFi^eld]. | 
 | class A { | 
 |   static final String [!myStaticField!] = ''; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_constructor() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = A^(); | 
 | } | 
 |  | 
 | class A { | 
 |   [!A!](); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_constructor_redirectingSuper_wildcards() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   final int x, y; | 
 |   A(this.[!x!], [this.y = 0]); | 
 | } | 
 |  | 
 | class C extends A { | 
 |   final int c; | 
 |   C(this.c, super.^_); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_constructor_thisReference_wildcards() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   final int [!_!]; | 
 |   A(this.^_); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_constructorNamed() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = A.named^(); | 
 | } | 
 |  | 
 | class A { | 
 |   A.[!named!](); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_constructorNamed_typeName() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = A^.named(); | 
 | } | 
 |  | 
 | class [!A!] { | 
 |   A.named(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_directive_export() async { | 
 |     await verifyDirective(source: "export 'destin^ation.dart';"); | 
 |   } | 
 |  | 
 |   Future<void> test_directive_import() async { | 
 |     await verifyDirective(source: "import 'desti^nation.dart';"); | 
 |   } | 
 |  | 
 |   Future<void> test_directive_part() async { | 
 |     await verifyDirective( | 
 |       source: "part 'desti^nation.dart';", | 
 |       destination: "part of 'source.dart';", | 
 |     ); | 
 |   } | 
 |  | 
 |   Future<void> test_directive_partOf() async { | 
 |     await verifyDirective( | 
 |       source: "part of 'destin^ation.dart';", | 
 |       destination: "part 'source.dart';", | 
 |     ); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_constructor_named() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   A a = .nam^ed(); | 
 | } | 
 |  | 
 | class A { | 
 |   A.[!named!](); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_constructor_unnamed() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   A a = .ne^w(); | 
 | } | 
 |  | 
 | class A { | 
 |   [!A!](); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_enum() async { | 
 |     var contents = ''' | 
 | enum A { | 
 |   [!one!], | 
 | } | 
 |  | 
 | f() { | 
 |   A a = .on^e; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_extensionType() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   A a = .fie^ld; | 
 | } | 
 |  | 
 | extension type A(int x) { | 
 |   static A get [!field!] => A(1); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_field() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   A a = .fie^ld; | 
 | } | 
 |  | 
 | class A { | 
 |   static A [!field!] = A(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_dotShorthand_method() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   A a = .meth^od(); | 
 | } | 
 |  | 
 | class A { | 
 |   static A [!method!]() => A(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_field_underscore() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   int [!_!] = 1; | 
 |   int f() => _^; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_fieldFormalParam() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   final String [!a!]; | 
 |   A(this.^a); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_fromPlugins() async { | 
 |     if (!AnalysisServer.supportsPlugins) return; | 
 |     var pluginAnalyzedFilePath = join(projectFolderPath, 'lib', 'foo.foo'); | 
 |     var pluginAnalyzedFileUri = pathContext.toUri(pluginAnalyzedFilePath); | 
 |     var pluginResult = plugin.AnalysisGetNavigationResult( | 
 |       [pluginAnalyzedFilePath], | 
 |       [NavigationTarget(ElementKind.CLASS, 0, 0, 5, 0, 0)], | 
 |       [ | 
 |         NavigationRegion(0, 5, [0]), | 
 |       ], | 
 |     ); | 
 |     configureTestPlugin(respondWith: pluginResult); | 
 |  | 
 |     newFile(pluginAnalyzedFilePath, ''); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocation( | 
 |       pluginAnalyzedFileUri, | 
 |       lsp.Position(line: 0, character: 0), | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect( | 
 |       loc.range, | 
 |       equals( | 
 |         lsp.Range( | 
 |           start: lsp.Position(line: 0, character: 0), | 
 |           end: lsp.Position(line: 0, character: 5), | 
 |         ), | 
 |       ), | 
 |     ); | 
 |     expect(loc.uri, equals(pluginAnalyzedFileUri)); | 
 |   } | 
 |  | 
 |   Future<void> test_function() async { | 
 |     var contents = ''' | 
 | [!foo!]() { | 
 |   fo^o(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_function_inNullAwareElement_inList() async { | 
 |     var contents = ''' | 
 | bool? [!foo!]() => null; | 
 |  | 
 | bar() { | 
 |   return [?fo^o()]; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_function_inNullAwareElement_inSet() async { | 
 |     var contents = ''' | 
 | bool? [!foo!]() => null; | 
 |  | 
 | bar() { | 
 |   return {?fo^o()}; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_function_inNullAwareKey_inMap() async { | 
 |     var contents = ''' | 
 | bool? [!foo!]() => null; | 
 |  | 
 | bar() { | 
 |   return {?fo^o(): "value"}; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_function_inNullAwareValue_inMap() async { | 
 |     var contents = ''' | 
 | bool? [!foo!]() => null; | 
 |  | 
 | bar() { | 
 |   return {"key": ?fo^o()}; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_functionInPattern() async { | 
 |     var contents = ''' | 
 | bool [!greater!](int x, int y) => x > y; | 
 |  | 
 | foo(Object pair) { | 
 |   switch (pair) { | 
 |     case (int a, int b) when g^reater(a,b): | 
 |       break; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_importPrefix() async { | 
 |     var contents = ''' | 
 | import 'dart:math' as [!math!]; | 
 |  | 
 | ^math.Random? r; | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_importPrefix_multiple() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | import 'dart:math' as /*[0*/math/*0]*/; | 
 | import 'dart:async' as /*[1*/math/*1]*/; | 
 |  | 
 | /*[2*/^math/*2]*/.Random? r; | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(2)); | 
 |     for (var (index, loc) in res.indexed) { | 
 |       expect(loc.originSelectionRange, equals(code.ranges.last.range)); | 
 |       expect(loc.targetRange, equals(code.ranges[index].range)); | 
 |       expect(loc.targetSelectionRange, equals(code.ranges[index].range)); | 
 |     } | 
 |   } | 
 |  | 
 |   Future<void> test_importPrefix_multiple_alone() async { | 
 |     var code = TestCode.parse(''' | 
 | import 'dart:math' as /*[0*/math/*0]*/; | 
 | import 'dart:async' as /*[1*/math/*1]*/; | 
 |  | 
 | void foo() { | 
 |   // ignore: prefix_identifier_not_followed_by_dot | 
 |   /*[2*/^math/*2]*/; | 
 | } | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocation( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(2)); | 
 |     for (var (index, loc) in res.indexed) { | 
 |       expect(loc.range, equals(code.ranges[index].range)); | 
 |     } | 
 |   } | 
 |  | 
 |   Future<void> test_importPrefix_multiple_comment() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | import 'dart:math' as /*[0*/math/*0]*/; | 
 | import 'dart:async' as /*[1*/math/*1]*/; | 
 |  | 
 | /// This is a comment that talks about [/*[2*/^math/*2]*/]. | 
 | math.Random? r; | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(2)); | 
 |     for (var (index, loc) in res.indexed) { | 
 |       expect(loc.originSelectionRange, equals(code.ranges.last.range)); | 
 |       expect(loc.targetRange, equals(code.ranges[index].range)); | 
 |       expect(loc.targetSelectionRange, equals(code.ranges[index].range)); | 
 |     } | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_break_toDo() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!do!] { | 
 |     if (true) br^eak; | 
 |   } while (true); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_break_toFor() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!for!] (;;) { | 
 |     if (true) br^eak; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_break_toSwitch() async { | 
 |     var contents = ''' | 
 | void f(int x) { | 
 |   [!switch!] (x) { | 
 |     case 1: | 
 |       br^eak; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_break_toWhile() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!while!] (true) { | 
 |     if (true) br^eak; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_break_withLabel() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   outer: | 
 |   [!do!] { | 
 |     do { | 
 |       if (true) br^eak outer; | 
 |     } while (true); | 
 |   } while (true); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_continue_toFor() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!for!] (;;) { | 
 |     if (true) cont^inue; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_continue_toFor_insideSwitch() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!for!] (;;) { | 
 |     switch (true) { | 
 |       case _: cont^inue; | 
 |     } | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_continue_toWhile() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   [!while!] (true) { | 
 |     if (true) cont^inue; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_nestedLoop() async { | 
 |     var contents = ''' | 
 | void f() { | 
 |   for (;;) { | 
 |     [!while!] (true) { | 
 |       if (true) br^eak; | 
 |     } | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_noTarget() async { | 
 |     failTestOnErrorDiagnostic = false; | 
 |  | 
 |     var contents = ''' | 
 | void f() { | 
 |   br^eak; // no loop | 
 | } | 
 | '''; | 
 |     await testContents(contents, expectNoResults: true); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_return_toClosure() async { | 
 |     var contents = ''' | 
 | int foo() { | 
 |   return [1].firstWhere([!(!]i) { | 
 |     ret^urn true; | 
 |   }); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_return_toConstructor_named() async { | 
 |     var contents = ''' | 
 | class MyClass { | 
 |   MyClass.[!fooConstructor!]() { | 
 |     ret^urn; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_return_toConstructor_unnamed() async { | 
 |     var contents = ''' | 
 | class MyClass { | 
 |   [!MyClass!]() { | 
 |     ret^urn; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_return_toFunction() async { | 
 |     var contents = ''' | 
 | int [!foo!]() { | 
 |   if (true) ret^urn 42; | 
 |   return 0; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_return_toGetter() async { | 
 |     var contents = ''' | 
 | class C { | 
 |   int get [!value!] { | 
 |     if (true) ret^urn 42; | 
 |     return 0; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_keywordNavigation_yield_toFunction() async { | 
 |     var contents = ''' | 
 | Iterable<int> [!generator!]() sync* { | 
 |   yi^eld 1; | 
 |   yield 2; | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_label() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   [!lbl!]: | 
 |   for (;;) { | 
 |     break lb^l; | 
 |   } | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_locationLink_class() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | final a = /*[0*/MyCl^ass/*0]*/(); | 
 |  | 
 | /*[1*/class /*[2*/MyClass/*2]*/ {}/*1]*/ | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(code.ranges[0].range)); | 
 |     expect(loc.targetRange, equals(code.ranges[1].range)); | 
 |     expect(loc.targetSelectionRange, equals(code.ranges[2].range)); | 
 |   } | 
 |  | 
 |   Future<void> test_locationLink_extensionType_primaryConstructor() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | final a = /*[0*/MyExtens^ionType/*0]*/(1); | 
 |  | 
 | /*[1*/extension type /*[2*/MyExtensionType/*2]*/(int a) implements int {}/*1]*/ | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(code.ranges[0].range)); | 
 |     expect(loc.targetRange, equals(code.ranges[1].range)); | 
 |     expect(loc.targetSelectionRange, equals(code.ranges[2].range)); | 
 |   } | 
 |  | 
 |   Future<void> | 
 |   test_locationLink_extensionType_primaryConstructor_named() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | final a = MyExtensionType./*[0*/na^med/*0]*/(1); | 
 |  | 
 | /*[1*/extension type MyExtensionType./*[2*/named/*2]*/(int a) implements int {}/*1]*/ | 
 | '''); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(code.ranges[0].range)); | 
 |     expect(loc.targetRange, equals(code.ranges[1].range)); | 
 |     expect(loc.targetSelectionRange, equals(code.ranges[2].range)); | 
 |   } | 
 |  | 
 |   Future<void> test_locationLink_field() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var mainContents = ''' | 
 | import 'referenced.dart'; | 
 |  | 
 | void f() { | 
 |   Icons().[!ad^d!]; | 
 | } | 
 | '''; | 
 |  | 
 |     var referencedContents = ''' | 
 | void unrelatedFunction() {} | 
 |  | 
 | class Icons { | 
 |   /// `targetRange` should not include the dartDoc but should include the | 
 |   /// full field body. `targetSelectionRange` will be just the name. | 
 |   [!String add = "Test"!]; | 
 | } | 
 |  | 
 | void otherUnrelatedFunction() {} | 
 | '''; | 
 |  | 
 |     var referencedFilePath = join(projectFolderPath, 'lib', 'referenced.dart'); | 
 |     var referencedFileUri = toUri(referencedFilePath); | 
 |  | 
 |     var mainCode = TestCode.parse(mainContents); | 
 |     var referencedCode = TestCode.parse(referencedContents); | 
 |  | 
 |     newFile(mainFilePath, mainCode.code); | 
 |     newFile(referencedFilePath, referencedCode.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       mainCode.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(mainCode.range.range)); | 
 |     expect(loc.targetUri, equals(referencedFileUri)); | 
 |     expect(loc.targetRange, equals(referencedCode.range.range)); | 
 |     expect( | 
 |       loc.targetSelectionRange, | 
 |       equals(rangeOfString(referencedCode, 'add')), | 
 |     ); | 
 |   } | 
 |  | 
 |   Future<void> test_locationLink_function() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var mainContents = ''' | 
 | import 'referenced.dart'; | 
 |  | 
 | void f() { | 
 |   [!fo^o!](); | 
 | } | 
 | '''; | 
 |  | 
 |     var referencedContents = ''' | 
 | void unrelatedFunction() {} | 
 |  | 
 | /// `targetRange` should not include the dartDoc but should include the full | 
 | /// function body. `targetSelectionRange` will be just the name. | 
 | [!void foo() { | 
 |   // Contents of function | 
 | }!] | 
 |  | 
 | void otherUnrelatedFunction() {} | 
 | '''; | 
 |  | 
 |     var referencedFilePath = join(projectFolderPath, 'lib', 'referenced.dart'); | 
 |     var referencedFileUri = toUri(referencedFilePath); | 
 |  | 
 |     var mainCode = TestCode.parse(mainContents); | 
 |     var referencedCode = TestCode.parse(referencedContents); | 
 |  | 
 |     newFile(mainFilePath, mainCode.code); | 
 |     newFile(referencedFilePath, referencedCode.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       mainCode.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(mainCode.range.range)); | 
 |     expect(loc.targetUri, equals(referencedFileUri)); | 
 |     expect(loc.targetRange, equals(referencedCode.range.range)); | 
 |     expect( | 
 |       loc.targetSelectionRange, | 
 |       equals(rangeOfString(referencedCode, 'foo')), | 
 |     ); | 
 |   } | 
 |  | 
 |   /// Verify that for a variable declaration list with multiple variables, | 
 |   /// we use only this variables range so that other variables are not visible | 
 |   /// in the preview. | 
 |   Future<void> test_locationLink_variableDeclaration_multiple() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | var y=1, /*[0*//*[1*/x/*1]*/ = "Test"/*0]*/; | 
 |  | 
 | void f() { | 
 |   /*[2*/x/*2]*/^; | 
 | } | 
 | '''); | 
 |  | 
 |     newFile(mainFilePath, code.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.targetUri, mainFileUri); | 
 |     expect(loc.targetRange, code.ranges[0].range); | 
 |     expect(loc.targetSelectionRange, code.ranges[1].range); | 
 |     expect(loc.originSelectionRange, code.ranges[2].range); | 
 |   } | 
 |  | 
 |   /// Verify that for a variable declaration list with only a single variable, | 
 |   /// we expand the range to the variable declaration list so that the keyword | 
 |   /// or type show up in the preview. | 
 |   Future<void> test_locationLink_variableDeclaration_single() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | /*[0*/var /*[1*/x/*1]*/ = "Test"/*0]*/; | 
 |  | 
 | void f() { | 
 |   /*[2*/x/*2]*/^; | 
 | } | 
 | '''); | 
 |  | 
 |     newFile(mainFilePath, code.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.targetUri, mainFileUri); | 
 |     expect(loc.targetRange, code.ranges[0].range); | 
 |     expect(loc.targetSelectionRange, code.ranges[1].range); | 
 |     expect(loc.originSelectionRange, code.ranges[2].range); | 
 |   } | 
 |  | 
 |   Future<void> test_method_underscore() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   int [!_!]() => 1; | 
 |   int f() => _^(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_nonDartFile() async { | 
 |     newFile(pubspecFilePath, simplePubspecContent); | 
 |     await initialize(); | 
 |  | 
 |     var res = await getDefinitionAsLocation(pubspecFileUri, startOfDocPos); | 
 |     expect(res, isEmpty); | 
 |   } | 
 |  | 
 |   Future<void> test_part() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var mainContents = ''' | 
 | import 'lib.dart'; | 
 |  | 
 | void f() { | 
 |   Icons().[!ad^d!]; | 
 | } | 
 | '''; | 
 |  | 
 |     var libContents = ''' | 
 | part 'part.dart'; | 
 | '''; | 
 |  | 
 |     var partContents = ''' | 
 | part of 'lib.dart'; | 
 |  | 
 | void unrelatedFunction() {} | 
 |  | 
 | class Icons { | 
 |   /// `targetRange` should not include the dartDoc but should include the full | 
 |   /// function body. `targetSelectionRange` will be just the name. | 
 |   [!String add = "Test"!]; | 
 | } | 
 |  | 
 | void otherUnrelatedFunction() {} | 
 | '''; | 
 |  | 
 |     var libFilePath = join(projectFolderPath, 'lib', 'lib.dart'); | 
 |     var partFilePath = join(projectFolderPath, 'lib', 'part.dart'); | 
 |     var partFileUri = toUri(partFilePath); | 
 |  | 
 |     var mainCode = TestCode.parse(mainContents); | 
 |     var libCode = TestCode.parse(libContents); | 
 |     var partCode = TestCode.parse(partContents); | 
 |  | 
 |     newFile(mainFilePath, mainCode.code); | 
 |     newFile(libFilePath, libCode.code); | 
 |     newFile(partFilePath, partCode.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       mainCode.position.position, | 
 |     ); | 
 |  | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.originSelectionRange, equals(mainCode.range.range)); | 
 |     expect(loc.targetUri, equals(partFileUri)); | 
 |     expect(loc.targetRange, equals(partCode.range.range)); | 
 |     expect(loc.targetSelectionRange, equals(rangeOfString(partCode, 'add'))); | 
 |   } | 
 |  | 
 |   Future<void> test_patternVariable_ifCase_logicalOr() async { | 
 |     setLocationLinkSupport(); | 
 |  | 
 |     var code = TestCode.parse(''' | 
 | void f(Object? x) { | 
 |   if (x case int /*[0*//*0*/test/*0]*/ || [int /*[1*/test/*1]*/] when test > 0) { | 
 |     /*[2*//*1*/test/*2]*/ = 1; | 
 |   } | 
 | } | 
 | ''', positionShorthand: false); | 
 |  | 
 |     await initialize(); | 
 |     await openFile(mainFileUri, code.code); | 
 |  | 
 |     // Selecting on the first declaration of `test` | 
 |     var res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.positions.first.position, | 
 |     ); | 
 |     expect(res, hasLength(2)); | 
 |     for (var (index, loc) in res.indexed) { | 
 |       expect(loc.originSelectionRange, equals(code.ranges.first.range)); | 
 |       expect(loc.targetRange, equals(code.ranges[index].range)); | 
 |       expect(loc.targetSelectionRange, equals(code.ranges[index].range)); | 
 |     } | 
 |  | 
 |     // Selecting on the assignment of `test = 1` | 
 |     res = await getDefinitionAsLocationLinks( | 
 |       mainFileUri, | 
 |       code.positions.last.position, | 
 |     ); | 
 |     expect(res, hasLength(2)); | 
 |     for (var (index, loc) in res.indexed) { | 
 |       expect(loc.originSelectionRange, equals(code.ranges.last.range)); | 
 |       expect(loc.targetRange, equals(code.ranges[index].range)); | 
 |       expect(loc.targetSelectionRange, equals(code.ranges[index].range)); | 
 |     } | 
 |   } | 
 |  | 
 |   Future<void> test_sameLine() async { | 
 |     var contents = ''' | 
 | int plusOne(int [!value!]) => 1 + val^ue; | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_superFormalParam() async { | 
 |     var contents = ''' | 
 | class A { | 
 |   A({required int [!a!]}); | 
 | } | 
 | class B extends A { | 
 |   B({required super.^a}) : assert(a > 0); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_topLevelVariable_underscore() async { | 
 |     var contents = ''' | 
 | int [!_!] = 0; | 
 | int f = ^_; | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = A^; | 
 | } | 
 |  | 
 | class [!A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type_generic_end() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = A^<String>(); | 
 | } | 
 |  | 
 | class [!A!]<T> {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type_inNullAwareElement_inList() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = [?A^]; | 
 | } | 
 |  | 
 | class [!A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type_inNullAwareElement_inSet() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = {?A^}; | 
 | } | 
 |  | 
 | class [!A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type_inNullAwareKey_inMap() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = {?A^, "value"}; | 
 | } | 
 |  | 
 | class [!A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_type_inNullAwareValue_inMap() async { | 
 |     var contents = ''' | 
 | f() { | 
 |   final a = {"key": ?A^}; | 
 | } | 
 |  | 
 | class [!A!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_unexisting_implicit_new_constructor() async { | 
 |     var contents = ''' | 
 | class [!A!] { | 
 |   A.constructor(); | 
 | } | 
 |  | 
 | void f() { | 
 |   // ignore: new_with_undefined_constructor_default | 
 |   A^(); | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_unopenFile() async { | 
 |     var contents = ''' | 
 | [!foo!]() { | 
 |   fo^o(); | 
 | } | 
 | '''; | 
 |     var code = TestCode.parse(contents); | 
 |  | 
 |     newFile(mainFilePath, code.code); | 
 |     await testContents(contents, inOpenFile: false); | 
 |   } | 
 |  | 
 |   Future<void> test_variableInPattern() async { | 
 |     var contents = ''' | 
 | foo() { | 
 |   var m = <String, int>{}; | 
 |   const [!str!] = 'h'; | 
 |   if (m case {'d':3, s^tr:4, }){} | 
 | } | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   Future<void> test_varKeyword() async { | 
 |     var contents = ''' | 
 | va^r a = MyClass(); | 
 |  | 
 | class [!MyClass!] {} | 
 | '''; | 
 |  | 
 |     await testContents(contents); | 
 |   } | 
 |  | 
 |   /// Expects definitions at the location of `^` in [contents] will navigate to | 
 |   /// the range in `[!` brackets `!]` in `[contents]. | 
 |   Future<void> testContents( | 
 |     String contents, { | 
 |     bool inOpenFile = true, | 
 |     bool expectNoResults = false, | 
 |   }) async { | 
 |     var code = TestCode.parse(contents); | 
 |     await initialize(); | 
 |     if (inOpenFile) { | 
 |       await openFile(mainFileUri, code.code); | 
 |     } | 
 |     var res = await getDefinitionAsLocation( | 
 |       mainFileUri, | 
 |       code.position.position, | 
 |     ); | 
 |  | 
 |     if (expectNoResults) { | 
 |       expect( | 
 |         code.ranges, | 
 |         isEmpty, | 
 |         reason: 'TestCode should not contain ranges if expectNoResults=true', | 
 |       ); | 
 |       expect(res, isEmpty); | 
 |       return; | 
 |     } | 
 |  | 
 |     expect(code.ranges, hasLength(1)); | 
 |     expect(res, hasLength(1)); | 
 |     var loc = res.single; | 
 |     expect(loc.range, equals(code.range.range)); | 
 |     expect(loc.uri, equals(mainFileUri)); | 
 |   } | 
 |  | 
 |   /// Verifies that invoking Definition at `^` in [source] (which will be | 
 |   /// written into `source.dart`) navigate to `destination.dart` (with the | 
 |   /// content [destination]). | 
 |   Future<void> verifyDirective({ | 
 |     required String source, | 
 |     String destination = '', | 
 |   }) async { | 
 |     var destinationCode = TestCode.parse(destination); | 
 |     var sourceCode = TestCode.parse(source); | 
 |  | 
 |     var sourceFilePath = join(projectFolderPath, 'lib', 'source.dart'); | 
 |     var sourceFileUri = toUri(sourceFilePath); | 
 |     var destinationFilePath = join( | 
 |       projectFolderPath, | 
 |       'lib', | 
 |       'destination.dart', | 
 |     ); | 
 |     var destinationFileUri = toUri(destinationFilePath); | 
 |  | 
 |     newFile(sourceFilePath, sourceCode.code); | 
 |     newFile(destinationFilePath, destinationCode.code); | 
 |     await initialize(); | 
 |     var res = await getDefinitionAsLocation( | 
 |       sourceFileUri, | 
 |       sourceCode.position.position, | 
 |     ); | 
 |  | 
 |     expect(res.single.uri, equals(destinationFileUri)); | 
 |   } | 
 | } |