Skip to content

Commit a786576

Browse files
committed
Use messages for (some) public API errors
not entirely ready - looking for comments. BUG= [email protected] Review-Url: https://codereview.chromium.org/2979623002 .
1 parent 8623950 commit a786576

14 files changed

+200
-40
lines changed

pkg/front_end/lib/compilation_error.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ library front_end.compilation_error;
99
import 'package:source_span/source_span.dart' show SourceSpan;
1010

1111
/// A single error that occurred during compilation, and information about where
12-
/// it occurred.
12+
/// it occurred and how to fix it.
1313
///
1414
/// TODO(paulberry): add a reference to the analyzer error code.
1515
///
1616
/// Not intended to be implemented or extended by clients.
17+
// TODO(sigmund): rename to CompliationMessage
1718
abstract class CompilationError {
18-
/// A text description of how the user can fix the error. May be `null`.
19-
String get correction;
19+
/// A text description of the compile error.
20+
String get message;
21+
22+
/// A suggestion for the user to hint them on how to fix the error. May be
23+
/// `null`.
24+
String get tip;
2025

2126
/// The source span where the error occurred.
2227
SourceSpan get span;
23-
24-
/// A text description of the compile error.
25-
String get message;
2628
}

pkg/front_end/lib/kernel_generator.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:kernel/kernel.dart' show Program;
1212

1313
import 'compiler_options.dart';
1414
import 'src/base/processed_options.dart';
15+
import 'src/fasta/fasta_codes.dart';
1516
import 'src/kernel_generator_impl.dart';
1617

1718
/// Generates a kernel representation of the program whose main library is in
@@ -40,7 +41,7 @@ Future<Program> kernelForProgram(Uri source, CompilerOptions options) async {
4041
if (program == null) return null;
4142

4243
if (program.mainMethod == null) {
43-
pOptions.reportError("No 'main' method found.");
44+
pOptions.reportMessage(messageMissingMain.withLocation(source, -1));
4445
return null;
4546
}
4647

pkg/front_end/lib/src/base/processed_options.dart

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,19 @@ import 'package:front_end/compilation_error.dart';
88
import 'package:front_end/compiler_options.dart';
99
import 'package:front_end/file_system.dart';
1010
import 'package:front_end/src/base/performace_logger.dart';
11+
import 'package:front_end/src/fasta/fasta_codes.dart';
1112
import 'package:front_end/src/fasta/ticker.dart';
1213
import 'package:front_end/src/fasta/uri_translator.dart';
1314
import 'package:front_end/src/fasta/uri_translator_impl.dart';
15+
import 'package:front_end/src/fasta/problems.dart' show unimplemented;
1416
import 'package:front_end/src/incremental/byte_store.dart';
1517
import 'package:front_end/src/multi_root_file_system.dart';
1618
import 'package:kernel/kernel.dart'
1719
show Program, loadProgramFromBytes, CanonicalName;
1820
import 'package:kernel/target/targets.dart';
1921
import 'package:kernel/target/vm_fasta.dart';
2022
import 'package:package_config/packages_file.dart' as package_config;
21-
import 'package:source_span/source_span.dart' show SourceSpan;
23+
import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation;
2224

2325
/// All options needed for the front end implementation.
2426
///
@@ -111,38 +113,48 @@ class ProcessedOptions {
111113
return _raw.byteStore;
112114
}
113115

114-
// TODO(sigmund): delete. We should use messages with error codes directly
115-
// instead.
116-
void reportError(String message) {
117-
_raw.onError(new _CompilationError(message));
116+
// TODO(sigmund,ahe): delete in favor of reportMessage.
117+
void deprecated_reportError(String error) {
118+
_raw.onError(new _StringMessage(error));
118119
}
119120

121+
void reportMessage(LocatedMessage message) {
122+
_raw.onError(new _CompilationMessage(message));
123+
}
124+
125+
void reportMessageWithoutLocation(Message message) =>
126+
reportMessage(message.withLocation(null, -1));
127+
120128
/// Runs various validations checks on the input options. For instance,
121129
/// if an option is a path to a file, it checks that the file exists.
122130
Future<bool> validateOptions() async {
123131
for (var source in inputs) {
124132
if (source.scheme == 'file' &&
125133
!await fileSystem.entityForUri(source).exists()) {
126-
reportError("Entry-point file not found: $source");
134+
reportMessageWithoutLocation(
135+
templateMissingInputFile.withArguments('$source'));
127136
return false;
128137
}
129138
}
130139

131140
if (_raw.sdkRoot != null &&
132141
!await fileSystem.entityForUri(sdkRoot).exists()) {
133-
reportError("SDK root directory not found: ${sdkRoot}");
142+
reportMessageWithoutLocation(
143+
templateMissingSdkRoot.withArguments('$sdkRoot'));
134144
return false;
135145
}
136146

137147
var summary = sdkSummary;
138148
if (summary != null && !await fileSystem.entityForUri(summary).exists()) {
139-
reportError("SDK summary not found: ${summary}");
149+
reportMessageWithoutLocation(
150+
templateMissingSdkSummary.withArguments('$summary'));
140151
return false;
141152
}
142153

143154
if (compileSdk && summary != null) {
144-
reportError(
145-
"The compileSdk and sdkSummary options are mutually exclusive");
155+
reportMessageWithoutLocation(
156+
templateInternalProblemUnsupported.withArguments(
157+
"The compileSdk and sdkSummary options are mutually exclusive"));
146158
return false;
147159
}
148160
return true;
@@ -245,7 +257,7 @@ class ProcessedOptions {
245257
if (_packages == null) {
246258
if (_raw.packagesFileUri == null) {
247259
// TODO(sigmund,paulberry): implement
248-
throw new UnimplementedError('search for .packages');
260+
return unimplemented('search for .packages');
249261
} else if (_raw.packagesFileUri.path.isEmpty) {
250262
_packages = {};
251263
} else {
@@ -265,7 +277,7 @@ class ProcessedOptions {
265277
if (_raw.sdkRoot == null) {
266278
// TODO(paulberry): implement the algorithm for finding the SDK
267279
// automagically.
268-
throw new UnimplementedError('infer the default sdk location');
280+
return unimplemented('infer the default sdk location');
269281
}
270282
var root = _raw.sdkRoot;
271283
if (!root.path.endsWith('/')) {
@@ -346,12 +358,30 @@ class HermeticAccessException extends FileSystemException {
346358
String toString() => message;
347359
}
348360

349-
/// An error that only contains a message and no error location.
350-
class _CompilationError implements CompilationError {
351-
String get correction => null;
352-
SourceSpan get span => null;
361+
/// Wraps a [LocatedMessage] to implement the public [CompilationError] API.
362+
class _CompilationMessage implements CompilationError {
363+
final LocatedMessage original;
364+
365+
String get message => original.message;
366+
367+
String get tip => original.tip;
368+
369+
SourceSpan get span =>
370+
new SourceLocation(original.charOffset, sourceUrl: original.uri)
371+
.pointSpan();
372+
373+
_CompilationMessage(this.original);
374+
375+
String toString() => message;
376+
}
377+
378+
/// Wraps an error message as a [CompilationError] API.
379+
class _StringMessage implements CompilationError {
353380
final String message;
354-
_CompilationError(this.message);
381+
String get tip => null;
382+
SourceSpan get span => null;
383+
384+
_StringMessage(this.message);
355385

356386
String toString() => message;
357387
}

pkg/front_end/lib/src/fasta/fasta_codes_generated.dart

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,28 @@ Message _withArgumentsInternalProblemUnsupported(String name) {
14321432
arguments: {'name': name});
14331433
}
14341434

1435+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1436+
const Template<Message Function(String string)>
1437+
templateInternalVerificationError =
1438+
const Template<Message Function(String string)>(
1439+
messageTemplate:
1440+
r"""Verification of the generated program failed: #string.""",
1441+
withArguments: _withArgumentsInternalVerificationError);
1442+
1443+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1444+
const Code<Message Function(String string)> codeInternalVerificationError =
1445+
const Code<Message Function(String string)>(
1446+
"InternalVerificationError",
1447+
templateInternalVerificationError,
1448+
);
1449+
1450+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1451+
Message _withArgumentsInternalVerificationError(String string) {
1452+
return new Message(codeInternalVerificationError,
1453+
message: """Verification of the generated program failed: $string.""",
1454+
arguments: {'string': string});
1455+
}
1456+
14351457
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
14361458
const Code<Null> codeInvalidAwaitFor = messageInvalidAwaitFor;
14371459

@@ -1582,6 +1604,35 @@ const MessageCode messageMissingExponent = const MessageCode("MissingExponent",
15821604
tip:
15831605
r"""Make sure there is an exponent, and remove any whitespace before it.""");
15841606

1607+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1608+
const Template<Message Function(String string)> templateMissingInputFile =
1609+
const Template<Message Function(String string)>(
1610+
messageTemplate: r"""Input file not found: #string.""",
1611+
withArguments: _withArgumentsMissingInputFile);
1612+
1613+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1614+
const Code<Message Function(String string)> codeMissingInputFile =
1615+
const Code<Message Function(String string)>(
1616+
"MissingInputFile",
1617+
templateMissingInputFile,
1618+
);
1619+
1620+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1621+
Message _withArgumentsMissingInputFile(String string) {
1622+
return new Message(codeMissingInputFile,
1623+
message: """Input file not found: $string.""",
1624+
arguments: {'string': string});
1625+
}
1626+
1627+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1628+
const Code<Null> codeMissingMain = messageMissingMain;
1629+
1630+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1631+
const MessageCode messageMissingMain = const MessageCode("MissingMain",
1632+
dart2jsCode: "MISSING_MAIN",
1633+
message: r"""No 'main' method found.""",
1634+
tip: r"""Try adding a method named 'main' to your program.""");
1635+
15851636
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
15861637
const Template<
15871638
Message Function(Uri uri_)> templateMissingPartOf = const Template<
@@ -1606,6 +1657,46 @@ Message _withArgumentsMissingPartOf(Uri uri_) {
16061657
arguments: {'uri': uri_});
16071658
}
16081659

1660+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1661+
const Template<Message Function(String string)> templateMissingSdkRoot =
1662+
const Template<Message Function(String string)>(
1663+
messageTemplate: r"""SDK root directory not found: #string.""",
1664+
withArguments: _withArgumentsMissingSdkRoot);
1665+
1666+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1667+
const Code<Message Function(String string)> codeMissingSdkRoot =
1668+
const Code<Message Function(String string)>(
1669+
"MissingSdkRoot",
1670+
templateMissingSdkRoot,
1671+
);
1672+
1673+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1674+
Message _withArgumentsMissingSdkRoot(String string) {
1675+
return new Message(codeMissingSdkRoot,
1676+
message: """SDK root directory not found: $string.""",
1677+
arguments: {'string': string});
1678+
}
1679+
1680+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1681+
const Template<Message Function(String string)> templateMissingSdkSummary =
1682+
const Template<Message Function(String string)>(
1683+
messageTemplate: r"""SDK summary not found: #string.""",
1684+
withArguments: _withArgumentsMissingSdkSummary);
1685+
1686+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1687+
const Code<Message Function(String string)> codeMissingSdkSummary =
1688+
const Code<Message Function(String string)>(
1689+
"MissingSdkSummary",
1690+
templateMissingSdkSummary,
1691+
);
1692+
1693+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
1694+
Message _withArgumentsMissingSdkSummary(String string) {
1695+
return new Message(codeMissingSdkSummary,
1696+
message: """SDK summary not found: $string.""",
1697+
arguments: {'string': string});
1698+
}
1699+
16091700
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
16101701
const Code<Null> codeNamedFunctionExpression = messageNamedFunctionExpression;
16111702

pkg/front_end/lib/src/fasta/kernel/kernel_target.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ class KernelTarget extends TargetImplementation {
643643

644644
void verify() {
645645
var verifyErrors = verifyProgram(program);
646-
errors.addAll(verifyErrors.map((error) => '$error'));
646+
errors.addAll(verifyErrors.map((error) => error.message));
647647
ticker.logMs("Verified program");
648648
}
649649

pkg/front_end/lib/src/fasta/kernel/verifier.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ import 'package:kernel/verifier.dart' show VerificationError, VerifyingVisitor;
2424

2525
import '../deprecated_problems.dart' show deprecated_printUnexpected;
2626

27+
import '../fasta_codes.dart';
28+
2729
import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
2830

29-
List<VerificationError> verifyProgram(Program program,
30-
{bool isOutline: false}) {
31+
List<LocatedMessage> verifyProgram(Program program, {bool isOutline: false}) {
3132
FastaVerifyingVisitor verifier = new FastaVerifyingVisitor(isOutline);
3233
program.accept(verifier);
33-
return verifier.errors;
34+
return verifier.errors.map(convertError).toList();
3435
}
3536

3637
class FastaVerifyingVisitor extends VerifyingVisitor
@@ -106,3 +107,13 @@ class FastaVerifyingVisitor extends VerifyingVisitor
106107
problem(null, "Unexpected appearance of the unknown type.");
107108
}
108109
}
110+
111+
LocatedMessage convertError(VerificationError error) {
112+
var node = error.node ?? error.context;
113+
int offset = node?.fileOffset ?? -1;
114+
var file = node?.location?.file;
115+
Uri uri = file == null ? null : Uri.parse(file);
116+
return templateInternalVerificationError
117+
.withArguments(error.details)
118+
.withLocation(uri, offset);
119+
}

pkg/front_end/lib/src/fasta/problems.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ dynamic internalProblem(Message message, int charOffset, Uri uri) {
3434
}
3535
}
3636

37-
dynamic unimplemented(String what, int charOffset, Uri uri) {
37+
dynamic unimplemented(String what, [int charOffset = -1, Uri uri = null]) {
3838
return internalProblem(
3939
templateInternalProblemUnimplemented.withArguments(what),
4040
charOffset,

pkg/front_end/lib/src/kernel_generator_impl.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Future<CompilerResult> generateKernelInternal(ProcessedOptions options,
120120
trimProgram(summaryProgram, (uri) => !excluded.contains(uri));
121121
}
122122
if (options.verify) {
123-
verifyProgram(summaryProgram).forEach((e) => options.reportError('$e'));
123+
verifyProgram(summaryProgram).forEach(options.reportMessage);
124124
}
125125
if (options.debugDump) {
126126
printProgramText(summaryProgram,
@@ -147,7 +147,7 @@ Future<CompilerResult> generateKernelInternal(ProcessedOptions options,
147147
}
148148

149149
if (kernelTarget.errors.isNotEmpty) {
150-
kernelTarget.errors.forEach(options.reportError);
150+
kernelTarget.errors.forEach(options.deprecated_reportError);
151151
return null;
152152
}
153153

@@ -156,7 +156,7 @@ Future<CompilerResult> generateKernelInternal(ProcessedOptions options,
156156
program: program,
157157
deps: kernelTarget.loader.getDependencies());
158158
} on deprecated_InputError catch (e) {
159-
options.reportError(e.deprecated_format());
159+
options.deprecated_reportError(e.deprecated_format());
160160
return null;
161161
} catch (e, t) {
162162
return reportCrash(e, t);

pkg/front_end/messages.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,9 @@ InternalProblemAlreadyInitialized:
624624
InternalProblemBodyOnAbstractMethod:
625625
template: "Attempting to set body on abstract method."
626626

627+
InternalVerificationError:
628+
template: "Verification of the generated program failed: #string."
629+
627630
LocalDefinitionHidesExport:
628631
template: "Local definition of '#name' hides export from '#uri'."
629632

@@ -781,3 +784,17 @@ PartOfUseUri:
781784

782785
PartOfUriMismatch:
783786
template: "Using '#uri' as part of '#uri2' but its 'part of' declaration says '#string'."
787+
788+
MissingMain:
789+
template: "No 'main' method found."
790+
tip: "Try adding a method named 'main' to your program."
791+
dart2jsCode: MISSING_MAIN
792+
793+
MissingInputFile:
794+
template: "Input file not found: #string."
795+
796+
MissingSdkRoot:
797+
template: "SDK root directory not found: #string."
798+
799+
MissingSdkSummary:
800+
template: "SDK summary not found: #string."

0 commit comments

Comments
 (0)