Implement line and column numbers.

R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2704753002 .
This commit is contained in:
Peter von der Ahé 2017-02-20 10:04:12 +01:00
parent fd918a2725
commit d32f47b293
29 changed files with 388 additions and 161 deletions

View file

@ -53,15 +53,18 @@ class AstBuilder extends ScopeListener {
bool isFirstIdentifier = false;
@override
final Uri uri;
/// If `true`, the first call to [handleIdentifier] should push a
/// List<SimpleIdentifier> on the stack, and [handleQualified] should append
/// to the list.
var accumulateIdentifierComponents = false;
AstBuilder(this.library, this.member, this.elementStore, Scope scope)
: super(scope);
Uri get uri => library.fileUri ?? library.uri;
AstBuilder(this.library, this.member, this.elementStore, Scope scope,
[Uri uri])
: uri = uri ?? library.fileUri, super(scope);
createJumpTarget(JumpTargetKind kind, int charOffset) {
// TODO(ahe): Implement jump targets.

View file

@ -12,9 +12,11 @@ import 'package:front_end/src/fasta/ast_kind.dart' show
import 'package:front_end/src/fasta/compiler_command_line.dart' show
CompilerCommandLine;
import 'package:front_end/src/fasta/compiler_context.dart' show
CompilerContext;
import 'package:front_end/src/fasta/outline.dart' show
doCompile,
parseArguments;
doCompile;
import 'package:front_end/src/fasta/errors.dart' show
InputError;
@ -29,20 +31,23 @@ const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
main(List<String> arguments) async {
Uri uri;
CompilerCommandLine cl;
for (int i = 0; i < iterations; i++) {
if (i > 0) {
print("\n");
}
try {
cl = parseArguments("run", arguments);
uri =
await doCompile(cl, new Ticker(isVerbose:cl.verbose), AstKind.Kernel);
} on InputError catch (e) {
print(e.format());
exit(1);
}
if (exitCode != 0) exit(exitCode);
await CompilerCommandLine.withGlobalOptions(
"run", arguments, (CompilerContext c) async {
if (i > 0) {
print("\n");
}
try {
uri = await doCompile(c, new Ticker(isVerbose: c.options.verbose),
AstKind.Kernel);
} on InputError catch (e) {
print(e.format());
exit(1);
}
if (exitCode != 0) exit(exitCode);
if (i + 1 == iterations) {
exit(await run(uri, c));
}
});
}
exit(await run(uri, cl));
}

View file

@ -7,6 +7,9 @@ library fasta.builder;
import '../errors.dart' show
internalError;
import '../messages.dart' show
nit;
export 'class_builder.dart' show
ClassBuilder;
@ -127,16 +130,17 @@ abstract class Builder {
preferred = other;
hidden = this;
} else {
print("${library.uri}: Note: '$name' is imported from both "
nit(library.fileUri, -1, "'$name' is imported from both "
"'${getUri(this)}' and '${getUri(other)}'.");
return library.buildAmbiguousBuilder(name, this, other, charOffset);
}
if (isLocal) {
print("${library.uri}: Note: local definition of '$name' hides imported "
nit(library.fileUri, -1, "Local definition of '$name' hides imported "
"version from '${getUri(other)}'.");
} else {
print("${library.uri}: import of '$name' (from '${getUri(preferred)}') "
"hides imported version from '${getUri(hidden)}'.");
nit(library.fileUri, -1, "Import of '$name' "
"(from '${getUri(preferred)}') hides imported version from "
"'${getUri(hidden)}'.");
}
return preferred;
}

View file

@ -10,6 +10,9 @@ import 'builder.dart' show
Builder,
TypeBuilder;
import '../messages.dart' show
warning;
import 'scope.dart' show
Scope;
@ -54,7 +57,7 @@ class ConstructorReferenceBuilder extends Builder {
target = builder.constructors[suffix ?? ""];
}
if (target == null) {
print("Couldn't find constructor $fullNameForErrors.");
warning(null, -1, "Couldn't find constructor '$fullNameForErrors'.");
}
}
}

View file

@ -9,6 +9,9 @@ import 'builder.dart' show
LibraryBuilder,
MemberBuilder;
import '../messages.dart' show
warning;
import 'package:kernel/ast.dart' show
Member;
@ -32,8 +35,8 @@ class PrefixBuilder extends Builder {
// TODO(ahe): Move this to KernelPrefixBuilder.
Builder builder = exports[name];
if (builder == null) {
// TODO(ahe): Report error?
print("${this.name} has no member named $name");
warning(parent.fileUri, -1,
"'${this.name}' has no member named '$name'.");
}
if (builder is DillMemberBuilder) {
return builder.member.isInstanceMember

View file

@ -11,11 +11,15 @@ import 'command_line.dart' show
CommandLine,
argumentError;
import 'compiler_context.dart' show
CompilerContext;
const Map<String, dynamic> optionSpecification = const <String, dynamic>{
"-o": Uri,
"--output": Uri,
"--platform": Uri,
"--packages": Uri,
"--fatal": ",",
};
class CompilerCommandLine extends CommandLine {
@ -65,6 +69,26 @@ class CompilerCommandLine extends CommandLine {
? null
: options["--platform"] ?? Uri.base.resolve("platform.dill");
}
Set<String> get fatal {
return new Set<String>.from(options["--fatal"] ?? <String>[]);
}
bool get areErrorsFatal => fatal.contains("errors");
bool get areWarningsFatal => fatal.contains("warnings");
bool get areNitsFatal => fatal.contains("nits");
static dynamic withGlobalOptions(String programName, List<String> arguments,
dynamic f(CompilerContext context)) {
return CompilerContext.withGlobalOptions(
new CompilerCommandLine(programName, arguments), f);
}
static CompilerCommandLine forRootContext() {
return new CompilerCommandLine("", [""]);
}
}
String computeUsage(String programName, bool verbose) {
@ -140,4 +164,12 @@ Supported options:
--compile-sdk
Compile the SDK from scratch instead of reading it from 'platform.dill'.
--fatal=errors
--fatal=warnings
--fatal=nits
Makes messages of the given kinds fatal, that is, immediately stop the
compiler with a non-zero exit-code. In --verbose mode, also display an
internal stack trace from the compiler. Multiple kinds can be separated by
commas, for example, --fatal=errors,warnings.
""";

View file

@ -0,0 +1,40 @@
// Copyright (c) 2017, 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.
library fasta.compiler_context;
import 'dart:async' show
Zone,
runZoned;
import 'package:kernel/ast.dart' show
Source;
import 'compiler_command_line.dart' show
CompilerCommandLine;
final Object compilerContextKey = new Object();
final CompilerContext rootContext =
new CompilerContext(CompilerCommandLine.forRootContext());
class CompilerContext {
final CompilerCommandLine options;
final Map<String, Source> uriToSource = <String, Source>{};
CompilerContext(this.options);
static CompilerContext get current {
return Zone.current[compilerContextKey] ?? rootContext;
}
/// Perform [action] in a [Zone] where [cl] will be available as
/// `CompilerContext.current.options`.
static dynamic withGlobalOptions(CompilerCommandLine cl,
dynamic action(CompilerContext c)) {
CompilerContext c = new CompilerContext(cl);
return runZoned(() => action(c), zoneValues: {compilerContextKey: c});
}
}

View file

@ -45,6 +45,10 @@ class DillTarget extends TargetImplementation {
loader = new DillLoader(this);
}
void addLineStarts(Uri uri, List<int> lineStarts) {
internalError("Unsupported operation.");
}
void read(Uri uri) {
if (loader.input == null) {
loader.input = uri;

View file

@ -20,8 +20,7 @@ import 'dart:io' show
import 'colors.dart' show
red;
import 'util/relativize.dart' show
relativizeUri;
import 'messages.dart' as messages;
const String defaultServerAddress = "http://127.0.0.1:59410/";
@ -41,8 +40,13 @@ Uri firstSourceUri;
/// error: " and a short description that may help a developer debug the issue.
/// This method should be called instead of using `throw`, as this allows us to
/// ensure that there are no throws anywhere in the codebase.
dynamic internalError(Object error) {
throw error;
dynamic internalError(Object error, [Uri uri, int charOffset = -1]) {
if (uri == null && charOffset == -1) {
throw error;
} else {
throw messages.format(
uri, charOffset, "Internal error: ${safeToString(error)}");
}
}
/// Used to report an error in input.
@ -58,6 +62,12 @@ dynamic inputError(Uri uri, int charOffset, Object error) {
throw new InputError(uri, charOffset, error);
}
String colorError(String message) {
// TODO(ahe): Colors need to be optional. Doesn't work well in Emacs or on
// Windows.
return red(message);
}
class InputError {
final Uri uri;
@ -71,15 +81,8 @@ class InputError {
toString() => "InputError: $error";
String format() {
// TODO(ahe): Colors need to be optional. Doesn't work well in Emacs or on
// Windows.
String message = red("Error: ${safeToString(error)}");
if (uri != null) {
String position = charOffset == -1 ? "" : "$charOffset:";
return "${relativizeUri(uri)}:$position $message";
} else {
return message;
}
return messages.format(
uri, charOffset, colorError("Error: ${safeToString(error)}"));
}
}

View file

@ -79,8 +79,6 @@ import 'redirecting_factory_body.dart' show
import 'kernel_builder.dart';
const bool showNits = false;
final Name callName = new Name("call");
final Name plusName = new Name("+");
@ -126,6 +124,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
final bool isDartLibrary;
@override
final Uri uri;
Scope formalParameterScope;
bool isFirstIdentifier = false;
@ -148,7 +149,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
BodyBuilder(KernelLibraryBuilder library, this.member, Scope scope,
this.formalParameterScope, this.hierarchy, this.coreTypes,
this.classBuilder, this.isInstanceMember)
this.classBuilder, this.isInstanceMember, this.uri)
: enclosingScope = scope,
library = library,
isDartLibrary = library.uri.scheme == "dart",
@ -272,9 +273,6 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
switchScope = pop();
}
@override
Uri get uri => library.fileUri ?? library.uri;
@override
JumpTarget createJumpTarget(JumpTargetKind kind, int charOffset) {
return new JumpTarget(kind, member, charOffset);
@ -340,7 +338,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
@override
void endMember() {
debugEvent("Member");
checkEmpty();
checkEmpty(-1);
}
@override
@ -1153,9 +1151,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
return builder.buildTypesWithBuiltArguments(arguments);
}
if (builder == null) {
print("$uri: Type not found: $name");
warning("Type not found: '$name'.", charOffset);
} else {
print("$uri: Not a type: $name");
warning("Not a type: '$name'.", charOffset);
}
// TODO(ahe): Create an error somehow.
return const DynamicType();
@ -1300,7 +1298,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
FieldBuilder field = builder;
if (type != null) {
nit("Ignoring type on 'this' parameter '${name.name}'.",
name.fileOffset);
thisKeyword.charOffset);
}
type = field.target.type ?? const DynamicType();
variable = new VariableDeclaration(name.name, type: type,
@ -2167,7 +2165,8 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
super.handleRecoverableError(token, kind, arguments);
if (!hasParserError) {
print("$uri:${recoverableErrors.last}");
print(new InputError(uri, recoverableErrors.last.beginOffset,
recoverableErrors.last.kind).format());
}
hasParserError = true;
}
@ -2189,17 +2188,6 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
return super.handleUnrecoverableError(token, kind, arguments);
}
void warning(error, [int charOffset = -1]) {
String message = new InputError(uri, charOffset, error).format();
print(message);
}
void nit(error, [int charOffset = -1]) {
if (!showNits) return;
String message = new InputError(uri, charOffset, error).format();
print(message);
}
@override
Expression buildCompileTimeError(error, [int charOffset = -1]) {
String message = new InputError(uri, charOffset, error).format();

View file

@ -16,6 +16,7 @@ import 'package:kernel/core_types.dart' show
CoreTypes;
import '../errors.dart' show
InputError,
internalError;
import 'frontend_accessors.dart' as kernel show
@ -694,7 +695,7 @@ class VariableAccessor extends kernel.VariableAccessor
Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri,
int charOffset, CoreTypes coreTypes,
{bool isSuper: false, isGetter: false, isSetter: false}) {
print("$uri:$charOffset: method not found: '$name'.");
print(new InputError(uri, charOffset, "Method not found: '$name'.").format());
Constructor constructor = coreTypes.getCoreClass(
"dart:core", "NoSuchMethodError").constructors.first;
return new Throw(new ConstructorInvocation(

View file

@ -17,6 +17,9 @@ import 'package:kernel/ast.dart' show
import '../errors.dart' show
internalError;
import '../messages.dart' show
warning;
import 'kernel_builder.dart' show
Builder,
ClassBuilder,
@ -105,9 +108,9 @@ abstract class KernelClassBuilder
} else {
// TODO(ahe): Throw NSM error. This requires access to core
// types.
String message =
"Missing constructor: ${redirectionTarget.fullNameForErrors}";
print(message);
String message = "Redirection constructor target not found: "
"${redirectionTarget.fullNameForErrors}";
warning(library.fileUri, -1, message);
builder.body = new ExpressionStatement(
new Throw(new StringLiteral(message)));
}

View file

@ -15,6 +15,9 @@ import 'package:kernel/ast.dart' show
import 'package:kernel/type_algebra.dart' show
substitute;
import '../messages.dart' show
warning;
import 'kernel_builder.dart' show
FormalParameterBuilder,
FunctionTypeAliasBuilder,
@ -45,7 +48,8 @@ class KernelFunctionTypeAliasBuilder
if (thisType == const InvalidType()) {
thisType = const DynamicType();
// TODO(ahe): Build an error somehow.
print("${parent.uri}: Cyclic typedef: $name.");
warning(parent.uri, -1,
"The typedef '$name' has a reference to itself.");
}
return thisType;
}

View file

@ -8,6 +8,9 @@ import 'package:kernel/ast.dart' show
DartType,
DynamicType;
import '../messages.dart' show
warning;
import 'kernel_builder.dart' show
InvalidTypeBuilder,
KernelTypeBuilder;
@ -19,14 +22,14 @@ class KernelInvalidTypeBuilder
DartType buildType(List<KernelTypeBuilder> arguments) {
// TODO(ahe): Implement error handling.
print("No type for: $name");
warning(fileUri, charOffset, "No type for: '$name'.");
return const DynamicType();
}
/// [Arguments] have already been built.
DartType buildTypesWithBuiltArguments(List<DartType> arguments) {
// TODO(ahe): Implement error handling.
print("No type for: $name");
warning(fileUri, charOffset, "No type for: '$name'.");
return const DynamicType();
}
}

View file

@ -10,8 +10,8 @@ import 'package:kernel/ast.dart' show
Supertype,
VoidType;
import '../errors.dart' show
inputError;
import '../messages.dart' show
warning;
import 'kernel_builder.dart' show
KernelClassBuilder,
@ -30,18 +30,19 @@ class KernelNamedTypeBuilder
KernelInvalidTypeBuilder buildInvalidType(String name) {
// TODO(ahe): Record error instead of printing.
print("$fileUri:$charOffset: Type not found: $name");
warning(fileUri, charOffset, "Type not found: '$name'.");
return new KernelInvalidTypeBuilder(name, charOffset, fileUri);
}
DartType handleMissingType() {
// TODO(ahe): Record error instead of printing.
print("$fileUri:$charOffset: No type for: $name");
warning(fileUri, charOffset, "No type for: '$name'.");
return const DynamicType();
}
Supertype handleMissingSuperType() {
throw inputError(fileUri, charOffset, "No type for: $name");
warning(fileUri, charOffset, "No type for: '$name'.");
return null;
}
DartType build() {

View file

@ -40,6 +40,9 @@ import 'package:kernel/type_algebra.dart' show
import '../errors.dart' show
internalError;
import '../messages.dart' show
warning;
import '../loader.dart' show
Loader;
@ -129,7 +132,8 @@ abstract class KernelFunctionBuilder
substitution[parameter] = const DynamicType();
}
}
print("Can only use type variables in instance methods.");
warning(fileUri, charOffset,
"Can only use type variables in instance methods.");
return substitute(type, substitution);
}
Set<TypeParameter> set = typeParameters.toSet();

View file

@ -75,6 +75,12 @@ import '../errors.dart' show
reportCrash,
resetCrashReporting;
import '../util/relativize.dart' show
relativizeUri;
import '../compiler_context.dart' show
CompilerContext;
import 'kernel_builder.dart' show
Builder,
ClassBuilder,
@ -92,18 +98,29 @@ import 'kernel_builder.dart' show
class KernelTarget extends TargetImplementation {
final DillTarget dillTarget;
/// Shared with [CompilerContext].
final Map<String, Source> uriToSource;
SourceLoader<Library> loader;
Program program;
final List errors = [];
KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator)
KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator,
[Map<String, Source> uriToSource])
: dillTarget = dillTarget,
uriToSource = uriToSource ?? CompilerContext.current.uriToSource,
super(dillTarget.ticker, uriTranslator) {
resetCrashReporting();
loader = new SourceLoader<Library>(this);
}
void addLineStarts(Uri uri, List<int> lineStarts) {
String fileUri = relativizeUri(uri);
uriToSource[fileUri] = new Source(lineStarts, fileUri);
}
void read(Uri uri) {
loader.read(uri);
}
@ -317,7 +334,9 @@ class KernelTarget extends TargetImplementation {
program.mainMethod = builder.procedure;
}
}
setup_builtin_library.transformProgram(program);
if (errors.isEmpty || dillTarget.isLoaded) {
setup_builtin_library.transformProgram(program);
}
ticker.logMs("Linked program");
return program;
}

View file

@ -0,0 +1,74 @@
// Copyright (c) 2016, 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.
library fasta.messages;
import 'package:kernel/ast.dart' show
Location,
Program;
import 'util/relativize.dart' show
relativizeUri;
import 'compiler_context.dart' show
CompilerContext;
import 'errors.dart' show
InputError;
import 'colors.dart' show
cyan,
magenta;
const bool hideNits = false;
const bool hideWarnings = false;
void warning(Uri uri, int charOffset, String message) {
if (hideWarnings) return;
print(format(uri, charOffset, colorWarning("Warning: $message")));
if (CompilerContext.current.options.areWarningsFatal) {
if (CompilerContext.current.options.verbose) print(StackTrace.current);
throw new InputError(
uri, charOffset, "Compilation aborted due to fatal warnings.");
}
}
void nit(Uri uri, int charOffset, String message) {
if (hideNits) return;
print(format(uri, charOffset, colorNit("Nit: $message")));
if (CompilerContext.current.options.areNitsFatal) {
if (CompilerContext.current.options.verbose) print(StackTrace.current);
throw new InputError(
uri, charOffset, "Compilation aborted due to fatal nits.");
}
}
String colorWarning(String message) {
// TODO(ahe): Colors need to be optional. Doesn't work well in Emacs or on
// Windows.
return magenta(message);
}
String colorNit(String message) {
// TODO(ahe): Colors need to be optional. Doesn't work well in Emacs or on
// Windows.
return cyan(message);
}
String format(Uri uri, int charOffset, String message) {
if (uri != null) {
String path = relativizeUri(uri);
String position = charOffset == -1
? path : "${getLocation(path, charOffset)}";
return "$position: $message";
} else {
return message;
}
}
Location getLocation(String path, int charOffset) {
return new Program(null, CompilerContext.current.uriToSource)
.getLocation(path, charOffset);
}

View file

@ -16,6 +16,9 @@ import 'package:kernel/verifier.dart' show
import 'compiler_command_line.dart' show
CompilerCommandLine;
import 'compiler_context.dart' show
CompilerContext;
import 'errors.dart' show
InputError,
inputError;
@ -40,15 +43,16 @@ import 'ast_kind.dart' show
import 'testing/kernel_chain.dart' show
computePatchedSdk;
CompilerCommandLine parseArguments(String programName, List<String> arguments) {
return new CompilerCommandLine(programName, arguments);
}
Future<KernelTarget> outline(List<String> arguments) async {
try {
CompilerCommandLine cl = parseArguments("outline", arguments);
if (cl.verbose) print("Building outlines for ${arguments.join(' ')}");
return await doOutline(cl, new Ticker(isVerbose: cl.verbose), cl.output);
return await CompilerCommandLine.withGlobalOptions(
"outline", arguments, (CompilerContext c) async {
if (c.options.verbose) {
print("Building outlines for ${arguments.join(' ')}");
}
return await doOutline(c, new Ticker(isVerbose: c.options.verbose),
c.options.output);
});
} on InputError catch (e) {
exitCode = 1;
print(e.format());
@ -58,12 +62,14 @@ Future<KernelTarget> outline(List<String> arguments) async {
Future<Uri> compile(List<String> arguments) async {
try {
CompilerCommandLine cl = parseArguments("compile", arguments);
if (cl.verbose) {
print("Compiling directly to Kernel: ${arguments.join(' ')}");
}
return
await doCompile(cl, new Ticker(isVerbose: cl.verbose), AstKind.Kernel);
return await CompilerCommandLine.withGlobalOptions(
"compile", arguments, (CompilerContext c) async {
if (c.options.verbose) {
print("Compiling directly to Kernel: ${arguments.join(' ')}");
}
return await doCompile(c, new Ticker(isVerbose: c.options.verbose),
AstKind.Kernel);
});
} on InputError catch (e) {
exitCode = 1;
print(e.format());
@ -73,10 +79,14 @@ Future<Uri> compile(List<String> arguments) async {
Future<Uri> kompile(List<String> arguments) async {
try {
CompilerCommandLine cl = parseArguments("kompile", arguments);
if (cl.verbose) print("Compiling via analyzer: ${arguments.join(' ')}");
return await doCompile(
cl, new Ticker(isVerbose: cl.verbose), AstKind.Analyzer);
return await CompilerCommandLine.withGlobalOptions(
"kompile", arguments, (CompilerContext c) async {
if (c.options.verbose) {
print("Compiling via analyzer: ${arguments.join(' ')}");
}
return await doCompile(c, new Ticker(isVerbose: c.options.verbose),
AstKind.Analyzer);
});
} on InputError catch (e) {
exitCode = 1;
print(e.format());
@ -84,19 +94,20 @@ Future<Uri> kompile(List<String> arguments) async {
}
}
Future<KernelTarget> doOutline(CompilerCommandLine cl, Ticker ticker,
Future<KernelTarget> doOutline(CompilerContext c, Ticker ticker,
[Uri output]) async {
Uri sdk = await computePatchedSdk();
ticker.logMs("Found patched SDK");
TranslateUri uriTranslator = await TranslateUri.parse(sdk);
ticker.logMs("Read packages file");
DillTarget dillTarget = new DillTarget(ticker, uriTranslator);
KernelTarget kernelTarget = new KernelTarget(dillTarget, uriTranslator);
Uri platform = cl.platform;
KernelTarget kernelTarget =
new KernelTarget(dillTarget, uriTranslator, c.uriToSource);
Uri platform = c.options.platform;
if (platform != null) {
dillTarget.read(platform);
}
String argument = cl.arguments.first;
String argument = c.options.arguments.first;
Uri uri = Uri.base.resolve(argument);
String path = uriTranslator.translate(uri)?.path ?? argument;
if (path.endsWith(".dart")) {
@ -106,29 +117,28 @@ Future<KernelTarget> doOutline(CompilerCommandLine cl, Ticker ticker,
}
await dillTarget.writeOutline(null);
await kernelTarget.writeOutline(output);
if (cl.dumpIr && output != null) {
if (c.options.dumpIr && output != null) {
kernelTarget.dumpIr();
}
return kernelTarget;
}
Future<Uri> doCompile(CompilerCommandLine cl, Ticker ticker,
AstKind kind) async {
KernelTarget kernelTarget = await doOutline(cl, ticker);
Future<Uri> doCompile(CompilerContext c, Ticker ticker, AstKind kind) async {
KernelTarget kernelTarget = await doOutline(c, ticker);
if (exitCode != 0) return null;
Uri uri = cl.output;
Uri uri = c.options.output;
await kernelTarget.writeProgram(uri, kind);
if (cl.dumpIr) {
if (c.options.dumpIr) {
kernelTarget.dumpIr();
}
if (cl.verify) {
if (c.options.verify) {
try {
verifyProgram(kernelTarget.program);
ticker.logMs("Verified program");
} catch (e, s) {
exitCode = 1;
print("Verification of program failed: $e");
if (s != null && cl.verbose) {
if (s != null && c.options.verbose) {
print(s);
}
}

View file

@ -17,15 +17,15 @@ import 'testing/kernel_chain.dart' show
computeDartVm,
computePatchedSdk;
import 'compiler_command_line.dart' show
CompilerCommandLine;
import 'compiler_context.dart' show
CompilerContext;
Future<int> run(Uri uri, CompilerCommandLine cl) async {
Future<int> run(Uri uri, CompilerContext c) async {
Uri sdk = await computePatchedSdk();
Uri dartVm = computeDartVm(sdk);
List<String> arguments = <String>["${uri.toFilePath()}"]
..addAll(cl.arguments.skip(1));
if (cl.verbose) {
..addAll(c.options.arguments.skip(1));
if (c.options.verbose) {
print("Running ${dartVm.toFilePath()} ${arguments.join(' ')}");
}
StdioProcess result = await StdioProcess.run(dartVm.toFilePath(), arguments);

View file

@ -78,15 +78,16 @@ class DietListener extends StackListener {
/// this is the instance scope of [currentClass].
Scope memberScope;
@override
Uri uri;
DietListener(SourceLibraryBuilder library, this.elementStore, this.hierarchy,
this.coreTypes, this.astKind)
: library = library,
uri = library.fileUri,
memberScope = library.scope,
isDartLibrary = library.uri.scheme == "dart";
@override
Uri get uri => library.uri;
void discard(int n) {
for (int i =0; i < n; i++) {
pop();
@ -192,7 +193,7 @@ class DietListener extends StackListener {
void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
debugEvent("FunctionTypeAlias");
discard(2); // Name + endToken.
checkEmpty();
checkEmpty(typedefKeyword.charOffset);
}
@override
@ -213,7 +214,7 @@ class DietListener extends StackListener {
debugEvent("TopLevelMethod");
Token bodyToken = pop();
String name = pop();
checkEmpty();
checkEmpty(beginToken.charOffset);
buildFunctionBody(bodyToken, lookupBuilder(beginToken, getOrSet, name));
}
@ -363,7 +364,7 @@ class DietListener extends StackListener {
debugEvent("FactoryMethod");
BeginGroupToken bodyToken = pop();
String name = pop();
checkEmpty();
checkEmpty(beginToken.charOffset);
if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
return;
}
@ -381,7 +382,7 @@ class DietListener extends StackListener {
debugEvent("Method");
Token bodyToken = pop();
String name = pop();
checkEmpty();
checkEmpty(beginToken.charOffset);
if (bodyToken == null) {
return;
}
@ -394,10 +395,10 @@ class DietListener extends StackListener {
case AstKind.Kernel:
return new BodyBuilder(library, builder, memberScope,
formalParameterScope, hierarchy, coreTypes, currentClass,
isInstanceMember);
isInstanceMember, uri);
case AstKind.Analyzer:
return new AstBuilder(library, builder, elementStore, memberScope);
return new AstBuilder(library, builder, elementStore, memberScope, uri);
}
return internalError("Unknown $astKind");
@ -423,7 +424,7 @@ class DietListener extends StackListener {
@override
void endMember() {
debugEvent("Member");
checkEmpty();
checkEmpty(-1);
}
@override
@ -440,7 +441,7 @@ class DietListener extends StackListener {
void endClassBody(int memberCount, Token beginToken, Token endToken) {
debugEvent("ClassBody");
currentClass = null;
checkEmpty();
checkEmpty(beginToken.charOffset);
memberScope = library.scope;
}
@ -448,7 +449,7 @@ class DietListener extends StackListener {
void endClassDeclaration(int interfacesCount, Token beginToken,
Token extendsKeyword, Token implementsKeyword, Token endToken) {
debugEvent("ClassDeclaration");
checkEmpty();
checkEmpty(beginToken.charOffset);
}
@override
@ -456,7 +457,7 @@ class DietListener extends StackListener {
debugEvent("Enum");
discard(count);
pop(); // Name.
checkEmpty();
checkEmpty(enumKeyword.charOffset);
}
@override
@ -464,7 +465,7 @@ class DietListener extends StackListener {
Token classKeyword, Token implementsKeyword, Token endToken) {
debugEvent("NamedMixinApplication");
pop(); // Name.
checkEmpty();
checkEmpty(classKeyword.charOffset);
}
@override
@ -490,7 +491,7 @@ class DietListener extends StackListener {
Parser parser = new Parser(listener);
token = parser.parseFormalParametersOpt(token);
var formals = listener.pop();
listener.checkEmpty();
listener.checkEmpty(token.charOffset);
listener.prepareInitializers();
token = parser.parseInitializersOpt(token);
token = parser.parseAsyncModifier(token);
@ -499,7 +500,7 @@ class DietListener extends StackListener {
bool allowAbstract = true;
parser.parseFunctionBody(token, isExpression, allowAbstract);
var body = listener.pop();
listener.checkEmpty();
listener.checkEmpty(token.charOffset);
listener.finishFunction(formals, asyncModifier, body);
} on InputError {
rethrow;
@ -515,7 +516,7 @@ class DietListener extends StackListener {
} else {
token = parser.parseMember(token);
}
listener.checkEmpty();
listener.checkEmpty(token.charOffset);
}
Builder lookupBuilder(Token token, Token getOrSet, String name) {
@ -531,7 +532,7 @@ class DietListener extends StackListener {
builder = library.members[name];
}
if (builder == null) {
return internalError("@${token.charOffset}: builder not found: $name");
return internalError("Builder not found: $name", uri, token.charOffset);
}
if (builder.next != null) {
Builder getterBuilder;
@ -554,14 +555,13 @@ class DietListener extends StackListener {
return builder;
}
@override
void debugEvent(String name) {
// print(" ${stack.join('\n ')}");
// print(name);
}
bool get isTargetingDartVm {
// TODO(ahe): Find a more reliable way to check if this is the Dart VM.
return coreTypes.getCoreLibrary("dart:_js_helper") == null;
}
@override
void debugEvent(String name) {
// printEvent(name);
}
}

View file

@ -141,7 +141,7 @@ class OutlineBuilder extends UnhandledListener {
List<MetadataBuilder> metadata = pop();
library.addExport(
metadata, uri, conditionalUris, combinators, exportKeyword.charOffset);
checkEmpty();
checkEmpty(exportKeyword.charOffset);
}
@override
@ -156,7 +156,7 @@ class OutlineBuilder extends UnhandledListener {
library.addImport(metadata, uri, conditionalUris, prefix, combinators,
deferredKeyword != null, importKeyword.charOffset,
asKeyword?.next?.charOffset ?? -1);
checkEmpty();
checkEmpty(importKeyword.charOffset);
}
@override
@ -165,7 +165,7 @@ class OutlineBuilder extends UnhandledListener {
String uri = pop();
List<MetadataBuilder> metadata = pop();
library.addPart(metadata, uri);
checkEmpty();
checkEmpty(partKeyword.charOffset);
}
@override
@ -218,7 +218,7 @@ class OutlineBuilder extends UnhandledListener {
List<MetadataBuilder> metadata = pop();
library.addClass(metadata, modifiers, name, typeVariables, supertype,
interfaces, beginToken.charOffset);
checkEmpty();
checkEmpty(beginToken.charOffset);
}
ProcedureKind computeProcedureKind(Token token) {
@ -246,7 +246,7 @@ class OutlineBuilder extends UnhandledListener {
int modifiers = Modifier.validate(pop(),
isAbstract: kind == MethodBody.Abstract);
List<MetadataBuilder> metadata = pop();
checkEmpty();
checkEmpty(beginToken.charOffset);
library.addProcedure(metadata, modifiers, returnType, name,
typeVariables, formals, asyncModifier, computeProcedureKind(getOrSet),
beginToken.charOffset, nativeMethodName, isTopLevel: true);
@ -334,7 +334,7 @@ class OutlineBuilder extends UnhandledListener {
library.addNamedMixinApplication(
metadata, name, typeVariables, modifiers, mixinApplication, interfaces,
classKeyword.charOffset);
checkEmpty();
checkEmpty(classKeyword.charOffset);
}
@override
@ -448,7 +448,7 @@ class OutlineBuilder extends UnhandledListener {
String name = pop();
List<MetadataBuilder> metadata = pop();
library.addEnum(metadata, name, constants, enumKeyword.charOffset);
checkEmpty();
checkEmpty(enumKeyword.charOffset);
}
@override
@ -467,7 +467,7 @@ class OutlineBuilder extends UnhandledListener {
library.addFunctionTypeAlias(
metadata, returnType, name, typeVariables, formals,
typedefKeyword.charOffset);
checkEmpty();
checkEmpty(typedefKeyword.charOffset);
}
@override
@ -478,7 +478,7 @@ class OutlineBuilder extends UnhandledListener {
int modifiers = Modifier.validate(pop());
List<MetadataBuilder> metadata = pop();
library.addFields(metadata, modifiers, type, names);
checkEmpty();
checkEmpty(beginToken.charOffset);
}
@override

View file

@ -14,6 +14,9 @@ import '../combinator.dart' show
import '../errors.dart' show
internalError;
import '../messages.dart' show
warning;
import '../import.dart' show
Import;
@ -302,14 +305,14 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
void includePart(SourceLibraryBuilder<T, R> part) {
if (name != null) {
if (part.partOf == null) {
print("${part.uri} has no 'part of' declaration but is used as a part "
"by ${name} ($uri)");
warning(part.fileUri, -1, "Has no 'part of' declaration but is used as "
"a part by ${name} ($uri).");
parts.remove(part);
return;
}
if (part.partOf != name) {
print("${part.uri} is part of '${part.partOf}' but is used as a part "
"by '${name}' ($uri)");
warning(part.fileUri, -1, "Is part of '${part.partOf}' but is used as "
"a part by '${name}' ($uri).");
parts.remove(part);
return;
}

View file

@ -15,6 +15,7 @@ import 'package:front_end/src/fasta/scanner/io.dart' show
import 'package:front_end/src/fasta/scanner.dart' show
ErrorToken,
ScannerResult,
Token,
scan;
@ -34,6 +35,9 @@ import '../errors.dart' show
InputError,
inputError;
import '../messages.dart' show
warning;
import '../export.dart' show
Export;
@ -86,13 +90,16 @@ class SourceLoader<L> extends Loader<L> {
try {
List<int> bytes = await readBytesFromFile(uri);
byteCount += bytes.length - 1;
Token token = scan(bytes).tokens;
ScannerResult result = scan(bytes);
Token token = result.tokens;
if (!suppressLexicalErrors) {
target.addLineStarts(library.fileUri, result.lineStarts);
}
while (token is ErrorToken) {
if (!suppressLexicalErrors) {
ErrorToken error = token;
String message = new InputError(
uri, token.charOffset, error.assertionMessage).format();
print(message);
print(new InputError(uri, token.charOffset, error.assertionMessage)
.format());
}
token = token.next;
}
@ -128,6 +135,7 @@ class SourceLoader<L> extends Loader<L> {
for (SourceLibraryBuilder part in library.parts) {
Token tokens = await tokenize(part);
if (tokens != null) {
listener.uri = part.fileUri;
parser.parseUnit(tokens);
}
}
@ -335,8 +343,8 @@ class SourceLoader<L> extends Loader<L> {
reported.add(cls);
}
}
print("${cls.name} is a supertype of itself via "
"${involved.map((c) => c.name).join(' ')}");
warning(cls.fileUri, cls.charOffset, "'${cls.name}' is a supertype of "
"itself via '${involved.map((c) => c.name).join(' ')}'.");
}
});
ticker.logMs("Found cycles");

View file

@ -16,6 +16,8 @@ import '../errors.dart' show inputError, internalError;
import '../quote.dart' show unescapeString;
import '../messages.dart' as messages;
enum NullValue {
Arguments,
Block,
@ -121,10 +123,10 @@ abstract class StackListener extends Listener {
debugEvent("Initializer");
}
void checkEmpty() {
void checkEmpty(int charOffset) {
if (stack.isNotEmpty) {
internalError("${runtimeType}: Stack not empty $uri:\n"
" ${stack.join('\n ')}");
internalError("${runtimeType}: Stack not empty:\n"
" ${stack.join('\n ')}", uri, charOffset);
}
if (recoverableErrors.isNotEmpty) {
// TODO(ahe): Handle recoverable errors better.
@ -135,13 +137,13 @@ abstract class StackListener extends Listener {
@override
void endTopLevelDeclaration(Token token) {
debugEvent("TopLevelDeclaration");
checkEmpty();
checkEmpty(token.charOffset);
}
@override
void endCompilationUnit(int count, Token token) {
debugEvent("CompilationUnit");
checkEmpty();
checkEmpty(token.charOffset);
}
@override
@ -229,4 +231,12 @@ abstract class StackListener extends Listener {
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
throw inputError(uri, token.charOffset, "$kind $arguments");
}
void nit(String message, [int charOffset = -1]) {
messages.nit(uri, charOffset, message);
}
void warning(String message, [int charOffset = -1]) {
messages.warning(uri, charOffset, message);
}
}

View file

@ -73,4 +73,6 @@ abstract class TargetImplementation extends Target {
loader.read(Uri.parse(uri));
}
}
void addLineStarts(Uri uri, List<int> lineStarts);
}

View file

@ -37,7 +37,7 @@ rasta/bad_setter_initializer: Crash
rasta/bad_unicode: Fail
rasta/breaking_bad: Crash
rasta/cascades: Crash
rasta/class_hierarchy: Fail
rasta/class_hierarchy: Crash
rasta/class_member: Crash
rasta/constant_get_and_invoke: Crash
rasta/deferred_lib: Fail

View file

@ -3609,7 +3609,7 @@ class Program extends TreeNode {
Program([List<Library> libraries, Map<String, Source> uriToSource])
: libraries = libraries ?? <Library>[],
uriToSource = uriToSource ?? <String, Source>{} {
setParents(libraries, this);
setParents(this.libraries, this);
}
accept(TreeVisitor v) => v.visitProgram(this);

View file

@ -175,7 +175,7 @@ Future<CompilationResult> parseScriptImpl(DartLoaderBatch batch_loader,
.toList(growable: false));
}
} on InputError catch (e) {
return new CompilationError(<String>[e.error]);
return new CompilationError(<String>[e.format()]);
}
} else {
DartOptions dartOptions = new DartOptions(