[macros] Tweak diagnostic for unexpected macro implementation exception.

The only expected exceptions at this point are DiagnosticException and MacroException subtypes; everything else is a bug in the implementation.

Tweak the diagnostic to explain that it's due to a bug in the macro. Add the exception message and stack trace as a context message, and a fix hint to contact the author.

Add a language test.

Retry landing with updates to `pkg/analyzer/test/summary/macro_test`.

R=jensj@google.com, scheglov@google.com, sigmund@google.com

Change-Id: Iebc3df784922dcb6ef112ba8d023d5388516373b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352361
Reviewed-by: Jake Macdonald <jakemac@google.com>
Auto-Submit: Morgan :) <davidmorgan@google.com>
Commit-Queue: Morgan :) <davidmorgan@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
David Morgan 2024-02-22 13:53:20 +00:00 committed by Commit Queue
parent 6ce7ec657e
commit e680eb4c4f
7 changed files with 120 additions and 38 deletions

View file

@ -66,9 +66,7 @@ Future<MacroExecutionResult> executeTypesMacro(
builder.failWithException(e);
} else {
// Convert exceptions thrown by macro implementations into diagnostics.
builder.report(new Diagnostic(
new DiagnosticMessage('Unhandled error: $e\n' 'Stack trace:\n$s'),
Severity.error));
builder.report(_unexpectedExceptionDiagnostic(e, s));
}
}
return builder.result;
@ -146,9 +144,7 @@ Future<MacroExecutionResult> executeDeclarationsMacro(Macro macro,
builder.failWithException(e);
} else {
// Convert exceptions thrown by macro implementations into diagnostics.
builder.report(new Diagnostic(
new DiagnosticMessage('Unhandled error: $e\n' 'Stack trace:\n$s'),
Severity.error));
builder.report(_unexpectedExceptionDiagnostic(e, s));
}
}
return builder.result;
@ -223,10 +219,21 @@ Future<MacroExecutionResult> executeDefinitionMacro(Macro macro, Object target,
builder.failWithException(e);
} else {
// Convert exceptions thrown by macro implementations into diagnostics.
builder.report(new Diagnostic(
new DiagnosticMessage('Unhandled error: $e\n' 'Stack trace:\n$s'),
Severity.error));
builder.report(_unexpectedExceptionDiagnostic(e, s));
}
}
return builder.result;
}
// It's a bug in the macro but we need to show something to the user; put the
// debug detail in a context message and suggest reporting to the author.
Diagnostic _unexpectedExceptionDiagnostic(
Object thrown, StackTrace stackTrace) =>
new Diagnostic(
new DiagnosticMessage(
'Macro application failed due to a bug in the macro.'),
Severity.error,
contextMessages: [
new DiagnosticMessage('$thrown\n$stackTrace'),
],
correctionMessage: 'Try reporting the failure to the macro author.');

View file

@ -90,10 +90,10 @@ class A {}
18,
10,
messageContains: [
'Unhandled error',
'package:test/a.dart',
'unresolved',
'MyMacro',
'Macro application failed due to a bug in the macro.',
],
contextMessages: [
message('/home/test/lib/test.dart', 18, 10),
],
),
]);
@ -908,10 +908,10 @@ class A {}
18,
10,
messageContains: [
'Unhandled error',
'package:test/a.dart',
'12345',
'MyMacro',
'Macro application failed due to a bug in the macro.'
],
contextMessages: [
message('/home/test/lib/test.dart', 18, 10),
],
),
]);

View file

@ -794,7 +794,7 @@ class _ElementWriter {
validator(object.message);
} else {
final message = object.message;
const stackTraceText = 'Stack trace:';
const stackTraceText = '#0';
final stackTraceIndex = message.indexOf(stackTraceText);
if (stackTraceIndex >= 0) {
final end = stackTraceIndex + stackTraceText.length;

View file

@ -5388,8 +5388,13 @@ class A {}
..withConstructors = false
..withMetadata = false
..macroDiagnosticMessageValidator = (message) {
expect(message, contains('unresolved'));
expect(message, contains('executeTypesMacro'));
if (message.contains('#0')) {
// It's the context: stack trace with the underlying issue.
expect(message, contains('unresolved'));
} else {
// It's the main message.
expect(message, contains('failed due to a bug in the macro'));
}
};
checkElementText(library, r'''
library
@ -5403,7 +5408,12 @@ library
message: MacroDiagnosticMessage
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}
@ -6724,12 +6734,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My declarations phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My declarations phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}
@ -6761,12 +6777,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My declarations phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My declarations phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}
@ -6802,12 +6824,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My declarations phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My declarations phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
accessors
synthetic get foo @-1
returnType: int
@ -6850,12 +6878,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My declarations phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My declarations phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}
@ -6885,12 +6919,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My definitions phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My definitions phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}
@ -6920,12 +6960,18 @@ library
macroDiagnostics
MacroDiagnostic
message: MacroDiagnosticMessage
message:
Unhandled error: My types phase
Stack trace: <cut>
message: Macro application failed due to a bug in the macro.
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
contextMessages
MacroDiagnosticMessage
message:
My types phase
#0 <cut>
target: ApplicationMacroDiagnosticTarget
annotationIndex: 0
severity: error
correctionMessage: Try reporting the failure to the macro author.
''');
}

View file

@ -1721,6 +1721,7 @@ successive
suffixed
suffixing
sugared
suggest
suggests
suite
sum

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.
// ignore_for_file: deprecated_member_use
import 'package:_fe_analyzer_shared/src/macros/api.dart';
macro class ThrowOther implements ClassDeclarationsMacro {
final Object other;
const ThrowOther({required this.other});
Future<void> buildDeclarationsForClass(
ClassDeclaration clazz, MemberDeclarationBuilder builder) async {
throw other;
}
}

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.
// SharedOptions=--enable-experiment=macros
import 'impl/throw_other_macro.dart';
@ThrowOther(other: 'some unexpected error')
// [error line 8, column 1, length 43]
// [analyzer] COMPILE_TIME_ERROR.MACRO_ERROR
// [cfe] unspecified
class A {}