Version 2.17.0-40.0.dev
Merge commit '8781ab0151888a4b9eef50f0777d0a0908166d05' into 'dev'
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index e8838ce..3c7bbac 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -155,7 +155,7 @@
case DeclarationKind.FUNCTION:
return protocol.ElementKind.FUNCTION;
case DeclarationKind.FUNCTION_TYPE_ALIAS:
- return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+ return protocol.ElementKind.TYPE_ALIAS;
case DeclarationKind.GETTER:
return protocol.ElementKind.GETTER;
case DeclarationKind.METHOD:
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 1dd0f73..490b25f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -14,18 +14,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart'
- show
- ClassElement,
- ConstructorElement,
- Element,
- ElementKind,
- FieldElement,
- FunctionElement,
- LibraryElement,
- LocalVariableElement,
- PropertyAccessorElement,
- TopLevelVariableElement;
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
@@ -60,6 +49,7 @@
double hasDeprecated = 0.0,
double isConstant = 0.0,
double isNoSuchMethod = 0.0,
+ double isNotImported = 0.0,
double keyword = 0.0,
double startsWithDollar = 0.0,
double superMatches = 0.0}) {
@@ -68,6 +58,7 @@
assert(hasDeprecated.between(-1.0, 0.0));
assert(isConstant.between(0.0, 1.0));
assert(isNoSuchMethod.between(-1.0, 0.0));
+ assert(isNotImported.between(-1.0, 0.0));
assert(keyword.between(0.0, 1.0));
assert(startsWithDollar.between(-1.0, 0.0));
assert(superMatches.between(0.0, 1.0));
@@ -77,6 +68,7 @@
hasDeprecated,
isConstant,
isNoSuchMethod,
+ isNotImported,
keyword,
startsWithDollar,
superMatches,
@@ -147,6 +139,7 @@
0.50, // hasDeprecated
1.00, // isConstant
1.00, // isNoSuchMethod
+ 1.00, // isNotImported
1.00, // keyword
0.50, // startsWithDollar
1.00, // superMatches
@@ -328,6 +321,25 @@
: 0.0;
}
+ /// Return the feature for the not-yet-imported property.
+ double isNotImportedFeature(bool isNotImported, Element element) {
+ if (isNotImported) {
+ var enclosing = element.enclosingElement;
+ // The most often case is that we suggest a class.
+ if (enclosing is CompilationUnitElement) {
+ return -1.0;
+ }
+ // But we could also suggest an extension method.
+ if (enclosing is ExtensionElement) {
+ if (!element.isStaticExtensionMember) {
+ return -1.0;
+ }
+ }
+ }
+ // The library is imported, or an unexpected element.
+ return 0.0;
+ }
+
/// Return the value of the _keyword_ feature for the [keyword] when
/// completing at the given [completionLocation].
double keywordFeature(String keyword, String? completionLocation) {
@@ -1047,3 +1059,11 @@
return null;
}
}
+
+extension on Element {
+ bool get isStaticExtensionMember {
+ final self = this;
+ return self is PropertyAccessorElement && self.isStatic ||
+ self is MethodElement && self.isStatic;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 50197a2..d814bb5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -17,6 +17,11 @@
final CompletionBudget budget;
final NotImportedSuggestions additionalData;
+ /// When a library is imported with combinators, we cannot skip it, there
+ /// might be elements that were excluded, but should be suggested. So, here
+ /// we record elements that are already imported.
+ final Set<Element> _importedElements = Set.identity();
+
NotImportedContributor(
DartCompletionRequest request,
SuggestionBuilder builder,
@@ -40,6 +45,20 @@
return;
}
+ var importedLibraries = Set<LibraryElement>.identity();
+ for (var import in request.libraryElement.imports) {
+ var importedLibrary = import.importedLibrary;
+ if (importedLibrary != null) {
+ if (import.combinators.isEmpty) {
+ importedLibraries.add(importedLibrary);
+ } else {
+ _importedElements.addAll(
+ import.namespace.definedNames.values,
+ );
+ }
+ }
+ }
+
// Use single instance to track getter / setter pairs.
var extensionContributor = ExtensionMemberContributor(request, builder);
@@ -55,13 +74,14 @@
}
var element = analysisDriver.getLibraryByFile(file);
- if (element == null) {
+ if (element == null || importedLibraries.contains(element)) {
continue;
}
var exportNamespace = element.exportNamespace;
var exportElements = exportNamespace.definedNames.values.toList();
+ builder.isNotImportedLibrary = true;
builder.laterReplacesEarlier = false;
builder.suggestionAdded = (suggestion) {
additionalData.set.add(suggestion);
@@ -74,16 +94,19 @@
extensionContributor.addExtensions(
exportElements.whereType<ExtensionElement>().toList(),
);
- }
- builder.laterReplacesEarlier = true;
- builder.suggestionAdded = null;
+ builder.isNotImportedLibrary = false;
+ builder.laterReplacesEarlier = true;
+ builder.suggestionAdded = null;
+ }
}
void _buildSuggestions(List<Element> elements) {
var visitor = LibraryElementSuggestionBuilder(request, builder);
for (var element in elements) {
- element.accept(visitor);
+ if (!_importedElements.contains(element)) {
+ element.accept(visitor);
+ }
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 3ec8bec..56f5717 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -181,6 +181,10 @@
final Map<String, CompletionSuggestion> _suggestionMap =
<String, CompletionSuggestion>{};
+ /// This flag is set to `true` while adding suggestions for top-level
+ /// elements from not-yet-imported libraries.
+ bool isNotImportedLibrary = false;
+
/// A flag indicating whether a suggestion should replace any earlier
/// suggestions for the same completion (`true`) or whether earlier
/// suggestions should take priority over more recent suggestions.
@@ -269,6 +273,8 @@
elementKind: elementKind,
hasDeprecated: hasDeprecated,
isConstant: isConstant,
+ isNotImported: request.featureComputer
+ .isNotImportedFeature(isNotImportedLibrary, accessor),
startsWithDollar: startsWithDollar,
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
@@ -662,6 +668,8 @@
hasDeprecated: hasDeprecated,
isConstant: isConstant,
isNoSuchMethod: isNoSuchMethod,
+ isNotImported: request.featureComputer
+ .isNotImportedFeature(isNotImportedLibrary, method),
startsWithDollar: startsWithDollar,
superMatches: superMatches,
inheritanceDistance: inheritanceDistance,
@@ -938,6 +946,8 @@
elementKind: elementKind,
hasDeprecated: hasDeprecated,
isConstant: isConstant,
+ isNotImported: request.featureComputer
+ .isNotImportedFeature(isNotImportedLibrary, accessor),
startsWithDollar: startsWithDollar,
superMatches: superMatches,
);
@@ -1049,6 +1059,7 @@
double hasDeprecated = 0.0,
double isConstant = 0.0,
double isNoSuchMethod = 0.0,
+ double isNotImported = 0.0,
double keyword = 0.0,
double startsWithDollar = 0.0,
double superMatches = 0.0,
@@ -1061,6 +1072,7 @@
hasDeprecated: hasDeprecated,
isConstant: isConstant,
isNoSuchMethod: isNoSuchMethod,
+ isNotImported: isNotImported,
keyword: keyword,
startsWithDollar: startsWithDollar,
superMatches: superMatches);
@@ -1071,6 +1083,7 @@
hasDeprecated: hasDeprecated,
isConstant: isConstant,
isNoSuchMethod: isNoSuchMethod,
+ isNotImported: isNotImported,
keyword: keyword,
startsWithDollar: startsWithDollar,
superMatches: superMatches,
@@ -1101,6 +1114,8 @@
elementKind: elementKind,
hasDeprecated: hasDeprecated,
isConstant: isConstant,
+ isNotImported: request.featureComputer
+ .isNotImportedFeature(isNotImportedLibrary, element),
);
}
@@ -1296,6 +1311,7 @@
double hasDeprecated,
double isConstant,
double isNoSuchMethod,
+ double isNotImported,
double keyword,
double startsWithDollar,
double superMatches,
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 50a6021..732e5bb 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -132,7 +132,9 @@
);
await driver.createProject(packageRoots: packageRoots);
- newPubspecYamlFile(projectPath, '');
+ newPubspecYamlFile(projectPath, '''
+name: project
+''');
newDotPackagesFile(projectPath, content: '''
project:${toUri('$projectPath/lib')}
''');
@@ -279,9 +281,9 @@
}
''');
assertSuggestion(
- completion: 'E.e',
- element: ElementKind.ENUM_CONSTANT,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'E.e',
+ element: ElementKind.ENUM_CONSTANT,
+ );
}
/// See: https://github.com/dart-lang/sdk/issues/40620
@@ -327,9 +329,9 @@
''');
assertSuggestion(
- completion: 'A',
- element: ElementKind.CLASS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'A',
+ element: ElementKind.CLASS,
+ );
}
Future<void> test_project_lib() async {
@@ -356,33 +358,33 @@
element: ElementKind.CONSTRUCTOR,
kind: CompletionSuggestionKind.INVOCATION);
assertSuggestion(
- completion: 'A',
- element: ElementKind.CLASS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'A',
+ element: ElementKind.CLASS,
+ );
assertSuggestion(
- completion: 'E',
- element: ElementKind.ENUM,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'E',
+ element: ElementKind.ENUM,
+ );
assertSuggestion(
- completion: 'Ex',
- element: ElementKind.EXTENSION,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'Ex',
+ element: ElementKind.EXTENSION,
+ );
assertSuggestion(
- completion: 'M',
- element: ElementKind.MIXIN,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'M',
+ element: ElementKind.MIXIN,
+ );
assertSuggestion(
- completion: 'T',
- element: ElementKind.FUNCTION_TYPE_ALIAS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'T',
+ element: ElementKind.TYPE_ALIAS,
+ );
assertSuggestion(
- completion: 'T2',
- element: ElementKind.TYPE_ALIAS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'T2',
+ element: ElementKind.TYPE_ALIAS,
+ );
assertSuggestion(
- completion: 'v',
- element: ElementKind.TOP_LEVEL_VARIABLE,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'v',
+ element: ElementKind.TOP_LEVEL_VARIABLE,
+ );
}
Future<void> test_project_lib_fields_class() async {
@@ -415,9 +417,9 @@
''');
assertSuggestion(
- completion: 'A.f',
- element: ElementKind.FIELD,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'A.f',
+ element: ElementKind.FIELD,
+ );
}
Future<void> test_project_lib_getters_class() async {
@@ -450,9 +452,9 @@
''');
assertSuggestion(
- completion: 'A.g',
- element: ElementKind.GETTER,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'A.g',
+ element: ElementKind.GETTER,
+ );
}
/// See: https://github.com/dart-lang/sdk/issues/40626
@@ -468,9 +470,41 @@
''');
assertSuggestion(
- completion: 'g',
- element: ElementKind.GETTER,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'g',
+ element: ElementKind.GETTER,
+ );
+ }
+
+ Future<void> test_project_lib_methods_class() async {
+ await addProjectFile('lib/a.dart', r'''
+class A {
+ void foo() => 0;
+}
+''');
+
+ await addTestFile('''
+void f() {
+ ^
+}
+''');
+
+ assertNoSuggestion(completion: 'A.foo');
+ }
+
+ Future<void> test_project_lib_methods_static() async {
+ await addProjectFile('lib/a.dart', r'''
+class A {
+ static void foo() => 0;
+}
+''');
+
+ await addTestFile('''
+void f() {
+ ^
+}
+''');
+
+ assertNoSuggestion(completion: 'A.foo');
}
@failingTest
@@ -541,9 +575,9 @@
''');
assertSuggestion(
- completion: 's',
- element: ElementKind.SETTER,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 's',
+ element: ElementKind.SETTER,
+ );
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38739')
@@ -596,16 +630,17 @@
''');
expect(
+ suggestionWith(
+ completion: 'A',
+ element: ElementKind.CONSTRUCTOR,
+ ).relevance,
+ greaterThan(
suggestionWith(
- completion: 'A',
- element: ElementKind.CONSTRUCTOR,
- kind: CompletionSuggestionKind.INVOCATION)
- .relevance,
- greaterThan(suggestionWith(
- completion: 'A',
- element: ElementKind.CLASS,
- kind: CompletionSuggestionKind.INVOCATION)
- .relevance));
+ completion: 'A',
+ element: ElementKind.CLASS,
+ ).relevance,
+ ),
+ );
}
/// See: https://github.com/dart-lang/sdk/issues/35529
@@ -620,13 +655,13 @@
''');
assertSuggestion(
- completion: 'M',
- element: ElementKind.MIXIN,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'M',
+ element: ElementKind.MIXIN,
+ );
assertSuggestion(
- completion: 'A',
- element: ElementKind.CLASS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'A',
+ element: ElementKind.CLASS,
+ );
}
Future<void> test_sdk_lib_future_isNotDuplicated() async {
@@ -682,17 +717,17 @@
// + Classes.
assertSuggestion(
- completion: 'HashMap',
- file: '/sdk/lib/collection/collection.dart',
- element: ElementKind.CLASS,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'HashMap',
+ file: '/sdk/lib/collection/collection.dart',
+ element: ElementKind.CLASS,
+ );
// + Top level variables.
assertSuggestion(
- completion: 'pi',
- file: '/sdk/lib/math/math.dart',
- element: ElementKind.TOP_LEVEL_VARIABLE,
- kind: CompletionSuggestionKind.INVOCATION);
+ completion: 'pi',
+ file: '/sdk/lib/math/math.dart',
+ element: ElementKind.TOP_LEVEL_VARIABLE,
+ );
// (No typedefs, enums, extensions defined in the Mock SDK.)
}
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 09285b7..66720b9 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -130,6 +130,20 @@
return suggestions;
}
+ Future<List<CompletionSuggestion>> getSuggestions2() async {
+ await waitForTasksFinished();
+
+ var request = CompletionGetSuggestions2Params(
+ testFilePath,
+ completionOffset,
+ 1 << 16,
+ timeout: 60 * 1000,
+ ).toRequest('0');
+ var response = await waitResponse(request);
+ var result = CompletionGetSuggestions2Result.fromResponse(response);
+ return result.suggestions;
+ }
+
@override
File newFile(String path, String content) =>
resourceProvider.newFile(resourceProvider.convertPath(path), content);
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index ab3ae47..aa70c28 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -334,6 +334,256 @@
..suggestions.withElementClass.isEmpty;
}
+ Future<void> test_notImported_lowerRelevance_extension_getter() async {
+ await _configureWithWorkspaceRoot();
+
+ newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+ int get foo01 => 0;
+}
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+ int get foo02 => 0;
+}
+''');
+
+ var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+
+void f() {
+ 0.foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_extension_method() async {
+ await _configureWithWorkspaceRoot();
+
+ newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+ void foo01() {}
+}
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+ void foo02() {}
+}
+''');
+
+ var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+
+void f() {
+ 0.foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_extension_setter() async {
+ await _configureWithWorkspaceRoot();
+
+ newFile('$testPackageLibPath/a.dart', content: '''
+extension E1 on int {
+ set foo01(int _) {}
+}
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+extension E2 on int {
+ set foo02(int _) {}
+}
+''');
+
+ var response = await _getTestCodeSuggestions(r'''
+import 'b.dart';
+
+void f() {
+ 0.foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_topLevel_class() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+class A02 {}
+''');
+
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+ A0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 2);
+
+ // `A01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.withElementClass.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('A02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('A01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_topLevel_getter() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+int get foo01 => 0;
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+int get foo02 => 0;
+''');
+
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+ foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_topLevel_setter() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+set foo01(int _) {}
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+set foo02(int _) {}
+''');
+
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+ foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
+ Future<void> test_notImported_lowerRelevance_topLevel_variable() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+var foo01 = 0;
+''');
+
+ newFile('$testPackageLibPath/b.dart', content: '''
+var foo02 = 0;
+''');
+
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'b.dart';
+
+void f() {
+ foo0^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // `foo01` relevance is decreased because it is not yet imported.
+ check(response).suggestions.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo02')
+ ..libraryUriToImport.isNull,
+ (suggestion) => suggestion
+ ..completion.isEqualTo('foo01')
+ ..libraryUriToImport.isEqualTo('package:test/a.dart'),
+ ]);
+ }
+
Future<void> test_notImported_pub_dependencies_inLib() async {
writeTestPackagePubspecYamlFile(r'''
name: test
@@ -522,7 +772,7 @@
await _configureWithWorkspaceRoot();
var response = await _getTestCodeSuggestions('''
-import 'a.dart' show A01;
+import 'a.dart' show A02;
void f() {
A0^
@@ -533,12 +783,16 @@
..assertComplete()
..hasReplacement(left: 2);
+ // Note:
+ // 1. A02 is the first, because it is already imported.
+ // 2. A01 is still suggested, but with lower relevance.
+ // 3. A03 has the same relevance (not tested), but sorted by name.
check(response).suggestions.withElementClass.matches([
(suggestion) => suggestion
- ..completion.isEqualTo('A01')
+ ..completion.isEqualTo('A02')
..libraryUriToImport.isNull,
(suggestion) => suggestion
- ..completion.isEqualTo('A02')
+ ..completion.isEqualTo('A01')
..libraryUriToImport.isEqualTo('package:test/a.dart'),
(suggestion) => suggestion
..completion.isEqualTo('A03')
@@ -1371,6 +1625,29 @@
]);
}
+ Future<void> test_unprefixed_imported_withPrefix_class() async {
+ await _configureWithWorkspaceRoot();
+
+ var response = await _getTestCodeSuggestions('''
+import 'dart:math' as math;
+
+void f() {
+ Rand^
+}
+''');
+
+ check(response)
+ ..assertComplete()
+ ..hasReplacement(left: 4);
+
+ // No suggestion without the `math` prefix.
+ check(response).suggestions.withElementClass.matches([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('math.Random')
+ ..libraryUriToImport.isNull,
+ ]);
+ }
+
Future<void> test_unprefixed_sorts_byScore() async {
await _configureWithWorkspaceRoot();
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
index 3b95fd5..477d52b 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
@@ -519,7 +519,7 @@
"label": "MyAlias",
"declaringLibraryUri": "package:test/a.dart",
"element": {
- "kind": "FUNCTION_TYPE_ALIAS",
+ "kind": "TYPE_ALIAS",
"name": "MyAlias",
"location": {
"file": ${jsonOfPath(path)},
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index aba444c..06e0298 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1899,6 +1899,7 @@
0.0,
0.0,
0.0,
+ 0.0,
0.0
];
@@ -1923,6 +1924,7 @@
double hasDeprecated = 0.0,
double isConstant = 0.0,
double isNoSuchMethod = 0.0,
+ double isNotImported = 0.0,
double keyword = 0.0,
double startsWithDollar = 0.0,
double superMatches = 0.0,
@@ -1935,6 +1937,7 @@
hasDeprecated,
isConstant,
isNoSuchMethod,
+ isNotImported,
keyword,
startsWithDollar,
superMatches,
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index 8c78fc5..6f9b09b 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -3051,6 +3051,7 @@
correctionMessage:
"Try removing the code point or using the Unicode escape sequence "
"'\\u{0}'.",
+ hasPublishedDocs: true,
);
/**
@@ -3096,6 +3097,7 @@
correctionMessage:
"Try removing the code point or using the Unicode escape sequence "
"'\\u{0}'.",
+ hasPublishedDocs: true,
);
/**
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 8e8b939..e373a74 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -66,6 +66,9 @@
}
abstract class Timer {
+ factory Timer(Duration duration, void Function() callback) {
+ throw 0;
+ }
static void run(void callback()) {}
}
''',
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 8507f19..1e292cc 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -16515,7 +16515,7 @@
TEXT_DIRECTION_CODE_POINT_IN_COMMENT:
problemMessage: The Unicode code point 'U+{0}' changes the appearance of text from how it's interpreted by the compiler.
correctionMessage: Try removing the code point or using the Unicode escape sequence '\u{0}'.
- hasPublishedDocs: false
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the unicode sequence of the code point.
@@ -16555,7 +16555,7 @@
TEXT_DIRECTION_CODE_POINT_IN_LITERAL:
problemMessage: The Unicode code point 'U+{0}' changes the appearance of text from how it's interpreted by the compiler.
correctionMessage: Try removing the code point or using the Unicode escape sequence '\u{0}'.
- hasPublishedDocs: false
+ hasPublishedDocs: true
comment: |-
Parameters:
0: the unicode sequence of the code point.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index ea27263..16c003c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -557,6 +557,9 @@
js.Program program = js.Program([
if (isFirst) buildGeneratedBy(),
if (isFirst) buildDeferredInitializerGlobal(),
+ if (_options.experimentalTrackAllocations)
+ js.js.statement("var allocations = #deferredGlobal['allocations']",
+ {'deferredGlobal': deferredInitializersGlobal}),
js.js.statement('$deferredInitializersGlobal.current = #', code)
]);
diff --git a/tools/VERSION b/tools/VERSION
index af0f4b8..f398668 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 39
+PRERELEASE 40
PRERELEASE_PATCH 0
\ No newline at end of file