mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 22:01:19 +00:00
[dart2js] Inline CompilerDiagnosticReporter into its super.
Change-Id: I3b675df3069f2ff7cb74374bcc2ee1caa31e8610 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/238800 Reviewed-by: Mark Zhou <markzipan@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
parent
ca99bde913
commit
9f33a4a052
|
@ -24,7 +24,7 @@ import 'deferred_load/program_split_constraints/nodes.dart' as psc
|
|||
show ConstraintData;
|
||||
import 'deferred_load/program_split_constraints/parser.dart' as psc show Parser;
|
||||
import 'diagnostics/code_location.dart';
|
||||
import 'diagnostics/messages.dart' show Message, MessageTemplate;
|
||||
import 'diagnostics/messages.dart' show Message;
|
||||
import 'dump_info.dart' show DumpInfoTask;
|
||||
import 'elements/entities.dart';
|
||||
import 'enqueue.dart' show Enqueuer, ResolutionEnqueuer;
|
||||
|
@ -36,7 +36,6 @@ import 'inferrer/powersets/powersets.dart' show PowersetStrategy;
|
|||
import 'inferrer/typemasks/masks.dart' show TypeMaskStrategy;
|
||||
import 'inferrer/types.dart'
|
||||
show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
|
||||
import 'io/source_information.dart' show SourceInformation;
|
||||
import 'ir/modular.dart';
|
||||
import 'js_backend/backend.dart' show CodegenInputs;
|
||||
import 'js_backend/enqueuer.dart';
|
||||
|
@ -54,16 +53,12 @@ import 'phase/modular_analysis.dart' as modular_analysis;
|
|||
import 'serialization/task.dart';
|
||||
import 'serialization/serialization.dart';
|
||||
import 'serialization/strategies.dart';
|
||||
import 'ssa/nodes.dart' show HInstruction;
|
||||
import 'universe/selector.dart' show Selector;
|
||||
import 'universe/codegen_world_builder.dart';
|
||||
import 'universe/resolution_world_builder.dart';
|
||||
import 'universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
|
||||
import 'world.dart' show JClosedWorld;
|
||||
|
||||
typedef MakeReporterFunction = CompilerDiagnosticReporter Function(
|
||||
Compiler compiler, CompilerOptions options);
|
||||
|
||||
/// Implementation of the compiler using a [api.CompilerInput] for supplying
|
||||
/// the sources.
|
||||
class Compiler {
|
||||
|
@ -73,7 +68,7 @@ class Compiler {
|
|||
|
||||
KernelFrontendStrategy frontendStrategy;
|
||||
JsBackendStrategy backendStrategy;
|
||||
CompilerDiagnosticReporter _reporter;
|
||||
DiagnosticReporter _reporter;
|
||||
Map<Entity, WorldImpact> _impactCache;
|
||||
GenericTask userHandlerTask;
|
||||
GenericTask userProviderTask;
|
||||
|
@ -122,8 +117,6 @@ class Compiler {
|
|||
DumpInfoTask dumpInfoTask;
|
||||
SerializationTask serializationTask;
|
||||
|
||||
bool get hasCrashed => _reporter.hasCrashed;
|
||||
|
||||
Progress progress = const Progress();
|
||||
|
||||
static const int PHASE_SCANNING = 0;
|
||||
|
@ -142,8 +135,7 @@ class Compiler {
|
|||
// Callback function used for testing codegen enqueuing.
|
||||
void Function() onCodegenQueueEmptyForTesting;
|
||||
|
||||
Compiler(this.provider, this._outputProvider, this.handler, this.options,
|
||||
{MakeReporterFunction makeReporter})
|
||||
Compiler(this.provider, this._outputProvider, this.handler, this.options)
|
||||
// NOTE: allocating measurer is done upfront to ensure the wallclock is
|
||||
// started before other computations.
|
||||
: measurer = Measurer(enableTaskMeasurements: options.verbose),
|
||||
|
@ -164,11 +156,7 @@ class Compiler {
|
|||
CompilerTask kernelFrontEndTask;
|
||||
selfTask = GenericTask('self', measurer);
|
||||
_outputProvider = _CompilerOutput(this, outputProvider);
|
||||
if (makeReporter != null) {
|
||||
_reporter = makeReporter(this, options);
|
||||
} else {
|
||||
_reporter = CompilerDiagnosticReporter(this);
|
||||
}
|
||||
_reporter = DiagnosticReporter(this);
|
||||
kernelFrontEndTask = GenericTask('Front end', measurer);
|
||||
frontendStrategy = KernelFrontendStrategy(
|
||||
kernelFrontEndTask, options, reporter, environment);
|
||||
|
@ -950,293 +938,6 @@ class _CompilerOutput implements api.CompilerOutput {
|
|||
}
|
||||
}
|
||||
|
||||
/// Information about suppressed warnings and hints for a given library.
|
||||
class SuppressionInfo {
|
||||
int warnings = 0;
|
||||
int hints = 0;
|
||||
}
|
||||
|
||||
class CompilerDiagnosticReporter extends DiagnosticReporter {
|
||||
final Compiler compiler;
|
||||
@override
|
||||
CompilerOptions get options => compiler.options;
|
||||
|
||||
Entity _currentElement;
|
||||
bool hasCrashed = false;
|
||||
|
||||
/// `true` if the last diagnostic was filtered, in which case the
|
||||
/// accompanying info message should be filtered as well.
|
||||
bool lastDiagnosticWasFiltered = false;
|
||||
|
||||
/// Map containing information about the warnings and hints that have been
|
||||
/// suppressed for each library.
|
||||
Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{};
|
||||
|
||||
CompilerDiagnosticReporter(this.compiler);
|
||||
|
||||
Entity get currentElement => _currentElement;
|
||||
|
||||
@override
|
||||
DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
SourceSpan span = spanFromSpannable(spannable);
|
||||
MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
|
||||
Message message = template.message(arguments, options);
|
||||
return DiagnosticMessage(span, spannable, message);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportError(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportWarning(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportHint(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportInfo(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reportDiagnosticInternal(message, infos, api.Diagnostic.INFO);
|
||||
}
|
||||
|
||||
void reportDiagnosticInternal(DiagnosticMessage message,
|
||||
List<DiagnosticMessage> infos, api.Diagnostic kind) {
|
||||
if (!options.showAllPackageWarnings &&
|
||||
message.spannable != NO_LOCATION_SPANNABLE) {
|
||||
switch (kind) {
|
||||
case api.Diagnostic.WARNING:
|
||||
case api.Diagnostic.HINT:
|
||||
Entity element = elementFromSpannable(message.spannable);
|
||||
if (!compiler.inUserCode(element, assumeInUserCode: true)) {
|
||||
Uri uri = compiler.getCanonicalUri(element);
|
||||
if (options.showPackageWarningsFor(uri)) {
|
||||
reportDiagnostic(message, infos, kind);
|
||||
return;
|
||||
}
|
||||
SuppressionInfo info =
|
||||
suppressedWarnings.putIfAbsent(uri, () => SuppressionInfo());
|
||||
if (kind == api.Diagnostic.WARNING) {
|
||||
info.warnings++;
|
||||
} else {
|
||||
info.hints++;
|
||||
}
|
||||
lastDiagnosticWasFiltered = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case api.Diagnostic.INFO:
|
||||
if (lastDiagnosticWasFiltered) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastDiagnosticWasFiltered = false;
|
||||
reportDiagnostic(message, infos, kind);
|
||||
}
|
||||
|
||||
void reportDiagnostic(DiagnosticMessage message,
|
||||
List<DiagnosticMessage> infos, api.Diagnostic kind) {
|
||||
compiler.reportDiagnostic(message, infos, kind);
|
||||
if (kind == api.Diagnostic.ERROR ||
|
||||
kind == api.Diagnostic.CRASH ||
|
||||
(options.fatalWarnings && kind == api.Diagnostic.WARNING)) {
|
||||
compiler.fatalDiagnosticReported(message, infos, kind);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get hasReportedError => compiler.compilationFailed;
|
||||
|
||||
/// Perform an operation, [f], returning the return value from [f]. If an
|
||||
/// error occurs then report it as having occurred during compilation of
|
||||
/// [element]. Can be nested.
|
||||
@override
|
||||
withCurrentElement(Entity element, f()) {
|
||||
Entity old = currentElement;
|
||||
_currentElement = element;
|
||||
try {
|
||||
return f();
|
||||
} on SpannableAssertionFailure catch (ex) {
|
||||
if (!hasCrashed) {
|
||||
reportAssertionFailure(ex);
|
||||
pleaseReportCrash();
|
||||
}
|
||||
hasCrashed = true;
|
||||
rethrow;
|
||||
} on StackOverflowError {
|
||||
// We cannot report anything useful in this case, because we
|
||||
// do not have enough stack space.
|
||||
rethrow;
|
||||
} catch (ex) {
|
||||
if (hasCrashed) rethrow;
|
||||
try {
|
||||
unhandledExceptionOnElement(element);
|
||||
} catch (doubleFault) {
|
||||
// Ignoring exceptions in exception handling.
|
||||
}
|
||||
rethrow;
|
||||
} finally {
|
||||
_currentElement = old;
|
||||
}
|
||||
}
|
||||
|
||||
void reportAssertionFailure(SpannableAssertionFailure ex) {
|
||||
String message =
|
||||
(ex.message != null) ? tryToString(ex.message) : tryToString(ex);
|
||||
reportDiagnosticInternal(
|
||||
createMessage(ex.node, MessageKind.GENERIC, {'text': message}),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
}
|
||||
|
||||
/// Using [frontendStrategy] to compute a [SourceSpan] from spannable using
|
||||
/// the [currentElement] as context.
|
||||
SourceSpan _spanFromStrategy(Spannable spannable) {
|
||||
SourceSpan span;
|
||||
if (compiler.phase == Compiler.PHASE_COMPILING) {
|
||||
span =
|
||||
compiler.backendStrategy.spanFromSpannable(spannable, currentElement);
|
||||
} else {
|
||||
span = compiler.frontendStrategy
|
||||
.spanFromSpannable(spannable, currentElement);
|
||||
}
|
||||
if (span != null) return span;
|
||||
throw 'No error location.';
|
||||
}
|
||||
|
||||
@override
|
||||
SourceSpan spanFromSpannable(Spannable spannable) {
|
||||
if (spannable == CURRENT_ELEMENT_SPANNABLE) {
|
||||
spannable = currentElement;
|
||||
} else if (spannable == NO_LOCATION_SPANNABLE) {
|
||||
if (currentElement == null) return null;
|
||||
spannable = currentElement;
|
||||
}
|
||||
if (spannable is SourceSpan) {
|
||||
return spannable;
|
||||
} else if (spannable is HInstruction) {
|
||||
Entity element = spannable.sourceElement;
|
||||
if (element == null) element = currentElement;
|
||||
SourceInformation position = spannable.sourceInformation;
|
||||
if (position != null) return position.sourceSpan;
|
||||
return _spanFromStrategy(element);
|
||||
} else {
|
||||
return _spanFromStrategy(spannable);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
internalError(Spannable spannable, reason) {
|
||||
String message = tryToString(reason);
|
||||
reportDiagnosticInternal(
|
||||
createMessage(spannable, MessageKind.GENERIC, {'text': message}),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
throw 'Internal Error: $message';
|
||||
}
|
||||
|
||||
void unhandledExceptionOnElement(Entity element) {
|
||||
if (hasCrashed) return;
|
||||
hasCrashed = true;
|
||||
reportDiagnostic(createMessage(element, MessageKind.COMPILER_CRASHED),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.CRASH);
|
||||
pleaseReportCrash();
|
||||
}
|
||||
|
||||
void pleaseReportCrash() {
|
||||
print(MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
|
||||
.message({'buildId': compiler.options.buildId}, options));
|
||||
}
|
||||
|
||||
/// Finds the approximate [Element] for [node]. [currentElement] is used as
|
||||
/// the default value.
|
||||
Entity elementFromSpannable(Spannable node) {
|
||||
Entity element;
|
||||
if (node is Entity) {
|
||||
element = node;
|
||||
} else if (node is HInstruction) {
|
||||
element = node.sourceElement;
|
||||
}
|
||||
return element ?? currentElement;
|
||||
}
|
||||
|
||||
@override
|
||||
void log(message) {
|
||||
Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC]
|
||||
.message({'text': '$message'}, options);
|
||||
reportDiagnostic(DiagnosticMessage(null, null, msg),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.VERBOSE_INFO);
|
||||
}
|
||||
|
||||
String tryToString(object) {
|
||||
try {
|
||||
return object.toString();
|
||||
} catch (_) {
|
||||
return '<exception in toString()>';
|
||||
}
|
||||
}
|
||||
|
||||
onError(Uri uri, error, StackTrace stackTrace) {
|
||||
try {
|
||||
if (!hasCrashed) {
|
||||
hasCrashed = true;
|
||||
if (error is SpannableAssertionFailure) {
|
||||
reportAssertionFailure(error);
|
||||
} else {
|
||||
reportDiagnostic(
|
||||
createMessage(
|
||||
SourceSpan(uri, 0, 0), MessageKind.COMPILER_CRASHED),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
}
|
||||
pleaseReportCrash();
|
||||
}
|
||||
} catch (doubleFault) {
|
||||
// Ignoring exceptions in exception handling.
|
||||
}
|
||||
return Future.error(error, stackTrace);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCrashInUserCode(String message, exception, stackTrace) {
|
||||
hasCrashed = true;
|
||||
print('$message: ${tryToString(exception)}');
|
||||
print(tryToString(stackTrace));
|
||||
}
|
||||
|
||||
void reportSuppressedMessagesSummary() {
|
||||
if (!options.showAllPackageWarnings && !options.suppressWarnings) {
|
||||
suppressedWarnings.forEach((Uri uri, SuppressionInfo info) {
|
||||
MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS;
|
||||
if (info.warnings == 0) {
|
||||
kind = MessageKind.HIDDEN_HINTS;
|
||||
} else if (info.hints == 0) {
|
||||
kind = MessageKind.HIDDEN_WARNINGS;
|
||||
}
|
||||
MessageTemplate template = MessageTemplate.TEMPLATES[kind];
|
||||
Message message = template.message({
|
||||
'warnings': info.warnings.toString(),
|
||||
'hints': info.hints.toString(),
|
||||
'uri': uri.toString(),
|
||||
}, options);
|
||||
reportDiagnostic(DiagnosticMessage(null, null, message),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.HINT);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _TimingData {
|
||||
final String description;
|
||||
final int milliseconds;
|
||||
|
|
|
@ -4,72 +4,313 @@
|
|||
|
||||
library dart2js.diagnostic_listener;
|
||||
|
||||
import '../../compiler.dart' as api;
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../elements/entities.dart';
|
||||
import '../options.dart' show DiagnosticOptions;
|
||||
import '../io/source_information.dart';
|
||||
import '../options.dart';
|
||||
import '../ssa/nodes.dart' show HInstruction;
|
||||
import 'messages.dart';
|
||||
import 'source_span.dart' show SourceSpan;
|
||||
import 'spannable.dart' show Spannable;
|
||||
import 'spannable.dart';
|
||||
|
||||
// TODO(johnniwinther): Rename and cleanup this interface. Add severity enum.
|
||||
abstract class DiagnosticReporter {
|
||||
DiagnosticOptions get options;
|
||||
class DiagnosticReporter {
|
||||
final Compiler _compiler;
|
||||
|
||||
// TODO(karlklose): rename log to something like reportInfo.
|
||||
void log(message);
|
||||
CompilerOptions get options => _compiler.options;
|
||||
|
||||
internalError(Spannable spannable, message);
|
||||
Entity _currentElement;
|
||||
bool _hasCrashed = false;
|
||||
|
||||
/// Creates a [SourceSpan] for [node] in scope of the current element.
|
||||
///
|
||||
/// If [node] is a [Node] we assert in checked mode that the corresponding
|
||||
/// tokens can be found within the tokens of the current element.
|
||||
SourceSpan spanFromSpannable(Spannable node);
|
||||
/// `true` if the last diagnostic was filtered, in which case the
|
||||
/// accompanying info message should be filtered as well.
|
||||
bool _lastDiagnosticWasFiltered = false;
|
||||
|
||||
/// Map containing information about the warnings and hints that have been
|
||||
/// suppressed for each library.
|
||||
final Map<Uri, SuppressionInfo> _suppressedWarnings = {};
|
||||
|
||||
DiagnosticReporter(this._compiler);
|
||||
|
||||
Entity get currentElement => _currentElement;
|
||||
|
||||
DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
SourceSpan span = spanFromSpannable(spannable);
|
||||
MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
|
||||
Message message = template.message(arguments, options);
|
||||
return DiagnosticMessage(span, spannable, message);
|
||||
}
|
||||
|
||||
void reportError(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
_reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR);
|
||||
}
|
||||
|
||||
void reportErrorMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
reportError(createMessage(spannable, messageKind, arguments));
|
||||
}
|
||||
|
||||
void reportError(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
|
||||
void reportWarning(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
_reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING);
|
||||
}
|
||||
|
||||
void reportWarningMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
reportWarning(createMessage(spannable, messageKind, arguments));
|
||||
}
|
||||
|
||||
void reportWarning(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
|
||||
void reportHint(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
_reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
|
||||
}
|
||||
|
||||
void reportHintMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
reportHint(createMessage(spannable, messageKind, arguments));
|
||||
}
|
||||
|
||||
void reportHint(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
|
||||
void reportInfo(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
_reportDiagnosticInternal(message, infos, api.Diagnostic.INFO);
|
||||
}
|
||||
|
||||
void reportInfoMessage(Spannable node, MessageKind errorCode,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
reportInfo(createMessage(node, errorCode, arguments));
|
||||
}
|
||||
|
||||
void reportInfo(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
|
||||
void _reportDiagnosticInternal(DiagnosticMessage message,
|
||||
List<DiagnosticMessage> infos, api.Diagnostic kind) {
|
||||
if (!options.showAllPackageWarnings &&
|
||||
message.spannable != NO_LOCATION_SPANNABLE) {
|
||||
switch (kind) {
|
||||
case api.Diagnostic.WARNING:
|
||||
case api.Diagnostic.HINT:
|
||||
Entity element = _elementFromSpannable(message.spannable);
|
||||
if (!_compiler.inUserCode(element, assumeInUserCode: true)) {
|
||||
Uri uri = _compiler.getCanonicalUri(element);
|
||||
if (options.showPackageWarningsFor(uri)) {
|
||||
_reportDiagnostic(message, infos, kind);
|
||||
return;
|
||||
}
|
||||
SuppressionInfo info =
|
||||
_suppressedWarnings.putIfAbsent(uri, () => SuppressionInfo());
|
||||
if (kind == api.Diagnostic.WARNING) {
|
||||
info.warnings++;
|
||||
} else {
|
||||
info.hints++;
|
||||
}
|
||||
_lastDiagnosticWasFiltered = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case api.Diagnostic.INFO:
|
||||
if (_lastDiagnosticWasFiltered) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
_lastDiagnosticWasFiltered = false;
|
||||
_reportDiagnostic(message, infos, kind);
|
||||
}
|
||||
|
||||
/// Set current element of this reporter to [element]. This is used for
|
||||
/// creating [SourceSpan] in [spanFromSpannable].
|
||||
withCurrentElement(Entity element, f());
|
||||
|
||||
DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]);
|
||||
void _reportDiagnostic(DiagnosticMessage message,
|
||||
List<DiagnosticMessage> infos, api.Diagnostic kind) {
|
||||
_compiler.reportDiagnostic(message, infos, kind);
|
||||
if (kind == api.Diagnostic.ERROR ||
|
||||
kind == api.Diagnostic.CRASH ||
|
||||
(options.fatalWarnings && kind == api.Diagnostic.WARNING)) {
|
||||
_compiler.fatalDiagnosticReported(message, infos, kind);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if a crash, an error or a fatal warning has been reported.
|
||||
bool get hasReportedError;
|
||||
bool get hasReportedError => _compiler.compilationFailed;
|
||||
|
||||
/// Set current element of this reporter to [element]. This is used for
|
||||
/// creating [SourceSpan] in [spanFromSpannable]. That is,
|
||||
/// [withCurrentElement] performs an operation, [f], returning the return
|
||||
/// value from [f]. If an error occurs then report it as having occurred
|
||||
/// during compilation of [element]. Can be nested.
|
||||
dynamic withCurrentElement(Entity element, dynamic f()) {
|
||||
Entity old = currentElement;
|
||||
_currentElement = element;
|
||||
try {
|
||||
return f();
|
||||
} on SpannableAssertionFailure catch (ex) {
|
||||
if (!_hasCrashed) {
|
||||
_reportAssertionFailure(ex);
|
||||
_pleaseReportCrash();
|
||||
}
|
||||
_hasCrashed = true;
|
||||
rethrow;
|
||||
} on StackOverflowError {
|
||||
// We cannot report anything useful in this case, because we
|
||||
// do not have enough stack space.
|
||||
rethrow;
|
||||
} catch (ex) {
|
||||
if (_hasCrashed) rethrow;
|
||||
try {
|
||||
_unhandledExceptionOnElement(element);
|
||||
} catch (doubleFault) {
|
||||
// Ignoring exceptions in exception handling.
|
||||
}
|
||||
rethrow;
|
||||
} finally {
|
||||
_currentElement = old;
|
||||
}
|
||||
}
|
||||
|
||||
void _reportAssertionFailure(SpannableAssertionFailure ex) {
|
||||
String message =
|
||||
(ex.message != null) ? tryToString(ex.message) : tryToString(ex);
|
||||
_reportDiagnosticInternal(
|
||||
createMessage(ex.node, MessageKind.GENERIC, {'text': message}),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
}
|
||||
|
||||
/// Using [frontendStrategy] to compute a [SourceSpan] from spannable using
|
||||
/// the [currentElement] as context.
|
||||
SourceSpan _spanFromStrategy(Spannable spannable) {
|
||||
SourceSpan span;
|
||||
if (_compiler.phase == Compiler.PHASE_COMPILING) {
|
||||
span = _compiler.backendStrategy
|
||||
.spanFromSpannable(spannable, currentElement);
|
||||
} else {
|
||||
span = _compiler.frontendStrategy
|
||||
.spanFromSpannable(spannable, currentElement);
|
||||
}
|
||||
if (span != null) return span;
|
||||
throw 'No error location.';
|
||||
}
|
||||
|
||||
/// Creates a [SourceSpan] for [node] in scope of the current element.
|
||||
///
|
||||
/// If [node] is a [Node] we assert in checked mode that the corresponding
|
||||
/// tokens can be found within the tokens of the current element.
|
||||
SourceSpan spanFromSpannable(Spannable spannable) {
|
||||
if (spannable == CURRENT_ELEMENT_SPANNABLE) {
|
||||
spannable = currentElement;
|
||||
} else if (spannable == NO_LOCATION_SPANNABLE) {
|
||||
if (currentElement == null) return null;
|
||||
spannable = currentElement;
|
||||
}
|
||||
if (spannable is SourceSpan) {
|
||||
return spannable;
|
||||
} else if (spannable is HInstruction) {
|
||||
Entity element = spannable.sourceElement;
|
||||
if (element == null) element = currentElement;
|
||||
SourceInformation position = spannable.sourceInformation;
|
||||
if (position != null) return position.sourceSpan;
|
||||
return _spanFromStrategy(element);
|
||||
} else {
|
||||
return _spanFromStrategy(spannable);
|
||||
}
|
||||
}
|
||||
|
||||
dynamic internalError(Spannable spannable, reason) {
|
||||
String message = tryToString(reason);
|
||||
_reportDiagnosticInternal(
|
||||
createMessage(spannable, MessageKind.GENERIC, {'text': message}),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
throw 'Internal Error: $message';
|
||||
}
|
||||
|
||||
void _unhandledExceptionOnElement(Entity element) {
|
||||
if (_hasCrashed) return;
|
||||
_hasCrashed = true;
|
||||
_reportDiagnostic(createMessage(element, MessageKind.COMPILER_CRASHED),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.CRASH);
|
||||
_pleaseReportCrash();
|
||||
}
|
||||
|
||||
void _pleaseReportCrash() {
|
||||
print(MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
|
||||
.message({'buildId': _compiler.options.buildId}, options));
|
||||
}
|
||||
|
||||
/// Finds the approximate [Element] for [node]. [currentElement] is used as
|
||||
/// the default value.
|
||||
Entity _elementFromSpannable(Spannable node) {
|
||||
Entity element;
|
||||
if (node is Entity) {
|
||||
element = node;
|
||||
} else if (node is HInstruction) {
|
||||
element = node.sourceElement;
|
||||
}
|
||||
return element ?? currentElement;
|
||||
}
|
||||
|
||||
void log(message) {
|
||||
Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC]
|
||||
.message({'text': '$message'}, options);
|
||||
_reportDiagnostic(DiagnosticMessage(null, null, msg),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.VERBOSE_INFO);
|
||||
}
|
||||
|
||||
String tryToString(object) {
|
||||
try {
|
||||
return object.toString();
|
||||
} catch (_) {
|
||||
return '<exception in toString()>';
|
||||
}
|
||||
}
|
||||
|
||||
Future onError(Uri uri, error, StackTrace stackTrace) {
|
||||
try {
|
||||
if (!_hasCrashed) {
|
||||
_hasCrashed = true;
|
||||
if (error is SpannableAssertionFailure) {
|
||||
_reportAssertionFailure(error);
|
||||
} else {
|
||||
_reportDiagnostic(
|
||||
createMessage(
|
||||
SourceSpan(uri, 0, 0), MessageKind.COMPILER_CRASHED),
|
||||
const <DiagnosticMessage>[],
|
||||
api.Diagnostic.CRASH);
|
||||
}
|
||||
_pleaseReportCrash();
|
||||
}
|
||||
} catch (doubleFault) {
|
||||
// Ignoring exceptions in exception handling.
|
||||
}
|
||||
return Future.error(error, stackTrace);
|
||||
}
|
||||
|
||||
/// Called when an [exception] is thrown from user-provided code, like from
|
||||
/// the input provider or diagnostics handler.
|
||||
void onCrashInUserCode(String message, exception, stackTrace) {}
|
||||
void onCrashInUserCode(String message, exception, stackTrace) {
|
||||
_hasCrashed = true;
|
||||
print('$message: ${tryToString(exception)}');
|
||||
print(tryToString(stackTrace));
|
||||
}
|
||||
|
||||
void reportSuppressedMessagesSummary() {
|
||||
if (!options.showAllPackageWarnings && !options.suppressWarnings) {
|
||||
_suppressedWarnings.forEach((Uri uri, SuppressionInfo info) {
|
||||
MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS;
|
||||
if (info.warnings == 0) {
|
||||
kind = MessageKind.HIDDEN_HINTS;
|
||||
} else if (info.hints == 0) {
|
||||
kind = MessageKind.HIDDEN_WARNINGS;
|
||||
}
|
||||
MessageTemplate template = MessageTemplate.TEMPLATES[kind];
|
||||
Message message = template.message({
|
||||
'warnings': info.warnings.toString(),
|
||||
'hints': info.hints.toString(),
|
||||
'uri': uri.toString(),
|
||||
}, options);
|
||||
_reportDiagnostic(DiagnosticMessage(null, null, message),
|
||||
const <DiagnosticMessage>[], api.Diagnostic.HINT);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DiagnosticMessage {
|
||||
|
@ -79,3 +320,9 @@ class DiagnosticMessage {
|
|||
|
||||
DiagnosticMessage(this.sourceSpan, this.spannable, this.message);
|
||||
}
|
||||
|
||||
/// Information about suppressed warnings and hints for a given library.
|
||||
class SuppressionInfo {
|
||||
int warnings = 0;
|
||||
int hints = 0;
|
||||
}
|
||||
|
|
|
@ -341,7 +341,7 @@ class OutputUnitIrComputer extends IrDataExtractor<Features> {
|
|||
/// corresponding to [object] at location [sourceSpan]. We also perform error
|
||||
/// checking to ensure that the same [id] isn't added twice.
|
||||
void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
|
||||
Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
|
||||
Map<Id, ActualData<T>> actualMap, DiagnosticReporter reporter) {
|
||||
if (actualMap.containsKey(id)) {
|
||||
ActualData<T> existingData = actualMap[id];
|
||||
reportHere(reporter, sourceSpan,
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
// Copyright (c) 2015, 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.
|
||||
|
||||
// @dart = 2.7
|
||||
|
||||
library dart2js.diagnostic_reporter.helper;
|
||||
|
||||
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
|
||||
import 'package:compiler/src/diagnostics/messages.dart';
|
||||
import 'package:compiler/src/diagnostics/source_span.dart';
|
||||
import 'package:compiler/src/diagnostics/spannable.dart';
|
||||
import 'package:compiler/src/elements/entities.dart';
|
||||
import 'package:compiler/src/options.dart';
|
||||
|
||||
abstract class DiagnosticReporterWrapper extends DiagnosticReporter {
|
||||
DiagnosticReporter get reporter;
|
||||
|
||||
@override
|
||||
DiagnosticMessage createMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
return reporter.createMessage(spannable, messageKind, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
internalError(Spannable spannable, message) {
|
||||
return reporter.internalError(spannable, message);
|
||||
}
|
||||
|
||||
@override
|
||||
void log(message) {
|
||||
return reporter.log(message);
|
||||
}
|
||||
|
||||
@override
|
||||
DiagnosticOptions get options => reporter.options;
|
||||
|
||||
@override
|
||||
void reportError(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reporter.reportError(message, infos);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportHint(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reporter.reportHint(message, infos);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportInfo(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reporter.reportInfo(message, infos);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportInfoMessage(Spannable node, MessageKind errorCode,
|
||||
[Map<String, String> arguments = const {}]) {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
reporter.reportInfoMessage(node, errorCode, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
void reportWarning(DiagnosticMessage message,
|
||||
[List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
||||
reporter.reportWarning(message, infos);
|
||||
}
|
||||
|
||||
@override
|
||||
SourceSpan spanFromSpannable(Spannable node) {
|
||||
return reporter.spanFromSpannable(node);
|
||||
}
|
||||
|
||||
@override
|
||||
withCurrentElement(Entity element, f()) {
|
||||
return reporter.withCurrentElement(element, f);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get hasReportedError => reporter.hasReportedError;
|
||||
}
|
|
@ -28,7 +28,6 @@ import 'package:compiler/src/serialization/serialization.dart';
|
|||
import 'package:compiler/src/options.dart' show CompilerOptions;
|
||||
import 'package:compiler/src/universe/world_impact.dart';
|
||||
import 'package:compiler/src/world.dart';
|
||||
import 'diagnostic_reporter_helper.dart';
|
||||
import '../helpers/memory_compiler.dart';
|
||||
|
||||
class TestCompiler extends Compiler {
|
||||
|
@ -46,10 +45,8 @@ class TestCompiler extends Compiler {
|
|||
String this.testMarker,
|
||||
String this.testType,
|
||||
Function this.onTest)
|
||||
: reporter = new TestDiagnosticReporter(),
|
||||
super(inputProvider, outputProvider, handler, options) {
|
||||
reporter.compiler = this;
|
||||
reporter.reporter = super.reporter;
|
||||
: super(inputProvider, outputProvider, handler, options) {
|
||||
reporter = new TestDiagnosticReporter(this);
|
||||
test('Compiler');
|
||||
}
|
||||
|
||||
|
@ -122,10 +119,10 @@ class TestBackendStrategy extends JsBackendStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
class TestDiagnosticReporter extends DiagnosticReporterWrapper {
|
||||
class TestDiagnosticReporter extends DiagnosticReporter {
|
||||
TestCompiler compiler;
|
||||
@override
|
||||
DiagnosticReporter reporter;
|
||||
|
||||
TestDiagnosticReporter(this.compiler) : super(compiler);
|
||||
|
||||
@override
|
||||
withCurrentElement(Entity element, f()) {
|
||||
|
|
|
@ -18,6 +18,8 @@ const OBJECT = 'Object';
|
|||
const NULL = 'Null';
|
||||
|
||||
class Listener extends DiagnosticReporter {
|
||||
Listener() : super(null);
|
||||
|
||||
String errorMessage;
|
||||
@override
|
||||
internalError(spannable, message) {
|
||||
|
|
Loading…
Reference in a new issue