| 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 |