mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +00:00
[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:
parent
4f77ee4b88
commit
a866d22f5e
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
|
@ -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 {}
|
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue