OLD | NEW |
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.parser.partial_elements; | 5 library dart2js.parser.partial_elements; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart' show | 8 import '../common/resolution.dart' show Parsing, Resolution; |
9 Parsing, | |
10 Resolution; | |
11 import '../dart_types.dart' show DynamicType; | 9 import '../dart_types.dart' show DynamicType; |
12 import '../elements/elements.dart' show | 10 import '../elements/elements.dart' |
13 CompilationUnitElement, | 11 show |
14 ConstructorElement, | 12 CompilationUnitElement, |
15 Element, | 13 ConstructorElement, |
16 ElementKind, | 14 Element, |
17 GetterElement, | 15 ElementKind, |
18 LibraryElement, | 16 GetterElement, |
19 MetadataAnnotation, | 17 LibraryElement, |
20 MethodElement, | 18 MetadataAnnotation, |
21 SetterElement, | 19 MethodElement, |
22 STATE_NOT_STARTED, | 20 SetterElement, |
23 STATE_DONE; | 21 STATE_NOT_STARTED, |
24 import '../elements/modelx.dart' show | 22 STATE_DONE; |
25 BaseFunctionElementX, | 23 import '../elements/modelx.dart' |
26 ClassElementX, | 24 show |
27 ConstructorElementX, | 25 BaseFunctionElementX, |
28 DeclarationSite, | 26 ClassElementX, |
29 ElementX, | 27 ConstructorElementX, |
30 FieldElementX, | 28 DeclarationSite, |
31 GetterElementX, | 29 ElementX, |
32 MetadataAnnotationX, | 30 FieldElementX, |
33 MethodElementX, | 31 GetterElementX, |
34 SetterElementX, | 32 MetadataAnnotationX, |
35 TypedefElementX, | 33 MethodElementX, |
36 VariableList; | 34 SetterElementX, |
37 import '../elements/visitor.dart' show | 35 TypedefElementX, |
38 ElementVisitor; | 36 VariableList; |
39 import '../tokens/token.dart' show | 37 import '../elements/visitor.dart' show ElementVisitor; |
40 BadInputToken, | 38 import '../tokens/token.dart' |
41 BeginGroupToken, | 39 show |
42 ErrorToken, | 40 BadInputToken, |
43 KeywordToken, | 41 BeginGroupToken, |
44 StringToken, | 42 ErrorToken, |
45 Token, | 43 KeywordToken, |
46 UnmatchedToken, | 44 StringToken, |
47 UnterminatedToken; | 45 Token, |
48 import '../tokens/token_constants.dart' as Tokens show | 46 UnmatchedToken, |
49 EOF_TOKEN; | 47 UnterminatedToken; |
| 48 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN; |
50 import '../tree/tree.dart'; | 49 import '../tree/tree.dart'; |
51 | 50 |
52 import 'class_element_parser.dart' show | 51 import 'class_element_parser.dart' show ClassElementParser; |
53 ClassElementParser; | 52 import 'parser.dart' show Parser; |
54 import 'parser.dart' show | 53 import 'listener.dart' show ParserError; |
55 Parser; | 54 import 'member_listener.dart' show MemberListener; |
56 import 'listener.dart' show | 55 import 'node_listener.dart' show NodeListener; |
57 ParserError; | |
58 import 'member_listener.dart' show | |
59 MemberListener; | |
60 import 'node_listener.dart' show | |
61 NodeListener; | |
62 | 56 |
63 abstract class PartialElement implements DeclarationSite { | 57 abstract class PartialElement implements DeclarationSite { |
64 Token beginToken; | 58 Token beginToken; |
65 Token endToken; | 59 Token endToken; |
66 | 60 |
67 bool hasParseError = false; | 61 bool hasParseError = false; |
68 | 62 |
69 bool get isMalformed => hasParseError; | 63 bool get isMalformed => hasParseError; |
70 | 64 |
71 DeclarationSite get declarationSite => this; | 65 DeclarationSite get declarationSite => this; |
(...skipping 12 matching lines...) Expand all Loading... |
84 */ | 78 */ |
85 Token _position; | 79 Token _position; |
86 | 80 |
87 void init(Token beginToken, Token getOrSet, Token endToken) { | 81 void init(Token beginToken, Token getOrSet, Token endToken) { |
88 this.beginToken = beginToken; | 82 this.beginToken = beginToken; |
89 this.getOrSet = getOrSet; | 83 this.getOrSet = getOrSet; |
90 this.endToken = endToken; | 84 this.endToken = endToken; |
91 _position = ElementX.findNameToken( | 85 _position = ElementX.findNameToken( |
92 beginToken, | 86 beginToken, |
93 modifiers.isFactory || isGenerativeConstructor, | 87 modifiers.isFactory || isGenerativeConstructor, |
94 name, enclosingElement.name); | 88 name, |
| 89 enclosingElement.name); |
95 } | 90 } |
96 | 91 |
97 bool get hasNode => cachedNode != null; | 92 bool get hasNode => cachedNode != null; |
98 | 93 |
99 FunctionExpression get node { | 94 FunctionExpression get node { |
100 assert(invariant(this, cachedNode != null, | 95 assert(invariant(this, cachedNode != null, |
101 message: "Node has not been computed for $this.")); | 96 message: "Node has not been computed for $this.")); |
102 return cachedNode; | 97 return cachedNode; |
103 } | 98 } |
104 | 99 |
(...skipping 14 matching lines...) Expand all Loading... |
119 | 114 |
120 void reusePartialFunctionMixin() { | 115 void reusePartialFunctionMixin() { |
121 cachedNode = null; | 116 cachedNode = null; |
122 } | 117 } |
123 | 118 |
124 DeclarationSite get declarationSite; | 119 DeclarationSite get declarationSite; |
125 } | 120 } |
126 | 121 |
127 abstract class PartialFunctionElement | 122 abstract class PartialFunctionElement |
128 implements PartialElement, PartialFunctionMixin { | 123 implements PartialElement, PartialFunctionMixin { |
129 | 124 factory PartialFunctionElement(String name, Token beginToken, Token getOrSet, |
130 factory PartialFunctionElement( | 125 Token endToken, Modifiers modifiers, Element enclosingElement, |
131 String name, | |
132 Token beginToken, | |
133 Token getOrSet, | |
134 Token endToken, | |
135 Modifiers modifiers, | |
136 Element enclosingElement, | |
137 {bool hasBody: true}) { | 126 {bool hasBody: true}) { |
138 if (getOrSet == null) { | 127 if (getOrSet == null) { |
139 return new PartialMethodElement( | 128 return new PartialMethodElement( |
140 name, beginToken, endToken, modifiers, | 129 name, beginToken, endToken, modifiers, enclosingElement, |
141 enclosingElement, hasBody: hasBody); | 130 hasBody: hasBody); |
142 } else if (identical(getOrSet.stringValue, 'get')) { | 131 } else if (identical(getOrSet.stringValue, 'get')) { |
143 return new PartialGetterElement( | 132 return new PartialGetterElement( |
144 name, beginToken, getOrSet, endToken, modifiers, | 133 name, beginToken, getOrSet, endToken, modifiers, enclosingElement, |
145 enclosingElement, hasBody: hasBody); | 134 hasBody: hasBody); |
146 } else { | 135 } else { |
147 assert(identical(getOrSet.stringValue, 'set')); | 136 assert(identical(getOrSet.stringValue, 'set')); |
148 return new PartialSetterElement( | 137 return new PartialSetterElement( |
149 name, beginToken, getOrSet, endToken, modifiers, | 138 name, beginToken, getOrSet, endToken, modifiers, enclosingElement, |
150 enclosingElement, hasBody: hasBody); | 139 hasBody: hasBody); |
151 } | 140 } |
152 } | 141 } |
153 | 142 |
154 PartialFunctionElement copyWithEnclosing(Element enclosing); | 143 PartialFunctionElement copyWithEnclosing(Element enclosing); |
155 } | 144 } |
156 | 145 |
157 | |
158 class PartialMethodElement extends MethodElementX | 146 class PartialMethodElement extends MethodElementX |
159 with PartialElement, PartialFunctionMixin | 147 with PartialElement, PartialFunctionMixin |
160 implements PartialFunctionElement { | 148 implements PartialFunctionElement { |
161 PartialMethodElement(String name, | 149 PartialMethodElement(String name, Token beginToken, Token endToken, |
162 Token beginToken, | 150 Modifiers modifiers, Element enclosing, |
163 Token endToken, | 151 {bool hasBody: true}) |
164 Modifiers modifiers, | |
165 Element enclosing, | |
166 {bool hasBody: true}) | |
167 : super(name, ElementKind.FUNCTION, modifiers, enclosing, hasBody) { | 152 : super(name, ElementKind.FUNCTION, modifiers, enclosing, hasBody) { |
168 init(beginToken, null, endToken); | 153 init(beginToken, null, endToken); |
169 } | 154 } |
170 | 155 |
171 void reuseElement() { | 156 void reuseElement() { |
172 super.reuseElement(); | 157 super.reuseElement(); |
173 reusePartialFunctionMixin(); | 158 reusePartialFunctionMixin(); |
174 } | 159 } |
175 | 160 |
176 PartialMethodElement copyWithEnclosing(Element enclosing) { | 161 PartialMethodElement copyWithEnclosing(Element enclosing) { |
177 return new PartialMethodElement( | 162 return new PartialMethodElement( |
178 name, beginToken, endToken, modifiers, enclosing, hasBody: hasBody); | 163 name, beginToken, endToken, modifiers, enclosing, |
| 164 hasBody: hasBody); |
179 } | 165 } |
180 } | 166 } |
181 | 167 |
182 class PartialGetterElement extends GetterElementX | 168 class PartialGetterElement extends GetterElementX |
183 with PartialElement, PartialFunctionMixin | 169 with PartialElement, PartialFunctionMixin |
184 implements GetterElement, PartialFunctionElement { | 170 implements GetterElement, PartialFunctionElement { |
185 PartialGetterElement(String name, | 171 PartialGetterElement(String name, Token beginToken, Token getToken, |
186 Token beginToken, | 172 Token endToken, Modifiers modifiers, Element enclosing, |
187 Token getToken, | 173 {bool hasBody: true}) |
188 Token endToken, | |
189 Modifiers modifiers, | |
190 Element enclosing, | |
191 {bool hasBody: true}) | |
192 : super(name, modifiers, enclosing, hasBody) { | 174 : super(name, modifiers, enclosing, hasBody) { |
193 init(beginToken, getToken, endToken); | 175 init(beginToken, getToken, endToken); |
194 } | 176 } |
195 | 177 |
196 @override | 178 @override |
197 SetterElement get setter => abstractField.setter; | 179 SetterElement get setter => abstractField.setter; |
198 | 180 |
199 void reuseElement() { | 181 void reuseElement() { |
200 super.reuseElement(); | 182 super.reuseElement(); |
201 reusePartialFunctionMixin(); | 183 reusePartialFunctionMixin(); |
202 } | 184 } |
203 | 185 |
204 PartialGetterElement copyWithEnclosing(Element enclosing) { | 186 PartialGetterElement copyWithEnclosing(Element enclosing) { |
205 return new PartialGetterElement( | 187 return new PartialGetterElement( |
206 name, beginToken, getOrSet, endToken, modifiers, enclosing, | 188 name, beginToken, getOrSet, endToken, modifiers, enclosing, |
207 hasBody: hasBody); | 189 hasBody: hasBody); |
208 } | 190 } |
209 } | 191 } |
210 | 192 |
211 class PartialSetterElement extends SetterElementX | 193 class PartialSetterElement extends SetterElementX |
212 with PartialElement, PartialFunctionMixin | 194 with PartialElement, PartialFunctionMixin |
213 implements SetterElement, PartialFunctionElement { | 195 implements SetterElement, PartialFunctionElement { |
214 PartialSetterElement(String name, | 196 PartialSetterElement(String name, Token beginToken, Token setToken, |
215 Token beginToken, | 197 Token endToken, Modifiers modifiers, Element enclosing, |
216 Token setToken, | 198 {bool hasBody: true}) |
217 Token endToken, | |
218 Modifiers modifiers, | |
219 Element enclosing, | |
220 {bool hasBody: true}) | |
221 : super(name, modifiers, enclosing, hasBody) { | 199 : super(name, modifiers, enclosing, hasBody) { |
222 init(beginToken, setToken, endToken); | 200 init(beginToken, setToken, endToken); |
223 } | 201 } |
224 | 202 |
225 @override | 203 @override |
226 GetterElement get getter => abstractField.getter; | 204 GetterElement get getter => abstractField.getter; |
227 | 205 |
228 void reuseElement() { | 206 void reuseElement() { |
229 super.reuseElement(); | 207 super.reuseElement(); |
230 reusePartialFunctionMixin(); | 208 reusePartialFunctionMixin(); |
231 } | 209 } |
232 | 210 |
233 PartialSetterElement copyWithEnclosing(Element enclosing) { | 211 PartialSetterElement copyWithEnclosing(Element enclosing) { |
234 return new PartialSetterElement( | 212 return new PartialSetterElement( |
235 name, beginToken, getOrSet, endToken, modifiers, enclosing, | 213 name, beginToken, getOrSet, endToken, modifiers, enclosing, |
236 hasBody: hasBody); | 214 hasBody: hasBody); |
237 } | 215 } |
238 } | 216 } |
239 | 217 |
240 // TODO(johnniwinther): Create [PartialGenerativeConstructor] and | 218 // TODO(johnniwinther): Create [PartialGenerativeConstructor] and |
241 // [PartialFactoryConstructor] subclasses and make this abstract. | 219 // [PartialFactoryConstructor] subclasses and make this abstract. |
242 class PartialConstructorElement extends ConstructorElementX | 220 class PartialConstructorElement extends ConstructorElementX |
243 with PartialElement, PartialFunctionMixin { | 221 with PartialElement, PartialFunctionMixin { |
244 PartialConstructorElement(String name, | 222 PartialConstructorElement(String name, Token beginToken, Token endToken, |
245 Token beginToken, | 223 ElementKind kind, Modifiers modifiers, Element enclosing) |
246 Token endToken, | |
247 ElementKind kind, | |
248 Modifiers modifiers, | |
249 Element enclosing) | |
250 : super(name, kind, modifiers, enclosing) { | 224 : super(name, kind, modifiers, enclosing) { |
251 init(beginToken, null, endToken); | 225 init(beginToken, null, endToken); |
252 } | 226 } |
253 | 227 |
254 void reuseElement() { | 228 void reuseElement() { |
255 super.reuseElement(); | 229 super.reuseElement(); |
256 reusePartialFunctionMixin(); | 230 reusePartialFunctionMixin(); |
257 } | 231 } |
258 } | 232 } |
259 | 233 |
260 class PartialFieldList extends VariableList with PartialElement { | 234 class PartialFieldList extends VariableList with PartialElement { |
261 PartialFieldList(Token beginToken, | 235 PartialFieldList( |
262 Token endToken, | 236 Token beginToken, Token endToken, Modifiers modifiers, bool hasParseError) |
263 Modifiers modifiers, | |
264 bool hasParseError) | |
265 : super(modifiers) { | 237 : super(modifiers) { |
266 super.beginToken = beginToken; | 238 super.beginToken = beginToken; |
267 super.endToken = endToken; | 239 super.endToken = endToken; |
268 super.hasParseError = hasParseError; | 240 super.hasParseError = hasParseError; |
269 } | 241 } |
270 | 242 |
271 VariableDefinitions parseNode(Element element, Parsing parsing) { | 243 VariableDefinitions parseNode(Element element, Parsing parsing) { |
272 if (definitions != null) return definitions; | 244 if (definitions != null) return definitions; |
273 DiagnosticReporter reporter = parsing.reporter; | 245 DiagnosticReporter reporter = parsing.reporter; |
274 reporter.withCurrentElement(element, () { | 246 reporter.withCurrentElement(element, () { |
275 definitions = parse( | 247 definitions = parse(parsing, element, declarationSite, |
276 parsing, element, declarationSite, | |
277 (Parser parser) => parser.parseMember(beginToken)); | 248 (Parser parser) => parser.parseMember(beginToken)); |
278 | 249 |
279 if (!hasParseError && | 250 if (!hasParseError && |
280 !definitions.modifiers.isVar && | 251 !definitions.modifiers.isVar && |
281 !definitions.modifiers.isFinal && | 252 !definitions.modifiers.isFinal && |
282 !definitions.modifiers.isConst && | 253 !definitions.modifiers.isConst && |
283 definitions.type == null && | 254 definitions.type == null && |
284 !definitions.isErroneous) { | 255 !definitions.isErroneous) { |
285 reporter.reportErrorMessage( | 256 reporter.reportErrorMessage(definitions, MessageKind.GENERIC, { |
286 definitions, | 257 'text': 'A field declaration must start with var, final, ' |
287 MessageKind.GENERIC, | 258 'const, or a type annotation.' |
288 { 'text': 'A field declaration must start with var, final, ' | 259 }); |
289 'const, or a type annotation.' }); | |
290 } | 260 } |
291 }); | 261 }); |
292 return definitions; | 262 return definitions; |
293 } | 263 } |
294 | 264 |
295 computeType(Element element, Resolution resolution) { | 265 computeType(Element element, Resolution resolution) { |
296 if (type != null) return type; | 266 if (type != null) return type; |
297 // TODO(johnniwinther): Compute this in the resolver. | 267 // TODO(johnniwinther): Compute this in the resolver. |
298 VariableDefinitions node = parseNode(element, resolution.parsing); | 268 VariableDefinitions node = parseNode(element, resolution.parsing); |
299 if (node.type != null) { | 269 if (node.type != null) { |
300 type = resolution.reporter.withCurrentElement(element, () { | 270 type = resolution.reporter.withCurrentElement(element, () { |
301 return resolution.resolveTypeAnnotation(element, node.type); | 271 return resolution.resolveTypeAnnotation(element, node.type); |
302 }); | 272 }); |
303 } else { | 273 } else { |
304 type = const DynamicType(); | 274 type = const DynamicType(); |
305 } | 275 } |
306 assert(type != null); | 276 assert(type != null); |
307 return type; | 277 return type; |
308 } | 278 } |
309 } | 279 } |
310 | 280 |
311 class PartialTypedefElement extends TypedefElementX with PartialElement { | 281 class PartialTypedefElement extends TypedefElementX with PartialElement { |
312 | |
313 PartialTypedefElement( | 282 PartialTypedefElement( |
314 String name, | 283 String name, Element enclosing, Token beginToken, Token endToken) |
315 Element enclosing, | |
316 Token beginToken, | |
317 Token endToken) | |
318 : super(name, enclosing) { | 284 : super(name, enclosing) { |
319 this.beginToken = beginToken; | 285 this.beginToken = beginToken; |
320 this.endToken = endToken; | 286 this.endToken = endToken; |
321 } | 287 } |
322 | 288 |
323 Token get token => beginToken; | 289 Token get token => beginToken; |
324 | 290 |
325 Node parseNode(Parsing parsing) { | 291 Node parseNode(Parsing parsing) { |
326 if (cachedNode != null) return cachedNode; | 292 if (cachedNode != null) return cachedNode; |
327 cachedNode = parse( | 293 cachedNode = parse(parsing, this, declarationSite, |
328 parsing, this, declarationSite, | |
329 (p) => p.parseTopLevelDeclaration(token)); | 294 (p) => p.parseTopLevelDeclaration(token)); |
330 return cachedNode; | 295 return cachedNode; |
331 } | 296 } |
332 | 297 |
333 Token get position => findMyName(token); | 298 Token get position => findMyName(token); |
334 } | 299 } |
335 | 300 |
336 /// A [MetadataAnnotation] which is constructed on demand. | 301 /// A [MetadataAnnotation] which is constructed on demand. |
337 class PartialMetadataAnnotation extends MetadataAnnotationX | 302 class PartialMetadataAnnotation extends MetadataAnnotationX |
338 implements PartialElement { | 303 implements PartialElement { |
(...skipping 20 matching lines...) Expand all Loading... |
359 assert(token != null); | 324 assert(token != null); |
360 return token; | 325 return token; |
361 } | 326 } |
362 | 327 |
363 void set endToken(_) { | 328 void set endToken(_) { |
364 throw new UnsupportedError("endToken="); | 329 throw new UnsupportedError("endToken="); |
365 } | 330 } |
366 | 331 |
367 Node parseNode(Parsing parsing) { | 332 Node parseNode(Parsing parsing) { |
368 if (cachedNode != null) return cachedNode; | 333 if (cachedNode != null) return cachedNode; |
369 var metadata = parse(parsing, | 334 var metadata = parse(parsing, annotatedElement, declarationSite, |
370 annotatedElement, | 335 (p) => p.parseMetadata(beginToken)); |
371 declarationSite, | |
372 (p) => p.parseMetadata(beginToken)); | |
373 if (metadata is Metadata) { | 336 if (metadata is Metadata) { |
374 cachedNode = metadata.expression; | 337 cachedNode = metadata.expression; |
375 return cachedNode; | 338 return cachedNode; |
376 } else { | 339 } else { |
377 assert (metadata is ErrorNode); | 340 assert(metadata is ErrorNode); |
378 return metadata; | 341 return metadata; |
379 } | 342 } |
380 } | 343 } |
381 | 344 |
382 bool get hasNode => cachedNode != null; | 345 bool get hasNode => cachedNode != null; |
383 | 346 |
384 Node get node { | 347 Node get node { |
385 assert(invariant(this, hasNode)); | 348 assert(invariant(this, hasNode)); |
386 return cachedNode; | 349 return cachedNode; |
387 } | 350 } |
388 } | 351 } |
389 | 352 |
390 class PartialClassElement extends ClassElementX with PartialElement { | 353 class PartialClassElement extends ClassElementX with PartialElement { |
391 ClassNode cachedNode; | 354 ClassNode cachedNode; |
392 | 355 |
393 PartialClassElement(String name, | 356 PartialClassElement( |
394 Token beginToken, | 357 String name, Token beginToken, Token endToken, Element enclosing, int id) |
395 Token endToken, | |
396 Element enclosing, | |
397 int id) | |
398 : super(name, enclosing, id, STATE_NOT_STARTED) { | 358 : super(name, enclosing, id, STATE_NOT_STARTED) { |
399 this.beginToken = beginToken; | 359 this.beginToken = beginToken; |
400 this.endToken = endToken; | 360 this.endToken = endToken; |
401 } | 361 } |
402 | 362 |
403 void set supertypeLoadState(int state) { | 363 void set supertypeLoadState(int state) { |
404 assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1); | 364 assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1); |
405 assert(state <= STATE_DONE); | 365 assert(state <= STATE_DONE); |
406 super.supertypeLoadState = state; | 366 super.supertypeLoadState = state; |
407 } | 367 } |
(...skipping 17 matching lines...) Expand all Loading... |
425 DiagnosticReporter reporter = parsing.reporter; | 385 DiagnosticReporter reporter = parsing.reporter; |
426 reporter.withCurrentElement(this, () { | 386 reporter.withCurrentElement(this, () { |
427 parsing.measure(() { | 387 parsing.measure(() { |
428 MemberListener listener = new MemberListener( | 388 MemberListener listener = new MemberListener( |
429 parsing.getScannerOptionsFor(this), reporter, this); | 389 parsing.getScannerOptionsFor(this), reporter, this); |
430 Parser parser = new ClassElementParser(listener, parsing.parserOptions); | 390 Parser parser = new ClassElementParser(listener, parsing.parserOptions); |
431 try { | 391 try { |
432 Token token = parser.parseTopLevelDeclaration(beginToken); | 392 Token token = parser.parseTopLevelDeclaration(beginToken); |
433 assert(identical(token, endToken.next)); | 393 assert(identical(token, endToken.next)); |
434 cachedNode = listener.popNode(); | 394 cachedNode = listener.popNode(); |
435 assert( | 395 assert(invariant(beginToken, listener.nodes.isEmpty, |
436 invariant( | 396 message: "Non-empty listener stack: ${listener.nodes}")); |
437 beginToken, listener.nodes.isEmpty, | |
438 message: "Non-empty listener stack: ${listener.nodes}")); | |
439 } on ParserError { | 397 } on ParserError { |
440 // TODO(ahe): Often, a ParserError is thrown while parsing the class | 398 // TODO(ahe): Often, a ParserError is thrown while parsing the class |
441 // body. This means that the stack actually contains most of the | 399 // body. This means that the stack actually contains most of the |
442 // information synthesized below. Consider rewriting the parser so | 400 // information synthesized below. Consider rewriting the parser so |
443 // endClassDeclaration is called before parsing the class body. | 401 // endClassDeclaration is called before parsing the class body. |
444 Identifier name = new Identifier(findMyName(beginToken)); | 402 Identifier name = new Identifier(findMyName(beginToken)); |
445 NodeList typeParameters = null; | 403 NodeList typeParameters = null; |
446 Node supertype = null; | 404 Node supertype = null; |
447 NodeList interfaces = listener.makeNodeList(0, null, null, ","); | 405 NodeList interfaces = listener.makeNodeList(0, null, null, ","); |
448 Token extendsKeyword = null; | 406 Token extendsKeyword = null; |
449 NodeList body = listener.makeNodeList(0, beginToken, endToken, null); | 407 NodeList body = listener.makeNodeList(0, beginToken, endToken, null); |
450 cachedNode = new ClassNode( | 408 cachedNode = new ClassNode( |
451 Modifiers.EMPTY, name, typeParameters, supertype, interfaces, | 409 Modifiers.EMPTY, |
452 beginToken, extendsKeyword, body, endToken); | 410 name, |
| 411 typeParameters, |
| 412 supertype, |
| 413 interfaces, |
| 414 beginToken, |
| 415 extendsKeyword, |
| 416 body, |
| 417 endToken); |
453 hasParseError = true; | 418 hasParseError = true; |
454 } | 419 } |
455 }); | 420 }); |
456 if (isPatched) { | 421 if (isPatched) { |
457 parsing.parsePatchClass(patch); | 422 parsing.parsePatchClass(patch); |
458 } | 423 } |
459 }); | 424 }); |
460 return cachedNode; | 425 return cachedNode; |
461 } | 426 } |
462 | 427 |
463 Token get position => beginToken; | 428 Token get position => beginToken; |
464 | 429 |
465 // TODO(johnniwinther): Ensure that modifiers are always available. | 430 // TODO(johnniwinther): Ensure that modifiers are always available. |
466 Modifiers get modifiers => | 431 Modifiers get modifiers => |
467 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY; | 432 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY; |
468 | 433 |
469 accept(ElementVisitor visitor, arg) { | 434 accept(ElementVisitor visitor, arg) { |
470 return visitor.visitClassElement(this, arg); | 435 return visitor.visitClassElement(this, arg); |
471 } | 436 } |
472 | 437 |
473 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) { | 438 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) { |
474 return new PartialClassElement(name, beginToken, endToken, enclosing, id); | 439 return new PartialClassElement(name, beginToken, endToken, enclosing, id); |
475 } | 440 } |
476 } | 441 } |
477 | 442 |
478 Node parse( | 443 Node parse(Parsing parsing, ElementX element, PartialElement partial, |
479 Parsing parsing, | |
480 ElementX element, | |
481 PartialElement partial, | |
482 doParse(Parser parser)) { | 444 doParse(Parser parser)) { |
483 DiagnosticReporter reporter = parsing.reporter; | 445 DiagnosticReporter reporter = parsing.reporter; |
484 return parsing.measure(() { | 446 return parsing.measure(() { |
485 return reporter.withCurrentElement(element, () { | 447 return reporter.withCurrentElement(element, () { |
486 CompilationUnitElement unit = element.compilationUnit; | 448 CompilationUnitElement unit = element.compilationUnit; |
487 NodeListener listener = new NodeListener( | 449 NodeListener listener = new NodeListener( |
488 parsing.getScannerOptionsFor(element), reporter, unit); | 450 parsing.getScannerOptionsFor(element), reporter, unit); |
489 listener.memberErrors = listener.memberErrors.prepend(false); | 451 listener.memberErrors = listener.memberErrors.prepend(false); |
490 try { | 452 try { |
491 if (partial.hasParseError) { | 453 if (partial.hasParseError) { |
492 listener.suppressParseErrors = true; | 454 listener.suppressParseErrors = true; |
493 } | 455 } |
494 doParse(new Parser(listener, parsing.parserOptions)); | 456 doParse(new Parser(listener, parsing.parserOptions)); |
495 } on ParserError catch (e) { | 457 } on ParserError catch (e) { |
496 partial.hasParseError = true; | 458 partial.hasParseError = true; |
497 return new ErrorNode(element.position, e.reason); | 459 return new ErrorNode(element.position, e.reason); |
498 } | 460 } |
499 Node node = listener.popNode(); | 461 Node node = listener.popNode(); |
500 assert(listener.nodes.isEmpty); | 462 assert(listener.nodes.isEmpty); |
501 return node; | 463 return node; |
502 }); | 464 }); |
503 }); | 465 }); |
504 } | 466 } |
OLD | NEW |