Augment. Issue 55295. Report AUGMENTATION_WITHOUT_DECLARATION.
Bug: https://github.com/dart-lang/sdk/issues/55295 Change-Id: I50811e1ccd7a2be0e71b18eefa9ecb76ac1aef73 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/359961 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
Commit Queue
parent
dbcf24cedb
commit
3bf33b667c
@@ -209,6 +209,8 @@ CompileTimeErrorCode.ASSIGNMENT_TO_TYPE:
|
||||
status: noFix
|
||||
CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT:
|
||||
status: hasFix
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION:
|
||||
status: noFix
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_IMPORT:
|
||||
status: needsFix
|
||||
notes: |-
|
||||
|
||||
@@ -214,6 +214,14 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode AUGMENTATION_WITHOUT_DECLARATION =
|
||||
CompileTimeErrorCode(
|
||||
'AUGMENTATION_WITHOUT_DECLARATION',
|
||||
"The declaration being augmented doesn't exist.",
|
||||
correctionMessage:
|
||||
"Try changing the augmentation to match an existing declaration.",
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode AUGMENTATION_WITHOUT_IMPORT =
|
||||
CompileTimeErrorCode(
|
||||
'AUGMENTATION_WITHOUT_IMPORT',
|
||||
|
||||
@@ -64,6 +64,7 @@ const List<ErrorCode> errorCodeValues = [
|
||||
CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
|
||||
CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
|
||||
CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT,
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION,
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_IMPORT,
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_LIBRARY,
|
||||
CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER,
|
||||
|
||||
@@ -439,6 +439,12 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
void visitClassDeclaration(covariant ClassDeclarationImpl node) {
|
||||
try {
|
||||
final element = node.declaredElement!;
|
||||
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
|
||||
final augmented = element.augmented;
|
||||
if (augmented == null) {
|
||||
return;
|
||||
@@ -570,6 +576,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
}
|
||||
_checkForUndefinedConstructorInInitializerImplicit(node);
|
||||
_checkForReturnInGenerativeConstructor(node);
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
_reportMacroDiagnostics(element);
|
||||
super.visitConstructorDeclaration(node);
|
||||
});
|
||||
@@ -781,9 +791,13 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
_checkForNonFinalFieldInEnum(node);
|
||||
|
||||
for (final field in fields.variables) {
|
||||
if (field.declaredElement case final FieldElementImpl element) {
|
||||
_reportMacroDiagnostics(element);
|
||||
}
|
||||
var element = field.declaredElement;
|
||||
element as FieldElementImpl;
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
_reportMacroDiagnostics(element);
|
||||
}
|
||||
|
||||
super.visitFieldDeclaration(node);
|
||||
@@ -867,6 +881,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
_returnTypeVerifier.verifyReturnType(returnType);
|
||||
_checkForMainFunction1(node.name, node.declaredElement!);
|
||||
_checkForMainFunction2(node);
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
_reportMacroDiagnostics(element);
|
||||
super.visitFunctionDeclaration(node);
|
||||
});
|
||||
@@ -1068,6 +1086,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
_checkForTypeAnnotationDeferredClass(returnType);
|
||||
_returnTypeVerifier.verifyReturnType(returnType);
|
||||
_checkForWrongTypeParameterVarianceInMethod(node);
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
_reportMacroDiagnostics(element);
|
||||
super.visitMethodDeclaration(node);
|
||||
});
|
||||
@@ -1097,6 +1119,12 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
// TODO(scheglov): Verify for all mixin errors.
|
||||
try {
|
||||
final element = node.declaredElement!;
|
||||
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
|
||||
final augmented = element.augmented;
|
||||
if (augmented == null) {
|
||||
return;
|
||||
@@ -1425,14 +1453,14 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
_checkForNotInitializedNonNullableVariable(node.variables, true);
|
||||
|
||||
for (var variable in node.variables.variables) {
|
||||
_checkForMainFunction1(variable.name, variable.declaredElement!);
|
||||
}
|
||||
|
||||
for (final variable in node.variables.variables) {
|
||||
var element = variable.declaredElement;
|
||||
if (element is TopLevelVariableElementImpl) {
|
||||
_reportMacroDiagnostics(element);
|
||||
}
|
||||
element as TopLevelVariableElementImpl;
|
||||
_checkForMainFunction1(variable.name, element);
|
||||
_checkAugmentations(
|
||||
augmentKeyword: node.augmentKeyword,
|
||||
element: element,
|
||||
);
|
||||
_reportMacroDiagnostics(element);
|
||||
}
|
||||
|
||||
super.visitTopLevelVariableDeclaration(node);
|
||||
@@ -1507,6 +1535,26 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
_isInLateLocalVariable.removeLast();
|
||||
}
|
||||
|
||||
void _checkAugmentations<T extends ElementImpl>({
|
||||
required Token? augmentKeyword,
|
||||
required T element,
|
||||
}) {
|
||||
if (augmentKeyword == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (element is AugmentableElement<T>) {
|
||||
var augmentationTarget = element.augmentationTarget;
|
||||
if (augmentationTarget == null) {
|
||||
errorReporter.atToken(
|
||||
augmentKeyword,
|
||||
CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks the class for problems with the superclass, mixins, or implemented
|
||||
/// interfaces.
|
||||
///
|
||||
|
||||
@@ -1109,6 +1109,9 @@ CompileTimeErrorCode:
|
||||
}
|
||||
}
|
||||
```
|
||||
AUGMENTATION_WITHOUT_DECLARATION:
|
||||
problemMessage: The declaration being augmented doesn't exist.
|
||||
correctionMessage: Try changing the augmentation to match an existing declaration.
|
||||
AUGMENTATION_WITHOUT_IMPORT:
|
||||
problemMessage: The library does not import this augmentation.
|
||||
correctionMessage: Try updating the augmented library to import this augmentation.
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
// Copyright (c) 2024, 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:analyzer/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(AugmentationWithoutDeclarationTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class AugmentationWithoutDeclarationTest extends PubPackageResolutionTest {
|
||||
test_class() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_constructor() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment A.named();
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_field() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment int foo = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_getter() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment int get foo => 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_method() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment void foo() {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_method_valid() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {
|
||||
void foo() {}
|
||||
}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment void foo() {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_setter() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment class A {
|
||||
augment set foo(int _) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 47, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment mixin A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_topLevel_function() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment void foo() {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_topLevel_function_valid() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
|
||||
void foo() {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment void foo() {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_topLevel_getter() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment int get foo => 0;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_topLevel_setter() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment set foo(int _) {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_topLevel_variable() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
import augment 'test.dart';
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
library augment 'a.dart';
|
||||
|
||||
augment int foo = 0;
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AUGMENTATION_WITHOUT_DECLARATION, 27, 7),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,8 @@ import 'assignment_to_type_test.dart' as assignment_to_type;
|
||||
import 'async_for_in_wrong_context_test.dart' as async_for_in_wrong_context;
|
||||
import 'async_keyword_used_as_identifier_test.dart'
|
||||
as async_keyword_used_as_identifier;
|
||||
import 'augmentation_without_declaration_test.dart'
|
||||
as augmentation_without_declaration;
|
||||
import 'await_in_late_local_variable_initializer_test.dart'
|
||||
as await_in_late_local_variable_initializer;
|
||||
import 'await_in_wrong_context_test.dart' as await_in_wrong_context;
|
||||
@@ -929,6 +931,7 @@ main() {
|
||||
assignment_to_type.main();
|
||||
async_for_in_wrong_context.main();
|
||||
async_keyword_used_as_identifier.main();
|
||||
augmentation_without_declaration.main();
|
||||
await_in_late_local_variable_initializer.main();
|
||||
await_in_wrong_context.main();
|
||||
await_of_incompatible_type.main();
|
||||
|
||||
Reference in New Issue
Block a user