Macro. Issue 55101. Catch exceptions during macro instantiations.

Bug: https://github.com/dart-lang/sdk/issues/55101
Change-Id: I1c34d1ad55e0bb3a1b1bd10779c0f21d6b6a6aa1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/355881
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2024-03-05 20:12:31 +00:00 committed by Commit Queue
parent f262bab262
commit 8605d7e682
3 changed files with 73 additions and 23 deletions

View file

@ -466,28 +466,28 @@ class LibraryMacroApplier {
continue;
}
final arguments = await _runWithCatchingExceptions(
final instance = await _runWithCatchingExceptions(
() async {
return _buildArguments(
final arguments = _buildArguments(
annotationIndex: annotationIndex,
constructor: constructorElement,
node: importedMacro.arguments,
);
return await importedMacro.bundleExecutor.instantiate(
libraryUri: importedMacro.macroLibrary.source.uri,
className: importedMacro.macroClass.name,
constructorName: importedMacro.constructorName ?? '',
arguments: arguments,
);
},
targetElement: targetElement,
annotationIndex: annotationIndex,
);
if (arguments == null) {
if (instance == null) {
continue;
}
final instance = await importedMacro.bundleExecutor.instantiate(
libraryUri: importedMacro.macroLibrary.source.uri,
className: importedMacro.macroClass.name,
constructorName: importedMacro.constructorName ?? '',
arguments: arguments,
);
final phasesToExecute = macro.Phase.values.where((phase) {
return instance.shouldExecute(targetDeclarationKind, phase);
}).toSet();

View file

@ -788,18 +788,28 @@ class _ElementWriter {
}
}
/// Returns `true` if patterns were printed.
/// Returns `false` if no patterns configured.
bool printMessagePatterns(String message) {
var patterns = configuration.macroDiagnosticMessagePatterns;
if (patterns == null) {
return false;
}
_sink.writelnWithIndent('contains');
_sink.withIndent(() {
for (var pattern in patterns) {
if (message.contains(pattern)) {
_sink.writelnWithIndent(pattern);
}
}
});
return true;
}
void writeMessage(MacroDiagnosticMessage object) {
// Write the message.
if (configuration.macroDiagnosticMessagePatterns case var patterns?) {
_sink.writelnWithIndent('contains');
_sink.withIndent(() {
for (var pattern in patterns) {
if (object.message.contains(pattern)) {
_sink.writelnWithIndent(pattern);
}
}
});
} else {
if (!printMessagePatterns(object.message)) {
final message = object.message;
const stackTraceText = '#0';
final stackTraceIndex = message.indexOf(stackTraceText);
@ -908,9 +918,11 @@ class _ElementWriter {
_sink.writelnWithIndent(
'annotationIndex: ${diagnostic.annotationIndex}',
);
_sink.writelnWithIndent(
'message: ${diagnostic.message}',
);
if (!printMessagePatterns(diagnostic.message)) {
_sink.writelnWithIndent(
'message: ${diagnostic.message}',
);
}
if (configuration.withMacroStackTraces) {
_sink.writelnWithIndent(
'stackTrace:\n${diagnostic.stackTrace}',

View file

@ -7105,6 +7105,44 @@ My definitions phase
''');
}
test_macroDiagnostics_throwException_duringInstantiating() async {
newFile(
'$testPackageLibPath/diagnostic.dart',
_getMacroCode('diagnostic.dart'),
);
final library = await buildLibrary(r'''
import 'diagnostic.dart';
@MacroWithArguments()
class A {}
''');
configuration
..withConstructors = false
..withMetadata = false
..macroDiagnosticMessagePatterns = [
'NoSuchMethodError',
'Closure call with mismatched arguments',
'Tried calling: MacroWithArguments.MacroWithArguments()',
];
checkElementText(library, r'''
library
imports
package:test/diagnostic.dart
definingUnit
classes
class A @55
macroDiagnostics
ExceptionMacroDiagnostic
annotationIndex: 0
contains
NoSuchMethodError
Closure call with mismatched arguments
Tried calling: MacroWithArguments.MacroWithArguments()
''');
}
test_macroDiagnostics_throwException_duringIntrospection() async {
newFile(
'$testPackageLibPath/diagnostic.dart',