OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /// Source information system that maps spans of Dart AST nodes to spans of | |
6 /// JavaScript nodes. | |
7 | |
8 library dart2js.source_information.start_end; | |
9 | |
10 import '../dart2jslib.dart' show | |
11 MessageKind, | |
12 SourceSpan; | |
13 import '../elements/elements.dart' show | |
14 AstElement, | |
15 LocalElement; | |
16 import '../js/js.dart' as js; | |
17 import '../js/js_source_mapping.dart'; | |
18 import '../scanner/scannerlib.dart' show Token; | |
19 import '../tree/tree.dart' show Node, Send; | |
20 | |
21 import 'source_file.dart'; | |
22 import 'source_information.dart'; | |
23 | |
24 /// Source information that contains start source position and optionally an | |
25 /// end source position. | |
26 class StartEndSourceInformation extends SourceInformation { | |
27 @override | |
28 final SourceLocation startPosition; | |
29 | |
30 @override | |
31 final SourceLocation endPosition; | |
32 | |
33 StartEndSourceInformation(this.startPosition, [this.endPosition]); | |
34 | |
35 @override | |
36 List<SourceLocation> get sourceLocations { | |
37 if (endPosition == null) { | |
38 return <SourceLocation>[startPosition]; | |
39 } else { | |
40 return <SourceLocation>[startPosition, endPosition]; | |
41 } | |
42 } | |
43 | |
44 @override | |
45 SourceSpan get sourceSpan { | |
46 Uri uri = startPosition.sourceUri; | |
47 int begin = startPosition.offset; | |
48 int end = endPosition == null ? begin : endPosition.offset; | |
49 return new SourceSpan(uri, begin, end); | |
50 } | |
51 | |
52 int get hashCode { | |
53 return 0x7FFFFFFF & | |
54 (startPosition.hashCode * 17 + endPosition.hashCode * 19); | |
55 } | |
56 | |
57 bool operator ==(other) { | |
58 if (identical(this, other)) return true; | |
59 if (other is! StartEndSourceInformation) return false; | |
60 return startPosition == other.startPosition && | |
61 endPosition == other.endPosition; | |
62 } | |
63 | |
64 // TODO(johnniwinther): Remove this method. Source information should be | |
65 // computed based on the element by provided from statements and expressions. | |
floitsch
2015/06/29 08:55:52
-by-
Johnni Winther
2015/06/29 12:36:29
TODO was stale. Replaced with the appropriate.
| |
66 static StartEndSourceInformation computeSourceInformation( | |
67 AstElement element) { | |
68 | |
69 AstElement implementation = element.implementation; | |
70 SourceFile sourceFile = implementation.compilationUnit.script.file; | |
71 String name = computeElementNameForSourceMaps(element); | |
72 Node node = implementation.node; | |
73 Token beginToken; | |
74 Token endToken; | |
75 if (node == null) { | |
76 // Synthesized node. Use the enclosing element for the location. | |
77 beginToken = endToken = element.position; | |
78 } else { | |
79 beginToken = node.getBeginToken(); | |
80 endToken = node.getEndToken(); | |
81 } | |
82 // TODO(podivilov): find the right sourceFile here and remove offset | |
floitsch
2015/06/29 08:55:52
I think we can safely reassign this TODO.
Johnni Winther
2015/06/29 12:36:29
Done.
| |
83 // checks below. | |
84 SourceLocation sourcePosition, endSourcePosition; | |
85 if (beginToken.charOffset < sourceFile.length) { | |
86 sourcePosition = | |
87 new OffsetSourceLocation(sourceFile, beginToken.charOffset, name); | |
88 } | |
89 if (endToken.charOffset < sourceFile.length) { | |
90 endSourcePosition = | |
91 new OffsetSourceLocation(sourceFile, endToken.charOffset, name); | |
92 } | |
93 return new StartEndSourceInformation(sourcePosition, endSourcePosition); | |
94 } | |
95 | |
96 String get shortText { | |
97 StringBuffer sb = new StringBuffer(); | |
98 sb.write('${startPosition.sourceUri.pathSegments.last}:'); | |
99 // Use 1-based line/startPosition info to match usual dart tool output. | |
100 sb.write('[${startPosition.line + 1},${startPosition.column + 1}]'); | |
101 if (endPosition != null) { | |
102 sb.write('-[${endPosition.line + 1},${endPosition.column + 1}]'); | |
103 } | |
104 return sb.toString(); | |
105 } | |
106 | |
107 String toString() { | |
108 StringBuffer sb = new StringBuffer(); | |
floitsch
2015/06/29 08:55:52
create a helper function?
Only seems to differ in
Johnni Winther
2015/06/29 12:36:29
Done.
| |
109 sb.write('${startPosition.sourceUri}:'); | |
110 // Use 1-based line/column info to match usual dart tool output. | |
111 sb.write('[${startPosition.line + 1},${startPosition.column + 1}]'); | |
112 if (endPosition != null) { | |
113 sb.write('-[${endPosition.line + 1},${endPosition.column + 1}]'); | |
114 } | |
115 return sb.toString(); | |
116 } | |
117 } | |
118 | |
119 class StartEndSourceInformationStrategy | |
120 implements JavaScriptSourceInformationStrategy { | |
121 const StartEndSourceInformationStrategy(); | |
122 | |
123 @override | |
124 SourceInformationBuilder createBuilderForContext(AstElement element) { | |
125 return new StartEndSourceInformationBuilder(element); | |
126 } | |
127 | |
128 @override | |
129 SourceInformationProcessor createProcessor(SourceMapper sourceMapper) { | |
130 return new StartEndSourceInformationProcessor(sourceMapper); | |
131 } | |
132 } | |
133 | |
134 class StartEndSourceInformationProcessor extends SourceInformationProcessor { | |
135 final SourceMapper sourceMapper; | |
136 js.Node root; | |
floitsch
2015/06/29 08:55:52
comments what "root" is.
unless there are subclass
Johnni Winther
2015/06/29 12:36:29
Done.
| |
137 | |
138 StartEndSourceInformationProcessor(this.sourceMapper); | |
139 | |
140 @override | |
141 void onPositions(js.Node node, | |
142 int startPosition, | |
143 int endPosition, | |
144 int closingPosition) { | |
145 if (node.sourceInformation != null) { | |
146 StartEndSourceInformation sourceInformation = node.sourceInformation; | |
147 sourceMapper.register( | |
148 node, startPosition, sourceInformation.startPosition); | |
149 if (sourceInformation.endPosition != null) { | |
150 sourceMapper.register(node, endPosition, sourceInformation.endPosition); | |
151 } | |
152 if (root == null) { | |
153 sourceMapper.register(node, endPosition, null); | |
154 root = node; | |
155 } | |
156 } | |
157 } | |
158 } | |
159 | |
160 /// [SourceInformationBuilder] that generates [PositionSourceInformation]. | |
161 class StartEndSourceInformationBuilder extends SourceInformationBuilder { | |
162 final SourceFile sourceFile; | |
163 final String name; | |
164 | |
165 StartEndSourceInformationBuilder(AstElement element) | |
166 : sourceFile = element.compilationUnit.script.file, | |
167 name = computeElementNameForSourceMaps(element); | |
168 | |
169 SourceInformation buildDeclaration(AstElement element) { | |
170 return StartEndSourceInformation.computeSourceInformation(element); | |
171 } | |
172 | |
173 SourceLocation sourceFileLocationForToken(Token token) { | |
174 SourceLocation location = | |
175 new OffsetSourceLocation(sourceFile, token.charOffset, name); | |
176 checkValidSourceFileLocation(location, sourceFile, token.charOffset); | |
177 return location; | |
178 } | |
179 | |
180 void checkValidSourceFileLocation( | |
181 SourceLocation location, SourceFile sourceFile, int offset) { | |
182 if (!location.isValid) { | |
183 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | |
184 {'offset': offset, | |
185 'fileName': sourceFile.filename, | |
186 'length': sourceFile.length}); | |
187 } | |
188 } | |
189 | |
190 @override | |
191 SourceInformation buildLoop(Node node) { | |
192 return new StartEndSourceInformation( | |
193 sourceFileLocationForToken(node.getBeginToken()), | |
194 sourceFileLocationForToken(node.getEndToken())); | |
195 } | |
196 | |
197 @override | |
198 SourceInformation buildGeneric(Node node) { | |
199 return new StartEndSourceInformation( | |
200 sourceFileLocationForToken(node.getBeginToken())); | |
201 } | |
202 | |
203 @override | |
204 SourceInformation buildReturn(Node node) { | |
205 return buildGeneric(node); | |
206 } | |
207 | |
208 @override | |
209 SourceInformation buildGet(Node node) => buildGeneric(node); | |
210 | |
211 @override | |
212 SourceInformation buildAssignment(Node node) => buildGeneric(node); | |
213 | |
214 @override | |
215 SourceInformation buildCall(Node receiver, Node call) { | |
216 return buildGeneric(receiver); | |
217 } | |
218 | |
219 @override | |
220 SourceInformation buildIf(Node node) => buildGeneric(node); | |
221 | |
222 @override | |
223 SourceInformationBuilder forContext( | |
224 AstElement element, {SourceInformation sourceInformation}) { | |
225 return new StartEndSourceInformationBuilder(element); | |
226 } | |
227 } | |
228 | |
229 | |
230 | |
OLD | NEW |