OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 part of native; | 5 part of native; |
6 | 6 |
7 /// This class is a temporary work-around until we get a more powerful DartType. | 7 /// This class is a temporary work-around until we get a more powerful DartType. |
8 class SpecialType { | 8 class SpecialType { |
9 final String name; | 9 final String name; |
10 const SpecialType._(this.name); | 10 const SpecialType._(this.name); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 /// Each tag kind (including the 'type-tag's) can only occur once in the | 189 /// Each tag kind (including the 'type-tag's) can only occur once in the |
190 /// sequence. | 190 /// sequence. |
191 /// | 191 /// |
192 /// [specString] is the specification string, [resolveType] resolves named | 192 /// [specString] is the specification string, [resolveType] resolves named |
193 /// types into type values, [typesReturned] and [typesInstantiated] collects | 193 /// types into type values, [typesReturned] and [typesInstantiated] collects |
194 /// the types defined by the specification string, and [objectType] and | 194 /// the types defined by the specification string, and [objectType] and |
195 /// [nullType] define the types for `Object` and `Null`, respectively. The | 195 /// [nullType] define the types for `Object` and `Null`, respectively. The |
196 /// latter is used for the type strings of the form '' and 'var'. | 196 /// latter is used for the type strings of the form '' and 'var'. |
197 /// [validTags] can be used to restrict which tags are accepted. | 197 /// [validTags] can be used to restrict which tags are accepted. |
198 static void processSpecString( | 198 static void processSpecString( |
199 DiagnosticListener listener, | 199 DiagnosticReporter reporter, |
200 Spannable spannable, | 200 Spannable spannable, |
201 String specString, | 201 String specString, |
202 {Iterable<String> validTags, | 202 {Iterable<String> validTags, |
203 void setSideEffects(SideEffects newEffects), | 203 void setSideEffects(SideEffects newEffects), |
204 void setThrows(NativeThrowBehavior throwKind), | 204 void setThrows(NativeThrowBehavior throwKind), |
205 void setIsAllocation(bool isAllocation), | 205 void setIsAllocation(bool isAllocation), |
206 void setUseGvn(bool useGvn), | 206 void setUseGvn(bool useGvn), |
207 dynamic resolveType(String typeString), | 207 dynamic resolveType(String typeString), |
208 List typesReturned, | 208 List typesReturned, |
209 List typesInstantiated, | 209 List typesInstantiated, |
210 objectType, nullType}) { | 210 objectType, nullType}) { |
211 | 211 |
212 | 212 |
213 bool seenError = false; | 213 bool seenError = false; |
214 | 214 |
215 void reportError(String message) { | 215 void reportError(String message) { |
216 seenError = true; | 216 seenError = true; |
217 listener.reportErrorMessage( | 217 reporter.reportErrorMessage( |
218 spannable, MessageKind.GENERIC, {'text': message}); | 218 spannable, MessageKind.GENERIC, {'text': message}); |
219 } | 219 } |
220 | 220 |
221 const List<String> knownTags = const [ | 221 const List<String> knownTags = const [ |
222 'creates', 'returns', 'depends', 'effects', | 222 'creates', 'returns', 'depends', 'effects', |
223 'throws', 'gvn', 'new']; | 223 'throws', 'gvn', 'new']; |
224 | 224 |
225 /// Resolve a type string of one of the three forms: | 225 /// Resolve a type string of one of the three forms: |
226 /// * 'void' - in which case [onVoid] is called, | 226 /// * 'void' - in which case [onVoid] is called, |
227 /// * '' or 'var' - in which case [onVar] is called, | 227 /// * '' or 'var' - in which case [onVar] is called, |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 break; | 417 break; |
418 default: | 418 default: |
419 reportError("Unrecognized side-effect flag: '$dependency'."); | 419 reportError("Unrecognized side-effect flag: '$dependency'."); |
420 } | 420 } |
421 } | 421 } |
422 } | 422 } |
423 | 423 |
424 return sideEffects; | 424 return sideEffects; |
425 } | 425 } |
426 | 426 |
427 static NativeBehavior ofJsCall(Send jsCall, Compiler compiler, resolver) { | 427 static NativeBehavior ofJsCall( |
| 428 Send jsCall, |
| 429 DiagnosticReporter reporter, |
| 430 Parsing parsing, |
| 431 CoreTypes coreTypes, |
| 432 ForeignResolver resolver) { |
428 // The first argument of a JS-call is a string encoding various attributes | 433 // The first argument of a JS-call is a string encoding various attributes |
429 // of the code. | 434 // of the code. |
430 // | 435 // |
431 // 'Type1|Type2'. A union type. | 436 // 'Type1|Type2'. A union type. |
432 // '=Object'. A JavaScript Object, no subtype. | 437 // '=Object'. A JavaScript Object, no subtype. |
433 | 438 |
434 NativeBehavior behavior = new NativeBehavior(); | 439 NativeBehavior behavior = new NativeBehavior(); |
435 | 440 |
436 var argNodes = jsCall.arguments; | 441 var argNodes = jsCall.arguments; |
437 if (argNodes.isEmpty || argNodes.tail.isEmpty) { | 442 if (argNodes.isEmpty || argNodes.tail.isEmpty) { |
438 compiler.reportErrorMessage( | 443 reporter.reportErrorMessage( |
439 jsCall, | 444 jsCall, |
440 MessageKind.GENERIC, | 445 MessageKind.GENERIC, |
441 {'text': "JS expression takes two or more arguments."}); | 446 {'text': "JS expression takes two or more arguments."}); |
442 return behavior; | 447 return behavior; |
443 } | 448 } |
444 | 449 |
445 var specArgument = argNodes.head; | 450 var specArgument = argNodes.head; |
446 if (specArgument is !StringNode || specArgument.isInterpolation) { | 451 if (specArgument is !StringNode || specArgument.isInterpolation) { |
447 compiler.reportErrorMessage( | 452 reporter.reportErrorMessage( |
448 specArgument, MessageKind.GENERIC, | 453 specArgument, MessageKind.GENERIC, |
449 {'text': "JS first argument must be a string literal."}); | 454 {'text': "JS first argument must be a string literal."}); |
450 return behavior; | 455 return behavior; |
451 } | 456 } |
452 | 457 |
453 var codeArgument = argNodes.tail.head; | 458 var codeArgument = argNodes.tail.head; |
454 if (codeArgument is !StringNode || codeArgument.isInterpolation) { | 459 if (codeArgument is !StringNode || codeArgument.isInterpolation) { |
455 compiler.reportErrorMessage( | 460 reporter.reportErrorMessage( |
456 codeArgument, MessageKind.GENERIC, | 461 codeArgument, MessageKind.GENERIC, |
457 {'text': "JS second argument must be a string literal."}); | 462 {'text': "JS second argument must be a string literal."}); |
458 return behavior; | 463 return behavior; |
459 } | 464 } |
460 | 465 |
461 behavior.codeTemplate = | 466 behavior.codeTemplate = |
462 js.js.parseForeignJS(codeArgument.dartString.slowToString()); | 467 js.js.parseForeignJS(codeArgument.dartString.slowToString()); |
463 | 468 |
464 String specString = specArgument.dartString.slowToString(); | 469 String specString = specArgument.dartString.slowToString(); |
465 | 470 |
466 dynamic resolveType(String typeString) { | 471 dynamic resolveType(String typeString) { |
467 return _parseType( | 472 return _parseType( |
468 typeString, | 473 typeString, |
469 compiler.resolution, | 474 parsing, |
470 (name) => resolver.resolveTypeFromString(specArgument, name), | 475 (name) => resolver.resolveTypeFromString(specArgument, name), |
471 specArgument); | 476 specArgument); |
472 } | 477 } |
473 | 478 |
474 bool sideEffectsAreEncodedInSpecString = false; | 479 bool sideEffectsAreEncodedInSpecString = false; |
475 | 480 |
476 void setSideEffects(SideEffects newEffects) { | 481 void setSideEffects(SideEffects newEffects) { |
477 sideEffectsAreEncodedInSpecString = true; | 482 sideEffectsAreEncodedInSpecString = true; |
478 behavior.sideEffects.setTo(newEffects); | 483 behavior.sideEffects.setTo(newEffects); |
479 } | 484 } |
480 | 485 |
481 bool throwBehaviorFromSpecString = false; | 486 bool throwBehaviorFromSpecString = false; |
482 void setThrows(NativeThrowBehavior throwBehavior) { | 487 void setThrows(NativeThrowBehavior throwBehavior) { |
483 throwBehaviorFromSpecString = true; | 488 throwBehaviorFromSpecString = true; |
484 behavior.throwBehavior = throwBehavior; | 489 behavior.throwBehavior = throwBehavior; |
485 } | 490 } |
486 | 491 |
487 void setIsAllocation(bool isAllocation) { | 492 void setIsAllocation(bool isAllocation) { |
488 behavior.isAllocation = isAllocation; | 493 behavior.isAllocation = isAllocation; |
489 } | 494 } |
490 | 495 |
491 void setUseGvn(bool useGvn) { | 496 void setUseGvn(bool useGvn) { |
492 behavior.useGvn = useGvn; | 497 behavior.useGvn = useGvn; |
493 } | 498 } |
494 | 499 |
495 processSpecString(compiler, specArgument, | 500 processSpecString( |
| 501 reporter, |
| 502 specArgument, |
496 specString, | 503 specString, |
497 setSideEffects: setSideEffects, | 504 setSideEffects: setSideEffects, |
498 setThrows: setThrows, | 505 setThrows: setThrows, |
499 setIsAllocation: setIsAllocation, | 506 setIsAllocation: setIsAllocation, |
500 setUseGvn: setUseGvn, | 507 setUseGvn: setUseGvn, |
501 resolveType: resolveType, | 508 resolveType: resolveType, |
502 typesReturned: behavior.typesReturned, | 509 typesReturned: behavior.typesReturned, |
503 typesInstantiated: behavior.typesInstantiated, | 510 typesInstantiated: behavior.typesInstantiated, |
504 objectType: compiler.coreTypes.objectType, | 511 objectType: coreTypes.objectType, |
505 nullType: compiler.coreTypes.nullType); | 512 nullType: coreTypes.nullType); |
506 | 513 |
507 if (!sideEffectsAreEncodedInSpecString) { | 514 if (!sideEffectsAreEncodedInSpecString) { |
508 new SideEffectsVisitor(behavior.sideEffects) | 515 new SideEffectsVisitor(behavior.sideEffects) |
509 .visit(behavior.codeTemplate.ast); | 516 .visit(behavior.codeTemplate.ast); |
510 } | 517 } |
511 if (!throwBehaviorFromSpecString) { | 518 if (!throwBehaviorFromSpecString) { |
512 behavior.throwBehavior = | 519 behavior.throwBehavior = |
513 new ThrowBehaviorVisitor().analyze(behavior.codeTemplate.ast); | 520 new ThrowBehaviorVisitor().analyze(behavior.codeTemplate.ast); |
514 } | 521 } |
515 | 522 |
516 return behavior; | 523 return behavior; |
517 } | 524 } |
518 | 525 |
519 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( | 526 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( |
520 NativeBehavior behavior, | 527 NativeBehavior behavior, |
521 Send jsBuiltinOrEmbeddedGlobalCall, | 528 Send jsBuiltinOrEmbeddedGlobalCall, |
522 Compiler compiler, | 529 DiagnosticReporter reporter, |
| 530 Parsing parsing, |
| 531 CoreTypes coreTypes, |
523 ForeignResolver resolver, | 532 ForeignResolver resolver, |
524 {bool isBuiltin, | 533 {bool isBuiltin, |
525 List<String> validTags}) { | 534 List<String> validTags}) { |
526 // The first argument of a JS-embedded global call is a string encoding | 535 // The first argument of a JS-embedded global call is a string encoding |
527 // the type of the code. | 536 // the type of the code. |
528 // | 537 // |
529 // 'Type1|Type2'. A union type. | 538 // 'Type1|Type2'. A union type. |
530 // '=Object'. A JavaScript Object, no subtype. | 539 // '=Object'. A JavaScript Object, no subtype. |
531 | 540 |
532 String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global"; | 541 String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global"; |
533 | 542 |
534 Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments; | 543 Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments; |
535 if (argNodes.isEmpty) { | 544 if (argNodes.isEmpty) { |
536 compiler.internalError(jsBuiltinOrEmbeddedGlobalCall, | 545 reporter.internalError(jsBuiltinOrEmbeddedGlobalCall, |
537 "JS $builtinOrGlobal expression has no type."); | 546 "JS $builtinOrGlobal expression has no type."); |
538 } | 547 } |
539 | 548 |
540 // We don't check the given name. That needs to be done at a later point. | 549 // We don't check the given name. That needs to be done at a later point. |
541 // This is, because we want to allow non-literals (like references to | 550 // This is, because we want to allow non-literals (like references to |
542 // enums) as names. | 551 // enums) as names. |
543 if (argNodes.tail.isEmpty) { | 552 if (argNodes.tail.isEmpty) { |
544 compiler.internalError(jsBuiltinOrEmbeddedGlobalCall, | 553 reporter.internalError(jsBuiltinOrEmbeddedGlobalCall, |
545 'JS $builtinOrGlobal is missing name.'); | 554 'JS $builtinOrGlobal is missing name.'); |
546 } | 555 } |
547 | 556 |
548 if (!isBuiltin) { | 557 if (!isBuiltin) { |
549 if (!argNodes.tail.tail.isEmpty) { | 558 if (!argNodes.tail.tail.isEmpty) { |
550 compiler.internalError(argNodes.tail.tail.head, | 559 reporter.internalError(argNodes.tail.tail.head, |
551 'JS embedded global has more than 2 arguments'); | 560 'JS embedded global has more than 2 arguments'); |
552 } | 561 } |
553 } | 562 } |
554 | 563 |
555 LiteralString specLiteral = argNodes.head.asLiteralString(); | 564 LiteralString specLiteral = argNodes.head.asLiteralString(); |
556 if (specLiteral == null) { | 565 if (specLiteral == null) { |
557 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It | 566 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It |
558 // is not very satisfactory because it does not work for void, dynamic. | 567 // is not very satisfactory because it does not work for void, dynamic. |
559 compiler.internalError(argNodes.head, "Unexpected first argument."); | 568 reporter.internalError(argNodes.head, "Unexpected first argument."); |
560 } | 569 } |
561 | 570 |
562 String specString = specLiteral.dartString.slowToString(); | 571 String specString = specLiteral.dartString.slowToString(); |
563 | 572 |
564 dynamic resolveType(String typeString) { | 573 dynamic resolveType(String typeString) { |
565 return _parseType( | 574 return _parseType( |
566 typeString, | 575 typeString, |
567 compiler.resolution, | 576 parsing, |
568 (name) => resolver.resolveTypeFromString(specLiteral, name), | 577 (name) => resolver.resolveTypeFromString(specLiteral, name), |
569 jsBuiltinOrEmbeddedGlobalCall); | 578 jsBuiltinOrEmbeddedGlobalCall); |
570 } | 579 } |
571 | 580 |
572 void setSideEffects(SideEffects newEffects) { | 581 void setSideEffects(SideEffects newEffects) { |
573 behavior.sideEffects.setTo(newEffects); | 582 behavior.sideEffects.setTo(newEffects); |
574 } | 583 } |
575 | 584 |
576 processSpecString(compiler, jsBuiltinOrEmbeddedGlobalCall, | 585 processSpecString( |
577 specString, | 586 reporter, |
578 validTags: validTags, | 587 jsBuiltinOrEmbeddedGlobalCall, |
579 resolveType: resolveType, | 588 specString, |
580 setSideEffects: setSideEffects, | 589 validTags: validTags, |
581 typesReturned: behavior.typesReturned, | 590 resolveType: resolveType, |
582 typesInstantiated: behavior.typesInstantiated, | 591 setSideEffects: setSideEffects, |
583 objectType: compiler.coreTypes.objectType, | 592 typesReturned: behavior.typesReturned, |
584 nullType: compiler.coreTypes.nullType); | 593 typesInstantiated: behavior.typesInstantiated, |
| 594 objectType: coreTypes.objectType, |
| 595 nullType: coreTypes.nullType); |
585 } | 596 } |
586 | 597 |
587 static NativeBehavior ofJsBuiltinCall(Send jsBuiltinCall, | 598 static NativeBehavior ofJsBuiltinCall( |
588 Compiler compiler, | 599 Send jsBuiltinCall, |
589 ForeignResolver resolver) { | 600 DiagnosticReporter reporter, |
| 601 Parsing parsing, |
| 602 CoreTypes coreTypes, |
| 603 ForeignResolver resolver) { |
590 NativeBehavior behavior = new NativeBehavior(); | 604 NativeBehavior behavior = new NativeBehavior(); |
591 behavior.sideEffects.setTo(new SideEffects()); | 605 behavior.sideEffects.setTo(new SideEffects()); |
592 | 606 |
593 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( | 607 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( |
594 behavior, jsBuiltinCall, compiler, resolver, isBuiltin: true); | 608 behavior, |
| 609 jsBuiltinCall, |
| 610 reporter, |
| 611 parsing, |
| 612 coreTypes, |
| 613 resolver, |
| 614 isBuiltin: true); |
595 | 615 |
596 return behavior; | 616 return behavior; |
597 } | 617 } |
598 | 618 |
599 static NativeBehavior ofJsEmbeddedGlobalCall(Send jsEmbeddedGlobalCall, | 619 static NativeBehavior ofJsEmbeddedGlobalCall( |
600 Compiler compiler, | 620 Send jsEmbeddedGlobalCall, |
601 ForeignResolver resolver) { | 621 DiagnosticReporter reporter, |
| 622 Parsing parsing, |
| 623 CoreTypes coreTypes, |
| 624 ForeignResolver resolver) { |
602 NativeBehavior behavior = new NativeBehavior(); | 625 NativeBehavior behavior = new NativeBehavior(); |
603 // TODO(sra): Allow the use site to override these defaults. | 626 // TODO(sra): Allow the use site to override these defaults. |
604 // Embedded globals are usually pre-computed data structures or JavaScript | 627 // Embedded globals are usually pre-computed data structures or JavaScript |
605 // functions that never change. | 628 // functions that never change. |
606 behavior.sideEffects.setTo(new SideEffects.empty()); | 629 behavior.sideEffects.setTo(new SideEffects.empty()); |
607 behavior.throwBehavior = NativeThrowBehavior.NEVER; | 630 behavior.throwBehavior = NativeThrowBehavior.NEVER; |
608 | 631 |
609 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( | 632 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( |
610 behavior, jsEmbeddedGlobalCall, compiler, resolver, | 633 behavior, |
| 634 jsEmbeddedGlobalCall, |
| 635 reporter, |
| 636 parsing, |
| 637 coreTypes, |
| 638 resolver, |
611 isBuiltin: false, | 639 isBuiltin: false, |
612 validTags: const ['returns', 'creates']); | 640 validTags: const ['returns', 'creates']); |
613 | 641 |
614 return behavior; | 642 return behavior; |
615 } | 643 } |
616 | 644 |
617 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { | 645 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { |
618 FunctionType type = method.computeType(compiler.resolution); | 646 FunctionType type = method.computeType(compiler.resolution); |
619 var behavior = new NativeBehavior(); | 647 var behavior = new NativeBehavior(); |
620 behavior.typesReturned.add(type.returnType); | 648 behavior.typesReturned.add(type.returnType); |
621 if (!type.returnType.isVoid) { | 649 if (!type.returnType.isVoid) { |
622 // Declared types are nullable. | 650 // Declared types are nullable. |
623 behavior.typesReturned.add(compiler.coreTypes.nullType); | 651 behavior.typesReturned.add(compiler.coreTypes.nullType); |
624 } | 652 } |
625 behavior._capture(type, compiler.resolution); | 653 behavior._capture(type, compiler.resolution); |
626 | 654 |
627 // TODO(sra): Optional arguments are currently missing from the | 655 // TODO(sra): Optional arguments are currently missing from the |
628 // DartType. This should be fixed so the following work-around can be | 656 // DartType. This should be fixed so the following work-around can be |
629 // removed. | 657 // removed. |
630 method.functionSignature.forEachOptionalParameter( | 658 method.functionSignature.forEachOptionalParameter( |
631 (ParameterElement parameter) { | 659 (ParameterElement parameter) { |
632 behavior._escape(parameter.type, compiler.resolution); | 660 behavior._escape(parameter.type, compiler.resolution); |
633 }); | 661 }); |
634 | 662 |
635 behavior._overrideWithAnnotations(method, compiler); | 663 behavior._overrideWithAnnotations(method, compiler); |
636 return behavior; | 664 return behavior; |
637 } | 665 } |
638 | 666 |
639 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) { | 667 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) { |
640 DartType type = field.computeType(compiler.resolution); | 668 Resolution resolution = compiler.resolution; |
| 669 DartType type = field.computeType(resolution); |
641 var behavior = new NativeBehavior(); | 670 var behavior = new NativeBehavior(); |
642 behavior.typesReturned.add(type); | 671 behavior.typesReturned.add(type); |
643 // Declared types are nullable. | 672 // Declared types are nullable. |
644 behavior.typesReturned.add(compiler.coreTypes.nullType); | 673 behavior.typesReturned.add(resolution.coreTypes.nullType); |
645 behavior._capture(type, compiler.resolution); | 674 behavior._capture(type, resolution); |
646 behavior._overrideWithAnnotations(field, compiler); | 675 behavior._overrideWithAnnotations(field, compiler); |
647 return behavior; | 676 return behavior; |
648 } | 677 } |
649 | 678 |
650 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) { | 679 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) { |
651 DartType type = field.computeType(compiler.resolution); | 680 Resolution resolution = compiler.resolution; |
| 681 DartType type = field.computeType(resolution); |
652 var behavior = new NativeBehavior(); | 682 var behavior = new NativeBehavior(); |
653 behavior._escape(type, compiler.resolution); | 683 behavior._escape(type, resolution); |
654 // We don't override the default behaviour - the annotations apply to | 684 // We don't override the default behaviour - the annotations apply to |
655 // loading the field. | 685 // loading the field. |
656 return behavior; | 686 return behavior; |
657 } | 687 } |
658 | 688 |
659 void _overrideWithAnnotations(Element element, Compiler compiler) { | 689 void _overrideWithAnnotations(Element element, Compiler compiler) { |
660 if (element.implementation.metadata.isEmpty) return; | 690 if (element.implementation.metadata.isEmpty) return; |
661 | 691 |
662 DartType lookup(String name) { | 692 DartType lookup(String name) { |
663 Element e = element.buildScope().lookup(name); | 693 Element e = element.buildScope().lookup(name); |
(...skipping 18 matching lines...) Expand all Loading... |
682 } | 712 } |
683 } | 713 } |
684 | 714 |
685 /** | 715 /** |
686 * Returns a list of type constraints from the annotations of | 716 * Returns a list of type constraints from the annotations of |
687 * [annotationClass]. | 717 * [annotationClass]. |
688 * Returns `null` if no constraints. | 718 * Returns `null` if no constraints. |
689 */ | 719 */ |
690 static _collect(Element element, Compiler compiler, Element annotationClass, | 720 static _collect(Element element, Compiler compiler, Element annotationClass, |
691 lookup(str)) { | 721 lookup(str)) { |
| 722 DiagnosticReporter reporter = compiler.reporter; |
692 var types = null; | 723 var types = null; |
693 for (MetadataAnnotation annotation in element.implementation.metadata) { | 724 for (MetadataAnnotation annotation in element.implementation.metadata) { |
694 annotation.ensureResolved(compiler.resolution); | 725 annotation.ensureResolved(compiler.resolution); |
695 ConstantValue value = | 726 ConstantValue value = |
696 compiler.constants.getConstantValue(annotation.constant); | 727 compiler.constants.getConstantValue(annotation.constant); |
697 if (!value.isConstructedObject) continue; | 728 if (!value.isConstructedObject) continue; |
698 ConstructedConstantValue constructedObject = value; | 729 ConstructedConstantValue constructedObject = value; |
699 if (constructedObject.type.element != annotationClass) continue; | 730 if (constructedObject.type.element != annotationClass) continue; |
700 | 731 |
701 Iterable<ConstantValue> fields = constructedObject.fields.values; | 732 Iterable<ConstantValue> fields = constructedObject.fields.values; |
702 // TODO(sra): Better validation of the constant. | 733 // TODO(sra): Better validation of the constant. |
703 if (fields.length != 1 || !fields.single.isString) { | 734 if (fields.length != 1 || !fields.single.isString) { |
704 compiler.internalError(annotation, | 735 reporter.internalError(annotation, |
705 'Annotations needs one string: ${annotation.node}'); | 736 'Annotations needs one string: ${annotation.node}'); |
706 } | 737 } |
707 StringConstantValue specStringConstant = fields.single; | 738 StringConstantValue specStringConstant = fields.single; |
708 String specString = specStringConstant.toDartString().slowToString(); | 739 String specString = specStringConstant.toDartString().slowToString(); |
709 for (final typeString in specString.split('|')) { | 740 for (final typeString in specString.split('|')) { |
710 var type = | 741 var type = _parseType(typeString, compiler.parsing, lookup, annotation); |
711 _parseType(typeString, compiler.resolution, lookup, annotation); | |
712 if (types == null) types = []; | 742 if (types == null) types = []; |
713 types.add(type); | 743 types.add(type); |
714 } | 744 } |
715 } | 745 } |
716 return types; | 746 return types; |
717 } | 747 } |
718 | 748 |
719 /// Models the behavior of having intances of [type] escape from Dart code | 749 /// Models the behavior of having intances of [type] escape from Dart code |
720 /// into native code. | 750 /// into native code. |
721 void _escape(DartType type, Resolution resolution) { | 751 void _escape(DartType type, Resolution resolution) { |
(...skipping 20 matching lines...) Expand all Loading... |
742 for (DartType parameter in functionType.parameterTypes) { | 772 for (DartType parameter in functionType.parameterTypes) { |
743 _escape(parameter, resolution); | 773 _escape(parameter, resolution); |
744 } | 774 } |
745 } else { | 775 } else { |
746 typesInstantiated.add(type); | 776 typesInstantiated.add(type); |
747 } | 777 } |
748 } | 778 } |
749 | 779 |
750 static dynamic _parseType( | 780 static dynamic _parseType( |
751 String typeString, | 781 String typeString, |
752 Resolution resolution, | 782 Parsing parsing, |
753 lookup(name), locationNodeOrElement) { | 783 lookup(name), locationNodeOrElement) { |
| 784 DiagnosticReporter reporter = parsing.reporter; |
754 if (typeString == '=Object') return SpecialType.JsObject; | 785 if (typeString == '=Object') return SpecialType.JsObject; |
755 if (typeString == 'dynamic') { | 786 if (typeString == 'dynamic') { |
756 return const DynamicType(); | 787 return const DynamicType(); |
757 } | 788 } |
758 var type = lookup(typeString); | 789 var type = lookup(typeString); |
759 if (type != null) return type; | 790 if (type != null) return type; |
760 | 791 |
761 int index = typeString.indexOf('<'); | 792 int index = typeString.indexOf('<'); |
762 if (index < 1) { | 793 if (index < 1) { |
763 resolution.listener.reportErrorMessage( | 794 reporter.reportErrorMessage( |
764 _errorNode(locationNodeOrElement, resolution.parsing), | 795 _errorNode(locationNodeOrElement, parsing), |
765 MessageKind.GENERIC, | 796 MessageKind.GENERIC, |
766 {'text': "Type '$typeString' not found."}); | 797 {'text': "Type '$typeString' not found."}); |
767 return const DynamicType(); | 798 return const DynamicType(); |
768 } | 799 } |
769 type = lookup(typeString.substring(0, index)); | 800 type = lookup(typeString.substring(0, index)); |
770 if (type != null) { | 801 if (type != null) { |
771 // TODO(sra): Parse type parameters. | 802 // TODO(sra): Parse type parameters. |
772 return type; | 803 return type; |
773 } | 804 } |
774 resolution.listener.reportErrorMessage( | 805 reporter.reportErrorMessage( |
775 _errorNode(locationNodeOrElement, resolution.parsing), | 806 _errorNode(locationNodeOrElement, parsing), |
776 MessageKind.GENERIC, | 807 MessageKind.GENERIC, |
777 {'text': "Type '$typeString' not found."}); | 808 {'text': "Type '$typeString' not found."}); |
778 return const DynamicType(); | 809 return const DynamicType(); |
779 } | 810 } |
780 | 811 |
781 static _errorNode(locationNodeOrElement, Parsing parsing) { | 812 static _errorNode(locationNodeOrElement, Parsing parsing) { |
782 if (locationNodeOrElement is Node) return locationNodeOrElement; | 813 if (locationNodeOrElement is Node) return locationNodeOrElement; |
783 return locationNodeOrElement.parseNode(parsing); | 814 return locationNodeOrElement.parseNode(parsing); |
784 } | 815 } |
785 } | 816 } |
OLD | NEW |