Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(714)

Side by Side Diff: pkg/compiler/lib/src/io/source_information.dart

Issue 1100723002: Add SourceInformationFactory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cleanup. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.source_information; 5 library dart2js.source_information;
6 6
7 import '../dart2jslib.dart' show SourceSpan; 7 import '../dart2jslib.dart' show SourceSpan, MessageKind;
8 import '../elements/elements.dart' show AstElement; 8 import '../elements/elements.dart' show AstElement;
9 import '../scanner/scannerlib.dart' show Token; 9 import '../scanner/scannerlib.dart' show Token;
10 import '../tree/tree.dart' show Node; 10 import '../tree/tree.dart' show Node;
11 import '../js/js.dart' show JavaScriptNodeSourceInformation; 11 import '../js/js.dart' show JavaScriptNodeSourceInformation;
12 import 'source_file.dart'; 12 import 'source_file.dart';
13 13
14 /// Interface for passing source information, for instance for use in source 14 /// Interface for passing source information, for instance for use in source
15 /// maps, through the backend. 15 /// maps, through the backend.
16 abstract class SourceInformation extends JavaScriptNodeSourceInformation { 16 abstract class SourceInformation extends JavaScriptNodeSourceInformation {
17 SourceSpan get sourceSpan; 17 SourceSpan get sourceSpan;
18 18
19 /// The source location associated with the start of the JS node. 19 /// The source location associated with the start of the JS node.
20 SourceLocation get startPosition; 20 SourceLocation get startPosition => null;
21
22 /// The source location associated with the closing of the JS node.
23 SourceLocation get closingPosition => null;
21 24
22 /// The source location associated with the end of the JS node. 25 /// The source location associated with the end of the JS node.
23 SourceLocation get endPosition; 26 SourceLocation get endPosition => null;
27 }
28
29 /// Factory for creating [SourceInformationBuilder]s.
30 class SourceInformationFactory {
31 const SourceInformationFactory();
32
33 /// Create a [SourceInformationBuilder] for [element].
34 SourceInformationBuilder forContext(AstElement element) {
35 return const SourceInformationBuilder();
36 }
37 }
38
39 /// Interface for generating [SourceInformation].
40 class SourceInformationBuilder {
41 const SourceInformationBuilder();
42
43 /// Create a [SourceInformationBuilder] for [element].
44 SourceInformationBuilder forContext(AstElement element) {
45 return this;
46 }
47
48 /// Generate [SourceInformation] the declaration of [element].
49 SourceInformation buildDeclaration(AstElement element) => null;
50
51 /// Generate [SourceInformation] for the generic [node].
52 @deprecated
53 SourceInformation buildGeneric(Node node) => null;
54
55 /// Generate [SourceInformation] for the return [node].
56 SourceInformation buildReturn(Node node) => null;
57
58 /// Generate [SourceInformation] for the loop [node].
59 SourceInformation buildLoop(Node node) => null;
60
61 /// Generate [SourceInformation] for the read access in [node].
62 SourceInformation buildGet(Node node) => null;
63
64 /// Generate [SourceInformation] for the invocation in [node].
65 SourceInformation buildCall(Node node) => null;
24 } 66 }
25 67
26 /// Source information that contains start source position and optionally an 68 /// Source information that contains start source position and optionally an
27 /// end source position. 69 /// end source position.
28 class StartEndSourceInformation implements SourceInformation { 70 class StartEndSourceInformation extends SourceInformation {
71 @override
29 final SourceLocation startPosition; 72 final SourceLocation startPosition;
73
74 @override
30 final SourceLocation endPosition; 75 final SourceLocation endPosition;
31 76
32 StartEndSourceInformation(this.startPosition, [this.endPosition]); 77 StartEndSourceInformation(this.startPosition, [this.endPosition]);
33 78
79 @override
34 SourceSpan get sourceSpan { 80 SourceSpan get sourceSpan {
35 Uri uri = startPosition.sourceUri; 81 Uri uri = startPosition.sourceUri;
36 int begin = startPosition.offset; 82 int begin = startPosition.offset;
37 int end = endPosition == null ? begin : endPosition.offset; 83 int end = endPosition == null ? begin : endPosition.offset;
38 return new SourceSpan(uri, begin, end); 84 return new SourceSpan(uri, begin, end);
39 } 85 }
40 86
41 int get hashCode { 87 int get hashCode {
42 return (startPosition.hashCode * 17 + 88 return 0x7FFFFFFF &
43 endPosition.hashCode * 19) 89 (startPosition.hashCode * 17 + endPosition.hashCode * 19);
44 & 0x7FFFFFFF;
45 } 90 }
46 91
47 bool operator ==(other) { 92 bool operator ==(other) {
48 if (identical(this, other)) return true; 93 if (identical(this, other)) return true;
49 if (other is! StartEndSourceInformation) return false; 94 if (other is! StartEndSourceInformation) return false;
50 return startPosition == other.startPosition && 95 return startPosition == other.startPosition &&
51 endPosition == other.endPosition; 96 endPosition == other.endPosition;
52 } 97 }
53 98
54 // TODO(johnniwinther): Remove this method. Source information should be 99 // TODO(johnniwinther): Remove this method. Source information should be
(...skipping 12 matching lines...) Expand all
67 beginToken = endToken = element.position; 112 beginToken = endToken = element.position;
68 } else { 113 } else {
69 beginToken = node.getBeginToken(); 114 beginToken = node.getBeginToken();
70 endToken = node.getEndToken(); 115 endToken = node.getEndToken();
71 } 116 }
72 // TODO(podivilov): find the right sourceFile here and remove offset 117 // TODO(podivilov): find the right sourceFile here and remove offset
73 // checks below. 118 // checks below.
74 SourceLocation sourcePosition, endSourcePosition; 119 SourceLocation sourcePosition, endSourcePosition;
75 if (beginToken.charOffset < sourceFile.length) { 120 if (beginToken.charOffset < sourceFile.length) {
76 sourcePosition = 121 sourcePosition =
77 new TokenSourceLocation(sourceFile, beginToken, name); 122 new OffsetSourceLocation(sourceFile, beginToken.charOffset, name);
78 } 123 }
79 if (endToken.charOffset < sourceFile.length) { 124 if (endToken.charOffset < sourceFile.length) {
80 endSourcePosition = 125 endSourcePosition =
81 new TokenSourceLocation(sourceFile, endToken, name); 126 new OffsetSourceLocation(sourceFile, endToken.charOffset, name);
82 } 127 }
83 return new StartEndSourceInformation(sourcePosition, endSourcePosition); 128 return new StartEndSourceInformation(sourcePosition, endSourcePosition);
84 } 129 }
85 130
86 String toString() { 131 String toString() {
87 StringBuffer sb = new StringBuffer(); 132 StringBuffer sb = new StringBuffer();
88 sb.write('${startPosition.sourceUri}:'); 133 sb.write('${startPosition.sourceUri}:');
89 // Use 1-based line/column info to match usual dart tool output. 134 // Use 1-based line/column info to match usual dart tool output.
90 sb.write('[${startPosition.line + 1},${startPosition.column + 1}]'); 135 sb.write('[${startPosition.line + 1},${startPosition.column + 1}]');
91 if (endPosition != null) { 136 if (endPosition != null) {
92 sb.write('-[${endPosition.line + 1},${endPosition.column + 1}]'); 137 sb.write('-[${endPosition.line + 1},${endPosition.column + 1}]');
93 } 138 }
94 return sb.toString(); 139 return sb.toString();
95 } 140 }
96 } 141 }
97 142
143 class StartEndSourceInformationFactory implements SourceInformationFactory {
144 const StartEndSourceInformationFactory();
145
146 @override
147 SourceInformationBuilder forContext(AstElement element) {
148 return new StartEndSourceInformationBuilder(element);
149 }
150 }
151
152 /// [SourceInformationBuilder] that generates [PositionSourceInformation].
153 class StartEndSourceInformationBuilder extends SourceInformationBuilder {
154 final SourceFile sourceFile;
155 final String name;
156
157 StartEndSourceInformationBuilder(AstElement element)
158 : sourceFile = element.compilationUnit.script.file,
159 name = element.name;
160
161 SourceInformation buildDeclaration(AstElement element) {
162 return StartEndSourceInformation.computeSourceInformation(element);
163 }
164
165 SourceLocation sourceFileLocationForToken(Token token) {
166 SourceLocation location =
167 new OffsetSourceLocation(sourceFile, token.charOffset, name);
168 checkValidSourceFileLocation(location, sourceFile, token.charOffset);
169 return location;
170 }
171
172 void checkValidSourceFileLocation(
173 SourceLocation location, SourceFile sourceFile, int offset) {
174 if (!location.isValid) {
175 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message(
176 {'offset': offset,
177 'fileName': sourceFile.filename,
178 'length': sourceFile.length});
179 }
180 }
181
182 @override
183 SourceInformation buildLoop(Node node) {
184 return new StartEndSourceInformation(
185 sourceFileLocationForToken(node.getBeginToken()),
186 sourceFileLocationForToken(node.getEndToken()));
187 }
188
189 @override
190 SourceInformation buildGeneric(Node node) {
191 return new StartEndSourceInformation(
192 sourceFileLocationForToken(node.getBeginToken()));
193 }
194
195 @override
196 SourceInformation buildReturn(Node node) => buildGeneric(node);
197
198 @override
199 SourceInformation buildGet(Node node) => buildGeneric(node);
200
201 @override
202 SourceInformation buildCall(Node node) => buildGeneric(node);
203
204 @override
205 SourceInformationBuilder forContext(
206 AstElement element, {SourceInformation sourceInformation}) {
207 return new StartEndSourceInformationBuilder(element);
208 }
209 }
210
98 /// [SourceInformation] that consists of an offset position into the source 211 /// [SourceInformation] that consists of an offset position into the source
99 /// code. 212 /// code.
100 class PositionSourceInformation implements SourceInformation { 213 class PositionSourceInformation extends SourceInformation {
101 final SourceLocation sourcePosition; 214 @override
215 final SourceLocation startPosition;
102 216
103 PositionSourceInformation(this.sourcePosition); 217 @override
218 final SourceLocation closingPosition;
104 219
105 SourceLocation get startPosition => sourcePosition; 220 PositionSourceInformation(this.startPosition,
106 SourceLocation get endPosition => null; 221 [this.closingPosition]);
107 222
223 @override
108 SourceSpan get sourceSpan { 224 SourceSpan get sourceSpan {
109 Uri uri = sourcePosition.sourceUri; 225 SourceLocation location =
110 int offset = sourcePosition.offset; 226 startPosition != null ? startPosition : closingPosition;
227 Uri uri = location.sourceUri;
228 int offset = location.offset;
111 return new SourceSpan(uri, offset, offset); 229 return new SourceSpan(uri, offset, offset);
112 } 230 }
113 231
114 int get hashCode { 232 int get hashCode {
115 return sourcePosition.hashCode * 17 & 0x7FFFFFFF; 233 return 0x7FFFFFFF &
234 (startPosition.hashCode * 17 + closingPosition.hashCode * 19);
116 } 235 }
117 236
118 bool operator ==(other) { 237 bool operator ==(other) {
119 if (identical(this, other)) return true; 238 if (identical(this, other)) return true;
120 if (other is! PositionSourceInformation) return false; 239 if (other is! PositionSourceInformation) return false;
121 return sourcePosition == other.sourcePosition; 240 return startPosition == other.startPosition &&
241 closingPosition == other.closingPosition;
122 } 242 }
123 243
124 String toString() { 244 String toString() {
125 StringBuffer sb = new StringBuffer(); 245 StringBuffer sb = new StringBuffer();
126 sb.write('${sourcePosition.sourceUri}:'); 246 if (startPosition != null) {
247 sb.write('${startPosition.sourceUri}:');
248 } else {
249 sb.write('${closingPosition.sourceUri}:');
250 }
127 // Use 1-based line/column info to match usual dart tool output. 251 // Use 1-based line/column info to match usual dart tool output.
128 sb.write('[${sourcePosition.line + 1},${sourcePosition.column + 1}]'); 252 if (startPosition != null) {
253 sb.write('[${startPosition.line + 1},'
254 '${startPosition.column + 1}]');
255 }
256 if (closingPosition != null) {
257 sb.write('-[${closingPosition.line + 1},'
258 '${closingPosition.column + 1}]');
259 }
129 return sb.toString(); 260 return sb.toString();
130 } 261 }
131 } 262 }
132 263
133 /// A location in a source file. 264 /// A location in a source file.
134 abstract class SourceLocation { 265 abstract class SourceLocation {
135 final SourceFile _sourceFile; 266 final SourceFile _sourceFile;
136 int _line; 267 int _line;
137 268
138 SourceLocation(this._sourceFile) { 269 SourceLocation(this._sourceFile) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 offset == other.offset && 304 offset == other.offset &&
174 sourceName == other.sourceName; 305 sourceName == other.sourceName;
175 } 306 }
176 307
177 String toString() { 308 String toString() {
178 // Use 1-based line/column info to match usual dart tool output. 309 // Use 1-based line/column info to match usual dart tool output.
179 return '${sourceUri}:[${line + 1},${column + 1}]'; 310 return '${sourceUri}:[${line + 1},${column + 1}]';
180 } 311 }
181 } 312 }
182 313
183 class TokenSourceLocation extends SourceLocation { 314 class OffsetSourceLocation extends SourceLocation {
184 final Token token; 315 final int offset;
185 final String sourceName; 316 final String sourceName;
186 317
187 TokenSourceLocation(SourceFile sourceFile, this.token, this.sourceName) 318 OffsetSourceLocation(SourceFile sourceFile, this.offset, this.sourceName)
188 : super(sourceFile); 319 : super(sourceFile);
floitsch 2015/04/21 11:31:53 indent++
Johnni Winther 2015/04/21 12:07:01 Done.
189 320
190 @override
191 int get offset => token.charOffset;
192 321
193 String toString() { 322 String toString() {
194 return '${super.toString()}:$sourceName'; 323 return '${super.toString()}:$sourceName';
195 } 324 }
196 } 325 }
326
327 class PositionSourceInformationFactory implements SourceInformationFactory {
328 const PositionSourceInformationFactory();
329
330 @override
331 SourceInformationBuilder forContext(AstElement element) {
332 return new PositionSourceInformationBuilder(element);
333 }
334 }
335
336 /// [SourceInformationBuilder] that generates [PositionSourceInformation].
337 class PositionSourceInformationBuilder implements SourceInformationBuilder {
338 final SourceFile sourceFile;
339 final String name;
340
341 PositionSourceInformationBuilder(AstElement element)
342 : sourceFile = element.implementation.compilationUnit.script.file,
343 name = element.name;
344
345 SourceInformation buildDeclaration(AstElement element) {
346 if (element.isSynthesized) {
347 return new PositionSourceInformation(
348 new OffsetSourceLocation(
349 sourceFile, element.position.charOffset, name));
350 } else {
351 return new PositionSourceInformation(
352 null,
353 new OffsetSourceLocation(sourceFile,
354 element.resolvedAst.node.getEndToken().charOffset, name));
355 }
356 }
357
358 SourceInformation buildBegin(Node node) {
359 return new PositionSourceInformation(new OffsetSourceLocation(
360 sourceFile, node.getBeginToken().charOffset, name));
361 }
362
363 @override
364 SourceInformation buildGeneric(Node node) => buildBegin(node);
365
366 @override
367 SourceInformation buildReturn(Node node) => buildBegin(node);
368
369 @override
370 SourceInformation buildLoop(Node node) => buildBegin(node);
371
372 @override
373 SourceInformation buildGet(Node node) => buildBegin(node);
374
375 @override
376 SourceInformation buildCall(Node node) => buildBegin(node);
377
378 @override
379 SourceInformationBuilder forContext(AstElement element) {
380 return new PositionSourceInformationBuilder(element);
381 }
382 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698