Version 3.5.0-103.0.dev
Merge 6e7aca792c018b0e48a023b81b5def2aab85be16 into dev
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index cb0662f..cdd1e18 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -226,6 +226,10 @@
/// Return the interface of the given [element]. It might include
/// private members, not necessary accessible in all libraries.
Interface getInterface(InterfaceElement element) {
+ if (element.augmentationTarget != null) {
+ throw ArgumentError('Interfaces can only be asked for declarations');
+ }
+
var result = _interfaces[element];
if (result != null) {
return result;
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index fce3dd1..20dc9cc 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -396,16 +396,20 @@
var element = field.declaredElement;
if (element is PropertyAccessorElement || element is FieldElement) {
Name name = Name(_currentLibrary.source.uri, element!.name);
- Element enclosingElement = element.enclosingElement!;
- if (enclosingElement is InterfaceElement) {
+ var enclosingElement = element.enclosingElement!;
+ var enclosingDeclaration = enclosingElement is InstanceElement
+ ? enclosingElement.augmented.declaration
+ : enclosingElement;
+ if (enclosingDeclaration is InterfaceElement) {
var overridden = _inheritanceManager
- .getMember2(enclosingElement, name, forSuper: true);
+ .getMember2(enclosingDeclaration, name, forSuper: true);
// Check for a setter.
if (overridden == null) {
Name setterName =
Name(_currentLibrary.source.uri, '${element.name}=');
- overridden = _inheritanceManager
- .getMember2(enclosingElement, setterName, forSuper: true);
+ overridden = _inheritanceManager.getMember2(
+ enclosingDeclaration, setterName,
+ forSuper: true);
}
return overridden;
}
@@ -579,6 +583,9 @@
bool wasInDoNotStoreMember = _inDoNotStoreMember;
var element = node.declaredElement!;
var enclosingElement = element.enclosingElement;
+ var enclosingDeclaration = enclosingElement is InstanceElement
+ ? enclosingElement.augmented.declaration
+ : enclosingElement;
_deprecatedVerifier.pushInDeprecatedValue(element.hasDeprecated);
if (element.hasDoNotStore) {
@@ -591,8 +598,9 @@
var name = Name(_currentLibrary.source.uri, element.name);
var elementIsOverride = element is ClassMemberElement &&
- enclosingElement is InterfaceElement
- ? _inheritanceManager.getOverridden2(enclosingElement, name) != null
+ enclosingDeclaration is InterfaceElement
+ ? _inheritanceManager.getOverridden2(enclosingDeclaration, name) !=
+ null
: false;
if (!node.isSetter && !elementIsOverride) {
@@ -603,8 +611,8 @@
_checkStrictInferenceInParameters(node.parameters, body: node.body);
}
- var overriddenElement = enclosingElement is InterfaceElement
- ? _inheritanceManager.getMember2(enclosingElement, name,
+ var overriddenElement = enclosingDeclaration is InterfaceElement
+ ? _inheritanceManager.getMember2(enclosingDeclaration, name,
forSuper: true)
: null;
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index b0cc66b..e397860 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -52,8 +52,10 @@
/// Check that there are no members with the same name.
void checkEnum(EnumDeclaration node) {
- var enumElement = node.declaredElement!;
- var enumName = enumElement.name;
+ var element = node.declaredElement!;
+ var augmented = element.augmented;
+ var declarationElement = augmented.declaration;
+ var declarationName = declarationElement.name;
var constructorNames = <String>{};
var instanceGetters = <String, Element>{};
@@ -69,7 +71,7 @@
for (var member in node.members) {
if (member is ConstructorDeclaration) {
- if (member.returnType.name == enumElement.name) {
+ if (member.returnType.name == declarationElement.name) {
var name = member.declaredElement!.name;
if (!constructorNames.add(name)) {
if (name.isEmpty) {
@@ -110,7 +112,7 @@
}
}
- if (enumName == 'values') {
+ if (declarationName == 'values') {
_errorReporter.atToken(
node.name,
CompileTimeErrorCode.ENUM_WITH_NAME_VALUES,
@@ -118,7 +120,7 @@
}
for (var constant in node.constants) {
- if (constant.name.lexeme == enumName) {
+ if (constant.name.lexeme == declarationName) {
_errorReporter.atToken(
constant.name,
CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
@@ -127,30 +129,30 @@
}
_checkConflictingConstructorAndStatic(
- interfaceElement: enumElement,
+ interfaceElement: declarationElement,
staticGetters: staticGetters,
staticSetters: staticSetters,
);
- for (var accessor in enumElement.accessors) {
+ for (var accessor in declarationElement.accessors) {
var baseName = accessor.displayName;
if (accessor.isStatic) {
- var instance = _getInterfaceMember(enumElement, baseName);
+ var instance = _getInterfaceMember(declarationElement, baseName);
if (instance != null && baseName != 'values') {
_errorReporter.atElement(
accessor,
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
- arguments: [enumName, baseName, enumName],
+ arguments: [declarationName, baseName, declarationName],
);
}
} else {
- var inherited = _getInheritedMember(enumElement, baseName);
+ var inherited = _getInheritedMember(declarationElement, baseName);
if (inherited is MethodElement) {
_errorReporter.atElement(
accessor,
CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD,
arguments: [
- enumElement.displayName,
+ declarationElement.displayName,
baseName,
inherited.enclosingElement.displayName,
],
@@ -159,25 +161,25 @@
}
}
- for (var method in enumElement.methods) {
+ for (var method in declarationElement.methods) {
var baseName = method.displayName;
if (method.isStatic) {
- var instance = _getInterfaceMember(enumElement, baseName);
+ var instance = _getInterfaceMember(declarationElement, baseName);
if (instance != null) {
_errorReporter.atElement(
method,
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
- arguments: [enumName, baseName, enumName],
+ arguments: [declarationName, baseName, declarationName],
);
}
} else {
- var inherited = _getInheritedMember(enumElement, baseName);
+ var inherited = _getInheritedMember(declarationElement, baseName);
if (inherited is PropertyAccessorElement) {
_errorReporter.atElement(
method,
CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
arguments: [
- enumElement.displayName,
+ declarationElement.displayName,
baseName,
inherited.enclosingElement.displayName,
],
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index ed327b5..3e99211 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -61,6 +61,10 @@
withClause: declaration.withClause,
);
} else if (declaration is ClassTypeAlias) {
+ var element = declaration.declaredElement!;
+ if (element.isAugmentation) {
+ continue;
+ }
verifier = _ClassVerifier(
typeSystem: _typeSystem,
typeProvider: _typeProvider,
@@ -69,13 +73,17 @@
featureSet: unit.featureSet,
library: library,
classNameToken: declaration.name,
- classElement: declaration.declaredElement!,
+ classElement: element,
strictCasts: _strictCasts,
implementsClause: declaration.implementsClause,
superclass: declaration.superclass,
withClause: declaration.withClause,
);
} else if (declaration is EnumDeclaration) {
+ var element = declaration.declaredElement!;
+ if (element.isAugmentation) {
+ continue;
+ }
verifier = _ClassVerifier(
typeSystem: _typeSystem,
typeProvider: _typeProvider,
@@ -84,7 +92,7 @@
featureSet: unit.featureSet,
library: library,
classNameToken: declaration.name,
- classElement: declaration.declaredElement!,
+ classElement: element,
strictCasts: _strictCasts,
implementsClause: declaration.implementsClause,
members: declaration.members,
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 2a56d3d..d91ed34 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -307,12 +307,13 @@
// TODO(brianwilkerson): Report this error.
return;
}
+ var enclosingAugmented = enclosingClass.augmented;
ConstructorElement? element;
var name = node.constructorName;
if (name == null) {
- element = enclosingClass.unnamedConstructor;
+ element = enclosingAugmented.unnamedConstructor;
} else {
- element = enclosingClass.getNamedConstructor(name.name);
+ element = enclosingAugmented.getNamedConstructor(name.name);
}
if (element == null) {
// TODO(brianwilkerson): Report this error and decide what element to
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index ad20b44..fcc4663 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -640,6 +640,11 @@
var element = node.declaredElement as EnumElementImpl;
var augmented = element.augmented;
+ _checkAugmentations(
+ augmentKeyword: node.augmentKeyword,
+ element: element,
+ );
+
_enclosingClass = element;
_duplicateDefinitionVerifier.checkEnum(node);
@@ -707,6 +712,12 @@
@override
void visitExtensionDeclaration(covariant ExtensionDeclarationImpl node) {
var element = node.declaredElement!;
+
+ _checkAugmentations(
+ augmentKeyword: node.augmentKeyword,
+ element: element,
+ );
+
_enclosingExtension = element;
_duplicateDefinitionVerifier.checkExtension(node);
_checkForConflictingExtensionTypeVariableErrorCodes();
@@ -734,6 +745,12 @@
var element = node.declaredElement!;
var augmented = element.augmented;
var declarationElement = augmented.declaration;
+
+ _checkAugmentations(
+ augmentKeyword: node.augmentKeyword,
+ element: element,
+ );
+
_enclosingClass = declarationElement;
_checkForBuiltInIdentifierAsName(node.name,
@@ -756,12 +773,12 @@
_checkForExtensionTypeImplementsItself(node, element);
_checkForExtensionTypeMemberConflicts(
node: node,
- element: element,
+ element: declarationElement,
);
_checkForExtensionTypeWithAbstractMember(node);
_checkForWrongTypeParameterVarianceInSuperinterfaces();
- var interface = _inheritanceManager.getInterface(element);
+ var interface = _inheritanceManager.getInterface(declarationElement);
GetterSetterTypesVerifier(
typeSystem: typeSystem,
errorReporter: errorReporter,
diff --git a/pkg/analyzer/test/src/diagnostics/augmentation_without_declaration_test.dart b/pkg/analyzer/test/src/diagnostics/augmentation_without_declaration_test.dart
index 3497f75..73eb7fe 100644
--- a/pkg/analyzer/test/src/diagnostics/augmentation_without_declaration_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/augmentation_without_declaration_test.dart
@@ -65,6 +65,24 @@
]);
}
+ test_class_field_static() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+class A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment class A {
+ augment static int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
test_class_getter() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
@@ -83,6 +101,24 @@
]);
}
+ test_class_getter_static() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+class A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment class A {
+ augment static int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
test_class_method() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
@@ -101,6 +137,24 @@
]);
}
+ test_class_method_static() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+class A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment class A {
+ augment static void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
test_class_method_valid() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
@@ -137,6 +191,282 @@
]);
}
+ test_class_setter_static() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+class A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment class A {
+ augment static set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_enum() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
+ ]);
+ }
+
+ test_enum_constructor() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+enum A {v}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {;
+ augment const A.named();
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_enum_field() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+enum A {v}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {;
+ augment final int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_enum_getter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+enum A {v}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {;
+ augment int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_enum_method() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+enum A {v}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {;
+ augment void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_enum_setter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+enum A {v}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment enum A {;
+ augment set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_extension() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension A {}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
+ ]);
+ }
+
+ test_extension_getter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension A on int {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension A {
+ augment int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 51, 7),
+ ]);
+ }
+
+ test_extension_method() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension A on int {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension A {
+ augment void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 51, 7),
+ ]);
+ }
+
+ test_extension_setter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension A on int {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension A {
+ augment set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 51, 7),
+ ]);
+ }
+
+ test_extensionType() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension type A(int it) {}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
+ ]);
+ }
+
+ test_extensionType_constructor() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension type A(int it) {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension type A(int it) {
+ augment A.named() : this(0);
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 64, 7),
+ ]);
+ }
+
+ test_extensionType_getter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension type A(int it) {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension type A(int it) {
+ augment int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 64, 7),
+ ]);
+ }
+
+ test_extensionType_method() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension type A(int it) {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension type A(int it) {
+ augment void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 64, 7),
+ ]);
+ }
+
+ test_extensionType_setter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+extension type A(int it) {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment extension type A(int it) {
+ augment set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 64, 7),
+ ]);
+ }
+
test_mixin() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
@@ -151,6 +481,96 @@
]);
}
+ test_mixin_field() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+mixin A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment mixin A {
+ augment int foo = 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_mixin_getter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+mixin A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment mixin A {
+ augment int get foo => 0;
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_mixin_method() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+mixin A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment mixin A {
+ augment void foo() {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
+ test_mixin_method_valid() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+mixin A {
+ void foo() {}
+}
+''');
+
+ await assertNoErrorsInCode(r'''
+augment library 'a.dart';
+
+augment mixin A {
+ augment void foo() {}
+}
+''');
+ }
+
+ test_mixin_setter() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import augment 'test.dart';
+
+mixin A {}
+''');
+
+ await assertErrorsInCode(r'''
+augment library 'a.dart';
+
+augment mixin A {
+ augment set foo(int _) {}
+}
+''', [
+ error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
+ ]);
+ }
+
test_topLevel_function() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
diff --git a/pkg/linter/lib/src/rules/annotate_redeclares.dart b/pkg/linter/lib/src/rules/annotate_redeclares.dart
index b2c78e5..3b5a8e3 100644
--- a/pkg/linter/lib/src/rules/annotate_redeclares.dart
+++ b/pkg/linter/lib/src/rules/annotate_redeclares.dart
@@ -91,7 +91,8 @@
var element = node.declaredElement;
if (element == null || element.hasRedeclare) return;
- var extensionType = parent.declaredElement;
+ var parentElement = parent.declaredElement;
+ var extensionType = parentElement?.augmented.declaration;
if (extensionType == null) return;
if (_redeclaresMember(element, extensionType)) {
diff --git a/pkg/linter/lib/src/rules/type_annotate_public_apis.dart b/pkg/linter/lib/src/rules/type_annotate_public_apis.dart
index a51c406..76456ee 100644
--- a/pkg/linter/lib/src/rules/type_annotate_public_apis.dart
+++ b/pkg/linter/lib/src/rules/type_annotate_public_apis.dart
@@ -8,6 +8,7 @@
import '../analyzer.dart';
import '../ast.dart';
+import '../extensions.dart';
import '../util/ascii_utils.dart';
const _desc = r'Type annotate public APIs.';
@@ -83,6 +84,8 @@
_Visitor(this.rule) : v = _VisitorHelper(rule);
@override
void visitFieldDeclaration(FieldDeclaration node) {
+ if (node.isAugmentation) return;
+
if (node.fields.type == null) {
node.fields.accept(v);
}
@@ -90,6 +93,8 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
+ if (node.isAugmentation) return;
+
if (!isPrivate(node.name) &&
// Only report on top-level functions, not those declared within the
// scope of another function.
@@ -115,6 +120,8 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
+ if (node.isAugmentation) return;
+
if (!isPrivate(node.name)) {
if (node.returnType == null && !node.isSetter) {
rule.reportLintForToken(node.name);
@@ -126,6 +133,8 @@
@override
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ if (node.isAugmentation) return;
+
if (node.variables.type == null) {
node.variables.accept(v);
}
diff --git a/pkg/linter/test/rules/type_annotate_public_apis_test.dart b/pkg/linter/test/rules/type_annotate_public_apis_test.dart
index 3162867..3282f38 100644
--- a/pkg/linter/test/rules/type_annotate_public_apis_test.dart
+++ b/pkg/linter/test/rules/type_annotate_public_apis_test.dart
@@ -19,6 +19,190 @@
@override
String get lintRule => 'type_annotate_public_apis';
+ test_augmentationClass_field() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+class A { }
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment class A {
+ var i;
+}
+''');
+
+ result = await resolveFile(a.path);
+ await assertNoDiagnosticsIn(errors);
+
+ result = await resolveFile(b.path);
+ await assertDiagnosticsIn(errors, [
+ lint(51, 1),
+ ]);
+ }
+
+ test_augmentationClass_method() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+class A { }
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment class A {
+ void f(x) { }
+}
+''');
+
+ result = await resolveFile(a.path);
+ await assertNoDiagnosticsIn(errors);
+
+ result = await resolveFile(b.path);
+ await assertDiagnosticsIn(errors, [
+ lint(54, 1),
+ ]);
+ }
+
+ test_augmentationTopLevelFunction() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+void f(x) { }
+''');
+
+ result = await resolveFile(a.path);
+ await assertNoDiagnosticsIn(errors);
+
+ result = await resolveFile(b.path);
+ await assertDiagnosticsIn(errors, [
+ lint(34, 1),
+ ]);
+ }
+
+ test_augmentationTopLevelVariable() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+var x;
+''');
+
+ result = await resolveFile(a.path);
+ await assertNoDiagnosticsIn(errors);
+
+ result = await resolveFile(b.path);
+ await assertDiagnosticsIn(errors, [
+ lint(31, 1),
+ ]);
+ }
+
+ test_augmentedField() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+class A {
+ var x;
+}
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment class A {
+ augment var x;
+}
+''');
+
+ result = await resolveFile(a.path);
+ await assertDiagnosticsIn(errors, [
+ lint(42, 1),
+ ]);
+
+ result = await resolveFile(b.path);
+ await assertNoDiagnosticsIn(errors);
+ }
+
+ test_augmentedMethod() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+class A {
+ void f(x) { }
+}
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment class A {
+ augment void f(x) { }
+}
+''');
+
+ result = await resolveFile(a.path);
+ await assertDiagnosticsIn(errors, [
+ lint(45, 1),
+ ]);
+
+ result = await resolveFile(b.path);
+ await assertNoDiagnosticsIn(errors);
+ }
+
+ test_augmentedTopLevelFunction() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+void f(x) { }
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment void f(x) { }
+''');
+
+ result = await resolveFile(a.path);
+ await assertDiagnosticsIn(errors, [
+ lint(33, 1),
+ ]);
+
+ result = await resolveFile(b.path);
+ await assertNoDiagnosticsIn(errors);
+ }
+
+ test_augmentedTopLevelVariable() async {
+ var a = newFile('$testPackageLibPath/a.dart', r'''
+import augment 'b.dart';
+
+var x;
+''');
+
+ var b = newFile('$testPackageLibPath/b.dart', r'''
+augment library 'a.dart';
+
+augment var x;
+''');
+
+ result = await resolveFile(a.path);
+ await assertDiagnosticsIn(errors, [
+ lint(30, 1),
+ ]);
+
+ result = await resolveFile(b.path);
+ await assertNoDiagnosticsIn(errors);
+ }
+
test_instanceField_onClass_hasInitializer() async {
await assertNoDiagnostics(r'''
class A {
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 9910c53..6e5e84d 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -31,6 +31,8 @@
```
See <https://github.com/dart-lang/sdk/issues/52965> for more information.
+- Introduce `TargetKind.optionalParameter`, to indicate that an annotation is
+ valid on any optional parameter declaration.
## 1.14.0
diff --git a/pkg/meta/lib/meta_meta.dart b/pkg/meta/lib/meta_meta.dart
index 58e3c62..f365daf 100644
--- a/pkg/meta/lib/meta_meta.dart
+++ b/pkg/meta/lib/meta_meta.dart
@@ -92,6 +92,12 @@
/// Indicates that an annotation is valid on any mixin declaration.
static const mixinType = TargetKind._('mixins', 'mixinType');
+ /// Indicates that an annotation is valid on any optional formal parameter
+ /// declaration, whether it's in a constructor, function (named or anonymous),
+ /// function type, function-typed formal parameter, or method.
+ static const optionalParameter =
+ TargetKind._('optional parameters', 'optionalParameter');
+
/// Indicates that an annotation is valid on any formal parameter declaration,
/// whether it's in a constructor, function (named or anonymous), function
/// type, function-typed formal parameter, or method.
@@ -138,6 +144,7 @@
getter,
method,
mixinType,
+ optionalParameter,
parameter,
setter,
topLevelVariable,
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index 689c4c0..f2e1b8a 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,7 +1,7 @@
name: meta
# Note, because version `2.0.0` was mistakenly released,
# the next major version must be `3.x.y`.
-version: 1.14.0
+version: 1.15.0-dev
description: >-
Annotations used to express developer intentions that can't otherwise be
deduced by statically analyzing source code.
diff --git a/tools/VERSION b/tools/VERSION
index 091279c..31ba114 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 3
MINOR 5
PATCH 0
-PRERELEASE 102
+PRERELEASE 103
PRERELEASE_PATCH 0