Version 2.17.0-146.0.dev
Merge commit '45bebe43bb8c224410e993657b3c80530fc5293a' into 'dev'
diff --git a/DEPS b/DEPS
index 58bfd5f..2c99002 100644
--- a/DEPS
+++ b/DEPS
@@ -109,7 +109,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_rev": "6f894c0ca33686122be9085f06e5b9bf6ad55262",
- "dartdoc_rev" : "57761bb61e455eedf93e18c99082445f82116300",
+ "dartdoc_rev" : "b3927dd89d6ff9c78dc88ab2901e63b6a3bf29b7",
"devtools_rev" : "b9f2039239cc72ac8b26f8a5fe46123f34d53ce1",
"ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
"fixnum_rev": "848341f061359ef7ddc0cad472c2ecbb036b28ac",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index 94a7a71..552f56e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -44,6 +44,16 @@
var widgetExpressions = <Expression>[];
if (analyzer.hasSelectedNodes) {
for (var selectedNode in analyzer.selectedNodes) {
+ // If the user has selected exactly a Widget constructor name (without
+ // the argument list), expand the selection.
+ //
+ // Text('foo')
+ // [^^^^]
+ var parent = selectedNode.parent;
+ if (selectedNode is ConstructorName &&
+ parent is InstanceCreationExpression) {
+ selectedNode = parent;
+ }
if (selectedNode is! Expression ||
!flutter.isWidgetExpression(selectedNode)) {
return;
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index e67e5f2..506df55 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -658,6 +658,53 @@
assertHasRegionTarget('new()', 'E();', targetLength: 0);
}
+ Future<void> test_enum_field() async {
+ addTestFile('''
+enum E {
+ v;
+ final int foo = 0;
+ void bar() {
+ foo;
+ foo = 1;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int foo');
+ assertHasRegionTarget('foo;', 'foo = 0;');
+ assertHasRegionTarget('foo = 1;', 'foo = 0;');
+ }
+
+ Future<void> test_enum_getter() async {
+ addTestFile('''
+enum E {
+ v;
+ int get foo => 0;
+ void bar() {
+ foo;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int get');
+ assertHasRegionTarget('foo;', 'foo =>');
+ }
+
+ Future<void> test_enum_implements() async {
+ addTestFile('''
+class A {}
+
+enum E implements A { // ref
+ v
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('A { // ref', 'A {}');
+ }
+
Future<void> test_enum_index() async {
addTestFile('''
enum E { a, b }
@@ -670,6 +717,34 @@
assertHasTargetInDartCore('index;');
}
+ Future<void> test_enum_method() async {
+ addTestFile('''
+enum E {
+ v;
+ void foo(int a) {}
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int ');
+ }
+
+ Future<void> test_enum_setter() async {
+ addTestFile('''
+enum E {
+ v;
+ set foo(int _) {}
+ void bar() {
+ foo = 0;
+ }
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegion('int _');
+ assertHasRegionTarget('foo = 0;', 'foo(');
+ }
+
Future<void> test_enum_typeParameter() async {
addTestFile('''
enum E<T> {
@@ -693,6 +768,19 @@
assertHasTarget('E');
}
+ Future<void> test_enum_with() async {
+ addTestFile('''
+mixin M {}
+
+enum E with M { // ref
+ v
+}
+''');
+ await prepareNavigation();
+
+ assertHasRegionTarget('M { // ref', 'M {}');
+ }
+
Future<void> test_extension_on() async {
addTestFile('''
class C //1
diff --git a/pkg/analysis_server/test/search/member_declarations_test.dart b/pkg/analysis_server/test/search/member_declarations_test.dart
index d838f8e..29e27c9 100644
--- a/pkg/analysis_server/test/search/member_declarations_test.dart
+++ b/pkg/analysis_server/test/search/member_declarations_test.dart
@@ -45,6 +45,185 @@
return null;
}
+ Future<void> test_class_methodField() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ int foo;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.FIELD, 'B');
+ }
+
+ Future<void> test_class_methodGetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ get foo => null;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ }
+
+ Future<void> test_class_methodGetterSetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ get foo => null;
+ set foo(x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(3));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_class_methodMethod() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ foo() {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.METHOD, 'B');
+ }
+
+ Future<void> test_class_methodSetter() async {
+ addTestFile('''
+class A {
+ foo() {}
+ bar() {}
+}
+class B {
+ set foo(x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_enum_methodField() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int foo;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.FIELD, 'B');
+ }
+
+ Future<void> test_enum_methodGetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int get foo => 0;
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ }
+
+ Future<void> test_enum_methodGetterSetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ int get foo => 0;
+ set foo(int x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(3));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.GETTER, 'B');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
+ Future<void> test_enum_methodMethod() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ void foo() {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.METHOD, 'B');
+ }
+
+ Future<void> test_enums_methodSetter() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+ void bar() {}
+}
+
+enum B {
+ v;
+ set foo(int x) {}
+}
+''');
+ await findMemberDeclarations('foo');
+ expect(results, hasLength(2));
+ assertHasDeclaration(ElementKind.METHOD, 'A');
+ assertHasDeclaration(ElementKind.SETTER, 'B');
+ }
+
Future<void> test_localVariable() async {
addTestFile('''
class A {
@@ -69,86 +248,4 @@
await findMemberDeclarations('foo');
expect(results, isEmpty);
}
-
- Future<void> test_methodField() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- int foo;
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.FIELD, 'B');
- }
-
- Future<void> test_methodGetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- get foo => null;
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.GETTER, 'B');
- }
-
- Future<void> test_methodGetterSetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- get foo => null;
- set foo(x) {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(3));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.GETTER, 'B');
- assertHasDeclaration(ElementKind.SETTER, 'B');
- }
-
- Future<void> test_methodMethod() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- foo() {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.METHOD, 'B');
- }
-
- Future<void> test_methodSetter() async {
- addTestFile('''
-class A {
- foo() {}
- bar() {}
-}
-class B {
- set foo(x) {}
-}
-''');
- await findMemberDeclarations('foo');
- expect(results, hasLength(2));
- assertHasDeclaration(ElementKind.METHOD, 'A');
- assertHasDeclaration(ElementKind.SETTER, 'B');
- }
}
diff --git a/pkg/analysis_server/test/search/member_references_test.dart b/pkg/analysis_server/test/search/member_references_test.dart
index a2c7b18..b5df9ae 100644
--- a/pkg/analysis_server/test/search/member_references_test.dart
+++ b/pkg/analysis_server/test/search/member_references_test.dart
@@ -29,75 +29,179 @@
return waitForSearchResults();
}
- Future<void> test_fields_explicit() async {
+ Future<void> test_class_fields_explicit() async {
addTestFile('''
class A {
var foo;
}
+
class B {
var foo;
}
-mainResolved(A a, B b) {
+
+void whenResolved(A a, B b) {
a.foo = 1;
b.foo = 2;
- print(a.foo); // resolved A
- print(b.foo); // resolved B
+ a.foo; // resolved A
+ b.foo; // resolved B
}
-mainUnresolved(a, b) {
+
+void whenUnresolved(a, b) {
a.foo = 10;
b.foo = 20;
- print(a.foo); // unresolved A
- print(b.foo); // unresolved B
+ a.foo; // unresolved A
+ b.foo; // unresolved B
}
''');
await findMemberReferences('foo');
assertNoResult(SearchResultKind.WRITE, 'foo = 1;');
assertNoResult(SearchResultKind.WRITE, 'foo = 2;');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved A');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved B');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
}
- Future<void> test_fields_implicit() async {
+ Future<void> test_class_fields_implicit() async {
addTestFile('''
class A {
- get foo => null;
+ int get foo => 0;
}
+
class B {
- get foo => null;
+ int get foo => 0;
}
-mainResolved(A a, B b) {
- print(a.foo); // resolved A
- print(b.foo); // resolved B
+
+void whenResolved(A a, B b) {
+ a.foo; // resolved A
+ b.foo; // resolved B
}
-mainUnresolved(a, b) {
- print(a.foo); // unresolved A
- print(b.foo); // unresolved B
+
+void whenUnresolved(a, b) {
+ a.foo; // unresolved A
+ b.foo; // unresolved B
}
''');
await findMemberReferences('foo');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved A');
- assertNoResult(SearchResultKind.READ, 'foo); // resolved B');
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved A', true);
- assertHasRef(SearchResultKind.READ, 'foo); // unresolved B', true);
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
}
- Future<void> test_methods() async {
+ Future<void> test_class_methods() async {
addTestFile('''
class A {
- foo() {}
+ void foo() {}
}
+
class B {
- foo() {}
+ void foo() {}
}
-mainResolved(A a, B b) {
+
+void whenResolved(A a, B b) {
a.foo(1);
b.foo(2);
}
-mainUnresolved(a, b) {
+
+void whenUnresolved(a, b) {
+ a.foo(10);
+ b.foo(20);
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.INVOCATION, 'foo(1)');
+ assertNoResult(SearchResultKind.INVOCATION, 'foo(2)');
+ assertHasRef(SearchResultKind.INVOCATION, 'foo(10)', true);
+ assertHasRef(SearchResultKind.INVOCATION, 'foo(20)', true);
+ }
+
+ Future<void> test_enum_fields_explicit() async {
+ addTestFile('''
+enum A {
+ v;
+ final foo = 0;
+}
+
+enum B {
+ v;
+ final foo = 0;
+}
+
+void whenResolved(A a, B b) {
+ a.foo = 1;
+ b.foo = 2;
+ a.foo; // resolved A
+ b.foo; // resolved B
+}
+
+whenUnresolved(a, b) {
+ a.foo = 10;
+ b.foo = 20;
+ a.foo; // unresolved A
+ b.foo; // unresolved B
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.WRITE, 'foo = 1;');
+ assertNoResult(SearchResultKind.WRITE, 'foo = 2;');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.WRITE, 'foo = 10;', true);
+ assertHasRef(SearchResultKind.WRITE, 'foo = 20;', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
+ }
+
+ Future<void> test_enum_fields_implicit() async {
+ addTestFile('''
+enum A {
+ v;
+ int get foo => 0;
+}
+
+enum B {
+ v;
+ int get foo => 0;
+}
+
+void whenResolved(A a, B b) {
+ a.foo; // resolved A
+ b.foo; // resolved B
+}
+
+void whenUnresolved(a, b) {
+ a.foo; // unresolved A
+ b.foo; // unresolved B
+}
+''');
+ await findMemberReferences('foo');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved A');
+ assertNoResult(SearchResultKind.READ, 'foo; // resolved B');
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved A', true);
+ assertHasRef(SearchResultKind.READ, 'foo; // unresolved B', true);
+ }
+
+ Future<void> test_enum_methods() async {
+ addTestFile('''
+enum A {
+ v;
+ void foo() {}
+}
+
+enum B {
+ v;
+ void foo() {}
+}
+
+void whenResolved(A a, B b) {
+ a.foo(1);
+ b.foo(2);
+}
+
+void whenUnresolved(a, b) {
a.foo(10);
b.foo(20);
}
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 2242204..977f966 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -53,6 +53,31 @@
return null;
}
+ Future<void> test_enum_startEndPattern() async {
+ addTestFile('''
+enum A {
+ v
+}
+
+enum A2 {
+ v
+}
+
+enum B {
+ v
+}
+
+enum D {
+ v
+}
+''');
+ await findTopLevelDeclarations('^[A-C]\$');
+ assertHasDeclaration(ElementKind.ENUM, 'A');
+ assertHasDeclaration(ElementKind.ENUM, 'B');
+ assertNoDeclaration(ElementKind.ENUM, 'A2');
+ assertNoDeclaration(ElementKind.ENUM, 'D');
+ }
+
Future<void> test_extensionDeclaration() async {
addTestFile('''
extension MyExtension on int {}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
index fc79cb7..5f53ffdd 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_column_test.dart
@@ -154,4 +154,36 @@
}
''');
}
+
+ Future<void> test_selectedWidgetName() async {
+ await resolveTestCode('''
+import 'package:flutter/widgets.dart';
+
+class FakeFlutter {
+ main() {
+ return Container(
+ child: Text('aaa'),
+ );
+ }
+}
+''');
+ await assertHasAssistAt(
+ 'Text(',
+ '''
+import 'package:flutter/widgets.dart';
+
+class FakeFlutter {
+ main() {
+ return Container(
+ child: Column(
+ children: [
+ Text('aaa'),
+ ],
+ ),
+ );
+ }
+}
+''',
+ length: 4);
+ }
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/defined_names.dart b/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
index c308535..d4d2ed2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/defined_names.dart
@@ -31,6 +31,12 @@
if (member is ClassDeclaration) {
member.members.forEach(appendClassMemberName);
}
+ if (member is EnumDeclaration) {
+ for (var constant in member.constants) {
+ appendName(names.classMemberNames, constant.name);
+ }
+ member.members.forEach(appendClassMemberName);
+ }
if (member is MixinDeclaration) {
member.members.forEach(appendClassMemberName);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 3dbb4a0..6df7913 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -154,6 +154,7 @@
var unitResult = await _driver.getUnitElement(file);
if (unitResult is UnitElementResult) {
unitResult.element.classes.forEach(addElements);
+ unitResult.element.enums.forEach(addElements);
unitResult.element.mixins.forEach(addElements);
}
}
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index 00fadde..496f77d 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -17,7 +17,7 @@
bool _isInNativeClass = false;
/// When a new class or mixin is entered, [_initFieldsMap] initializes this
- /// map, and [leaveClassOrMixin] resets it.
+ /// map, and [leaveClass] resets it.
///
/// [_InitState.notInit] or [_InitState.initInDeclaration] is set for each
/// field. Later [verify] is called to verify each constructor of the class.
@@ -35,14 +35,17 @@
}) : _typeSystem = typeSystem,
_errorReporter = errorReporter;
- void enterClass(ClassDeclaration node) {
+ void enterClass(ClassDeclaration node, ClassElementImpl element) {
_isInNativeClass = node.nativeClause != null;
- _initFieldsMap(node.declaredElement!);
+ _initFieldsMap(element.fields);
}
- void enterEnum(EnumDeclaration node) {
+ void enterEnum(EnumDeclaration node, EnumElementImpl element) {
_isInNativeClass = false;
- _initFieldsMap(node.declaredElement!);
+ _initFieldsMap(
+ element.fields,
+ enumConstants: element.constants,
+ );
}
void leaveClass() {
@@ -60,7 +63,7 @@
return;
}
- if (node.parent is! ClassDeclaration) {
+ if (!(node.parent is ClassDeclaration || node.parent is EnumDeclaration)) {
return;
}
@@ -98,13 +101,27 @@
_reportNotInitializedNonNullable(node, notInitNonNullableFields);
}
- void _initFieldsMap(ClassElement element) {
+ void _initFieldsMap(
+ List<FieldElement> fields, {
+ List<FieldElement>? enumConstants,
+ }) {
_initialFieldMap = <FieldElement, _InitState>{};
- for (var field in element.fields) {
- if (!field.isSynthetic) {
- _initialFieldMap![field] = field.hasInitializer
- ? _InitState.initInDeclaration
- : _InitState.notInit;
+
+ for (var field in fields) {
+ if (field.isSynthetic) {
+ continue;
+ }
+ if (enumConstants != null && field.name == 'index') {
+ continue;
+ }
+ _initialFieldMap![field] = field.hasInitializer
+ ? _InitState.initInDeclaration
+ : _InitState.notInit;
+ }
+
+ if (enumConstants != null) {
+ for (var field in enumConstants) {
+ _initialFieldMap![field] = _InitState.initInDeclaration;
}
}
}
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index f516e46..5d28080 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -444,7 +444,7 @@
}
_checkForConflictingClassMembers();
- _constructorFieldsVerifier.enterClass(node);
+ _constructorFieldsVerifier.enterClass(node, element);
_checkForFinalNotInitializedInClass(members);
_checkForBadFunctionUse(node);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
@@ -597,7 +597,7 @@
_checkClassInheritance(node, null, withClause, implementsClause);
}
- _constructorFieldsVerifier.enterEnum(node);
+ _constructorFieldsVerifier.enterEnum(node, element);
_checkForFinalNotInitializedInClass(node.members);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
_checkForMainFunction(node.name);
@@ -610,6 +610,7 @@
super.visitEnumDeclaration(node);
} finally {
+ _constructorFieldsVerifier.leaveClass();
_enclosingClass = outerClass;
}
}
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 940c8d7..a8fdcde 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -228,6 +228,7 @@
var name = constant.name.name;
var field = ConstFieldElementImpl(name, constant.name.offset)
..hasImplicitType = true
+ ..hasInitializer = true
..isConst = true
..isEnumConstant = true
..isStatic = true
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 996d5d5..53650c1 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -200,6 +200,40 @@
unorderedEquals(['a', 'b', 'd', 'e', 'f', 'g']));
}
+ test_definedClassMemberNames_enum() {
+ String path = convertPath('/aaa/lib/a.dart');
+ newFile(path, content: r'''
+enum E1 {
+ v1;
+ int field1, field2;
+ const E1();
+ const E1.namedConstructor();
+ void method() {}
+ get getter => 0;
+ set setter(_) {}
+}
+
+enum E2 {
+ v2;
+ get getter2 => 0;
+}
+''');
+ FileState file = fileSystemState.getFileForPath(path);
+ expect(
+ file.definedClassMemberNames,
+ unorderedEquals([
+ 'v1',
+ 'field1',
+ 'field2',
+ 'method',
+ 'getter',
+ 'setter',
+ 'v2',
+ 'getter2',
+ ]),
+ );
+ }
+
test_definedTopLevelNames() {
String path = convertPath('/aaa/lib/a.dart');
newFile(path, content: r'''
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 55dc51f..3410fd2 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -89,6 +89,28 @@
unorderedEquals([a.methods[0], b.fields[0]]));
}
+ test_classMembers_enum() async {
+ await resolveTestCode('''
+enum E1 {
+ v;
+ void test() {}
+}
+
+enum E2 {
+ v;
+ final int test = 0;
+}
+''');
+
+ expect(
+ await _findClassMembers('test'),
+ unorderedEquals([
+ findElement.method('test', of: 'E1'),
+ findElement.field('test', of: 'E2'),
+ ]),
+ );
+ }
+
test_classMembers_importNotDart() async {
await resolveTestCode('''
import 'not-dart.txt';
diff --git a/pkg/analyzer/test/src/diagnostics/field_initialized_by_multiple_initializers_test.dart b/pkg/analyzer/test/src/diagnostics/field_initialized_by_multiple_initializers_test.dart
index 6744663..d766eac 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initialized_by_multiple_initializers_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initialized_by_multiple_initializers_test.dart
@@ -19,7 +19,7 @@
static const _errorCode =
CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS;
- test_more_than_two_initializers() async {
+ test_class_more_than_two_initializers() async {
await assertErrorsInCode(r'''
class A {
int x;
@@ -31,7 +31,7 @@
]);
}
- test_multiple_names() async {
+ test_class_multiple_names() async {
await assertErrorsInCode(r'''
class A {
int x;
@@ -44,7 +44,7 @@
]);
}
- test_one_initializer() async {
+ test_class_one_initializer() async {
await assertNoErrorsInCode(r'''
class A {
int x;
@@ -54,7 +54,7 @@
''');
}
- test_two_initializers() async {
+ test_class_two_initializers() async {
await assertErrorsInCode(r'''
class A {
int x;
@@ -64,4 +64,29 @@
error(_errorCode, 34, 1),
]);
}
+
+ test_enum_one_initializer() async {
+ await assertNoErrorsInCode(r'''
+enum E {
+ v;
+ final int x;
+ final int y;
+ const E() : x = 0, y = 0;
+}
+''');
+ }
+
+ test_enum_two_initializers() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int x;
+ const E() : x = 0, x = 1;
+}
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 11, 1),
+ error(CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, 50,
+ 1),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initialized_in_initializer_and_declaration_test.dart b/pkg/analyzer/test/src/diagnostics/field_initialized_in_initializer_and_declaration_test.dart
index 63a379d..9bf6c15 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initialized_in_initializer_and_declaration_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initialized_in_initializer_and_declaration_test.dart
@@ -16,7 +16,7 @@
@reflectiveTest
class FieldInitializedInInitializerAndDeclarationTest
extends PubPackageResolutionTest {
- test_both() async {
+ test_class_both() async {
await assertErrorsInCode('''
class A {
final int x = 0;
@@ -29,4 +29,20 @@
1),
]);
}
+
+ test_enum_both() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ final int x = 0;
+ const E() : x = 1;
+}
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 11, 1),
+ error(
+ CompileTimeErrorCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION,
+ 47,
+ 1),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initialized_in_parameter_and_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/field_initialized_in_parameter_and_initializer_test.dart
index 1de0aff..e43a898 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initialized_in_parameter_and_initializer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initialized_in_parameter_and_initializer_test.dart
@@ -16,7 +16,7 @@
@reflectiveTest
class FinalInitializedInParameterAndInitializerTest
extends PubPackageResolutionTest {
- test_initializingFormal_initializer() async {
+ test_class_fieldFormalParameter_initializer() async {
await assertErrorsInCode(r'''
class A {
int x;
@@ -27,4 +27,18 @@
33, 1),
]);
}
+
+ test_enum_fieldFormalParameter_initializer() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v(0);
+ final int x;
+ const E(this.x) : x = 1;
+}
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 11, 4),
+ error(CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER,
+ 52, 1),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializer_factory_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializer_factory_constructor_test.dart
index eb9adaa..a028a27 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializer_factory_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializer_factory_constructor_test.dart
@@ -16,7 +16,7 @@
@reflectiveTest
class FieldInitializerFactoryConstructorTest extends PubPackageResolutionTest {
- test_fieldFormalParameter() async {
+ test_class_fieldFormalParameter() async {
await assertErrorsInCode(r'''
class A {
int x = 0;
@@ -27,7 +27,7 @@
]);
}
- test_functionTypedParameter() async {
+ test_class_fieldFormalParameter_functionTyped() async {
await assertErrorsInCode(r'''
class A {
int Function()? x;
@@ -40,4 +40,21 @@
error(ParserErrorCode.MISSING_FUNCTION_BODY, 56, 1),
]);
}
+
+ test_enum_fieldFormalParameter() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int x = 0;
+ const E();
+ factory E._(this.x) => throw 0;
+}
+
+void f() {
+ E._(0);
+}
+''', [
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, 60, 6),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
index 767bfa9..eb14c4f 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
@@ -18,7 +18,7 @@
@reflectiveTest
class FieldInitializerNotAssignableTest extends PubPackageResolutionTest {
- test_implicitCallReference() async {
+ test_class_implicitCallReference() async {
await assertNoErrorsInCode('''
class C {
void call(int p) {}
@@ -30,7 +30,7 @@
''');
}
- test_implicitCallReference_genericFunctionInstantiation() async {
+ test_class_implicitCallReference_genericFunctionInstantiation() async {
await assertNoErrorsInCode('''
class C {
void call<T>(T p) {}
@@ -42,7 +42,7 @@
''');
}
- test_unrelated() async {
+ test_class_unrelated() async {
await assertErrorsInCode('''
class A {
int x;
@@ -52,6 +52,20 @@
error(CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 31, 2),
]);
}
+
+ test_enum_unrelated() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ final int x;
+ const E() : x = '';
+}
+''', [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 11, 1),
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 47, 2),
+ error(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, 47, 2),
+ ]);
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializer_redirecting_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializer_redirecting_constructor_test.dart
index 682d603..6c4537f 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializer_redirecting_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializer_redirecting_constructor_test.dart
@@ -60,11 +60,11 @@
enum E {
v;
final int x;
- const E.named();
+ const E.named() : x = 0;
const E() : this.named(), x = 42;
}
''', [
- error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 76,
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 84,
6),
]);
}
@@ -74,11 +74,11 @@
enum E {
v;
final int x;
- const E.named();
+ const E.named() : x = 0;
const E() : x = 42, this.named();
}
''', [
- error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 62,
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 70,
6),
]);
}
@@ -88,11 +88,11 @@
enum E {
v(0);
final int x;
- const E.named();
+ const E.named() : x = 0;
const E(this.x) : this.named();
}
''', [
- error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 61,
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, 69,
6),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializing_formal_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializing_formal_not_assignable_test.dart
index f3ff4aa..7f098e3 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializing_formal_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializing_formal_not_assignable_test.dart
@@ -16,7 +16,7 @@
@reflectiveTest
class FieldInitializingFormalNotAssignableTest
extends PubPackageResolutionTest {
- test_dynamic() async {
+ test_class_dynamic() async {
await assertErrorsInCode('''
class A {
int x;
@@ -28,7 +28,7 @@
]);
}
- test_unrelated() async {
+ test_class_unrelated() async {
await assertErrorsInCode('''
class A {
int x;
@@ -39,4 +39,31 @@
13),
]);
}
+
+ test_enum_dynamic() async {
+ await assertErrorsInCode('''
+enum E {
+ v(0);
+ final int x;
+ const E(dynamic this.x);
+}
+''', [
+ error(CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, 42,
+ 14),
+ ]);
+ }
+
+ test_enum_unrelated() async {
+ await assertErrorsInCode('''
+enum E {
+ v('');
+ final int x;
+ const E(String this.x);
+}
+''', [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, 13, 2),
+ error(CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, 43,
+ 13),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/final_initialized_in_delcaration_and_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/final_initialized_in_delcaration_and_constructor_test.dart
index 0817c4e..d7a4b8e 100644
--- a/pkg/analyzer/test/src/diagnostics/final_initialized_in_delcaration_and_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_initialized_in_delcaration_and_constructor_test.dart
@@ -16,7 +16,7 @@
@reflectiveTest
class FinalInitializedInDeclarationAndConstructorTest
extends PubPackageResolutionTest {
- test_initializingFormal() async {
+ test_class_fieldFormalParameter() async {
await assertErrorsInCode('''
class A {
final x = 0;
@@ -29,4 +29,20 @@
1),
]);
}
+
+ test_enum_fieldFormalParameter() async {
+ await assertErrorsInCode('''
+enum E {
+ v(0);
+ final x = 0;
+ const E(this.x);
+}
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 11, 4),
+ error(
+ CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
+ 47,
+ 1),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_constructor_test.dart
index 3bd3afc..b85364f 100644
--- a/pkg/analyzer/test/src/diagnostics/final_not_initialized_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_constructor_test.dart
@@ -15,7 +15,7 @@
@reflectiveTest
class FinalNotInitializedConstructorTest extends PubPackageResolutionTest {
- test_1() async {
+ test_class_1() async {
await assertErrorsInCode('''
class A {
final int x;
@@ -26,7 +26,7 @@
]);
}
- test_2() async {
+ test_class_2() async {
await assertErrorsInCode('''
class A {
final int a;
@@ -38,21 +38,22 @@
]);
}
- test_3Plus() async {
+ test_class_3Plus() async {
await assertErrorsInCode('''
-class A {
+enum E {
+ v;
final int a;
final int b;
final int c;
- A() {}
+ const E();
}
''', [
error(
- CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS, 57, 1),
+ CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS, 67, 1),
]);
}
- Future<void> test_redirecting_error() async {
+ Future<void> test_class_redirecting_error() async {
await assertErrorsInCode('''
class A {
final int x;
@@ -64,7 +65,7 @@
]);
}
- Future<void> test_redirecting_no_error() async {
+ Future<void> test_class_redirecting_no_error() async {
await assertNoErrorsInCode('''
class A {
final int x;
@@ -74,7 +75,7 @@
''');
}
- Future<void> test_two_constructors_no_errors() async {
+ Future<void> test_class_two_constructors_no_errors() async {
await assertNoErrorsInCode('''
class A {
final int x;
@@ -83,4 +84,64 @@
}
''');
}
+
+ test_enum_1() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ final int x;
+ const E();
+}
+''', [
+ error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, 37, 1),
+ ]);
+ }
+
+ test_enum_2() async {
+ await assertErrorsInCode('''
+enum E {
+ v;
+ final int a;
+ final int b;
+ const E();
+}
+''', [
+ error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2, 52, 1),
+ ]);
+ }
+
+ Future<void> test_enum_redirecting_error() async {
+ await assertErrorsInCode('''
+enum E {
+ v1, v2._();
+ final int x;
+ const E() : this._();
+ const E._();
+}
+''', [
+ error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, 70, 1),
+ ]);
+ }
+
+ Future<void> test_enum_redirecting_no_error() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v1, v2._();
+ final int x;
+ const E() : this._();
+ const E._() : x = 0;
+}
+''');
+ }
+
+ Future<void> test_enum_two_constructors_no_errors() async {
+ await assertNoErrorsInCode('''
+enum E {
+ v1.zero(), v2.one();
+ final int x;
+ const E.zero() : x = 0;
+ const E.one() : x = 1;
+}
+''');
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/illegal_concrete_enum_member_declaration_test.dart b/pkg/analyzer/test/src/diagnostics/illegal_concrete_enum_member_declaration_test.dart
index c829d5a..bd3820e 100644
--- a/pkg/analyzer/test/src/diagnostics/illegal_concrete_enum_member_declaration_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/illegal_concrete_enum_member_declaration_test.dart
@@ -121,6 +121,19 @@
]);
}
+ test_index_field_notInitializer() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v;
+ final int index;
+ const E();
+}
+''', [
+ error(
+ CompileTimeErrorCode.ILLEGAL_CONCRETE_ENUM_MEMBER_DECLARATION, 26, 5),
+ ]);
+ }
+
test_index_getter() async {
await assertErrorsInCode(r'''
enum E {
diff --git a/pkg/dartdev/lib/src/templates/server_shelf.dart b/pkg/dartdev/lib/src/templates/server_shelf.dart
index cd23807..2292d39 100644
--- a/pkg/dartdev/lib/src/templates/server_shelf.dart
+++ b/pkg/dartdev/lib/src/templates/server_shelf.dart
@@ -55,7 +55,6 @@
dev_dependencies:
http: ^0.13.0
lints: ^1.0.0
- test_process: ^2.0.0
test: ^1.15.0
''';
@@ -183,22 +182,28 @@
''';
final String _test = r'''
+import 'dart:io';
+
import 'package:http/http.dart';
import 'package:test/test.dart';
-import 'package:test_process/test_process.dart';
void main() {
final port = '8080';
final host = 'http://0.0.0.0:$port';
+ late Process p;
setUp(() async {
- await TestProcess.start(
+ p = await Process.start(
'dart',
['run', 'bin/server.dart'],
environment: {'PORT': port},
);
+ // Wait for server to start and print to stdout.
+ await p.stdout.first;
});
+ tearDown(() => p.kill());
+
test('Root', () async {
final response = await get(Uri.parse(host + '/'));
expect(response.statusCode, 200);
@@ -210,6 +215,7 @@
expect(response.statusCode, 200);
expect(response.body, 'hello\n');
});
+
test('404', () async {
final response = await get(Uri.parse(host + '/foobar'));
expect(response.statusCode, 404);
diff --git a/tools/VERSION b/tools/VERSION
index e6ff919..7ade7c2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 145
+PRERELEASE 146
PRERELEASE_PATCH 0
\ No newline at end of file