[cfe] Report errors on macro declaration/annotation in the same library cycle

Change-Id: Ia8b7b572f8947e7b82f3468331cd33e430ef8376
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/356060
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2024-03-07 09:10:07 +00:00 committed by Commit Queue
parent 170e014e67
commit 9293d2fc33
22 changed files with 486 additions and 30 deletions

View file

@ -11451,6 +11451,41 @@ Message _withArgumentsMacroClassNotDeclaredMacro(String name) {
);
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateMacroDefinitionApplicationSameLibraryCycle =
const Template<Message Function(String name)>(
"MacroDefinitionApplicationSameLibraryCycle",
problemMessageTemplate:
r"""The macro '#name' can't be applied in the same library cycle where it is defined.""",
correctionMessageTemplate:
r"""Try moving it to a different library that does not import the one where it is applied.""",
withArguments: _withArgumentsMacroDefinitionApplicationSameLibraryCycle,
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)>
codeMacroDefinitionApplicationSameLibraryCycle =
const Code<Message Function(String name)>(
"MacroDefinitionApplicationSameLibraryCycle",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsMacroDefinitionApplicationSameLibraryCycle(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(
codeMacroDefinitionApplicationSameLibraryCycle,
problemMessage:
"""The macro '${name}' can't be applied in the same library cycle where it is defined.""",
correctionMessage:
"""Try moving it to a different library that does not import the one where it is applied.""",
arguments: {
'name': name,
},
);
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMainNotFunctionDeclaration =
messageMainNotFunctionDeclaration;

View file

@ -25,7 +25,8 @@ List<MacroApplication>? prebuildAnnotations(
{required SourceLibraryBuilder enclosingLibrary,
required List<MetadataBuilder>? metadataBuilders,
required Uri fileUri,
required Scope scope}) {
required Scope scope,
required Set<ClassBuilder> currentMacroDeclarations}) {
if (metadataBuilders == null) return null;
List<MacroApplication>? result;
for (MetadataBuilder metadataBuilder in metadataBuilders) {
@ -38,7 +39,20 @@ List<MacroApplication>? prebuildAnnotations(
MacroApplication? application = listener.popMacroApplication();
if (application != null) {
result ??= [];
result.add(application);
if (currentMacroDeclarations.contains(application.classBuilder)) {
ClassBuilder classBuilder = application.classBuilder;
UriOffset uriOffset = application.uriOffset;
enclosingLibrary.addProblem(
templateMacroDefinitionApplicationSameLibraryCycle
.withArguments(classBuilder.name),
uriOffset.fileOffset,
noLength,
uriOffset.uri);
result.add(
new MacroApplication.invalid(classBuilder, uriOffset: uriOffset));
} else {
result.add(application);
}
}
}
if (result != null && result.length > 1) {
@ -217,7 +231,7 @@ class _MacroListener implements Listener {
}
} else {
if (_macroClassBuilder != null && _unhandledReason != null) {
_erroneousMacroApplication = new MacroApplication.error(
_erroneousMacroApplication = new MacroApplication.unhandled(
_unhandledReason!, _macroClassBuilder!,
uriOffset: new UriOffset(uri, beginToken.next!.charOffset));
}

View file

@ -53,18 +53,36 @@ class MacroApplication {
final ClassBuilder classBuilder;
final String constructorName;
final macro.Arguments arguments;
final String? errorReason;
final bool isErroneous;
final String? unhandledReason;
/// Creates a [MacroApplication] for a macro annotation that should be
/// applied.
MacroApplication(this.classBuilder, this.constructorName, this.arguments,
{required this.uriOffset})
: errorReason = null;
: isErroneous = false,
unhandledReason = null;
MacroApplication.error(String this.errorReason, this.classBuilder,
/// Creates an erroneous [MacroApplication] for a macro annotation using
/// syntax that is not unhandled.
// TODO(johnniwinther): Separate this into unhandled (but valid) and
// unsupported (thus invalid) annotations.
MacroApplication.unhandled(String this.unhandledReason, this.classBuilder,
{required this.uriOffset})
: constructorName = '',
: isErroneous = true,
constructorName = '',
arguments = new macro.Arguments(const [], const {});
bool get isErroneous => errorReason != null;
/// Creates an erroneous [MacroApplication] for an invalid macro application
/// for which an error has been reported, which should _not_ be applied. For
/// instance a macro annotation of a macro declared in the same library cycle.
MacroApplication.invalid(this.classBuilder, {required this.uriOffset})
: constructorName = '',
isErroneous = true,
unhandledReason = null,
arguments = new macro.Arguments(const [], const {});
bool get isUnhandled => unhandledReason != null;
late macro.MacroInstanceIdentifier instanceIdentifier;
late Set<macro.Phase> phasesToExecute;
@ -245,10 +263,10 @@ void checkMacroApplications(
MacroApplication? macroApplication =
applications?.remove(annotation.fileOffset);
if (macroApplication != null) {
if (macroApplication.isErroneous) {
if (macroApplication.isUnhandled) {
libraryBuilder.addProblem(
templateUnhandledMacroApplication
.withArguments(macroApplication.errorReason!),
.withArguments(macroApplication.unhandledReason!),
annotation.fileOffset,
noLength,
fileUri);
@ -350,14 +368,17 @@ class MacroApplications {
bool get hasLoadableMacroIds => _pendingLibraryData.isNotEmpty;
void computeLibrariesMacroApplicationData(
Iterable<SourceLibraryBuilder> libraryBuilders) {
Iterable<SourceLibraryBuilder> libraryBuilders,
Set<ClassBuilder> currentMacroDeclarations) {
for (SourceLibraryBuilder libraryBuilder in libraryBuilders) {
_computeSourceLibraryMacroApplicationData(libraryBuilder);
_computeSourceLibraryMacroApplicationData(
libraryBuilder, currentMacroDeclarations);
}
}
void _computeSourceLibraryMacroApplicationData(
SourceLibraryBuilder libraryBuilder) {
SourceLibraryBuilder libraryBuilder,
Set<ClassBuilder> currentMacroDeclarations) {
// TODO(johnniwinther): Handle augmentation libraries.
LibraryMacroApplicationData libraryMacroApplicationData =
new LibraryMacroApplicationData();
@ -366,7 +387,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: libraryBuilder.scope,
fileUri: libraryBuilder.fileUri,
metadataBuilders: libraryBuilder.metadata);
metadataBuilders: libraryBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (libraryMacroApplications != null) {
libraryMacroApplicationData.libraryApplications =
new LibraryApplicationData(
@ -384,7 +406,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: classBuilder.fileUri,
metadataBuilders: classBuilder.metadata);
metadataBuilders: classBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (classMacroApplications != null) {
classMacroApplicationData.classApplications =
new ClassApplicationData(_macroIntrospection, libraryBuilder,
@ -398,7 +421,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
metadataBuilders: memberBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,
@ -409,7 +433,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
metadataBuilders: memberBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,
@ -429,7 +454,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
metadataBuilders: memberBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,
@ -440,7 +466,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: classBuilder.scope,
fileUri: memberBuilder.fileUri,
metadataBuilders: memberBuilder.metadata);
metadataBuilders: memberBuilder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
classMacroApplicationData.memberApplications[memberBuilder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,
@ -462,7 +489,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: libraryBuilder.scope,
fileUri: builder.fileUri,
metadataBuilders: builder.metadata);
metadataBuilders: builder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,
@ -473,7 +501,8 @@ class MacroApplications {
enclosingLibrary: libraryBuilder,
scope: libraryBuilder.scope,
fileUri: builder.fileUri,
metadataBuilders: builder.metadata);
metadataBuilders: builder.metadata,
currentMacroDeclarations: currentMacroDeclarations);
if (macroApplications != null) {
libraryMacroApplicationData.memberApplications[builder] =
new MemberApplicationData(_macroIntrospection, libraryBuilder,

View file

@ -217,6 +217,9 @@ class SourceLoader extends Loader {
ClassBuilder? _macroClassBuilder;
/// The macro declarations that are currently being compiled.
Set<ClassBuilder> _macroDeclarations = {};
SourceLoader(this.fileSystem, this.includeComments, this.target)
: dataForTesting =
retainDataForTesting ? new SourceLoaderDataForTesting() : null;
@ -1544,10 +1547,12 @@ severity: $severity
ClassBuilder builder = iterator.current;
if (builder.isMacro) {
Uri libraryUri = builder.libraryBuilder.importUri;
if (!target.context.options.runningPrecompilations
.contains(libraryUri) &&
!target.context.options.macroExecutor
.libraryIsRegistered(libraryUri)) {
if (target.context.options.runningPrecompilations
.contains(libraryUri)) {
// We are explicitly compiling this macro.
_macroDeclarations.add(builder);
} else if (!target.context.options.macroExecutor
.libraryIsRegistered(libraryUri)) {
(macroLibraries[libraryUri] ??= []).add(builder);
if (retainDataForTesting) {
(dataForTesting!.macroDeclarationData
@ -1681,11 +1686,22 @@ severity: $severity
// We have found the first needed layer of precompilation. There might
// be more layers but we'll compute these at the next attempt at
// compilation, when this layer has been precompiled.
// TODO(johnniwinther): Use this to trigger a precompile step.
return new NeededPrecompilations(neededPrecompilations);
}
}
}
if (compilationSteps.isNotEmpty) {
for (List<Uri> compilationStep in compilationSteps) {
for (Uri uri in compilationStep) {
List<ClassBuilder>? macroClasses = macroLibraries[uri];
if (macroClasses != null) {
// These macros are to be compiled during this (last) compilation
// step.
_macroDeclarations.addAll(macroClasses);
}
}
}
}
return null;
}
@ -1700,8 +1716,8 @@ severity: $severity
this,
target.context.options.macroExecutor,
dataForTesting?.macroApplicationData);
macroApplications
.computeLibrariesMacroApplicationData(sourceLibraryBuilders);
macroApplications.computeLibrariesMacroApplicationData(
sourceLibraryBuilders, _macroDeclarations);
if (macroApplications.hasLoadableMacroIds) {
target.benchmarker?.beginSubdivide(
BenchmarkSubdivides.computeMacroApplications_macroExecutorProvider);
@ -1715,8 +1731,8 @@ severity: $severity
Future<void> computeAdditionalMacroApplications(
MacroApplications macroApplications,
Iterable<SourceLibraryBuilder> sourceLibraryBuilders) async {
macroApplications
.computeLibrariesMacroApplicationData(sourceLibraryBuilders);
macroApplications.computeLibrariesMacroApplicationData(
sourceLibraryBuilders, _macroDeclarations);
if (macroApplications.hasLoadableMacroIds) {
target.benchmarker?.beginSubdivide(
BenchmarkSubdivides.computeMacroApplications_macroExecutorProvider);

View file

@ -711,6 +711,8 @@ ListLiteralTooManyTypeArguments/example: Fail
LoadLibraryTakesNoArguments/example: Fail
MacroClassNotDeclaredMacro/analyzerCode: Fail
MacroClassNotDeclaredMacro/example: Fail
MacroDefinitionApplicationSameLibraryCycle/analyzerCode: Fail
MacroDefinitionApplicationSameLibraryCycle/example: Fail
MainNotFunctionDeclaration/analyzerCode: Fail
MainNotFunctionDeclarationExported/analyzerCode: Fail
MainNotFunctionDeclarationExported/part_wrapped_script: Fail

View file

@ -7581,3 +7581,7 @@ InvalidMacroApplicationTarget:
NoMacroApplicationTarget:
problemMessage: "The macro can not be applied to this declaration."
MacroDefinitionApplicationSameLibraryCycle:
problemMessage: "The macro '#name' can't be applied in the same library cycle where it is defined."
correctionMessage: Try moving it to a different library that does not import the one where it is applied.

View file

@ -0,0 +1,37 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:8:2: Error: The macro 'Macro' can't be applied in the same library cycle where it is defined.
// Try moving it to a different library that does not import the one where it is applied.
// @Macro() // Error
// ^
//
import self as self;
import "main_lib.dart" as mai;
import "dart:async";
import "org-dartlang-test:///a/b/c/main_lib.dart";
@#C1
static method method() → dynamic {}
library;
import self as mai;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
import "org-dartlang-test:///a/b/c/main.dart";
macro class Macro extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → mai::Macro
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
constants {
#C1 = mai::Macro {}
}

View file

@ -0,0 +1,9 @@
// 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 'dart:async';
import 'main_lib.dart';
@Macro() // Error
method() {}

View file

@ -0,0 +1,14 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'main.dart';
macro class Macro implements FunctionDeclarationsMacro {
const Macro();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}

View file

@ -0,0 +1,56 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:9:2: Error: The macro 'Macro1' can't be applied in the same library cycle where it is defined.
// Try moving it to a different library that does not import the one where it is applied.
// @Macro1() // Error
// ^
//
import self as self;
import "main_lib1.dart" as mai;
import "main_lib2.dart" as mai2;
import "dart:async";
import "org-dartlang-test:///a/b/c/main_lib1.dart";
import "org-dartlang-test:///a/b/c/main_lib2.dart";
@#C1
@#C2
static method method() → dynamic {}
library;
import self as mai;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
import "org-dartlang-test:///a/b/c/main.dart";
macro class Macro1 extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → mai::Macro1
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
library;
import self as mai2;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
macro class Macro2 extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → mai2::Macro2
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
constants {
#C1 = mai::Macro1 {}
#C2 = mai2::Macro2 {}
}

View file

@ -0,0 +1,15 @@
// 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.
/*library:
Declarations Order:
method:Macro2.new()*/
import 'dart:async';
import 'main_lib1.dart';
import 'main_lib2.dart';
@Macro1() // Error
@Macro2() // Ok
method() {}

View file

@ -0,0 +1,14 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'main.dart';
macro class Macro1 implements FunctionDeclarationsMacro {
const Macro1();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}

View file

@ -0,0 +1,13 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class Macro2 implements FunctionDeclarationsMacro {
const Macro2();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}

View file

@ -0,0 +1,56 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:8:2: Error: The macro 'Macro1' can't be applied in the same library cycle where it is defined.
// Try moving it to a different library that does not import the one where it is applied.
// @Macro1() // Error
// ^
//
import self as self;
import "main_lib1.dart" as mai;
import "dart:async";
import "org-dartlang-test:///a/b/c/main_lib1.dart";
@#C1
static method method() → dynamic {}
library;
import self as mai;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "main_lib2.dart" as mai2;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
import "org-dartlang-test:///a/b/c/main.dart";
import "org-dartlang-test:///a/b/c/main_lib2.dart";
macro class Macro1 extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → mai::Macro1
: super core::Object::•()
;
@#C2
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
library;
import self as mai2;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
macro class Macro2 extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → mai2::Macro2
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
constants {
#C1 = mai::Macro1 {}
#C2 = mai2::Macro2 {}
}

View file

@ -0,0 +1,13 @@
// 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.
/*library:
Declarations Order:
Macro1.buildDeclarationsForFunction:Macro2.new()*/
import 'dart:async';
import 'main_lib1.dart';
@Macro1() // Error
method() {}

View file

@ -0,0 +1,16 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'main.dart';
import 'main_lib2.dart';
macro class Macro1 implements FunctionDeclarationsMacro {
const Macro1();
@Macro2() // Ok
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}

View file

@ -0,0 +1,13 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class Macro2 implements FunctionDeclarationsMacro {
const Macro2();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}

View file

@ -0,0 +1,28 @@
library;
import self as self;
import "dart:async";
import "org-dartlang-test:///a/b/c/main_lib.dart";
static method method() → dynamic {}
library;
import self as self2;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
macro class Macro extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → self2::Macro
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
@#C1
static method method() → dynamic {}
constants {
#C1 = self2::Macro {}
}

View file

@ -0,0 +1,12 @@
// 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.
/*library:
Declarations Order:
method:Macro.new()*/
import 'dart:async';
import 'main_lib.dart';
method() {}

View file

@ -0,0 +1,16 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class Macro implements FunctionDeclarationsMacro {
const Macro();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}
@Macro() // Error
method() {}

View file

@ -0,0 +1,16 @@
// 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 'dart:async';
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class Macro implements FunctionDeclarationsMacro {
const Macro();
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder) {}
}
@Macro() // Error
method() {}

View file

@ -0,0 +1,28 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:15:2: Error: The macro 'Macro' can't be applied in the same library cycle where it is defined.
// Try moving it to a different library that does not import the one where it is applied.
// @Macro() // Error
// ^
//
import self as self;
import "dart:core" as core;
import "package:_fe_analyzer_shared/src/macros/api.dart" as api;
import "dart:async";
import "package:_fe_analyzer_shared/src/macros/api.dart";
macro class Macro extends core::Object implements api::FunctionDeclarationsMacro /*hasConstConstructor*/ {
const constructor •() → self::Macro
: super core::Object::•()
;
method buildDeclarationsForFunction(api::FunctionDeclaration function, api::DeclarationBuilder builder) → FutureOr<void> {}
}
@#C1
static method method() → dynamic {}
constants {
#C1 = self::Macro {}
}