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'; |