| 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/resolution.dart' show |
| 8 Parsing, |
| 9 Resolution; |
| 7 import '../compiler.dart' show | 10 import '../compiler.dart' show |
| 8 Compiler; | 11 Compiler; |
| 9 import '../dart_types.dart' show DynamicType; | 12 import '../dart_types.dart' show DynamicType; |
| 10 import '../diagnostics/diagnostic_listener.dart'; | 13 import '../diagnostics/diagnostic_listener.dart'; |
| 11 import '../diagnostics/invariant.dart' show | 14 import '../diagnostics/invariant.dart' show |
| 12 invariant; | 15 invariant; |
| 13 import '../diagnostics/messages.dart'; | 16 import '../diagnostics/messages.dart'; |
| 14 import '../elements/elements.dart' show | 17 import '../elements/elements.dart' show |
| 15 CompilationUnitElement, | 18 CompilationUnitElement, |
| 16 ConstructorElement, | 19 ConstructorElement, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 } | 100 } |
| 98 | 101 |
| 99 bool get hasNode => cachedNode != null; | 102 bool get hasNode => cachedNode != null; |
| 100 | 103 |
| 101 FunctionExpression get node { | 104 FunctionExpression get node { |
| 102 assert(invariant(this, cachedNode != null, | 105 assert(invariant(this, cachedNode != null, |
| 103 message: "Node has not been computed for $this.")); | 106 message: "Node has not been computed for $this.")); |
| 104 return cachedNode; | 107 return cachedNode; |
| 105 } | 108 } |
| 106 | 109 |
| 107 FunctionExpression parseNode(DiagnosticListener listener) { | 110 FunctionExpression parseNode(Parsing parsing) { |
| 108 if (cachedNode != null) return cachedNode; | 111 if (cachedNode != null) return cachedNode; |
| 109 parseFunction(Parser p) { | 112 parseFunction(Parser p) { |
| 110 if (isClassMember && modifiers.isFactory) { | 113 if (isClassMember && modifiers.isFactory) { |
| 111 p.parseFactoryMethod(beginToken); | 114 p.parseFactoryMethod(beginToken); |
| 112 } else { | 115 } else { |
| 113 p.parseFunction(beginToken, getOrSet); | 116 p.parseFunction(beginToken, getOrSet); |
| 114 } | 117 } |
| 115 } | 118 } |
| 116 cachedNode = parse(listener, this, declarationSite, parseFunction); | 119 cachedNode = parse(parsing, this, declarationSite, parseFunction); |
| 117 return cachedNode; | 120 return cachedNode; |
| 118 } | 121 } |
| 119 | 122 |
| 120 Token get position => _position; | 123 Token get position => _position; |
| 121 | 124 |
| 122 void reusePartialFunctionMixin() { | 125 void reusePartialFunctionMixin() { |
| 123 cachedNode = null; | 126 cachedNode = null; |
| 124 } | 127 } |
| 125 | 128 |
| 126 DeclarationSite get declarationSite; | 129 DeclarationSite get declarationSite; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 PartialFieldList(Token beginToken, | 264 PartialFieldList(Token beginToken, |
| 262 Token endToken, | 265 Token endToken, |
| 263 Modifiers modifiers, | 266 Modifiers modifiers, |
| 264 bool hasParseError) | 267 bool hasParseError) |
| 265 : super(modifiers) { | 268 : super(modifiers) { |
| 266 super.beginToken = beginToken; | 269 super.beginToken = beginToken; |
| 267 super.endToken = endToken; | 270 super.endToken = endToken; |
| 268 super.hasParseError = hasParseError; | 271 super.hasParseError = hasParseError; |
| 269 } | 272 } |
| 270 | 273 |
| 271 VariableDefinitions parseNode(Element element, DiagnosticListener listener) { | 274 VariableDefinitions parseNode(Element element, Parsing parsing) { |
| 272 if (definitions != null) return definitions; | 275 if (definitions != null) return definitions; |
| 276 DiagnosticListener listener = parsing.listener; |
| 273 listener.withCurrentElement(element, () { | 277 listener.withCurrentElement(element, () { |
| 274 definitions = parse( | 278 definitions = parse( |
| 275 listener, element, declarationSite, | 279 parsing, element, declarationSite, |
| 276 (Parser parser) => parser.parseMember(beginToken)); | 280 (Parser parser) => parser.parseMember(beginToken)); |
| 277 | 281 |
| 278 if (!hasParseError && | 282 if (!hasParseError && |
| 279 !definitions.modifiers.isVar && | 283 !definitions.modifiers.isVar && |
| 280 !definitions.modifiers.isFinal && | 284 !definitions.modifiers.isFinal && |
| 281 !definitions.modifiers.isConst && | 285 !definitions.modifiers.isConst && |
| 282 definitions.type == null && | 286 definitions.type == null && |
| 283 !definitions.isErroneous) { | 287 !definitions.isErroneous) { |
| 284 listener.reportErrorMessage( | 288 listener.reportErrorMessage( |
| 285 definitions, | 289 definitions, |
| 286 MessageKind.GENERIC, | 290 MessageKind.GENERIC, |
| 287 { 'text': 'A field declaration must start with var, final, ' | 291 { 'text': 'A field declaration must start with var, final, ' |
| 288 'const, or a type annotation.' }); | 292 'const, or a type annotation.' }); |
| 289 } | 293 } |
| 290 }); | 294 }); |
| 291 return definitions; | 295 return definitions; |
| 292 } | 296 } |
| 293 | 297 |
| 294 computeType(Element element, Compiler compiler) { | 298 computeType(Element element, Resolution resolution) { |
| 295 if (type != null) return type; | 299 if (type != null) return type; |
| 296 // TODO(johnniwinther): Compute this in the resolver. | 300 // TODO(johnniwinther): Compute this in the resolver. |
| 297 compiler.withCurrentElement(element, () { | 301 VariableDefinitions node = parseNode(element, resolution.parsing); |
| 298 VariableDefinitions node = parseNode(element, compiler); | 302 if (node.type != null) { |
| 299 if (node.type != null) { | 303 type = resolution.resolveTypeAnnotation(element, node.type); |
| 300 type = compiler.resolver.resolveTypeAnnotation(element, node.type); | 304 } else { |
| 301 } else { | 305 type = const DynamicType(); |
| 302 type = const DynamicType(); | 306 } |
| 303 } | |
| 304 }); | |
| 305 assert(type != null); | 307 assert(type != null); |
| 306 return type; | 308 return type; |
| 307 } | 309 } |
| 308 } | 310 } |
| 309 | 311 |
| 310 class PartialTypedefElement extends TypedefElementX with PartialElement { | 312 class PartialTypedefElement extends TypedefElementX with PartialElement { |
| 311 | 313 |
| 312 PartialTypedefElement( | 314 PartialTypedefElement( |
| 313 String name, | 315 String name, |
| 314 Element enclosing, | 316 Element enclosing, |
| 315 Token beginToken, | 317 Token beginToken, |
| 316 Token endToken) | 318 Token endToken) |
| 317 : super(name, enclosing) { | 319 : super(name, enclosing) { |
| 318 this.beginToken = beginToken; | 320 this.beginToken = beginToken; |
| 319 this.endToken = endToken; | 321 this.endToken = endToken; |
| 320 } | 322 } |
| 321 | 323 |
| 322 Token get token => beginToken; | 324 Token get token => beginToken; |
| 323 | 325 |
| 324 Node parseNode(DiagnosticListener listener) { | 326 Node parseNode(Parsing parsing) { |
| 325 if (cachedNode != null) return cachedNode; | 327 if (cachedNode != null) return cachedNode; |
| 326 cachedNode = parse( | 328 cachedNode = parse( |
| 327 listener, this, declarationSite, | 329 parsing, this, declarationSite, |
| 328 (p) => p.parseTopLevelDeclaration(token)); | 330 (p) => p.parseTopLevelDeclaration(token)); |
| 329 return cachedNode; | 331 return cachedNode; |
| 330 } | 332 } |
| 331 | 333 |
| 332 Token get position => findMyName(token); | 334 Token get position => findMyName(token); |
| 333 } | 335 } |
| 334 | 336 |
| 335 /// A [MetadataAnnotation] which is constructed on demand. | 337 /// A [MetadataAnnotation] which is constructed on demand. |
| 336 class PartialMetadataAnnotation extends MetadataAnnotationX | 338 class PartialMetadataAnnotation extends MetadataAnnotationX |
| 337 implements PartialElement { | 339 implements PartialElement { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 356 token = token.next; | 358 token = token.next; |
| 357 } | 359 } |
| 358 assert(token != null); | 360 assert(token != null); |
| 359 return token; | 361 return token; |
| 360 } | 362 } |
| 361 | 363 |
| 362 void set endToken(_) { | 364 void set endToken(_) { |
| 363 throw new UnsupportedError("endToken="); | 365 throw new UnsupportedError("endToken="); |
| 364 } | 366 } |
| 365 | 367 |
| 366 Node parseNode(DiagnosticListener listener) { | 368 Node parseNode(Parsing parsing) { |
| 367 if (cachedNode != null) return cachedNode; | 369 if (cachedNode != null) return cachedNode; |
| 368 var metadata = parse(listener, | 370 var metadata = parse(parsing, |
| 369 annotatedElement, | 371 annotatedElement, |
| 370 declarationSite, | 372 declarationSite, |
| 371 (p) => p.parseMetadata(beginToken)); | 373 (p) => p.parseMetadata(beginToken)); |
| 372 if (metadata is Metadata) { | 374 if (metadata is Metadata) { |
| 373 cachedNode = metadata.expression; | 375 cachedNode = metadata.expression; |
| 374 return cachedNode; | 376 return cachedNode; |
| 375 } else { | 377 } else { |
| 376 assert (metadata is ErrorNode); | 378 assert (metadata is ErrorNode); |
| 377 return metadata; | 379 return metadata; |
| 378 } | 380 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 } | 414 } |
| 413 | 415 |
| 414 bool get hasNode => cachedNode != null; | 416 bool get hasNode => cachedNode != null; |
| 415 | 417 |
| 416 ClassNode get node { | 418 ClassNode get node { |
| 417 assert(invariant(this, cachedNode != null, | 419 assert(invariant(this, cachedNode != null, |
| 418 message: "Node has not been computed for $this.")); | 420 message: "Node has not been computed for $this.")); |
| 419 return cachedNode; | 421 return cachedNode; |
| 420 } | 422 } |
| 421 | 423 |
| 422 ClassNode parseNode(Compiler compiler) { | 424 ClassNode parseNode(Parsing parsing) { |
| 423 if (cachedNode != null) return cachedNode; | 425 if (cachedNode != null) return cachedNode; |
| 424 compiler.withCurrentElement(this, () { | 426 DiagnosticListener diagnosticListener = parsing.listener; |
| 425 compiler.parser.measure(() { | 427 diagnosticListener.withCurrentElement(this, () { |
| 426 MemberListener listener = new MemberListener(compiler, this); | 428 parsing.measure(() { |
| 429 MemberListener listener = new MemberListener(diagnosticListener, this); |
| 427 Parser parser = new ClassElementParser(listener); | 430 Parser parser = new ClassElementParser(listener); |
| 428 try { | 431 try { |
| 429 Token token = parser.parseTopLevelDeclaration(beginToken); | 432 Token token = parser.parseTopLevelDeclaration(beginToken); |
| 430 assert(identical(token, endToken.next)); | 433 assert(identical(token, endToken.next)); |
| 431 cachedNode = listener.popNode(); | 434 cachedNode = listener.popNode(); |
| 432 assert( | 435 assert( |
| 433 invariant( | 436 invariant( |
| 434 beginToken, listener.nodes.isEmpty, | 437 beginToken, listener.nodes.isEmpty, |
| 435 message: "Non-empty listener stack: ${listener.nodes}")); | 438 message: "Non-empty listener stack: ${listener.nodes}")); |
| 436 } on ParserError { | 439 } on ParserError { |
| 437 // TODO(ahe): Often, a ParserError is thrown while parsing the class | 440 // TODO(ahe): Often, a ParserError is thrown while parsing the class |
| 438 // body. This means that the stack actually contains most of the | 441 // body. This means that the stack actually contains most of the |
| 439 // information synthesized below. Consider rewriting the parser so | 442 // information synthesized below. Consider rewriting the parser so |
| 440 // endClassDeclaration is called before parsing the class body. | 443 // endClassDeclaration is called before parsing the class body. |
| 441 Identifier name = new Identifier(findMyName(beginToken)); | 444 Identifier name = new Identifier(findMyName(beginToken)); |
| 442 NodeList typeParameters = null; | 445 NodeList typeParameters = null; |
| 443 Node supertype = null; | 446 Node supertype = null; |
| 444 NodeList interfaces = listener.makeNodeList(0, null, null, ","); | 447 NodeList interfaces = listener.makeNodeList(0, null, null, ","); |
| 445 Token extendsKeyword = null; | 448 Token extendsKeyword = null; |
| 446 NodeList body = listener.makeNodeList(0, beginToken, endToken, null); | 449 NodeList body = listener.makeNodeList(0, beginToken, endToken, null); |
| 447 cachedNode = new ClassNode( | 450 cachedNode = new ClassNode( |
| 448 Modifiers.EMPTY, name, typeParameters, supertype, interfaces, | 451 Modifiers.EMPTY, name, typeParameters, supertype, interfaces, |
| 449 beginToken, extendsKeyword, body, endToken); | 452 beginToken, extendsKeyword, body, endToken); |
| 450 hasParseError = true; | 453 hasParseError = true; |
| 451 } | 454 } |
| 452 }); | 455 }); |
| 453 compiler.patchParser.measure(() { | 456 if (isPatched) { |
| 454 if (isPatched) { | 457 parsing.parsePatchClass(patch); |
| 455 // TODO(lrn): Perhaps extract functionality so it doesn't | 458 } |
| 456 // need compiler. | |
| 457 compiler.patchParser.parsePatchClassNode(patch); | |
| 458 } | |
| 459 }); | |
| 460 }); | 459 }); |
| 461 return cachedNode; | 460 return cachedNode; |
| 462 } | 461 } |
| 463 | 462 |
| 464 Token get position => beginToken; | 463 Token get position => beginToken; |
| 465 | 464 |
| 466 // TODO(johnniwinther): Ensure that modifiers are always available. | 465 // TODO(johnniwinther): Ensure that modifiers are always available. |
| 467 Modifiers get modifiers => | 466 Modifiers get modifiers => |
| 468 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY; | 467 cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY; |
| 469 | 468 |
| 470 accept(ElementVisitor visitor, arg) { | 469 accept(ElementVisitor visitor, arg) { |
| 471 return visitor.visitClassElement(this, arg); | 470 return visitor.visitClassElement(this, arg); |
| 472 } | 471 } |
| 473 | 472 |
| 474 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) { | 473 PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) { |
| 475 return new PartialClassElement(name, beginToken, endToken, enclosing, id); | 474 return new PartialClassElement(name, beginToken, endToken, enclosing, id); |
| 476 } | 475 } |
| 477 } | 476 } |
| 478 | 477 |
| 479 Node parse( | 478 Node parse( |
| 480 DiagnosticListener diagnosticListener, | 479 Parsing parsing, |
| 481 ElementX element, | 480 ElementX element, |
| 482 PartialElement partial, | 481 PartialElement partial, |
| 483 doParse(Parser parser)) { | 482 doParse(Parser parser)) { |
| 484 CompilationUnitElement unit = element.compilationUnit; | 483 DiagnosticListener diagnosticListener = parsing.listener; |
| 485 NodeListener listener = new NodeListener(diagnosticListener, unit); | 484 return parsing.measure(() { |
| 486 listener.memberErrors = listener.memberErrors.prepend(false); | 485 return diagnosticListener.withCurrentElement(element, () { |
| 487 try { | 486 CompilationUnitElement unit = element.compilationUnit; |
| 488 if (partial.hasParseError) { | 487 NodeListener listener = new NodeListener(diagnosticListener, unit); |
| 489 listener.suppressParseErrors = true; | 488 listener.memberErrors = listener.memberErrors.prepend(false); |
| 490 } | 489 try { |
| 491 doParse(new Parser(listener)); | 490 if (partial.hasParseError) { |
| 492 } on ParserError catch (e) { | 491 listener.suppressParseErrors = true; |
| 493 partial.hasParseError = true; | 492 } |
| 494 return new ErrorNode(element.position, e.reason); | 493 doParse(new Parser(listener)); |
| 495 } | 494 } on ParserError catch (e) { |
| 496 Node node = listener.popNode(); | 495 partial.hasParseError = true; |
| 497 assert(listener.nodes.isEmpty); | 496 return new ErrorNode(element.position, e.reason); |
| 498 return node; | 497 } |
| 498 Node node = listener.popNode(); |
| 499 assert(listener.nodes.isEmpty); |
| 500 return node; |
| 501 }); |
| 502 }); |
| 499 } | 503 } |
| OLD | NEW |