Skip to content

Commit 328bb27

Browse files
scheglovCommit Queue
authored and
Commit Queue
committed
Macro. Report MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE.
Bug: #54915 Change-Id: I0eb2d56b9fc4ad95c41de5681e22d55923845632 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/354382 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com>
1 parent 5f6daed commit 328bb27

File tree

9 files changed

+130
-13
lines changed

9 files changed

+130
-13
lines changed

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,8 @@ CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE:
10341034
status: noFix
10351035
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE:
10361036
status: needsEvaluation
1037+
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE:
1038+
status: noFix
10371039
CompileTimeErrorCode.MACRO_APPLICATION_ARGUMENT_ERROR:
10381040
status: noFix
10391041
CompileTimeErrorCode.MACRO_ERROR:

pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class LibraryAnalyzer {
8585
: _testingData = testingData,
8686
_typeSystemOperations = typeSystemOperations {
8787
_libraryVerificationContext = LibraryVerificationContext(
88+
libraryKind: _library,
8889
constructorFieldsVerifier: ConstructorFieldsVerifier(
8990
typeSystem: _typeSystem,
9091
),

pkg/analyzer/lib/src/dart/analysis/library_graph.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class LibraryCycle {
2626
/// The libraries that belong to this cycle.
2727
final List<LibraryFileKind> libraries;
2828

29+
/// The URIs of [libraries].
30+
final Set<Uri> libraryUris;
31+
2932
/// The library cycles that this cycle references directly.
3033
final Set<LibraryCycle> directDependencies;
3134

@@ -89,6 +92,7 @@ class LibraryCycle {
8992

9093
LibraryCycle({
9194
required this.libraries,
95+
required this.libraryUris,
9296
required this.directDependencies,
9397
required this.apiSignature,
9498
required this.implSignature,
@@ -212,9 +216,11 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
212216

213217
// Fill the cycle with libraries.
214218
var libraries = <LibraryFileKind>[];
219+
var libraryUris = <Uri>{};
215220
for (var node in scc) {
216221
final file = node.kind.file;
217222
libraries.add(node.kind);
223+
libraryUris.add(file.uri);
218224

219225
apiSignature.addLanguageVersion(file.packageLanguageVersion);
220226
apiSignature.addString(file.uriStr);
@@ -241,6 +247,7 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
241247
// Create the LibraryCycle instance for the cycle.
242248
var cycle = LibraryCycle(
243249
libraries: libraries.toFixedList(),
250+
libraryUris: libraryUris,
244251
directDependencies: directDependencies,
245252
apiSignature: apiSignature.toHex(),
246253
implSignature: implSignature.toHex(),

pkg/analyzer/lib/src/error/codes.g.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,18 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
30553055
"Try removing one or more macro applications to break the cycle.",
30563056
);
30573057

3058+
/// Parameters:
3059+
/// 0: the name of the macro class
3060+
static const CompileTimeErrorCode
3061+
MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE = CompileTimeErrorCode(
3062+
'MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE',
3063+
"The macro '{0}' can't be applied in the same library cycle where it is "
3064+
"defined.",
3065+
correctionMessage:
3066+
"Try moving it to a different library that does not import the one "
3067+
"where it is applied.",
3068+
);
3069+
30583070
/// Reported when the macro uses `Builder.report()` with `Severity.error`.
30593071
/// Parameters:
30603072
/// 0: the message

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ const List<ErrorCode> errorCodeValues = [
325325
CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
326326
CompileTimeErrorCode.MACRO_APPLICATION_ARGUMENT_ERROR,
327327
CompileTimeErrorCode.MACRO_DECLARATIONS_PHASE_INTROSPECTION_CYCLE,
328+
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
328329
CompileTimeErrorCode.MACRO_ERROR,
329330
CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION,
330331
CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE,

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
5454
import 'package:analyzer/src/generated/this_access_tracker.dart';
5555
import 'package:analyzer/src/summary2/macro_application_error.dart';
5656
import 'package:analyzer/src/summary2/macro_type_location.dart';
57+
import 'package:analyzer/src/utilities/extensions/element.dart';
5758
import 'package:analyzer/src/utilities/extensions/object.dart';
5859
import 'package:analyzer/src/utilities/extensions/string.dart';
5960
import 'package:collection/collection.dart';
@@ -6113,10 +6114,12 @@ class HiddenElements {
61136114
/// Information to pass from from the defining unit to augmentations.
61146115
class LibraryVerificationContext {
61156116
final duplicationDefinitionContext = DuplicationDefinitionContext();
6117+
final LibraryFileKind libraryKind;
61166118
final ConstructorFieldsVerifier constructorFieldsVerifier;
61176119
final Map<FileState, UnitAnalysis> units;
61186120

61196121
LibraryVerificationContext({
6122+
required this.libraryKind,
61206123
required this.constructorFieldsVerifier,
61216124
required this.units,
61226125
});
@@ -6148,6 +6151,10 @@ class LibraryVerificationContext {
61486151
entity: node,
61496152
);
61506153
}
6154+
6155+
bool libraryCycleContains(Uri uri) {
6156+
return libraryKind.libraryCycle.libraryUris.contains(uri);
6157+
}
61516158
}
61526159

61536160
class _MacroDiagnosticsReporter {
@@ -6162,6 +6169,8 @@ class _MacroDiagnosticsReporter {
61626169
});
61636170

61646171
void report() {
6172+
_reportApplicationFromSameLibraryCycle();
6173+
61656174
for (final diagnostic in element.macroDiagnostics) {
61666175
switch (diagnostic) {
61676176
case ArgumentMacroDiagnostic():
@@ -6182,7 +6191,7 @@ class _MacroDiagnosticsReporter {
61826191
final target = object.target;
61836192
switch (target) {
61846193
case ApplicationMacroDiagnosticTarget():
6185-
final node = _annotationNode(element, target.annotationIndex);
6194+
final node = element.annotationAst(target.annotationIndex);
61866195
return DiagnosticMessageImpl(
61876196
filePath: element.source!.fullName,
61886197
length: node.length,
@@ -6208,8 +6217,30 @@ class _MacroDiagnosticsReporter {
62086217
}
62096218
}
62106219

6220+
void _reportApplicationFromSameLibraryCycle() {
6221+
for (var annotation in element.metadata) {
6222+
var element = annotation.element;
6223+
if (element is! ConstructorElementImpl) continue;
6224+
6225+
var macroElement = element.enclosingElement;
6226+
if (macroElement is! ClassElementImpl) continue;
6227+
if (!macroElement.isMacro) continue;
6228+
6229+
var macroUri = macroElement.library.source.uri;
6230+
if (!libraryContext.libraryCycleContains(macroUri)) continue;
6231+
6232+
errorReporter.atNode(
6233+
_annotationNameIdentifier(annotation),
6234+
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
6235+
arguments: [
6236+
macroElement.name,
6237+
],
6238+
);
6239+
}
6240+
}
6241+
62116242
void _reportArgument(ArgumentMacroDiagnostic diagnostic) {
6212-
var annotation = _annotationNode(element, diagnostic.annotationIndex);
6243+
var annotation = element.annotationAst(diagnostic.annotationIndex);
62136244
var arguments = annotation.arguments!.arguments;
62146245
errorReporter.atNode(
62156246
arguments[diagnostic.argumentIndex],
@@ -6231,7 +6262,7 @@ class _MacroDiagnosticsReporter {
62316262
final target = diagnostic.message.target;
62326263
switch (target) {
62336264
case ApplicationMacroDiagnosticTarget():
6234-
var node = _annotationNode(element, target.annotationIndex);
6265+
var node = element.annotationAst(target.annotationIndex);
62356266
errorReporter.reportError(
62366267
AnalysisError.forValues(
62376268
source: element.source!,
@@ -6262,10 +6293,7 @@ class _MacroDiagnosticsReporter {
62626293
if (location == null) {
62636294
return;
62646295
}
6265-
var node = _annotationNode(
6266-
target.element,
6267-
target.annotationIndex,
6268-
);
6296+
var node = target.element.annotationAst(target.annotationIndex);
62696297
location.unitAnalysis.errorReporter.reportError(
62706298
AnalysisError.forValues(
62716299
source: target.element.source!,
@@ -6301,7 +6329,7 @@ class _MacroDiagnosticsReporter {
63016329

63026330
void _reportException(ExceptionMacroDiagnostic diagnostic) {
63036331
errorReporter.atNode(
6304-
_annotationNode(element, diagnostic.annotationIndex),
6332+
element.annotationAst(diagnostic.annotationIndex),
63056333
CompileTimeErrorCode.MACRO_INTERNAL_EXCEPTION,
63066334
arguments: [
63076335
diagnostic.message,
@@ -6343,24 +6371,30 @@ class _MacroDiagnosticsReporter {
63436371

63446372
void _reportInvalidTarget(InvalidMacroTargetDiagnostic diagnostic) {
63456373
errorReporter.atNode(
6346-
_annotationNode(element, diagnostic.annotationIndex),
6374+
element.annotationAst(diagnostic.annotationIndex),
63476375
CompileTimeErrorCode.INVALID_MACRO_APPLICATION_TARGET,
63486376
arguments: [
63496377
diagnostic.supportedKinds.commaSeparatedWithOr,
63506378
],
63516379
);
63526380
}
63536381

6354-
static AnnotationImpl _annotationNode(ElementImpl element, int index) {
6355-
var annotation = element.metadata[index];
6356-
return annotation.annotationAst;
6382+
static SimpleIdentifier _annotationNameIdentifier(
6383+
ElementAnnotationImpl annotation,
6384+
) {
6385+
var fullName = annotation.annotationAst.name;
6386+
if (fullName is PrefixedIdentifierImpl) {
6387+
return fullName.identifier;
6388+
} else {
6389+
return fullName as SimpleIdentifierImpl;
6390+
}
63576391
}
63586392

63596393
static SimpleIdentifier _macroAnnotationNameIdentifier({
63606394
required ElementImpl element,
63616395
required int annotationIndex,
63626396
}) {
6363-
var annotationNode = _annotationNode(element, annotationIndex);
6397+
var annotationNode = element.annotationAst(annotationIndex);
63646398
var fullName = annotationNode.name;
63656399
if (fullName is PrefixedIdentifierImpl) {
63666400
return fullName.identifier;

pkg/analyzer/lib/src/utilities/extensions/element.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:analyzer/dart/element/element.dart';
66
import 'package:analyzer/dart/element/nullability_suffix.dart';
77
import 'package:analyzer/dart/element/type.dart';
8+
import 'package:analyzer/src/dart/ast/ast.dart';
89
import 'package:analyzer/src/dart/element/element.dart';
910

1011
extension ElementExtension on Element {
@@ -27,6 +28,12 @@ extension ElementExtension on Element {
2728
}
2829
}
2930

31+
extension ElementImplExtension on ElementImpl {
32+
AnnotationImpl annotationAst(int index) {
33+
return metadata[index].annotationAst;
34+
}
35+
}
36+
3037
extension ListOfTypeParameterElementExtension on List<TypeParameterElement> {
3138
List<TypeParameterType> instantiateNone() {
3239
return map((e) {

pkg/analyzer/messages.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9550,6 +9550,12 @@ CompileTimeErrorCode:
95509550
comment: |-
95519551
Parameters:
95529552
0: the name of the introspected declaration
9553+
MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE:
9554+
problemMessage: "The macro '{0}' can't be applied in the same library cycle where it is defined."
9555+
correctionMessage: Try moving it to a different library that does not import the one where it is applied.
9556+
comment: |-
9557+
Parameters:
9558+
0: the name of the macro class
95539559
MAIN_FIRST_POSITIONAL_PARAMETER_TYPE:
95549560
problemMessage: "The type of the first positional parameter of the 'main' function must be a supertype of 'List<String>'."
95559561
correctionMessage: Try changing the type of the parameter.

pkg/analyzer/test/src/dart/resolution/macro_test.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,53 @@ class A3 {}
248248
]);
249249
}
250250

251+
test_diagnostic_definitionApplication_sameLibrary() async {
252+
await assertErrorsInCode('''
253+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
254+
255+
macro class MyMacro implements ClassDefinitionMacro {
256+
const MyMacro();
257+
258+
@override
259+
buildDefinitionForClass(declaration, builder) async {}
260+
}
261+
262+
@MyMacro()
263+
class A {}
264+
''', [
265+
error(
266+
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
267+
206,
268+
7),
269+
]);
270+
}
271+
272+
test_diagnostic_definitionApplication_sameLibraryCycle() async {
273+
newFile('$testPackageLibPath/a.dart', r'''
274+
import 'package:_fe_analyzer_shared/src/macros/api.dart';
275+
import 'test.dart';
276+
277+
macro class MyMacro implements ClassDefinitionMacro {
278+
const MyMacro();
279+
280+
@override
281+
buildDefinitionForClass(declaration, builder) async {}
282+
}
283+
''');
284+
285+
await assertErrorsInCode('''
286+
import 'a.dart';
287+
288+
@MyMacro()
289+
class A {}
290+
''', [
291+
error(
292+
CompileTimeErrorCode.MACRO_DEFINITION_APPLICATION_SAME_LIBRARY_CYCLE,
293+
19,
294+
7),
295+
]);
296+
}
297+
251298
test_diagnostic_invalidTarget_wantsClassOrMixin_hasFunction() async {
252299
await assertErrorsInCode('''
253300
import 'diagnostic.dart';

0 commit comments

Comments
 (0)