| 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 import '../common.dart'; | 5 import '../common.dart'; |
| 6 import '../common/backend_api.dart' show ForeignResolver; | 6 import '../common/backend_api.dart' show BackendClasses, ForeignResolver; |
| 7 import '../common/resolution.dart' show ParsingContext, Resolution; | 7 import '../common/resolution.dart' show ParsingContext, Resolution; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../compile_time_constants.dart' show ConstantEnvironment; |
| 9 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
| 11 import '../core_types.dart' show CommonElements; | 12 import '../core_types.dart' show CommonElements; |
| 13 import '../elements/elements.dart'; |
| 14 import '../elements/entities.dart'; |
| 12 import '../elements/resolution_types.dart'; | 15 import '../elements/resolution_types.dart'; |
| 13 import '../elements/elements.dart'; | 16 import '../elements/types.dart'; |
| 14 import '../js/js.dart' as js; | 17 import '../js/js.dart' as js; |
| 15 import '../js_backend/js_backend.dart'; | 18 import '../js_backend/js_backend.dart'; |
| 19 import '../js_backend/backend_helpers.dart'; |
| 20 import '../options.dart'; |
| 16 import '../tree/tree.dart'; | 21 import '../tree/tree.dart'; |
| 17 import '../universe/side_effects.dart' show SideEffects; | 22 import '../universe/side_effects.dart' show SideEffects; |
| 18 import '../util/util.dart'; | 23 import '../util/util.dart'; |
| 19 import 'enqueue.dart'; | |
| 20 import 'js.dart'; | 24 import 'js.dart'; |
| 21 | 25 |
| 22 typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString); | 26 typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString); |
| 23 | 27 |
| 24 /// This class is a temporary work-around until we get a more powerful DartType. | 28 /// This class is a temporary work-around until we get a more powerful DartType. |
| 25 class SpecialType { | 29 class SpecialType { |
| 26 final String name; | 30 final String name; |
| 27 const SpecialType._(this.name); | 31 const SpecialType._(this.name); |
| 28 | 32 |
| 29 /// The type Object, but no subtypes: | 33 /// The type Object, but no subtypes: |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 | 759 |
| 756 ResolutionDartType lookup(String name) { | 760 ResolutionDartType lookup(String name) { |
| 757 Element e = element.buildScope().lookup(name); | 761 Element e = element.buildScope().lookup(name); |
| 758 if (e == null) return null; | 762 if (e == null) return null; |
| 759 if (e is! ClassElement) return null; | 763 if (e is! ClassElement) return null; |
| 760 ClassElement cls = e; | 764 ClassElement cls = e; |
| 761 cls.ensureResolved(compiler.resolution); | 765 cls.ensureResolved(compiler.resolution); |
| 762 return cls.thisType; | 766 return cls.thisType; |
| 763 } | 767 } |
| 764 | 768 |
| 765 return ofMethod(element, type, metadata, lookup, compiler, | 769 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 770 return builder.buildMethodBehavior(type, metadata, lookup, |
| 766 isJsInterop: compiler.backend.isJsInterop(element)); | 771 isJsInterop: compiler.backend.isJsInterop(element)); |
| 767 } | 772 } |
| 768 | 773 |
| 769 static NativeBehavior ofMethod( | |
| 770 Spannable spannable, | |
| 771 ResolutionFunctionType type, | |
| 772 List<ConstantExpression> metadata, | |
| 773 TypeLookup lookupType, | |
| 774 Compiler compiler, | |
| 775 {bool isJsInterop}) { | |
| 776 var behavior = new NativeBehavior(); | |
| 777 var returnType = type.returnType; | |
| 778 // Note: For dart:html and other internal libraries we maintain, we can | |
| 779 // trust the return type and use it to limit what we enqueue. We have to | |
| 780 // be more conservative about JS interop types and assume they can return | |
| 781 // anything (unless the user provides the experimental flag to trust the | |
| 782 // type of js-interop APIs). We do restrict the allocation effects and say | |
| 783 // that interop calls create only interop types (which may be unsound if | |
| 784 // an interop call returns a DOM type and declares a dynamic return type, | |
| 785 // but otherwise we would include a lot of code by default). | |
| 786 // TODO(sigmund,sra): consider doing something better for numeric types. | |
| 787 behavior.typesReturned.add( | |
| 788 !isJsInterop || compiler.options.trustJSInteropTypeAnnotations | |
| 789 ? returnType | |
| 790 : const ResolutionDynamicType()); | |
| 791 if (!type.returnType.isVoid) { | |
| 792 // Declared types are nullable. | |
| 793 behavior.typesReturned.add(compiler.commonElements.nullType); | |
| 794 } | |
| 795 behavior._capture(type, compiler.resolution, | |
| 796 isInterop: isJsInterop, compiler: compiler); | |
| 797 | |
| 798 for (ResolutionDartType type in type.optionalParameterTypes) { | |
| 799 behavior._escape(type, compiler.resolution); | |
| 800 } | |
| 801 for (ResolutionDartType type in type.namedParameterTypes) { | |
| 802 behavior._escape(type, compiler.resolution); | |
| 803 } | |
| 804 | |
| 805 behavior._overrideWithAnnotations( | |
| 806 spannable, metadata, lookupType, compiler); | |
| 807 return behavior; | |
| 808 } | |
| 809 | |
| 810 static NativeBehavior ofFieldElementLoad( | 774 static NativeBehavior ofFieldElementLoad( |
| 811 MemberElement element, Compiler compiler) { | 775 MemberElement element, Compiler compiler) { |
| 812 Resolution resolution = compiler.resolution; | 776 Resolution resolution = compiler.resolution; |
| 813 ResolutionDartType type = element.computeType(resolution); | 777 ResolutionDartType type = element.computeType(resolution); |
| 814 List<ConstantExpression> metadata = <ConstantExpression>[]; | 778 List<ConstantExpression> metadata = <ConstantExpression>[]; |
| 815 for (MetadataAnnotation annotation in element.implementation.metadata) { | 779 for (MetadataAnnotation annotation in element.implementation.metadata) { |
| 816 annotation.ensureResolved(compiler.resolution); | 780 annotation.ensureResolved(compiler.resolution); |
| 817 metadata.add(annotation.constant); | 781 metadata.add(annotation.constant); |
| 818 } | 782 } |
| 819 | 783 |
| 820 ResolutionDartType lookup(String name) { | 784 ResolutionDartType lookup(String name) { |
| 821 Element e = element.buildScope().lookup(name); | 785 Element e = element.buildScope().lookup(name); |
| 822 if (e == null) return null; | 786 if (e == null) return null; |
| 823 if (e is! ClassElement) return null; | 787 if (e is! ClassElement) return null; |
| 824 ClassElement cls = e; | 788 ClassElement cls = e; |
| 825 cls.ensureResolved(compiler.resolution); | 789 cls.ensureResolved(compiler.resolution); |
| 826 return cls.thisType; | 790 return cls.thisType; |
| 827 } | 791 } |
| 828 | 792 |
| 829 return ofFieldLoad(element, type, metadata, lookup, compiler, | 793 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 794 return builder.buildFieldLoadBehavior(type, metadata, lookup, |
| 830 isJsInterop: compiler.backend.isJsInterop(element)); | 795 isJsInterop: compiler.backend.isJsInterop(element)); |
| 831 } | 796 } |
| 832 | 797 |
| 833 static NativeBehavior ofFieldLoad( | 798 static NativeBehavior ofFieldElementStore( |
| 834 Spannable spannable, | 799 MemberElement field, Compiler compiler) { |
| 835 ResolutionDartType type, | 800 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 836 List<ConstantExpression> metadata, | 801 ResolutionDartType type = field.computeType(compiler.resolution); |
| 837 TypeLookup lookupType, | 802 return builder.buildFieldStoreBehavior(type); |
| 838 Compiler compiler, | |
| 839 {bool isJsInterop}) { | |
| 840 Resolution resolution = compiler.resolution; | |
| 841 var behavior = new NativeBehavior(); | |
| 842 // TODO(sigmund,sra): consider doing something better for numeric types. | |
| 843 behavior.typesReturned.add( | |
| 844 !isJsInterop || compiler.options.trustJSInteropTypeAnnotations | |
| 845 ? type | |
| 846 : const ResolutionDynamicType()); | |
| 847 // Declared types are nullable. | |
| 848 behavior.typesReturned.add(resolution.commonElements.nullType); | |
| 849 behavior._capture(type, resolution, | |
| 850 isInterop: isJsInterop, compiler: compiler); | |
| 851 behavior._overrideWithAnnotations( | |
| 852 spannable, metadata, lookupType, compiler); | |
| 853 return behavior; | |
| 854 } | 803 } |
| 855 | 804 |
| 856 static NativeBehavior ofFieldElementStore( | 805 static dynamic /*DartType|SpecialType*/ _parseType(String typeString, |
| 857 MemberElement field, Resolution resolution) { | 806 Spannable spannable, DiagnosticReporter reporter, TypeLookup lookupType) { |
| 858 ResolutionDartType type = field.computeType(resolution); | 807 if (typeString == '=Object') return SpecialType.JsObject; |
| 859 return ofFieldStore(type, resolution); | 808 if (typeString == 'dynamic') { |
| 809 return const ResolutionDynamicType(); |
| 810 } |
| 811 var type = lookupType(typeString); |
| 812 if (type != null) return type; |
| 813 |
| 814 int index = typeString.indexOf('<'); |
| 815 if (index < 1) { |
| 816 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, |
| 817 {'text': "Type '$typeString' not found."}); |
| 818 return const ResolutionDynamicType(); |
| 819 } |
| 820 type = lookupType(typeString.substring(0, index)); |
| 821 if (type != null) { |
| 822 // TODO(sra): Parse type parameters. |
| 823 return type; |
| 824 } |
| 825 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, |
| 826 {'text': "Type '$typeString' not found."}); |
| 827 return const ResolutionDynamicType(); |
| 860 } | 828 } |
| 829 } |
| 861 | 830 |
| 862 static NativeBehavior ofFieldStore( | 831 abstract class BehaviorBuilder { |
| 863 ResolutionDartType type, Resolution resolution) { | 832 CommonElements get commonElements; |
| 864 var behavior = new NativeBehavior(); | 833 BackendClasses get backendClasses; |
| 865 behavior._escape(type, resolution); | 834 BackendHelpers get helpers; |
| 866 // We don't override the default behaviour - the annotations apply to | 835 DiagnosticReporter get reporter; |
| 867 // loading the field. | 836 ConstantEnvironment get constants; |
| 868 return behavior; | 837 bool get trustJSInteropTypeAnnotations; |
| 869 } | 838 |
| 839 Resolution get resolution => null; |
| 840 |
| 841 NativeBehavior _behavior; |
| 870 | 842 |
| 871 void _overrideWithAnnotations( | 843 void _overrideWithAnnotations( |
| 872 Spannable spannable, | 844 Iterable<ConstantExpression> metadata, TypeLookup lookupType) { |
| 873 Iterable<ConstantExpression> metadata, | |
| 874 TypeLookup lookupType, | |
| 875 Compiler compiler) { | |
| 876 if (metadata.isEmpty) return; | 845 if (metadata.isEmpty) return; |
| 877 | 846 |
| 878 NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer; | 847 List creates = |
| 879 var creates = _collect(spannable, metadata, compiler, | 848 _collect(metadata, helpers.annotationCreatesClass, lookupType); |
| 880 enqueuer.annotationCreatesClass, lookupType); | 849 List returns = |
| 881 var returns = _collect(spannable, metadata, compiler, | 850 _collect(metadata, helpers.annotationReturnsClass, lookupType); |
| 882 enqueuer.annotationReturnsClass, lookupType); | |
| 883 | 851 |
| 884 if (creates != null) { | 852 if (creates != null) { |
| 885 typesInstantiated | 853 _behavior.typesInstantiated |
| 886 ..clear() | 854 ..clear() |
| 887 ..addAll(creates); | 855 ..addAll(creates); |
| 888 } | 856 } |
| 889 if (returns != null) { | 857 if (returns != null) { |
| 890 typesReturned | 858 _behavior.typesReturned |
| 891 ..clear() | 859 ..clear() |
| 892 ..addAll(returns); | 860 ..addAll(returns); |
| 893 } | 861 } |
| 894 } | 862 } |
| 895 | 863 |
| 896 /** | 864 /** |
| 897 * Returns a list of type constraints from the annotations of | 865 * Returns a list of type constraints from the annotations of |
| 898 * [annotationClass]. | 866 * [annotationClass]. |
| 899 * Returns `null` if no constraints. | 867 * Returns `null` if no constraints. |
| 900 */ | 868 */ |
| 901 static _collect(Spannable spannable, Iterable<ConstantExpression> metadata, | 869 List _collect(Iterable<ConstantExpression> metadata, |
| 902 Compiler compiler, Element annotationClass, TypeLookup lookupType) { | 870 ClassEntity annotationClass, TypeLookup lookupType) { |
| 903 DiagnosticReporter reporter = compiler.reporter; | |
| 904 var types = null; | 871 var types = null; |
| 905 for (ConstantExpression constant in metadata) { | 872 for (ConstantExpression constant in metadata) { |
| 906 ConstantValue value = compiler.constants.getConstantValue(constant); | 873 ConstantValue value = constants.getConstantValue(constant); |
| 907 if (!value.isConstructedObject) continue; | 874 if (!value.isConstructedObject) continue; |
| 908 ConstructedConstantValue constructedObject = value; | 875 ConstructedConstantValue constructedObject = value; |
| 909 if (constructedObject.type.element != annotationClass) continue; | 876 if (constructedObject.type.element != annotationClass) continue; |
| 910 | 877 |
| 911 Iterable<ConstantValue> fields = constructedObject.fields.values; | 878 Iterable<ConstantValue> fields = constructedObject.fields.values; |
| 912 // TODO(sra): Better validation of the constant. | 879 // TODO(sra): Better validation of the constant. |
| 913 if (fields.length != 1 || !fields.single.isString) { | 880 if (fields.length != 1 || !fields.single.isString) { |
| 914 reporter.internalError(spannable, | 881 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 915 'Annotations needs one string: ${constant.toStructuredText()}'); | 882 'Annotations needs one string: ${constant.toStructuredText()}'); |
| 916 } | 883 } |
| 917 StringConstantValue specStringConstant = fields.single; | 884 StringConstantValue specStringConstant = fields.single; |
| 918 String specString = specStringConstant.toDartString().slowToString(); | 885 String specString = specStringConstant.toDartString().slowToString(); |
| 919 for (final typeString in specString.split('|')) { | 886 for (final typeString in specString.split('|')) { |
| 920 var type = _parseType(typeString, spannable, reporter, lookupType); | 887 var type = NativeBehavior._parseType( |
| 888 typeString, CURRENT_ELEMENT_SPANNABLE, reporter, lookupType); |
| 921 if (types == null) types = []; | 889 if (types == null) types = []; |
| 922 types.add(type); | 890 types.add(type); |
| 923 } | 891 } |
| 924 } | 892 } |
| 925 return types; | 893 return types; |
| 926 } | 894 } |
| 927 | 895 |
| 928 /// Models the behavior of having intances of [type] escape from Dart code | 896 /// Models the behavior of having intances of [type] escape from Dart code |
| 929 /// into native code. | 897 /// into native code. |
| 930 void _escape(ResolutionDartType type, Resolution resolution) { | 898 void _escape(DartType type) { |
| 931 type.computeUnaliased(resolution); | 899 if (type is ResolutionDartType) { |
| 900 type.computeUnaliased(resolution); |
| 901 } |
| 932 type = type.unaliased; | 902 type = type.unaliased; |
| 933 if (type is ResolutionFunctionType) { | 903 if (type is FunctionType) { |
| 934 ResolutionFunctionType functionType = type; | 904 FunctionType functionType = type; |
| 935 // A function might be called from native code, passing us novel | 905 // A function might be called from native code, passing us novel |
| 936 // parameters. | 906 // parameters. |
| 937 _escape(functionType.returnType, resolution); | 907 _escape(functionType.returnType); |
| 938 for (ResolutionDartType parameter in functionType.parameterTypes) { | 908 for (DartType parameter in functionType.parameterTypes) { |
| 939 _capture(parameter, resolution); | 909 _capture(parameter); |
| 940 } | 910 } |
| 941 } | 911 } |
| 942 } | 912 } |
| 943 | 913 |
| 944 /// Models the behavior of Dart code receiving instances and methods of [type] | 914 /// Models the behavior of Dart code receiving instances and methods of [type] |
| 945 /// from native code. We usually start the analysis by capturing a native | 915 /// from native code. We usually start the analysis by capturing a native |
| 946 /// method that has been used. | 916 /// method that has been used. |
| 947 /// | 917 /// |
| 948 /// We assume that JS-interop APIs cannot instantiate Dart types or | 918 /// We assume that JS-interop APIs cannot instantiate Dart types or |
| 949 /// non-JSInterop native types. | 919 /// non-JSInterop native types. |
| 950 void _capture(ResolutionDartType type, Resolution resolution, | 920 void _capture(DartType type, {bool isInterop: false}) { |
| 951 {bool isInterop: false, Compiler compiler}) { | 921 if (type is ResolutionDartType) { |
| 952 type.computeUnaliased(resolution); | 922 type.computeUnaliased(resolution); |
| 923 } |
| 953 type = type.unaliased; | 924 type = type.unaliased; |
| 954 if (type is ResolutionFunctionType) { | 925 if (type is FunctionType) { |
| 955 ResolutionFunctionType functionType = type; | 926 FunctionType functionType = type; |
| 956 _capture(functionType.returnType, resolution, | 927 _capture(functionType.returnType, isInterop: isInterop); |
| 957 isInterop: isInterop, compiler: compiler); | 928 for (DartType parameter in functionType.parameterTypes) { |
| 958 for (ResolutionDartType parameter in functionType.parameterTypes) { | 929 _escape(parameter); |
| 959 _escape(parameter, resolution); | |
| 960 } | 930 } |
| 961 } else { | 931 } else { |
| 962 JavaScriptBackend backend = compiler?.backend; | |
| 963 if (!isInterop) { | 932 if (!isInterop) { |
| 964 typesInstantiated.add(type); | 933 _behavior.typesInstantiated.add(type); |
| 965 } else { | 934 } else { |
| 966 if (type.element != null && backend.isNative(type.element)) { | 935 if (type is InterfaceType && |
| 936 backendClasses.isNativeClass(type.element)) { |
| 967 // Any declared native or interop type (isNative implies isJsInterop) | 937 // Any declared native or interop type (isNative implies isJsInterop) |
| 968 // is assumed to be allocated. | 938 // is assumed to be allocated. |
| 969 typesInstantiated.add(type); | 939 _behavior.typesInstantiated.add(type); |
| 970 } | 940 } |
| 971 | 941 |
| 972 if (!compiler.options.trustJSInteropTypeAnnotations || | 942 if (!trustJSInteropTypeAnnotations || |
| 973 type.isDynamic || | 943 type.isDynamic || |
| 974 type.isObject) { | 944 type == commonElements.objectType) { |
| 975 // By saying that only JS-interop types can be created, we prevent | 945 // By saying that only JS-interop types can be created, we prevent |
| 976 // pulling in every other native type (e.g. all of dart:html) when a | 946 // pulling in every other native type (e.g. all of dart:html) when a |
| 977 // JS interop API returns dynamic or when we don't trust the type | 947 // JS interop API returns dynamic or when we don't trust the type |
| 978 // annotations. This means that to some degree we still use the return | 948 // annotations. This means that to some degree we still use the return |
| 979 // type to decide whether to include native types, even if we don't | 949 // type to decide whether to include native types, even if we don't |
| 980 // trust the type annotation. | 950 // trust the type annotation. |
| 981 ClassElement cls = backend.helpers.jsJavaScriptObjectClass; | 951 ClassElement cls = helpers.jsJavaScriptObjectClass; |
| 982 cls.ensureResolved(resolution); | 952 cls.ensureResolved(resolution); |
| 983 typesInstantiated.add(cls.thisType); | 953 _behavior.typesInstantiated.add(cls.thisType); |
| 984 } else { | 954 } else { |
| 985 // Otherwise, when the declared type is a Dart type, we do not | 955 // Otherwise, when the declared type is a Dart type, we do not |
| 986 // register an allocation because we assume it cannot be instantiated | 956 // register an allocation because we assume it cannot be instantiated |
| 987 // from within the JS-interop code. It must have escaped from another | 957 // from within the JS-interop code. It must have escaped from another |
| 988 // API. | 958 // API. |
| 989 } | 959 } |
| 990 } | 960 } |
| 991 } | 961 } |
| 992 } | 962 } |
| 993 | 963 |
| 994 static dynamic /*DartType|SpecialType*/ _parseType(String typeString, | 964 NativeBehavior buildFieldLoadBehavior(DartType type, |
| 995 Spannable spannable, DiagnosticReporter reporter, TypeLookup lookupType) { | 965 Iterable<ConstantExpression> metadata, TypeLookup lookupType, |
| 996 if (typeString == '=Object') return SpecialType.JsObject; | 966 {bool isJsInterop}) { |
| 997 if (typeString == 'dynamic') { | 967 _behavior = new NativeBehavior(); |
| 998 return const ResolutionDynamicType(); | 968 // TODO(sigmund,sra): consider doing something better for numeric types. |
| 969 _behavior.typesReturned.add(!isJsInterop || trustJSInteropTypeAnnotations |
| 970 ? type |
| 971 : commonElements.dynamicType); |
| 972 // Declared types are nullable. |
| 973 _behavior.typesReturned.add(commonElements.nullType); |
| 974 _capture(type, isInterop: isJsInterop); |
| 975 _overrideWithAnnotations(metadata, lookupType); |
| 976 return _behavior; |
| 977 } |
| 978 |
| 979 NativeBehavior buildFieldStoreBehavior(DartType type) { |
| 980 _behavior = new NativeBehavior(); |
| 981 _escape(type); |
| 982 // We don't override the default behaviour - the annotations apply to |
| 983 // loading the field. |
| 984 return _behavior; |
| 985 } |
| 986 |
| 987 NativeBehavior buildMethodBehavior(FunctionType type, |
| 988 List<ConstantExpression> metadata, TypeLookup lookupType, |
| 989 {bool isJsInterop}) { |
| 990 _behavior = new NativeBehavior(); |
| 991 DartType returnType = type.returnType; |
| 992 // Note: For dart:html and other internal libraries we maintain, we can |
| 993 // trust the return type and use it to limit what we enqueue. We have to |
| 994 // be more conservative about JS interop types and assume they can return |
| 995 // anything (unless the user provides the experimental flag to trust the |
| 996 // type of js-interop APIs). We do restrict the allocation effects and say |
| 997 // that interop calls create only interop types (which may be unsound if |
| 998 // an interop call returns a DOM type and declares a dynamic return type, |
| 999 // but otherwise we would include a lot of code by default). |
| 1000 // TODO(sigmund,sra): consider doing something better for numeric types. |
| 1001 _behavior.typesReturned.add(!isJsInterop || trustJSInteropTypeAnnotations |
| 1002 ? returnType |
| 1003 : commonElements.dynamicType); |
| 1004 if (!type.returnType.isVoid) { |
| 1005 // Declared types are nullable. |
| 1006 _behavior.typesReturned.add(commonElements.nullType); |
| 999 } | 1007 } |
| 1000 var type = lookupType(typeString); | 1008 _capture(type, isInterop: isJsInterop); |
| 1001 if (type != null) return type; | |
| 1002 | 1009 |
| 1003 int index = typeString.indexOf('<'); | 1010 for (DartType type in type.optionalParameterTypes) { |
| 1004 if (index < 1) { | 1011 _escape(type); |
| 1005 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, | |
| 1006 {'text': "Type '$typeString' not found."}); | |
| 1007 return const ResolutionDynamicType(); | |
| 1008 } | 1012 } |
| 1009 type = lookupType(typeString.substring(0, index)); | 1013 for (DartType type in type.namedParameterTypes) { |
| 1010 if (type != null) { | 1014 _escape(type); |
| 1011 // TODO(sra): Parse type parameters. | |
| 1012 return type; | |
| 1013 } | 1015 } |
| 1014 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, | 1016 |
| 1015 {'text': "Type '$typeString' not found."}); | 1017 _overrideWithAnnotations(metadata, lookupType); |
| 1016 return const ResolutionDynamicType(); | 1018 return _behavior; |
| 1017 } | 1019 } |
| 1018 } | 1020 } |
| 1021 |
| 1022 class ResolverBehaviorBuilder extends BehaviorBuilder { |
| 1023 final Compiler compiler; |
| 1024 |
| 1025 ResolverBehaviorBuilder(this.compiler); |
| 1026 |
| 1027 @override |
| 1028 CommonElements get commonElements => compiler.commonElements; |
| 1029 |
| 1030 @override |
| 1031 bool get trustJSInteropTypeAnnotations => |
| 1032 compiler.options.trustJSInteropTypeAnnotations; |
| 1033 |
| 1034 @override |
| 1035 ConstantEnvironment get constants => compiler.constants; |
| 1036 |
| 1037 @override |
| 1038 DiagnosticReporter get reporter => compiler.reporter; |
| 1039 |
| 1040 @override |
| 1041 BackendHelpers get helpers { |
| 1042 JavaScriptBackend backend = compiler.backend; |
| 1043 return backend.helpers; |
| 1044 } |
| 1045 |
| 1046 @override |
| 1047 BackendClasses get backendClasses => compiler.backend.backendClasses; |
| 1048 |
| 1049 @override |
| 1050 Resolution get resolution => compiler.resolution; |
| 1051 } |
| OLD | NEW |