Chromium Code Reviews| 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..e419adb25880fbb1d1ca23c494db453c7a457486 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 USE_NEW_SOURCE_INFO = |
| + 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 a implicit return in [element]. |
|
floitsch
2015/06/29 08:55:52
an implicit
Johnni Winther
2015/06/29 12:36:29
Done.
|
| + 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; |
| } |
| -} |
| +} |