| Index: pkg/compiler/lib/src/compiler.dart
|
| diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
|
| index da40955d4c945f3de5256c0288213d9ee3776a6b..2cffc6220bd047441f66527bfb8bd56868df8d0c 100644
|
| --- a/pkg/compiler/lib/src/compiler.dart
|
| +++ b/pkg/compiler/lib/src/compiler.dart
|
| @@ -126,8 +126,8 @@ abstract class Compiler {
|
| // TODO(zarah): Remove this map and incorporate compile-time errors
|
| // in the model.
|
| /// Tracks elements with compile-time errors.
|
| - final Map<Element, List<DiagnosticMessage>> elementsWithCompileTimeErrors =
|
| - new Map<Element, List<DiagnosticMessage>>();
|
| + final Map<Entity, List<DiagnosticMessage>> elementsWithCompileTimeErrors =
|
| + new Map<Entity, List<DiagnosticMessage>>();
|
|
|
| final Environment environment;
|
| // TODO(sigmund): delete once we migrate the rest of the compiler to use
|
| @@ -135,7 +135,7 @@ abstract class Compiler {
|
| @deprecated
|
| fromEnvironment(String name) => environment.valueOf(name);
|
|
|
| - Element get currentElement => _reporter.currentElement;
|
| + Entity get currentElement => _reporter.currentElement;
|
|
|
| List<CompilerTask> tasks;
|
| ScannerTask scanner;
|
| @@ -519,7 +519,10 @@ abstract class Compiler {
|
| WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
|
| mainFunction = frontEndStrategy.computeMain(rootLibrary, mainImpact);
|
|
|
| - mirrorUsageAnalyzerTask.analyzeUsage(rootLibrary);
|
| + if (!options.loadFromDill) {
|
| + // TODO(johnniwinther): Support mirrors usages analysis from dill.
|
| + mirrorUsageAnalyzerTask.analyzeUsage(rootLibrary);
|
| + }
|
|
|
| // In order to see if a library is deferred, we must compute the
|
| // compile-time constants that are metadata. This means adding
|
| @@ -557,7 +560,8 @@ abstract class Compiler {
|
| }
|
| }
|
| }
|
| - if (commonElements.mirrorsLibrary != null) {
|
| + if (commonElements.mirrorsLibrary != null && !options.loadFromDill) {
|
| + // TODO(johnniwinther): Support mirrors from dill.
|
| resolveLibraryMetadata();
|
| }
|
| reporter.log('Resolving...');
|
| @@ -931,19 +935,19 @@ abstract class Compiler {
|
| }
|
|
|
| /// Returns [true] if a compile-time error has been reported for element.
|
| - bool elementHasCompileTimeError(Element element) {
|
| + bool elementHasCompileTimeError(Entity element) {
|
| return elementsWithCompileTimeErrors.containsKey(element);
|
| }
|
|
|
| /// Associate [element] with a compile-time error [message].
|
| - void registerCompileTimeError(Element element, DiagnosticMessage message) {
|
| + void registerCompileTimeError(Entity element, DiagnosticMessage message) {
|
| // The information is only needed if [generateCodeWithCompileTimeErrors].
|
| if (options.generateCodeWithCompileTimeErrors) {
|
| if (element == null) {
|
| // Record as global error.
|
| // TODO(zarah): Extend element model to represent compile-time
|
| // errors instead of using a map.
|
| - element = mainFunction as MethodElement;
|
| + element = mainFunction;
|
| }
|
| elementsWithCompileTimeErrors
|
| .putIfAbsent(element, () => <DiagnosticMessage>[])
|
| @@ -1062,8 +1066,8 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
| if (kind == api.Diagnostic.ERROR ||
|
| kind == api.Diagnostic.CRASH ||
|
| (options.fatalWarnings && kind == api.Diagnostic.WARNING)) {
|
| - Element errorElement;
|
| - if (message.spannable is Element) {
|
| + Entity errorElement;
|
| + if (message.spannable is Entity) {
|
| errorElement = message.spannable;
|
| } else {
|
| errorElement = currentElement;
|
| @@ -1119,175 +1123,46 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
| api.Diagnostic.CRASH);
|
| }
|
|
|
| - @override
|
| - SourceSpan spanFromToken(Token token) => spanFromTokens(token, token);
|
| -
|
| - SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) {
|
| - if (begin == null || end == null) {
|
| - // TODO(ahe): We can almost always do better. Often it is only
|
| - // end that is null. Otherwise, we probably know the current
|
| - // URI.
|
| - throw 'Cannot find tokens to produce error message.';
|
| - }
|
| - if (uri == null && currentElement != null) {
|
| - if (currentElement is! Element) {
|
| - throw 'Can only find tokens from an Element.';
|
| - }
|
| - Element element = currentElement;
|
| - uri = element.compilationUnit.script.resourceUri;
|
| - assert(invariant(currentElement, () {
|
| - bool sameToken(Token token, Token sought) {
|
| - if (token == sought) return true;
|
| - if (token.stringValue == '>>') {
|
| - // `>>` is converted to `>` in the parser when needed.
|
| - return sought.stringValue == '>' &&
|
| - token.charOffset <= sought.charOffset &&
|
| - sought.charOffset < token.charEnd;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /// Check that [begin] and [end] can be found between [from] and [to].
|
| - validateToken(Token from, Token to) {
|
| - if (from == null || to == null) return true;
|
| - bool foundBegin = false;
|
| - bool foundEnd = false;
|
| - Token token = from;
|
| - while (true) {
|
| - if (sameToken(token, begin)) {
|
| - foundBegin = true;
|
| - }
|
| - if (sameToken(token, end)) {
|
| - foundEnd = true;
|
| - }
|
| - if (foundBegin && foundEnd) {
|
| - return true;
|
| - }
|
| - if (token == to || token == token.next || token.next == null) {
|
| - break;
|
| - }
|
| - token = token.next;
|
| - }
|
| -
|
| - // Create a good message for when the tokens were not found.
|
| - StringBuffer sb = new StringBuffer();
|
| - sb.write('Invalid current element: $element. ');
|
| - sb.write('Looking for ');
|
| - sb.write('[${begin} (${begin.hashCode}),');
|
| - sb.write('${end} (${end.hashCode})] in');
|
| -
|
| - token = from;
|
| - while (true) {
|
| - sb.write('\n ${token} (${token.hashCode})');
|
| - if (token == to || token == token.next || token.next == null) {
|
| - break;
|
| - }
|
| - token = token.next;
|
| - }
|
| - return sb.toString();
|
| - }
|
| -
|
| - if (element.enclosingClass != null &&
|
| - element.enclosingClass.isEnumClass) {
|
| - // Enums ASTs are synthesized (and give messed up messages).
|
| - return true;
|
| - }
|
| -
|
| - if (element is AstElement) {
|
| - AstElement astElement = element;
|
| - if (astElement.hasNode) {
|
| - Token from = astElement.node.getBeginToken();
|
| - Token to = astElement.node.getEndToken();
|
| - if (astElement.metadata.isNotEmpty) {
|
| - if (!astElement.metadata.first.hasNode) {
|
| - // We might try to report an error while parsing the metadata
|
| - // itself.
|
| - return true;
|
| - }
|
| - from = astElement.metadata.first.node.getBeginToken();
|
| - }
|
| - return validateToken(from, to);
|
| - }
|
| - }
|
| - return true;
|
| - }, message: "Invalid current element: $element [$begin,$end]."));
|
| - }
|
| - return new SourceSpan.fromTokens(uri, begin, end);
|
| - }
|
| -
|
| - SourceSpan spanFromNode(Node node) {
|
| - return spanFromTokens(node.getBeginToken(), node.getPrefixEndToken());
|
| + /// Using [frontEndStrategy] to compute a [SourceSpan] from spannable using
|
| + /// the [currentElement] as context.
|
| + SourceSpan _spanFromStrategy(Spannable spannable) {
|
| + SourceSpan span =
|
| + compiler.frontEndStrategy.spanFromSpannable(spannable, currentElement);
|
| + if (span != null) return span;
|
| + throw 'No error location.';
|
| }
|
|
|
| - SourceSpan spanFromElement(Element element) {
|
| - if (element != null && element.sourcePosition != null) {
|
| - return element.sourcePosition;
|
| - }
|
| - while (element != null && element.isSynthesized) {
|
| - element = element.enclosingElement;
|
| - }
|
| - if (element != null &&
|
| - element.sourcePosition == null &&
|
| - !element.isLibrary &&
|
| - !element.isCompilationUnit) {
|
| - // Sometimes, the backend fakes up elements that have no
|
| - // position. So we use the enclosing element instead. It is
|
| - // not a good error location, but cancel really is "internal
|
| - // error" or "not implemented yet", so the vicinity is good
|
| - // enough for now.
|
| - element = element.enclosingElement;
|
| - // TODO(ahe): I plan to overhaul this infrastructure anyways.
|
| - }
|
| - if (element == null) {
|
| - element = currentElement;
|
| - }
|
| - if (element == null) {
|
| - return null;
|
| + SourceSpan spanFromSpannable(Spannable spannable) {
|
| + if (spannable == CURRENT_ELEMENT_SPANNABLE) {
|
| + spannable = currentElement;
|
| + } else if (spannable == NO_LOCATION_SPANNABLE) {
|
| + if (currentElement == null) return null;
|
| + spannable = currentElement;
|
| }
|
| -
|
| - if (element.sourcePosition != null) {
|
| - return element.sourcePosition;
|
| + if (spannable is SourceSpan) {
|
| + return spannable;
|
| + } else if (spannable is HInstruction) {
|
| + Entity element = spannable.sourceElement;
|
| + if (element == null) element = currentElement;
|
| + SourceInformation position = spannable.sourceInformation;
|
| + if (position != null) return position.sourceSpan;
|
| + return _spanFromStrategy(element);
|
| + } else if (spannable is Local) {
|
| + Local local = spannable;
|
| + return _spanFromStrategy(local.executableContext);
|
| + } else {
|
| + return _spanFromStrategy(spannable);
|
| }
|
| - Token position = element.position;
|
| - Uri uri = element.compilationUnit.script.resourceUri;
|
| - return (position == null)
|
| - ? new SourceSpan(uri, 0, 0)
|
| - : spanFromTokens(position, position, uri);
|
| }
|
|
|
| - SourceSpan spanFromHInstruction(HInstruction instruction) {
|
| - Element element = _elementFromHInstruction(instruction);
|
| - if (element == null) element = currentElement;
|
| - SourceInformation position = instruction.sourceInformation;
|
| - if (position == null) return spanFromElement(element);
|
| - return position.sourceSpan;
|
| - }
|
| -
|
| - SourceSpan spanFromSpannable(Spannable node) {
|
| - if (node == CURRENT_ELEMENT_SPANNABLE) {
|
| - node = currentElement;
|
| - } else if (node == NO_LOCATION_SPANNABLE) {
|
| - if (currentElement == null) return null;
|
| - node = currentElement;
|
| - }
|
| - if (node is SourceSpan) {
|
| - return node;
|
| - } else if (node is Node) {
|
| - return spanFromNode(node);
|
| - } else if (node is HInstruction) {
|
| - return spanFromHInstruction(node);
|
| - } else if (node is Element) {
|
| - return spanFromElement(node);
|
| - } else if (node is MetadataAnnotation) {
|
| - return node.sourcePosition;
|
| - } else if (node is Local) {
|
| - Local local = node;
|
| - return spanFromElement(local.executableContext);
|
| - } else if (node is Entity) {
|
| - return spanFromElement(currentElement);
|
| - } else {
|
| - throw 'No error location.';
|
| + // TODO(johnniwinther): Move this to the parser listeners.
|
| + @override
|
| + SourceSpan spanFromToken(Token token) {
|
| + if (compiler.frontEndStrategy is ResolutionFrontEndStrategy) {
|
| + ResolutionFrontEndStrategy strategy = compiler.frontEndStrategy;
|
| + return strategy.spanFromToken(currentElement, token);
|
| }
|
| + throw 'No error location.';
|
| }
|
|
|
| Element _elementFromHInstruction(HInstruction instruction) {
|
| @@ -1296,10 +1171,10 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
| : null;
|
| }
|
|
|
| - internalError(Spannable node, reason) {
|
| + internalError(Spannable spannable, reason) {
|
| String message = tryToString(reason);
|
| reportDiagnosticInternal(
|
| - createMessage(node, MessageKind.GENERIC, {'text': message}),
|
| + createMessage(spannable, MessageKind.GENERIC, {'text': message}),
|
| const <DiagnosticMessage>[],
|
| api.Diagnostic.CRASH);
|
| throw 'Internal Error: $message';
|
|
|