Preserve stack traces for lint exceptions.
Currently, stack traces are overriden when exceptions are propagated
through a `LintRuleExceptionHandler`. This change allows a
`LintRuleExceptionHandler` to return `false`, indicating that callers
should rethrow the exception themselves, preserving the stack trace.
Change-Id: Ia7c97f01774d6e5d1b6cd8740cdd1128a0fa714e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/244942
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 65a3293..f024ba6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1384,7 +1384,10 @@
/// A method that can be passed to the `LinterVisitor` constructor to handle
/// exceptions that occur during linting.
- void logException(
+ ///
+ /// Returns `true` if the exception was fully handled, and `false` if the
+ /// exception should be rethrown.
+ bool logException(
AstNode node, Object visitor, dynamic exception, StackTrace stackTrace) {
StringBuffer buffer = StringBuffer();
buffer.write('Exception while using a ${visitor.runtimeType} to visit a ');
@@ -1402,9 +1405,7 @@
// TODO(39284): should this exception be silent?
AnalysisEngine.instance.instrumentationService.logException(
SilentException(buffer.toString(), exception, stackTrace));
- if (propagateExceptions) {
- throw exception;
- }
+ return !propagateExceptions;
}
}
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index b08cc00..3383df0 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -9,7 +9,10 @@
import 'package:analyzer/src/services/lint.dart';
/// The type of the function that handles exceptions in lints.
-typedef LintRuleExceptionHandler = void Function(
+///
+/// Returns `true` if the exception was fully handled, or `false` if
+/// the exception should be rethrown.
+typedef LintRuleExceptionHandler = bool Function(
AstNode node, LintRule linter, dynamic exception, StackTrace stackTrace);
/// The AST visitor that runs handlers for nodes from the [registry].
@@ -769,7 +772,10 @@
try {
node.accept(subscription.visitor);
} catch (exception, stackTrace) {
- exceptionHandler(node, subscription.linter, exception, stackTrace);
+ if (!exceptionHandler(
+ node, subscription.linter, exception, stackTrace)) {
+ rethrow;
+ }
}
timer?.stop();
}