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; bool isFirstIdentifier = false;
@override
final Uri uri;
/// If `true`, the first call to [handleIdentifier] should push a /// If `true`, the first call to [handleIdentifier] should push a
/// List<SimpleIdentifier> on the stack, and [handleQualified] should append /// List<SimpleIdentifier> on the stack, and [handleQualified] should append
/// to the list. /// to the list.
var accumulateIdentifierComponents = false; 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) { createJumpTarget(JumpTargetKind kind, int charOffset) {
// TODO(ahe): Implement jump targets. // 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 import 'package:front_end/src/fasta/compiler_command_line.dart' show
CompilerCommandLine; CompilerCommandLine;
import 'package:front_end/src/fasta/compiler_context.dart' show
CompilerContext;
import 'package:front_end/src/fasta/outline.dart' show import 'package:front_end/src/fasta/outline.dart' show
doCompile, doCompile;
parseArguments;
import 'package:front_end/src/fasta/errors.dart' show import 'package:front_end/src/fasta/errors.dart' show
InputError; InputError;
@ -29,20 +31,23 @@ const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
main(List<String> arguments) async { main(List<String> arguments) async {
Uri uri; Uri uri;
CompilerCommandLine cl;
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
if (i > 0) { await CompilerCommandLine.withGlobalOptions(
print("\n"); "run", arguments, (CompilerContext c) async {
} if (i > 0) {
try { print("\n");
cl = parseArguments("run", arguments); }
uri = try {
await doCompile(cl, new Ticker(isVerbose:cl.verbose), AstKind.Kernel); uri = await doCompile(c, new Ticker(isVerbose: c.options.verbose),
} on InputError catch (e) { AstKind.Kernel);
print(e.format()); } on InputError catch (e) {
exit(1); print(e.format());
} exit(1);
if (exitCode != 0) exit(exitCode); }
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 import '../errors.dart' show
internalError; internalError;
import '../messages.dart' show
nit;
export 'class_builder.dart' show export 'class_builder.dart' show
ClassBuilder; ClassBuilder;
@ -127,16 +130,17 @@ abstract class Builder {
preferred = other; preferred = other;
hidden = this; hidden = this;
} else { } else {
print("${library.uri}: Note: '$name' is imported from both " nit(library.fileUri, -1, "'$name' is imported from both "
"'${getUri(this)}' and '${getUri(other)}'."); "'${getUri(this)}' and '${getUri(other)}'.");
return library.buildAmbiguousBuilder(name, this, other, charOffset); return library.buildAmbiguousBuilder(name, this, other, charOffset);
} }
if (isLocal) { 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)}'."); "version from '${getUri(other)}'.");
} else { } else {
print("${library.uri}: import of '$name' (from '${getUri(preferred)}') " nit(library.fileUri, -1, "Import of '$name' "
"hides imported version from '${getUri(hidden)}'."); "(from '${getUri(preferred)}') hides imported version from "
"'${getUri(hidden)}'.");
} }
return preferred; return preferred;
} }

View file

@ -10,6 +10,9 @@ import 'builder.dart' show
Builder, Builder,
TypeBuilder; TypeBuilder;
import '../messages.dart' show
warning;
import 'scope.dart' show import 'scope.dart' show
Scope; Scope;
@ -54,7 +57,7 @@ class ConstructorReferenceBuilder extends Builder {
target = builder.constructors[suffix ?? ""]; target = builder.constructors[suffix ?? ""];
} }
if (target == null) { 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, LibraryBuilder,
MemberBuilder; MemberBuilder;
import '../messages.dart' show
warning;
import 'package:kernel/ast.dart' show import 'package:kernel/ast.dart' show
Member; Member;
@ -32,8 +35,8 @@ class PrefixBuilder extends Builder {
// TODO(ahe): Move this to KernelPrefixBuilder. // TODO(ahe): Move this to KernelPrefixBuilder.
Builder builder = exports[name]; Builder builder = exports[name];
if (builder == null) { if (builder == null) {
// TODO(ahe): Report error? warning(parent.fileUri, -1,
print("${this.name} has no member named $name"); "'${this.name}' has no member named '$name'.");
} }
if (builder is DillMemberBuilder) { if (builder is DillMemberBuilder) {
return builder.member.isInstanceMember return builder.member.isInstanceMember

View file

@ -11,11 +11,15 @@ import 'command_line.dart' show
CommandLine, CommandLine,
argumentError; argumentError;
import 'compiler_context.dart' show
CompilerContext;
const Map<String, dynamic> optionSpecification = const <String, dynamic>{ const Map<String, dynamic> optionSpecification = const <String, dynamic>{
"-o": Uri, "-o": Uri,
"--output": Uri, "--output": Uri,
"--platform": Uri, "--platform": Uri,
"--packages": Uri, "--packages": Uri,
"--fatal": ",",
}; };
class CompilerCommandLine extends CommandLine { class CompilerCommandLine extends CommandLine {
@ -65,6 +69,26 @@ class CompilerCommandLine extends CommandLine {
? null ? null
: options["--platform"] ?? Uri.base.resolve("platform.dill"); : 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) { String computeUsage(String programName, bool verbose) {
@ -140,4 +164,12 @@ Supported options:
--compile-sdk --compile-sdk
Compile the SDK from scratch instead of reading it from 'platform.dill'. 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); loader = new DillLoader(this);
} }
void addLineStarts(Uri uri, List<int> lineStarts) {
internalError("Unsupported operation.");
}
void read(Uri uri) { void read(Uri uri) {
if (loader.input == null) { if (loader.input == null) {
loader.input = uri; loader.input = uri;

View file

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

View file

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

View file

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

View file

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

View file

@ -15,6 +15,9 @@ import 'package:kernel/ast.dart' show
import 'package:kernel/type_algebra.dart' show import 'package:kernel/type_algebra.dart' show
substitute; substitute;
import '../messages.dart' show
warning;
import 'kernel_builder.dart' show import 'kernel_builder.dart' show
FormalParameterBuilder, FormalParameterBuilder,
FunctionTypeAliasBuilder, FunctionTypeAliasBuilder,
@ -45,7 +48,8 @@ class KernelFunctionTypeAliasBuilder
if (thisType == const InvalidType()) { if (thisType == const InvalidType()) {
thisType = const DynamicType(); thisType = const DynamicType();
// TODO(ahe): Build an error somehow. // 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; return thisType;
} }

View file

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

View file

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

View file

@ -40,6 +40,9 @@ import 'package:kernel/type_algebra.dart' show
import '../errors.dart' show import '../errors.dart' show
internalError; internalError;
import '../messages.dart' show
warning;
import '../loader.dart' show import '../loader.dart' show
Loader; Loader;
@ -129,7 +132,8 @@ abstract class KernelFunctionBuilder
substitution[parameter] = const DynamicType(); 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); return substitute(type, substitution);
} }
Set<TypeParameter> set = typeParameters.toSet(); Set<TypeParameter> set = typeParameters.toSet();

View file

@ -75,6 +75,12 @@ import '../errors.dart' show
reportCrash, reportCrash,
resetCrashReporting; resetCrashReporting;
import '../util/relativize.dart' show
relativizeUri;
import '../compiler_context.dart' show
CompilerContext;
import 'kernel_builder.dart' show import 'kernel_builder.dart' show
Builder, Builder,
ClassBuilder, ClassBuilder,
@ -92,18 +98,29 @@ import 'kernel_builder.dart' show
class KernelTarget extends TargetImplementation { class KernelTarget extends TargetImplementation {
final DillTarget dillTarget; final DillTarget dillTarget;
/// Shared with [CompilerContext].
final Map<String, Source> uriToSource;
SourceLoader<Library> loader; SourceLoader<Library> loader;
Program program; Program program;
final List errors = []; final List errors = [];
KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator) KernelTarget(DillTarget dillTarget, TranslateUri uriTranslator,
[Map<String, Source> uriToSource])
: dillTarget = dillTarget, : dillTarget = dillTarget,
uriToSource = uriToSource ?? CompilerContext.current.uriToSource,
super(dillTarget.ticker, uriTranslator) { super(dillTarget.ticker, uriTranslator) {
resetCrashReporting(); resetCrashReporting();
loader = new SourceLoader<Library>(this); 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) { void read(Uri uri) {
loader.read(uri); loader.read(uri);
} }
@ -317,7 +334,9 @@ class KernelTarget extends TargetImplementation {
program.mainMethod = builder.procedure; program.mainMethod = builder.procedure;
} }
} }
setup_builtin_library.transformProgram(program); if (errors.isEmpty || dillTarget.isLoaded) {
setup_builtin_library.transformProgram(program);
}
ticker.logMs("Linked program"); ticker.logMs("Linked program");
return 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 import 'compiler_command_line.dart' show
CompilerCommandLine; CompilerCommandLine;
import 'compiler_context.dart' show
CompilerContext;
import 'errors.dart' show import 'errors.dart' show
InputError, InputError,
inputError; inputError;
@ -40,15 +43,16 @@ import 'ast_kind.dart' show
import 'testing/kernel_chain.dart' show import 'testing/kernel_chain.dart' show
computePatchedSdk; computePatchedSdk;
CompilerCommandLine parseArguments(String programName, List<String> arguments) {
return new CompilerCommandLine(programName, arguments);
}
Future<KernelTarget> outline(List<String> arguments) async { Future<KernelTarget> outline(List<String> arguments) async {
try { try {
CompilerCommandLine cl = parseArguments("outline", arguments); return await CompilerCommandLine.withGlobalOptions(
if (cl.verbose) print("Building outlines for ${arguments.join(' ')}"); "outline", arguments, (CompilerContext c) async {
return await doOutline(cl, new Ticker(isVerbose: cl.verbose), cl.output); 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) { } on InputError catch (e) {
exitCode = 1; exitCode = 1;
print(e.format()); print(e.format());
@ -58,12 +62,14 @@ Future<KernelTarget> outline(List<String> arguments) async {
Future<Uri> compile(List<String> arguments) async { Future<Uri> compile(List<String> arguments) async {
try { try {
CompilerCommandLine cl = parseArguments("compile", arguments); return await CompilerCommandLine.withGlobalOptions(
if (cl.verbose) { "compile", arguments, (CompilerContext c) async {
print("Compiling directly to Kernel: ${arguments.join(' ')}"); if (c.options.verbose) {
} print("Compiling directly to Kernel: ${arguments.join(' ')}");
return }
await doCompile(cl, new Ticker(isVerbose: cl.verbose), AstKind.Kernel); return await doCompile(c, new Ticker(isVerbose: c.options.verbose),
AstKind.Kernel);
});
} on InputError catch (e) { } on InputError catch (e) {
exitCode = 1; exitCode = 1;
print(e.format()); print(e.format());
@ -73,10 +79,14 @@ Future<Uri> compile(List<String> arguments) async {
Future<Uri> kompile(List<String> arguments) async { Future<Uri> kompile(List<String> arguments) async {
try { try {
CompilerCommandLine cl = parseArguments("kompile", arguments); return await CompilerCommandLine.withGlobalOptions(
if (cl.verbose) print("Compiling via analyzer: ${arguments.join(' ')}"); "kompile", arguments, (CompilerContext c) async {
return await doCompile( if (c.options.verbose) {
cl, new Ticker(isVerbose: cl.verbose), AstKind.Analyzer); print("Compiling via analyzer: ${arguments.join(' ')}");
}
return await doCompile(c, new Ticker(isVerbose: c.options.verbose),
AstKind.Analyzer);
});
} on InputError catch (e) { } on InputError catch (e) {
exitCode = 1; exitCode = 1;
print(e.format()); 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 output]) async {
Uri sdk = await computePatchedSdk(); Uri sdk = await computePatchedSdk();
ticker.logMs("Found patched SDK"); ticker.logMs("Found patched SDK");
TranslateUri uriTranslator = await TranslateUri.parse(sdk); TranslateUri uriTranslator = await TranslateUri.parse(sdk);
ticker.logMs("Read packages file"); ticker.logMs("Read packages file");
DillTarget dillTarget = new DillTarget(ticker, uriTranslator); DillTarget dillTarget = new DillTarget(ticker, uriTranslator);
KernelTarget kernelTarget = new KernelTarget(dillTarget, uriTranslator); KernelTarget kernelTarget =
Uri platform = cl.platform; new KernelTarget(dillTarget, uriTranslator, c.uriToSource);
Uri platform = c.options.platform;
if (platform != null) { if (platform != null) {
dillTarget.read(platform); dillTarget.read(platform);
} }
String argument = cl.arguments.first; String argument = c.options.arguments.first;
Uri uri = Uri.base.resolve(argument); Uri uri = Uri.base.resolve(argument);
String path = uriTranslator.translate(uri)?.path ?? argument; String path = uriTranslator.translate(uri)?.path ?? argument;
if (path.endsWith(".dart")) { if (path.endsWith(".dart")) {
@ -106,29 +117,28 @@ Future<KernelTarget> doOutline(CompilerCommandLine cl, Ticker ticker,
} }
await dillTarget.writeOutline(null); await dillTarget.writeOutline(null);
await kernelTarget.writeOutline(output); await kernelTarget.writeOutline(output);
if (cl.dumpIr && output != null) { if (c.options.dumpIr && output != null) {
kernelTarget.dumpIr(); kernelTarget.dumpIr();
} }
return kernelTarget; return kernelTarget;
} }
Future<Uri> doCompile(CompilerCommandLine cl, Ticker ticker, Future<Uri> doCompile(CompilerContext c, Ticker ticker, AstKind kind) async {
AstKind kind) async { KernelTarget kernelTarget = await doOutline(c, ticker);
KernelTarget kernelTarget = await doOutline(cl, ticker);
if (exitCode != 0) return null; if (exitCode != 0) return null;
Uri uri = cl.output; Uri uri = c.options.output;
await kernelTarget.writeProgram(uri, kind); await kernelTarget.writeProgram(uri, kind);
if (cl.dumpIr) { if (c.options.dumpIr) {
kernelTarget.dumpIr(); kernelTarget.dumpIr();
} }
if (cl.verify) { if (c.options.verify) {
try { try {
verifyProgram(kernelTarget.program); verifyProgram(kernelTarget.program);
ticker.logMs("Verified program"); ticker.logMs("Verified program");
} catch (e, s) { } catch (e, s) {
exitCode = 1; exitCode = 1;
print("Verification of program failed: $e"); print("Verification of program failed: $e");
if (s != null && cl.verbose) { if (s != null && c.options.verbose) {
print(s); print(s);
} }
} }

View file

@ -17,15 +17,15 @@ import 'testing/kernel_chain.dart' show
computeDartVm, computeDartVm,
computePatchedSdk; computePatchedSdk;
import 'compiler_command_line.dart' show import 'compiler_context.dart' show
CompilerCommandLine; CompilerContext;
Future<int> run(Uri uri, CompilerCommandLine cl) async { Future<int> run(Uri uri, CompilerContext c) async {
Uri sdk = await computePatchedSdk(); Uri sdk = await computePatchedSdk();
Uri dartVm = computeDartVm(sdk); Uri dartVm = computeDartVm(sdk);
List<String> arguments = <String>["${uri.toFilePath()}"] List<String> arguments = <String>["${uri.toFilePath()}"]
..addAll(cl.arguments.skip(1)); ..addAll(c.options.arguments.skip(1));
if (cl.verbose) { if (c.options.verbose) {
print("Running ${dartVm.toFilePath()} ${arguments.join(' ')}"); print("Running ${dartVm.toFilePath()} ${arguments.join(' ')}");
} }
StdioProcess result = await StdioProcess.run(dartVm.toFilePath(), arguments); 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]. /// this is the instance scope of [currentClass].
Scope memberScope; Scope memberScope;
@override
Uri uri;
DietListener(SourceLibraryBuilder library, this.elementStore, this.hierarchy, DietListener(SourceLibraryBuilder library, this.elementStore, this.hierarchy,
this.coreTypes, this.astKind) this.coreTypes, this.astKind)
: library = library, : library = library,
uri = library.fileUri,
memberScope = library.scope, memberScope = library.scope,
isDartLibrary = library.uri.scheme == "dart"; isDartLibrary = library.uri.scheme == "dart";
@override
Uri get uri => library.uri;
void discard(int n) { void discard(int n) {
for (int i =0; i < n; i++) { for (int i =0; i < n; i++) {
pop(); pop();
@ -192,7 +193,7 @@ class DietListener extends StackListener {
void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
debugEvent("FunctionTypeAlias"); debugEvent("FunctionTypeAlias");
discard(2); // Name + endToken. discard(2); // Name + endToken.
checkEmpty(); checkEmpty(typedefKeyword.charOffset);
} }
@override @override
@ -213,7 +214,7 @@ class DietListener extends StackListener {
debugEvent("TopLevelMethod"); debugEvent("TopLevelMethod");
Token bodyToken = pop(); Token bodyToken = pop();
String name = pop(); String name = pop();
checkEmpty(); checkEmpty(beginToken.charOffset);
buildFunctionBody(bodyToken, lookupBuilder(beginToken, getOrSet, name)); buildFunctionBody(bodyToken, lookupBuilder(beginToken, getOrSet, name));
} }
@ -363,7 +364,7 @@ class DietListener extends StackListener {
debugEvent("FactoryMethod"); debugEvent("FactoryMethod");
BeginGroupToken bodyToken = pop(); BeginGroupToken bodyToken = pop();
String name = pop(); String name = pop();
checkEmpty(); checkEmpty(beginToken.charOffset);
if (bodyToken == null || optional("=", bodyToken.endGroup.next)) { if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
return; return;
} }
@ -381,7 +382,7 @@ class DietListener extends StackListener {
debugEvent("Method"); debugEvent("Method");
Token bodyToken = pop(); Token bodyToken = pop();
String name = pop(); String name = pop();
checkEmpty(); checkEmpty(beginToken.charOffset);
if (bodyToken == null) { if (bodyToken == null) {
return; return;
} }
@ -394,10 +395,10 @@ class DietListener extends StackListener {
case AstKind.Kernel: case AstKind.Kernel:
return new BodyBuilder(library, builder, memberScope, return new BodyBuilder(library, builder, memberScope,
formalParameterScope, hierarchy, coreTypes, currentClass, formalParameterScope, hierarchy, coreTypes, currentClass,
isInstanceMember); isInstanceMember, uri);
case AstKind.Analyzer: case AstKind.Analyzer:
return new AstBuilder(library, builder, elementStore, memberScope); return new AstBuilder(library, builder, elementStore, memberScope, uri);
} }
return internalError("Unknown $astKind"); return internalError("Unknown $astKind");
@ -423,7 +424,7 @@ class DietListener extends StackListener {
@override @override
void endMember() { void endMember() {
debugEvent("Member"); debugEvent("Member");
checkEmpty(); checkEmpty(-1);
} }
@override @override
@ -440,7 +441,7 @@ class DietListener extends StackListener {
void endClassBody(int memberCount, Token beginToken, Token endToken) { void endClassBody(int memberCount, Token beginToken, Token endToken) {
debugEvent("ClassBody"); debugEvent("ClassBody");
currentClass = null; currentClass = null;
checkEmpty(); checkEmpty(beginToken.charOffset);
memberScope = library.scope; memberScope = library.scope;
} }
@ -448,7 +449,7 @@ class DietListener extends StackListener {
void endClassDeclaration(int interfacesCount, Token beginToken, void endClassDeclaration(int interfacesCount, Token beginToken,
Token extendsKeyword, Token implementsKeyword, Token endToken) { Token extendsKeyword, Token implementsKeyword, Token endToken) {
debugEvent("ClassDeclaration"); debugEvent("ClassDeclaration");
checkEmpty(); checkEmpty(beginToken.charOffset);
} }
@override @override
@ -456,7 +457,7 @@ class DietListener extends StackListener {
debugEvent("Enum"); debugEvent("Enum");
discard(count); discard(count);
pop(); // Name. pop(); // Name.
checkEmpty(); checkEmpty(enumKeyword.charOffset);
} }
@override @override
@ -464,7 +465,7 @@ class DietListener extends StackListener {
Token classKeyword, Token implementsKeyword, Token endToken) { Token classKeyword, Token implementsKeyword, Token endToken) {
debugEvent("NamedMixinApplication"); debugEvent("NamedMixinApplication");
pop(); // Name. pop(); // Name.
checkEmpty(); checkEmpty(classKeyword.charOffset);
} }
@override @override
@ -490,7 +491,7 @@ class DietListener extends StackListener {
Parser parser = new Parser(listener); Parser parser = new Parser(listener);
token = parser.parseFormalParametersOpt(token); token = parser.parseFormalParametersOpt(token);
var formals = listener.pop(); var formals = listener.pop();
listener.checkEmpty(); listener.checkEmpty(token.charOffset);
listener.prepareInitializers(); listener.prepareInitializers();
token = parser.parseInitializersOpt(token); token = parser.parseInitializersOpt(token);
token = parser.parseAsyncModifier(token); token = parser.parseAsyncModifier(token);
@ -499,7 +500,7 @@ class DietListener extends StackListener {
bool allowAbstract = true; bool allowAbstract = true;
parser.parseFunctionBody(token, isExpression, allowAbstract); parser.parseFunctionBody(token, isExpression, allowAbstract);
var body = listener.pop(); var body = listener.pop();
listener.checkEmpty(); listener.checkEmpty(token.charOffset);
listener.finishFunction(formals, asyncModifier, body); listener.finishFunction(formals, asyncModifier, body);
} on InputError { } on InputError {
rethrow; rethrow;
@ -515,7 +516,7 @@ class DietListener extends StackListener {
} else { } else {
token = parser.parseMember(token); token = parser.parseMember(token);
} }
listener.checkEmpty(); listener.checkEmpty(token.charOffset);
} }
Builder lookupBuilder(Token token, Token getOrSet, String name) { Builder lookupBuilder(Token token, Token getOrSet, String name) {
@ -531,7 +532,7 @@ class DietListener extends StackListener {
builder = library.members[name]; builder = library.members[name];
} }
if (builder == null) { if (builder == null) {
return internalError("@${token.charOffset}: builder not found: $name"); return internalError("Builder not found: $name", uri, token.charOffset);
} }
if (builder.next != null) { if (builder.next != null) {
Builder getterBuilder; Builder getterBuilder;
@ -554,14 +555,13 @@ class DietListener extends StackListener {
return builder; return builder;
} }
@override
void debugEvent(String name) {
// print(" ${stack.join('\n ')}");
// print(name);
}
bool get isTargetingDartVm { bool get isTargetingDartVm {
// TODO(ahe): Find a more reliable way to check if this is the Dart VM. // TODO(ahe): Find a more reliable way to check if this is the Dart VM.
return coreTypes.getCoreLibrary("dart:_js_helper") == null; 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(); List<MetadataBuilder> metadata = pop();
library.addExport( library.addExport(
metadata, uri, conditionalUris, combinators, exportKeyword.charOffset); metadata, uri, conditionalUris, combinators, exportKeyword.charOffset);
checkEmpty(); checkEmpty(exportKeyword.charOffset);
} }
@override @override
@ -156,7 +156,7 @@ class OutlineBuilder extends UnhandledListener {
library.addImport(metadata, uri, conditionalUris, prefix, combinators, library.addImport(metadata, uri, conditionalUris, prefix, combinators,
deferredKeyword != null, importKeyword.charOffset, deferredKeyword != null, importKeyword.charOffset,
asKeyword?.next?.charOffset ?? -1); asKeyword?.next?.charOffset ?? -1);
checkEmpty(); checkEmpty(importKeyword.charOffset);
} }
@override @override
@ -165,7 +165,7 @@ class OutlineBuilder extends UnhandledListener {
String uri = pop(); String uri = pop();
List<MetadataBuilder> metadata = pop(); List<MetadataBuilder> metadata = pop();
library.addPart(metadata, uri); library.addPart(metadata, uri);
checkEmpty(); checkEmpty(partKeyword.charOffset);
} }
@override @override
@ -218,7 +218,7 @@ class OutlineBuilder extends UnhandledListener {
List<MetadataBuilder> metadata = pop(); List<MetadataBuilder> metadata = pop();
library.addClass(metadata, modifiers, name, typeVariables, supertype, library.addClass(metadata, modifiers, name, typeVariables, supertype,
interfaces, beginToken.charOffset); interfaces, beginToken.charOffset);
checkEmpty(); checkEmpty(beginToken.charOffset);
} }
ProcedureKind computeProcedureKind(Token token) { ProcedureKind computeProcedureKind(Token token) {
@ -246,7 +246,7 @@ class OutlineBuilder extends UnhandledListener {
int modifiers = Modifier.validate(pop(), int modifiers = Modifier.validate(pop(),
isAbstract: kind == MethodBody.Abstract); isAbstract: kind == MethodBody.Abstract);
List<MetadataBuilder> metadata = pop(); List<MetadataBuilder> metadata = pop();
checkEmpty(); checkEmpty(beginToken.charOffset);
library.addProcedure(metadata, modifiers, returnType, name, library.addProcedure(metadata, modifiers, returnType, name,
typeVariables, formals, asyncModifier, computeProcedureKind(getOrSet), typeVariables, formals, asyncModifier, computeProcedureKind(getOrSet),
beginToken.charOffset, nativeMethodName, isTopLevel: true); beginToken.charOffset, nativeMethodName, isTopLevel: true);
@ -334,7 +334,7 @@ class OutlineBuilder extends UnhandledListener {
library.addNamedMixinApplication( library.addNamedMixinApplication(
metadata, name, typeVariables, modifiers, mixinApplication, interfaces, metadata, name, typeVariables, modifiers, mixinApplication, interfaces,
classKeyword.charOffset); classKeyword.charOffset);
checkEmpty(); checkEmpty(classKeyword.charOffset);
} }
@override @override
@ -448,7 +448,7 @@ class OutlineBuilder extends UnhandledListener {
String name = pop(); String name = pop();
List<MetadataBuilder> metadata = pop(); List<MetadataBuilder> metadata = pop();
library.addEnum(metadata, name, constants, enumKeyword.charOffset); library.addEnum(metadata, name, constants, enumKeyword.charOffset);
checkEmpty(); checkEmpty(enumKeyword.charOffset);
} }
@override @override
@ -467,7 +467,7 @@ class OutlineBuilder extends UnhandledListener {
library.addFunctionTypeAlias( library.addFunctionTypeAlias(
metadata, returnType, name, typeVariables, formals, metadata, returnType, name, typeVariables, formals,
typedefKeyword.charOffset); typedefKeyword.charOffset);
checkEmpty(); checkEmpty(typedefKeyword.charOffset);
} }
@override @override
@ -478,7 +478,7 @@ class OutlineBuilder extends UnhandledListener {
int modifiers = Modifier.validate(pop()); int modifiers = Modifier.validate(pop());
List<MetadataBuilder> metadata = pop(); List<MetadataBuilder> metadata = pop();
library.addFields(metadata, modifiers, type, names); library.addFields(metadata, modifiers, type, names);
checkEmpty(); checkEmpty(beginToken.charOffset);
} }
@override @override

View file

@ -14,6 +14,9 @@ import '../combinator.dart' show
import '../errors.dart' show import '../errors.dart' show
internalError; internalError;
import '../messages.dart' show
warning;
import '../import.dart' show import '../import.dart' show
Import; Import;
@ -302,14 +305,14 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
void includePart(SourceLibraryBuilder<T, R> part) { void includePart(SourceLibraryBuilder<T, R> part) {
if (name != null) { if (name != null) {
if (part.partOf == null) { if (part.partOf == null) {
print("${part.uri} has no 'part of' declaration but is used as a part " warning(part.fileUri, -1, "Has no 'part of' declaration but is used as "
"by ${name} ($uri)"); "a part by ${name} ($uri).");
parts.remove(part); parts.remove(part);
return; return;
} }
if (part.partOf != name) { if (part.partOf != name) {
print("${part.uri} is part of '${part.partOf}' but is used as a part " warning(part.fileUri, -1, "Is part of '${part.partOf}' but is used as "
"by '${name}' ($uri)"); "a part by '${name}' ($uri).");
parts.remove(part); parts.remove(part);
return; 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 import 'package:front_end/src/fasta/scanner.dart' show
ErrorToken, ErrorToken,
ScannerResult,
Token, Token,
scan; scan;
@ -34,6 +35,9 @@ import '../errors.dart' show
InputError, InputError,
inputError; inputError;
import '../messages.dart' show
warning;
import '../export.dart' show import '../export.dart' show
Export; Export;
@ -86,13 +90,16 @@ class SourceLoader<L> extends Loader<L> {
try { try {
List<int> bytes = await readBytesFromFile(uri); List<int> bytes = await readBytesFromFile(uri);
byteCount += bytes.length - 1; 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) { while (token is ErrorToken) {
if (!suppressLexicalErrors) { if (!suppressLexicalErrors) {
ErrorToken error = token; ErrorToken error = token;
String message = new InputError( print(new InputError(uri, token.charOffset, error.assertionMessage)
uri, token.charOffset, error.assertionMessage).format(); .format());
print(message);
} }
token = token.next; token = token.next;
} }
@ -128,6 +135,7 @@ class SourceLoader<L> extends Loader<L> {
for (SourceLibraryBuilder part in library.parts) { for (SourceLibraryBuilder part in library.parts) {
Token tokens = await tokenize(part); Token tokens = await tokenize(part);
if (tokens != null) { if (tokens != null) {
listener.uri = part.fileUri;
parser.parseUnit(tokens); parser.parseUnit(tokens);
} }
} }
@ -335,8 +343,8 @@ class SourceLoader<L> extends Loader<L> {
reported.add(cls); reported.add(cls);
} }
} }
print("${cls.name} is a supertype of itself via " warning(cls.fileUri, cls.charOffset, "'${cls.name}' is a supertype of "
"${involved.map((c) => c.name).join(' ')}"); "itself via '${involved.map((c) => c.name).join(' ')}'.");
} }
}); });
ticker.logMs("Found cycles"); ticker.logMs("Found cycles");

View file

@ -16,6 +16,8 @@ import '../errors.dart' show inputError, internalError;
import '../quote.dart' show unescapeString; import '../quote.dart' show unescapeString;
import '../messages.dart' as messages;
enum NullValue { enum NullValue {
Arguments, Arguments,
Block, Block,
@ -121,10 +123,10 @@ abstract class StackListener extends Listener {
debugEvent("Initializer"); debugEvent("Initializer");
} }
void checkEmpty() { void checkEmpty(int charOffset) {
if (stack.isNotEmpty) { if (stack.isNotEmpty) {
internalError("${runtimeType}: Stack not empty $uri:\n" internalError("${runtimeType}: Stack not empty:\n"
" ${stack.join('\n ')}"); " ${stack.join('\n ')}", uri, charOffset);
} }
if (recoverableErrors.isNotEmpty) { if (recoverableErrors.isNotEmpty) {
// TODO(ahe): Handle recoverable errors better. // TODO(ahe): Handle recoverable errors better.
@ -135,13 +137,13 @@ abstract class StackListener extends Listener {
@override @override
void endTopLevelDeclaration(Token token) { void endTopLevelDeclaration(Token token) {
debugEvent("TopLevelDeclaration"); debugEvent("TopLevelDeclaration");
checkEmpty(); checkEmpty(token.charOffset);
} }
@override @override
void endCompilationUnit(int count, Token token) { void endCompilationUnit(int count, Token token) {
debugEvent("CompilationUnit"); debugEvent("CompilationUnit");
checkEmpty(); checkEmpty(token.charOffset);
} }
@override @override
@ -229,4 +231,12 @@ abstract class StackListener extends Listener {
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) { Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
throw inputError(uri, token.charOffset, "$kind $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)); 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/bad_unicode: Fail
rasta/breaking_bad: Crash rasta/breaking_bad: Crash
rasta/cascades: Crash rasta/cascades: Crash
rasta/class_hierarchy: Fail rasta/class_hierarchy: Crash
rasta/class_member: Crash rasta/class_member: Crash
rasta/constant_get_and_invoke: Crash rasta/constant_get_and_invoke: Crash
rasta/deferred_lib: Fail rasta/deferred_lib: Fail

View file

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

View file

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