[cfe] Show when syntax was unhandled in the error message

This updates the error reporting on incorrectly applied macro
application to show if an unimplemented for syntax was the cause.

This is to help identify when macro tests fail due to missing
implementation.

The CL includes handling of simple list literals in macro
annotations, an issue brought up this kind of error.

Change-Id: I4b6f9f7140c7bc000cfec54acbc6bbfeaf3429a2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345662
Reviewed-by: Morgan :) <davidmorgan@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2024-01-11 15:02:29 +00:00 committed by Commit Queue
parent 4f77ee4b88
commit a866d22f5e
11 changed files with 409 additions and 116 deletions

View file

@ -14264,6 +14264,32 @@ const MessageCode messageUnexpectedTokens = const MessageCode(
index: 123,
problemMessage: r"""Unexpected tokens.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String
name)> templateUnhandledMacroApplication = const Template<
Message Function(String name)>("UnhandledMacroApplication",
problemMessageTemplate:
r"""This macro application didn't apply correctly due to an unhandled #name.""",
withArguments: _withArgumentsUnhandledMacroApplication);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeUnhandledMacroApplication =
const Code<Message Function(String name)>(
"UnhandledMacroApplication",
);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsUnhandledMacroApplication(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeUnhandledMacroApplication,
problemMessage:
"""This macro application didn't apply correctly due to an unhandled ${name}.""",
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(

View file

@ -89,12 +89,12 @@ class _ArgumentsNode implements _Node {
_ArgumentsNode(this.positionalArguments, this.namedArguments);
}
class _PrimitiveValueNode implements _Node {
class _MacroArgumentNode implements _Node {
Object? get value => argument.value;
final macro.Argument argument;
_PrimitiveValueNode(this.argument);
_MacroArgumentNode(this.argument);
}
class _TokenNode implements _Node {
@ -119,6 +119,8 @@ class _NamedArgumentNode implements _Node {
}
class _MacroListener implements Listener {
ClassBuilder? _macroClassBuilder;
final SourceLibraryBuilder currentLibrary;
@override
@ -141,6 +143,19 @@ class _MacroListener implements Listener {
}
}
String? _unhandledReason;
String? get unhandled => _unhandledReason;
void set unhandled(String? value) {
if (value != null) {
_unhandledReason ??= value;
}
unrecognized = true;
}
MacroApplication? _erroneousMacroApplication;
_MacroListener(this.currentLibrary, this.uri, this.scope);
void pushUnsupported() {
@ -155,13 +170,13 @@ class _MacroListener implements Listener {
_Node pop() => _stack.removeLast();
MacroApplication? popMacroApplication() {
if (unrecognized) return null;
if (_stack.length != 1) return null;
if (unrecognized) return _erroneousMacroApplication;
if (_stack.length != 1) return _erroneousMacroApplication;
_Node node = pop();
if (node is _MacroApplicationNode) {
return node.application;
}
return null;
return _erroneousMacroApplication;
}
@override
@ -199,6 +214,12 @@ class _MacroListener implements Listener {
fileOffset: beginToken.next!.charOffset)));
return;
}
} else {
if (_macroClassBuilder != null && _unhandledReason != null) {
_erroneousMacroApplication = new MacroApplication.error(
_unhandledReason!, _macroClassBuilder!,
fileOffset: beginToken.next!.charOffset);
}
}
pushUnsupported();
}
@ -209,6 +230,7 @@ class _MacroListener implements Listener {
case IdentifierContext.metadataReference:
Builder? builder = scope.lookup(token.lexeme, token.charOffset, uri);
if (builder is ClassBuilder && builder.isMacro) {
_macroClassBuilder ??= builder;
push(new _MacroClassNode(token, builder));
} else if (builder is PrefixBuilder) {
push(new _PrefixNode(builder));
@ -222,6 +244,7 @@ class _MacroListener implements Listener {
Builder? builder =
node.prefixBuilder.lookup(token.lexeme, token.charOffset, uri);
if (builder is ClassBuilder && builder.isMacro) {
_macroClassBuilder ??= builder;
push(new _MacroClassNode(token, builder));
} else {
pushUnsupported();
@ -276,7 +299,7 @@ class _MacroListener implements Listener {
Map<String, macro.Argument> namedArguments = {};
for (int i = 0; i < count; i++) {
_Node node = pop();
if (node is _PrimitiveValueNode) {
if (node is _MacroArgumentNode) {
positionalArguments.add(node.argument);
} else if (node is _NamedArgumentNode &&
!namedArguments.containsKey(node.name)) {
@ -288,7 +311,8 @@ class _MacroListener implements Listener {
if (unrecognized) {
pushUnsupported();
} else {
push(new _ArgumentsNode(positionalArguments, namedArguments));
push(new _ArgumentsNode(
positionalArguments.reversed.toList(), namedArguments));
}
}
@ -320,8 +344,7 @@ class _MacroListener implements Listener {
} else {
_Node value = pop();
_Node name = pop();
if (name is _NamedArgumentIdentifierNode &&
value is _PrimitiveValueNode) {
if (name is _NamedArgumentIdentifierNode && value is _MacroArgumentNode) {
push(new _NamedArgumentNode(name.name, value.argument));
} else {
pushUnsupported();
@ -340,25 +363,25 @@ class _MacroListener implements Listener {
@override
void handleLiteralNull(Token token) {
push(new _PrimitiveValueNode(new macro.NullArgument()));
push(new _MacroArgumentNode(new macro.NullArgument()));
}
@override
void handleLiteralBool(Token token) {
push(new _PrimitiveValueNode(
new macro.BoolArgument(token.lexeme == 'true')));
push(
new _MacroArgumentNode(new macro.BoolArgument(token.lexeme == 'true')));
}
@override
void handleLiteralDouble(Token token) {
push(new _PrimitiveValueNode(
push(new _MacroArgumentNode(
new macro.DoubleArgument(double.parse(token.lexeme))));
}
@override
void handleLiteralInt(Token token) {
push(new _PrimitiveValueNode(
new macro.IntArgument(int.parse(token.lexeme))));
push(
new _MacroArgumentNode(new macro.IntArgument(int.parse(token.lexeme))));
}
@override
@ -379,7 +402,7 @@ class _MacroListener implements Listener {
if (unrecognized) {
pushUnsupported();
} else {
push(new _PrimitiveValueNode(new macro.StringArgument(text)));
push(new _MacroArgumentNode(new macro.StringArgument(text)));
}
} else {
pushUnsupported();
@ -393,7 +416,7 @@ class _MacroListener implements Listener {
@override
void handleStringPart(Token token) {
// TODO(johnniwinther): Should we support this?
_unhandled();
_unhandled('string interpolation');
}
@override
@ -404,7 +427,7 @@ class _MacroListener implements Listener {
List<String> values = [];
for (int i = 0; i < literalCount; i++) {
_Node node = pop();
if (node is _PrimitiveValueNode && node.value is String) {
if (node is _MacroArgumentNode && node.value is String) {
values.add(node.value as String);
} else {
_unsupported();
@ -413,7 +436,7 @@ class _MacroListener implements Listener {
if (unrecognized) {
pushUnsupported();
} else {
push(new _PrimitiveValueNode(
push(new _MacroArgumentNode(
new macro.StringArgument(values.reversed.join())));
}
}
@ -434,8 +457,8 @@ class _MacroListener implements Listener {
}
/// Called for listener events that are supported but not handled yet.
void _unhandled() {
unrecognized = true;
void _unhandled(String what) {
unhandled = what;
}
/// Called for listener events whose use in unknown.
@ -545,12 +568,16 @@ class _MacroListener implements Listener {
@override
void beginConstExpression(Token constKeyword) {
_unhandled();
// TODO(johnniwinther): This is called before an explicitly const
// constructor invocation. If supported this is probably a no-op.
_unhandled('const expression');
}
@override
void beginConstLiteral(Token token) {
_unhandled();
// TODO(johnniwinther): This is called before an explicitly const
// list/map/set literal. This is probably a no-op.
_unhandled('const literal');
}
@override
@ -671,38 +698,38 @@ class _MacroListener implements Listener {
@override
void beginRecordType(Token beginToken) {
_unhandled();
_unhandled('record type');
}
@override
void endRecordType(
Token leftBracket, Token? questionMark, int count, bool hasNamedFields) {
_unhandled();
_unhandled('record type');
}
@override
void beginRecordTypeEntry() {
_unhandled();
_unhandled('record type entry');
}
@override
void endRecordTypeEntry() {
_unhandled();
_unhandled('record type entry');
}
@override
void beginRecordTypeNamedFields(Token leftBracket) {
_unhandled();
_unhandled('record type named field');
}
@override
void endRecordTypeNamedFields(int count, Token leftBracket) {
_unhandled();
_unhandled('record type named field');
}
@override
void beginFunctionType(Token beginToken) {
_unhandled();
_unhandled('function type');
}
@override
@ -727,7 +754,8 @@ class _MacroListener implements Listener {
@override
void beginImplicitCreationExpression(Token token) {
_unhandled();
// TODO(johnniwinther): Should this be supported?
_unhandled('constructor invocation');
}
@override
@ -752,7 +780,7 @@ class _MacroListener implements Listener {
@override
void beginIsOperatorType(Token operator) {
_unhandled();
_unhandled('is-test');
}
@override
@ -778,7 +806,7 @@ class _MacroListener implements Listener {
@override
void beginLiteralSymbol(Token token) {
_unhandled();
_unhandled('symbol constant');
}
@override
@ -928,7 +956,8 @@ class _MacroListener implements Listener {
@override
void beginTypeArguments(Token token) {
_unhandled();
// TODO(johnniwinther): Should we support this?
_unhandled('type argument');
}
@override
@ -984,7 +1013,7 @@ class _MacroListener implements Listener {
@override
void endAsOperatorType(Token operator) {
_unhandled();
_unhandled('cast');
}
@override
@ -1090,7 +1119,7 @@ class _MacroListener implements Listener {
@override
void endConditionalExpression(Token question, Token colon) {
_unhandled();
_unhandled('conditional expression');
}
@override
@ -1294,7 +1323,7 @@ class _MacroListener implements Listener {
@override
void endFunctionType(Token functionToken, Token? questionMark) {
_unhandled();
_unhandled('function type');
}
@override
@ -1324,7 +1353,7 @@ class _MacroListener implements Listener {
@override
void endImplicitCreationExpression(Token token, Token openAngleBracket) {
_unhandled();
_unhandled('constructor invocation');
}
@override
@ -1361,7 +1390,7 @@ class _MacroListener implements Listener {
@override
void endIsOperatorType(Token operator) {
_unhandled();
_unhandled('is-test');
}
@override
@ -1376,7 +1405,7 @@ class _MacroListener implements Listener {
@override
void endLiteralSymbol(Token hashToken, int identifierCount) {
_unhandled();
_unhandled('symbol constant');
}
@override
@ -1560,7 +1589,7 @@ class _MacroListener implements Listener {
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
_unhandled();
_unhandled('type argument');
}
@override
@ -1611,7 +1640,7 @@ class _MacroListener implements Listener {
@override
void handleAsOperator(Token operator) {
_unhandled();
_unhandled('cast');
}
@override
@ -1667,7 +1696,7 @@ class _MacroListener implements Listener {
@override
void handleConditionalExpressionColon() {
_unhandled();
_unhandled('conditional expression');
}
@override
@ -1827,7 +1856,7 @@ class _MacroListener implements Listener {
@override
void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
_unhandled();
_unhandled('string interpolation');
}
@override
@ -1877,7 +1906,7 @@ class _MacroListener implements Listener {
@override
void handleIsOperator(Token isOperator, Token? not) {
_unhandled();
_unhandled('is-test');
}
@override
@ -1888,7 +1917,28 @@ class _MacroListener implements Listener {
@override
void handleLiteralList(
int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
_unhandled();
if (unrecognized) {
pushUnsupported();
return;
}
List<macro.Argument> elements =
new List.filled(count, new macro.NullArgument());
for (int i = count - 1; i >= 0; i--) {
_Node node = pop();
if (node is _MacroArgumentNode) {
elements[i] = node.argument;
} else {
_unsupported();
}
}
if (unrecognized) {
pushUnsupported();
} else {
push(new _MacroArgumentNode(new macro.ListArgument(
elements,
// TODO(johnniwinther): Support argument kinds
[macro.ArgumentKind.dynamic])));
}
}
@override
@ -1898,7 +1948,7 @@ class _MacroListener implements Listener {
@override
void handleLiteralMapEntry(Token colon, Token endToken) {
_unhandled();
_unhandled('map entry');
}
@override
@ -1914,7 +1964,7 @@ class _MacroListener implements Listener {
@override
void handleLiteralSetOrMap(int count, Token leftBrace, Token? constKeyword,
Token rightBrace, bool hasSetEntry) {
_unhandled();
_unhandled('map or set literal');
}
@override
@ -1954,7 +2004,7 @@ class _MacroListener implements Listener {
@override
void handleNewAsIdentifier(Token token) {
_unhandled();
_unhandled("'new' as an identifier");
}
@override
@ -2055,27 +2105,27 @@ class _MacroListener implements Listener {
@override
void beginPattern(Token token) {
_unhandled();
_unsupported();
}
@override
void beginPatternGuard(Token token) {
_unhandled();
_unsupported();
}
@override
void beginParenthesizedExpressionOrRecordLiteral(Token token) {
_unhandled();
_unhandled('parenthesized expression or record literal');
}
@override
void beginSwitchCaseWhenClause(Token when) {
_unhandled();
_unsupported();
}
@override
void endRecordLiteral(Token token, int count, Token? constKeyword) {
_unhandled();
_unhandled('record literal');
}
@override
@ -2085,22 +2135,22 @@ class _MacroListener implements Listener {
@override
void endPattern(Token token) {
_unhandled();
_unsupported();
}
@override
void endPatternGuard(Token token) {
_unhandled();
_unsupported();
}
@override
void endParenthesizedExpression(Token token) {
_unhandled();
_unhandled('parenthesized expression');
}
@override
void endSwitchCaseWhenClause(Token token) {
_unhandled();
_unsupported();
}
@override
@ -2152,7 +2202,8 @@ class _MacroListener implements Listener {
@override
void handleSend(Token beginToken, Token endToken) {
_unhandled();
// TODO(johnniwinther): Should we support this?
_unhandled('send');
}
@override
@ -2178,17 +2229,17 @@ class _MacroListener implements Listener {
@override
void handleSwitchCaseNoWhenClause(Token token) {
_unhandled();
_unsupported();
}
@override
void handleSwitchExpressionCasePattern(Token token) {
_unhandled();
_unsupported();
}
@override
void handleSymbolVoid(Token token) {
_unhandled();
_unhandled('void');
}
@override
@ -2213,7 +2264,8 @@ class _MacroListener implements Listener {
@override
void handleTypeArgumentApplication(Token openAngleBracket) {
_unhandled();
// TODO(johnniwinther): Should we support this?
_unhandled('instantiation');
}
@override

View file

@ -56,9 +56,18 @@ class MacroApplication {
final ClassBuilder classBuilder;
final String constructorName;
final macro.Arguments arguments;
final String? errorReason;
MacroApplication(this.classBuilder, this.constructorName, this.arguments,
{required this.fileOffset});
{required this.fileOffset})
: errorReason = null;
MacroApplication.error(String this.errorReason, this.classBuilder,
{required this.fileOffset})
: constructorName = '',
arguments = new macro.Arguments(const [], const {});
bool get isErroneous => errorReason != null;
late macro.MacroInstanceIdentifier instanceIdentifier;
@ -218,12 +227,18 @@ void checkMacroApplications(
// We cannot currently identify macro applications by offsets because
// file offsets on annotations are not stable.
// TODO(johnniwinther): Handle file uri + offset on annotations.
Map<Class, List<MacroApplication>> macroApplications = {};
Map<Class, Map<int, MacroApplication>> macroApplications = {};
if (applicationData != null) {
for (MacroApplication application
in applicationData.macroApplications) {
(macroApplications[application.classBuilder.cls] ??= [])
.add(application);
Map<int, MacroApplication> applications =
macroApplications[application.classBuilder.cls] ??= {};
int fileOffset = application.fileOffset;
assert(
!applications.containsKey(fileOffset),
"Multiple annotations at offset $fileOffset: "
"${applications[fileOffset]} and ${application}.");
applications[fileOffset] = application;
}
}
for (Expression annotation in annotations) {
@ -231,13 +246,18 @@ void checkMacroApplications(
Constant constant = annotation.constant;
if (constant is InstanceConstant &&
hierarchy.isSubInterfaceOf(constant.classNode, macroClass)) {
List<MacroApplication>? applications =
Map<int, MacroApplication>? applications =
macroApplications[constant.classNode];
if (applications != null) {
if (applications.length == 1) {
macroApplications.remove(constant.classNode);
} else {
applications.removeAt(0);
MacroApplication? macroApplication =
applications?.remove(annotation.fileOffset);
if (macroApplication != null) {
if (macroApplication.isErroneous) {
libraryBuilder.addProblem(
templateUnhandledMacroApplication
.withArguments(macroApplication.errorReason!),
annotation.fileOffset,
noLength,
fileUri);
}
} else {
// TODO(johnniwinther): Improve the diagnostics about why the
@ -320,6 +340,9 @@ class MacroApplications {
List<MacroApplication>? applications) async {
if (applications != null) {
for (MacroApplication application in applications) {
if (application.isErroneous) {
continue;
}
Uri libraryUri = application.classBuilder.libraryBuilder.importUri;
String macroClassName = application.classBuilder.name;
try {
@ -338,13 +361,15 @@ class MacroApplications {
application.constructorName,
application.arguments);
benchmarker?.endSubdivide();
} catch (e) {
throw "Error instantiating macro `${application}`: $e";
} catch (e, s) {
throw "Error instantiating macro `${application}`: "
"$e\n$s";
}
} catch (e) {
} catch (e, s) {
throw "Error loading macro class "
"'${application.classBuilder.name}' from "
"'${application.classBuilder.libraryBuilder.importUri}': $e";
"'${application.classBuilder.libraryBuilder.importUri}': "
"$e\n$s";
}
}
}
@ -501,6 +526,9 @@ class MacroApplications {
List<macro.MacroExecutionResult> results = [];
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.isErroneous) {
continue;
}
if (macroApplication.instanceIdentifier
.shouldExecute(_declarationKind(declaration), macro.Phase.types)) {
if (retainDataForTesting) {
@ -594,6 +622,9 @@ class MacroApplications {
macro.Declaration declaration = applicationData.declaration;
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.isErroneous) {
continue;
}
if (macroApplication.instanceIdentifier.shouldExecute(
_declarationKind(declaration), macro.Phase.declarations)) {
if (retainDataForTesting) {
@ -694,6 +725,9 @@ class MacroApplications {
macro.Declaration declaration = applicationData.declaration;
for (MacroApplication macroApplication
in applicationData.macroApplications) {
if (macroApplication.isErroneous) {
continue;
}
if (macroApplication.instanceIdentifier.shouldExecute(
_declarationKind(declaration), macro.Phase.definitions)) {
if (retainDataForTesting) {

View file

@ -1035,6 +1035,8 @@ UndefinedExtensionSetter/analyzerCode: Fail
UndefinedExtensionSetter/example: Fail
UnexpectedToken/part_wrapped_script1: Fail
UnexpectedToken/script1: Fail
UnhandledMacroApplication/analyzerCode: Fail
UnhandledMacroApplication/example: Fail
UnmatchedAugmentationClass/analyzerCode: Fail
UnmatchedAugmentationClass/part_wrapped_script: Fail
UnmatchedAugmentationClassMember/analyzerCode: Fail

View file

@ -7331,6 +7331,9 @@ JointPatternVariableWithLabelDefault:
UnsupportedMacroApplication:
problemMessage: "This macro application didn't apply correctly."
UnhandledMacroApplication:
problemMessage: "This macro application didn't apply correctly due to an unhandled #name."
ScriptTagInPartFile:
problemMessage: "A part file cannot have script tag."
correctionMessage: "Try removing the script tag or the 'part of' directive."

View file

@ -10,8 +10,9 @@ macro
class AnnotationsMacro
implements ClassDeclarationsMacro, FunctionDeclarationsMacro {
final Object? object;
final Object? additional;
const AnnotationsMacro(this.object);
const AnnotationsMacro(this.object, [this.additional]);
FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz,
MemberDeclarationBuilder builder) {}

View file

@ -2,12 +2,19 @@
// 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:
Class:AnnotationsMacro.new(ListArgument:[0, 1])
Class:AnnotationsMacro.new(ListArgument:[0])
Class:AnnotationsMacro.new(ListArgument:[])
Class:AnnotationsMacro.new(IntArgument:0,IntArgument:1)
Class:AnnotationsMacro.new(IntArgument:0)*/
import 'package:macro/annotations.dart';
int get a => 1;
const b = 2;
// TODO(johnniwinther): Support code arguments.
@AnnotationsMacro(Class)
@AnnotationsMacro(a + b)
@AnnotationsMacro(0)
@AnnotationsMacro(0, 1)
@AnnotationsMacro([])
@AnnotationsMacro([0])
@AnnotationsMacro([0, 1])
class Class {}

View file

@ -1,40 +1,31 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:12:2: Error: Constant evaluation error:
// @AnnotationsMacro(a + b)
// ^
// org-dartlang-test:///a/b/c/main.dart:12:19: Context: The invocation of 'a' is not allowed in a constant expression.
// @AnnotationsMacro(a + b)
// ^
// org-dartlang-test:///a/b/c/main.dart:13:7: Context: While analyzing:
// class Class {}
// ^
//
// org-dartlang-test:///a/b/c/main.dart:11:2: Error: This macro application didn't apply correctly.
// @AnnotationsMacro(Class)
// ^
//
import self as self;
import "package:macro/annotations.dart" as ann;
import "dart:core" as core;
import "package:macro/annotations.dart";
@#C2
@invalid-expression "The invocation of 'a' is not allowed in a constant expression."
@#C3
@#C5
@#C7
@#C9
@#C11
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
}
static const field core::int b = #C3;
static get a() → core::int
return 1;
constants {
#C1 = TypeLiteralConstant(self::Class*)
#C2 = ann::AnnotationsMacro {object:#C1}
#C3 = 2
#C1 = 0
#C2 = null
#C3 = ann::AnnotationsMacro {object:#C1, additional:#C2}
#C4 = 1
#C5 = ann::AnnotationsMacro {object:#C1, additional:#C4}
#C6 = <dynamic>[]
#C7 = ann::AnnotationsMacro {object:#C6, additional:#C2}
#C8 = <core::int*>[#C1]
#C9 = ann::AnnotationsMacro {object:#C8, additional:#C2}
#C10 = <core::int*>[#C1, #C4]
#C11 = ann::AnnotationsMacro {object:#C10, additional:#C2}
}

View file

@ -2,15 +2,15 @@ library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:17:2: Error: This macro application didn't apply correctly.
// org-dartlang-test:///a/b/c/main.dart:17:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(UserClass())
// ^
//
// org-dartlang-test:///a/b/c/main.dart:11:2: Error: This macro application didn't apply correctly.
// org-dartlang-test:///a/b/c/main.dart:11:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(UserClass())
// ^
//
// org-dartlang-test:///a/b/c/main.dart:13:4: Error: This macro application didn't apply correctly.
// org-dartlang-test:///a/b/c/main.dart:13:4: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(UserClass())
// ^
//
@ -25,18 +25,19 @@ class UserClass extends core::Object /*hasConstConstructor*/ {
: super core::Object::•()
;
}
@#C2
@#C3
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
@#C2
@#C3
method method() → dynamic {}
}
@#C2
@#C3
static method method() → dynamic {}
constants {
#C1 = self::UserClass {}
#C2 = ann::AnnotationsMacro {object:#C1}
#C2 = null
#C3 = ann::AnnotationsMacro {object:#C1, additional:#C2}
}

View file

@ -0,0 +1,30 @@
// 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:macro/annotations.dart';
int get a => 1;
const b = 2;
T id<T>(T t) => t;
@AnnotationsMacro(const Object())
@AnnotationsMacro(const [])
@AnnotationsMacro(const {})
@AnnotationsMacro(<void Function()>{})
@AnnotationsMacro(Object())
@AnnotationsMacro(#a)
@AnnotationsMacro((0))
@AnnotationsMacro((0,))
@AnnotationsMacro(<(int, {String a})>{})
@AnnotationsMacro(<(int, {String a})>{})
@AnnotationsMacro(0 is int)
@AnnotationsMacro(0 as int)
@AnnotationsMacro(true ? 0 : 1)
@AnnotationsMacro(Object.new())
@AnnotationsMacro("foo".length)
@AnnotationsMacro(id<int>)
// TODO(johnniwinther): Support code arguments.
@AnnotationsMacro(Class)
@AnnotationsMacro(a + b)
class Class {}

View file

@ -0,0 +1,146 @@
library;
//
// Problems in library:
//
// org-dartlang-test:///a/b/c/main.dart:29:2: Error: Constant evaluation error:
// @AnnotationsMacro(a + b)
// ^
// org-dartlang-test:///a/b/c/main.dart:29:19: Context: The invocation of 'a' is not allowed in a constant expression.
// @AnnotationsMacro(a + b)
// ^
// org-dartlang-test:///a/b/c/main.dart:30:7: Context: While analyzing:
// class Class {}
// ^
//
// org-dartlang-test:///a/b/c/main.dart:11:2: Error: This macro application didn't apply correctly due to an unhandled const expression.
// @AnnotationsMacro(const Object())
// ^
//
// org-dartlang-test:///a/b/c/main.dart:12:2: Error: This macro application didn't apply correctly due to an unhandled const literal.
// @AnnotationsMacro(const [])
// ^
//
// org-dartlang-test:///a/b/c/main.dart:13:2: Error: This macro application didn't apply correctly due to an unhandled const literal.
// @AnnotationsMacro(const {})
// ^
//
// org-dartlang-test:///a/b/c/main.dart:14:2: Error: This macro application didn't apply correctly due to an unhandled type argument.
// @AnnotationsMacro(<void Function()>{})
// ^
//
// org-dartlang-test:///a/b/c/main.dart:15:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(Object())
// ^
//
// org-dartlang-test:///a/b/c/main.dart:16:2: Error: This macro application didn't apply correctly due to an unhandled symbol constant.
// @AnnotationsMacro(#a)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:17:2: Error: This macro application didn't apply correctly due to an unhandled parenthesized expression or record literal.
// @AnnotationsMacro((0))
// ^
//
// org-dartlang-test:///a/b/c/main.dart:18:2: Error: This macro application didn't apply correctly due to an unhandled parenthesized expression or record literal.
// @AnnotationsMacro((0,))
// ^
//
// org-dartlang-test:///a/b/c/main.dart:19:2: Error: This macro application didn't apply correctly due to an unhandled type argument.
// @AnnotationsMacro(<(int, {String a})>{})
// ^
//
// org-dartlang-test:///a/b/c/main.dart:20:2: Error: This macro application didn't apply correctly due to an unhandled type argument.
// @AnnotationsMacro(<(int, {String a})>{})
// ^
//
// org-dartlang-test:///a/b/c/main.dart:21:2: Error: This macro application didn't apply correctly due to an unhandled is-test.
// @AnnotationsMacro(0 is int)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:22:2: Error: This macro application didn't apply correctly due to an unhandled cast.
// @AnnotationsMacro(0 as int)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:23:2: Error: This macro application didn't apply correctly due to an unhandled conditional expression.
// @AnnotationsMacro(true ? 0 : 1)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:24:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(Object.new())
// ^
//
// org-dartlang-test:///a/b/c/main.dart:25:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro("foo".length)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:26:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(id<int>)
// ^
//
// org-dartlang-test:///a/b/c/main.dart:28:2: Error: This macro application didn't apply correctly due to an unhandled send.
// @AnnotationsMacro(Class)
// ^
//
import self as self;
import "package:macro/annotations.dart" as ann;
import "dart:core" as core;
import "package:macro/annotations.dart";
@#C3
@#C5
@#C7
@#C9
@#C3
@#C11
@#C13
@#C15
@#C17
@#C17
@#C19
@#C13
@#C13
@#C3
@#C21
@#C24
@#C26
@invalid-expression "The invocation of 'a' is not allowed in a constant expression."
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
}
static const field core::int b = #C27;
static get a() → core::int
return 1;
static method id<T extends core::Object? = dynamic>(self::id::T% t) → self::id::T%
return t;
constants {
#C1 = core::Object {}
#C2 = null
#C3 = ann::AnnotationsMacro {object:#C1, additional:#C2}
#C4 = <dynamic>[]
#C5 = ann::AnnotationsMacro {object:#C4, additional:#C2}
#C6 = <dynamic, dynamic>{}
#C7 = ann::AnnotationsMacro {object:#C6, additional:#C2}
#C8 = <() →* void>{}
#C9 = ann::AnnotationsMacro {object:#C8, additional:#C2}
#C10 = #a
#C11 = ann::AnnotationsMacro {object:#C10, additional:#C2}
#C12 = 0
#C13 = ann::AnnotationsMacro {object:#C12, additional:#C2}
#C14 = (#C12)
#C15 = ann::AnnotationsMacro {object:#C14, additional:#C2}
#C16 = <(core::int*, {required a: core::String*})*>{}
#C17 = ann::AnnotationsMacro {object:#C16, additional:#C2}
#C18 = true
#C19 = ann::AnnotationsMacro {object:#C18, additional:#C2}
#C20 = 3
#C21 = ann::AnnotationsMacro {object:#C20, additional:#C2}
#C22 = static-tearoff self::id
#C23 = instantiation #C22 <core::int*>
#C24 = ann::AnnotationsMacro {object:#C23, additional:#C2}
#C25 = TypeLiteralConstant(self::Class*)
#C26 = ann::AnnotationsMacro {object:#C25, additional:#C2}
#C27 = 2
}