Index: pkg/compiler/lib/src/io/source_information.dart |
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart |
index e7b23eabf16033c2644321dc6abb60cc3aef99d4..3c4ea20ea84bd410a6d50cdec7260ac6c24dbbef 100644 |
--- a/pkg/compiler/lib/src/io/source_information.dart |
+++ b/pkg/compiler/lib/src/io/source_information.dart |
@@ -8,11 +8,14 @@ import '../dart2jslib.dart' show SourceSpan, MessageKind; |
import '../elements/elements.dart' show |
AstElement, |
LocalElement; |
-import '../scanner/scannerlib.dart' show Token; |
-import '../tree/tree.dart' show Node; |
-import '../js/js.dart' show JavaScriptNodeSourceInformation; |
+import '../tree/tree.dart' show Node, Send; |
+import '../js/js.dart' show |
+ JavaScriptNodeSourceInformation; |
import 'source_file.dart'; |
+bool useNewSourceInfo = |
+ const bool.fromEnvironment('USE_NEW_SOURCE_INFO', defaultValue: false); |
+ |
/// Interface for passing source information, for instance for use in source |
/// maps, through the backend. |
abstract class SourceInformation extends JavaScriptNodeSourceInformation { |
@@ -26,14 +29,20 @@ abstract class SourceInformation extends JavaScriptNodeSourceInformation { |
/// The source location associated with the end of the JS node. |
SourceLocation get endPosition => null; |
+ |
+ /// All source locations associated with this source information. |
+ List<SourceLocation> get sourceLocations; |
+ |
+ /// Return a short textual representation of the source location. |
+ String get shortText; |
} |
-/// Factory for creating [SourceInformationBuilder]s. |
-class SourceInformationFactory { |
- const SourceInformationFactory(); |
+/// Strategy for creating, processing and applying [SourceInformation]. |
+class SourceInformationStrategy { |
+ const SourceInformationStrategy(); |
/// Create a [SourceInformationBuilder] for [element]. |
- SourceInformationBuilder forContext(AstElement element) { |
+ SourceInformationBuilder createBuilderForContext(AstElement element) { |
return const SourceInformationBuilder(); |
} |
} |
@@ -43,9 +52,7 @@ class SourceInformationBuilder { |
const SourceInformationBuilder(); |
/// Create a [SourceInformationBuilder] for [element]. |
- SourceInformationBuilder forContext(AstElement element) { |
- return this; |
- } |
+ SourceInformationBuilder forContext(AstElement element) => this; |
/// Generate [SourceInformation] the declaration of [element]. |
SourceInformation buildDeclaration(AstElement element) => null; |
@@ -57,210 +64,32 @@ class SourceInformationBuilder { |
/// Generate [SourceInformation] for the return [node]. |
SourceInformation buildReturn(Node node) => null; |
+ /// Generate [SourceInformation] for an implicit return in [element]. |
+ SourceInformation buildImplicitReturn(AstElement element) => null; |
+ |
/// Generate [SourceInformation] for the loop [node]. |
SourceInformation buildLoop(Node node) => null; |
/// Generate [SourceInformation] for the read access in [node]. |
SourceInformation buildGet(Node node) => null; |
- /// Generate [SourceInformation] for the invocation in [node]. |
- SourceInformation buildCall(Node node) => null; |
-} |
- |
-/// Source information that contains start source position and optionally an |
-/// end source position. |
-class StartEndSourceInformation extends SourceInformation { |
- @override |
- final SourceLocation startPosition; |
- |
- @override |
- final SourceLocation endPosition; |
- |
- StartEndSourceInformation(this.startPosition, [this.endPosition]); |
- |
- @override |
- SourceSpan get sourceSpan { |
- Uri uri = startPosition.sourceUri; |
- int begin = startPosition.offset; |
- int end = endPosition == null ? begin : endPosition.offset; |
- return new SourceSpan(uri, begin, end); |
- } |
- |
- int get hashCode { |
- return 0x7FFFFFFF & |
- (startPosition.hashCode * 17 + endPosition.hashCode * 19); |
- } |
+ /// Generate [SourceInformation] for an invocation like `a.b()` where |
+ /// [receiver] points to the left-most part of the invocation, `a` in the |
+ /// example, and [call] points the 'name' of the call, `b` or `()` depending |
+ /// on whether `b` is a method or a field/getter. |
+ SourceInformation buildCall(Node receiver, Node call) => null; |
- bool operator ==(other) { |
- if (identical(this, other)) return true; |
- if (other is! StartEndSourceInformation) return false; |
- return startPosition == other.startPosition && |
- endPosition == other.endPosition; |
- } |
- |
- // TODO(johnniwinther): Remove this method. Source information should be |
- // computed based on the element by provided from statements and expressions. |
- static StartEndSourceInformation computeSourceInformation( |
- AstElement element) { |
- |
- AstElement implementation = element.implementation; |
- SourceFile sourceFile = implementation.compilationUnit.script.file; |
- String name = computeElementNameForSourceMaps(element); |
- Node node = implementation.node; |
- Token beginToken; |
- Token endToken; |
- if (node == null) { |
- // Synthesized node. Use the enclosing element for the location. |
- beginToken = endToken = element.position; |
- } else { |
- beginToken = node.getBeginToken(); |
- endToken = node.getEndToken(); |
- } |
- // TODO(podivilov): find the right sourceFile here and remove offset |
- // checks below. |
- SourceLocation sourcePosition, endSourcePosition; |
- if (beginToken.charOffset < sourceFile.length) { |
- sourcePosition = |
- new OffsetSourceLocation(sourceFile, beginToken.charOffset, name); |
- } |
- if (endToken.charOffset < sourceFile.length) { |
- endSourcePosition = |
- new OffsetSourceLocation(sourceFile, endToken.charOffset, name); |
- } |
- return new StartEndSourceInformation(sourcePosition, endSourcePosition); |
- } |
+ /// Generate [SourceInformation] for the if statement in [node]. |
+ SourceInformation buildIf(Node node) => null; |
- String toString() { |
- StringBuffer sb = new StringBuffer(); |
- sb.write('${startPosition.sourceUri}:'); |
- // Use 1-based line/column info to match usual dart tool output. |
- sb.write('[${startPosition.line + 1},${startPosition.column + 1}]'); |
- if (endPosition != null) { |
- sb.write('-[${endPosition.line + 1},${endPosition.column + 1}]'); |
- } |
- return sb.toString(); |
- } |
-} |
+ /// Generate [SourceInformation] for the constructor invocation in [node]. |
+ SourceInformation buildNew(Node node) => null; |
-class StartEndSourceInformationFactory implements SourceInformationFactory { |
- const StartEndSourceInformationFactory(); |
+ /// Generate [SourceInformation] for the throw in [node]. |
+ SourceInformation buildThrow(Node node) => null; |
- @override |
- SourceInformationBuilder forContext(AstElement element) { |
- return new StartEndSourceInformationBuilder(element); |
- } |
-} |
- |
-/// [SourceInformationBuilder] that generates [PositionSourceInformation]. |
-class StartEndSourceInformationBuilder extends SourceInformationBuilder { |
- final SourceFile sourceFile; |
- final String name; |
- |
- StartEndSourceInformationBuilder(AstElement element) |
- : sourceFile = element.compilationUnit.script.file, |
- name = computeElementNameForSourceMaps(element); |
- |
- SourceInformation buildDeclaration(AstElement element) { |
- return StartEndSourceInformation.computeSourceInformation(element); |
- } |
- |
- SourceLocation sourceFileLocationForToken(Token token) { |
- SourceLocation location = |
- new OffsetSourceLocation(sourceFile, token.charOffset, name); |
- checkValidSourceFileLocation(location, sourceFile, token.charOffset); |
- return location; |
- } |
- |
- void checkValidSourceFileLocation( |
- SourceLocation location, SourceFile sourceFile, int offset) { |
- if (!location.isValid) { |
- throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
- {'offset': offset, |
- 'fileName': sourceFile.filename, |
- 'length': sourceFile.length}); |
- } |
- } |
- |
- @override |
- SourceInformation buildLoop(Node node) { |
- return new StartEndSourceInformation( |
- sourceFileLocationForToken(node.getBeginToken()), |
- sourceFileLocationForToken(node.getEndToken())); |
- } |
- |
- @override |
- SourceInformation buildGeneric(Node node) { |
- return new StartEndSourceInformation( |
- sourceFileLocationForToken(node.getBeginToken())); |
- } |
- |
- @override |
- SourceInformation buildReturn(Node node) => buildGeneric(node); |
- |
- @override |
- SourceInformation buildGet(Node node) => buildGeneric(node); |
- |
- @override |
- SourceInformation buildCall(Node node) => buildGeneric(node); |
- |
- @override |
- SourceInformationBuilder forContext( |
- AstElement element, {SourceInformation sourceInformation}) { |
- return new StartEndSourceInformationBuilder(element); |
- } |
-} |
- |
-/// [SourceInformation] that consists of an offset position into the source |
-/// code. |
-class PositionSourceInformation extends SourceInformation { |
- @override |
- final SourceLocation startPosition; |
- |
- @override |
- final SourceLocation closingPosition; |
- |
- PositionSourceInformation(this.startPosition, |
- [this.closingPosition]); |
- |
- @override |
- SourceSpan get sourceSpan { |
- SourceLocation location = |
- startPosition != null ? startPosition : closingPosition; |
- Uri uri = location.sourceUri; |
- int offset = location.offset; |
- return new SourceSpan(uri, offset, offset); |
- } |
- |
- int get hashCode { |
- return 0x7FFFFFFF & |
- (startPosition.hashCode * 17 + closingPosition.hashCode * 19); |
- } |
- |
- bool operator ==(other) { |
- if (identical(this, other)) return true; |
- if (other is! PositionSourceInformation) return false; |
- return startPosition == other.startPosition && |
- closingPosition == other.closingPosition; |
- } |
- |
- String toString() { |
- StringBuffer sb = new StringBuffer(); |
- if (startPosition != null) { |
- sb.write('${startPosition.sourceUri}:'); |
- } else { |
- sb.write('${closingPosition.sourceUri}:'); |
- } |
- // Use 1-based line/column info to match usual dart tool output. |
- if (startPosition != null) { |
- sb.write('[${startPosition.line + 1},' |
- '${startPosition.column + 1}]'); |
- } |
- if (closingPosition != null) { |
- sb.write('-[${closingPosition.line + 1},' |
- '${closingPosition.column + 1}]'); |
- } |
- return sb.toString(); |
- } |
+ /// Generate [SourceInformation] for the assignment in [node]. |
+ SourceInformation buildAssignment(Node node) => null; |
} |
/// A location in a source file. |
@@ -307,6 +136,11 @@ abstract class SourceLocation { |
sourceName == other.sourceName; |
} |
+ String get shortText { |
+ // Use 1-based line/column info to match usual dart tool output. |
+ return '${sourceUri.pathSegments.last}:[${line + 1},${column + 1}]'; |
+ } |
+ |
String toString() { |
// Use 1-based line/column info to match usual dart tool output. |
return '${sourceUri}:[${line + 1},${column + 1}]'; |
@@ -320,65 +154,12 @@ class OffsetSourceLocation extends SourceLocation { |
OffsetSourceLocation(SourceFile sourceFile, this.offset, this.sourceName) |
: super(sourceFile); |
- String toString() { |
- return '${super.toString()}:$sourceName'; |
- } |
-} |
- |
-class PositionSourceInformationFactory implements SourceInformationFactory { |
- const PositionSourceInformationFactory(); |
- |
- @override |
- SourceInformationBuilder forContext(AstElement element) { |
- return new PositionSourceInformationBuilder(element); |
- } |
-} |
- |
-/// [SourceInformationBuilder] that generates [PositionSourceInformation]. |
-class PositionSourceInformationBuilder implements SourceInformationBuilder { |
- final SourceFile sourceFile; |
- final String name; |
- |
- PositionSourceInformationBuilder(AstElement element) |
- : sourceFile = element.implementation.compilationUnit.script.file, |
- name = computeElementNameForSourceMaps(element); |
- |
- SourceInformation buildDeclaration(AstElement element) { |
- if (element.isSynthesized) { |
- return new PositionSourceInformation( |
- new OffsetSourceLocation( |
- sourceFile, element.position.charOffset, name)); |
- } else { |
- return new PositionSourceInformation( |
- null, |
- new OffsetSourceLocation(sourceFile, |
- element.resolvedAst.node.getEndToken().charOffset, name)); |
- } |
+ String get shortText { |
+ return '${super.shortText}:$sourceName'; |
} |
- SourceInformation buildBegin(Node node) { |
- return new PositionSourceInformation(new OffsetSourceLocation( |
- sourceFile, node.getBeginToken().charOffset, name)); |
- } |
- |
- @override |
- SourceInformation buildGeneric(Node node) => buildBegin(node); |
- |
- @override |
- SourceInformation buildReturn(Node node) => buildBegin(node); |
- |
- @override |
- SourceInformation buildLoop(Node node) => buildBegin(node); |
- |
- @override |
- SourceInformation buildGet(Node node) => buildBegin(node); |
- |
- @override |
- SourceInformation buildCall(Node node) => buildBegin(node); |
- |
- @override |
- SourceInformationBuilder forContext(AstElement element) { |
- return new PositionSourceInformationBuilder(element); |
+ String toString() { |
+ return '${super.toString()}:$sourceName'; |
} |
} |
@@ -409,4 +190,4 @@ String computeElementNameForSourceMaps(AstElement element) { |
} else { |
return element.name; |
} |
-} |
+} |