Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 1376473007: Add the 'docRange' property and use it to compute documentation comment. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 library engine.resolver; 5 library engine.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'ast.dart'; 9 import 'ast.dart';
10 import 'constant.dart'; 10 import 'constant.dart';
(...skipping 26 matching lines...) Expand all
37 typedef ResolverVisitor ResolverVisitorFactory( 37 typedef ResolverVisitor ResolverVisitorFactory(
38 Library library, Source source, TypeProvider typeProvider); 38 Library library, Source source, TypeProvider typeProvider);
39 39
40 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor); 40 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor);
41 41
42 typedef TypeResolverVisitor TypeResolverVisitorFactory( 42 typedef TypeResolverVisitor TypeResolverVisitorFactory(
43 Library library, Source source, TypeProvider typeProvider); 43 Library library, Source source, TypeProvider typeProvider);
44 44
45 typedef void VoidFunction(); 45 typedef void VoidFunction();
46 46
47 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
48
49 typedef bool _SubtypeChecker<T>(T t1, T t2);
50
47 /** 51 /**
48 * Instances of the class `BestPracticesVerifier` traverse an AST structure look ing for 52 * Instances of the class `BestPracticesVerifier` traverse an AST structure look ing for
49 * violations of Dart best practices. 53 * violations of Dart best practices.
50 */ 54 */
51 class BestPracticesVerifier extends RecursiveAstVisitor<Object> { 55 class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
52 // static String _HASHCODE_GETTER_NAME = "hashCode"; 56 // static String _HASHCODE_GETTER_NAME = "hashCode";
53 57
54 static String _NULL_TYPE_NAME = "Null"; 58 static String _NULL_TYPE_NAME = "Null";
55 59
56 static String _TO_INT_METHOD_NAME = "toInt"; 60 static String _TO_INT_METHOD_NAME = "toInt";
(...skipping 2447 matching lines...) Expand 10 before | Expand all | Expand 10 after
2504 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl(element); 2508 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl(element);
2505 interfaceType.typeArguments = typeArguments; 2509 interfaceType.typeArguments = typeArguments;
2506 element.type = interfaceType; 2510 element.type = interfaceType;
2507 List<ConstructorElement> constructors = holder.constructors; 2511 List<ConstructorElement> constructors = holder.constructors;
2508 if (constructors.length == 0) { 2512 if (constructors.length == 0) {
2509 // 2513 //
2510 // Create the default constructor. 2514 // Create the default constructor.
2511 // 2515 //
2512 constructors = _createDefaultConstructors(interfaceType); 2516 constructors = _createDefaultConstructors(interfaceType);
2513 } 2517 }
2518 _setDocRange(element, node);
2514 element.abstract = node.isAbstract; 2519 element.abstract = node.isAbstract;
2515 element.accessors = holder.accessors; 2520 element.accessors = holder.accessors;
2516 element.constructors = constructors; 2521 element.constructors = constructors;
2517 element.fields = holder.fields; 2522 element.fields = holder.fields;
2518 element.methods = holder.methods; 2523 element.methods = holder.methods;
2519 element.typeParameters = typeParameters; 2524 element.typeParameters = typeParameters;
2520 element.validMixin = _isValidMixin; 2525 element.validMixin = _isValidMixin;
2521 int functionTypeCount = _functionTypesToFix.length; 2526 int functionTypeCount = _functionTypesToFix.length;
2522 for (int i = 0; i < functionTypeCount; i++) { 2527 for (int i = 0; i < functionTypeCount; i++) {
2523 _functionTypesToFix[i].typeArguments = typeArguments; 2528 _functionTypesToFix[i].typeArguments = typeArguments;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 _inFunction = true; 2582 _inFunction = true;
2578 try { 2583 try {
2579 _visitChildren(holder, node); 2584 _visitChildren(holder, node);
2580 } finally { 2585 } finally {
2581 _inFunction = wasInFunction; 2586 _inFunction = wasInFunction;
2582 } 2587 }
2583 FunctionBody body = node.body; 2588 FunctionBody body = node.body;
2584 SimpleIdentifier constructorName = node.name; 2589 SimpleIdentifier constructorName = node.name;
2585 ConstructorElementImpl element = 2590 ConstructorElementImpl element =
2586 new ConstructorElementImpl.forNode(constructorName); 2591 new ConstructorElementImpl.forNode(constructorName);
2592 _setDocRange(element, node);
2587 if (node.externalKeyword != null) { 2593 if (node.externalKeyword != null) {
2588 element.external = true; 2594 element.external = true;
2589 } 2595 }
2590 if (node.factoryKeyword != null) { 2596 if (node.factoryKeyword != null) {
2591 element.factory = true; 2597 element.factory = true;
2592 } 2598 }
2593 element.functions = holder.functions; 2599 element.functions = holder.functions;
2594 element.labels = holder.labels; 2600 element.labels = holder.labels;
2595 element.localVariables = holder.localVariables; 2601 element.localVariables = holder.localVariables;
2596 element.parameters = holder.parameters; 2602 element.parameters = holder.parameters;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2681 normalParameter.accept(this); 2687 normalParameter.accept(this);
2682 holder.validate(); 2688 holder.validate();
2683 return null; 2689 return null;
2684 } 2690 }
2685 2691
2686 @override 2692 @override
2687 Object visitEnumDeclaration(EnumDeclaration node) { 2693 Object visitEnumDeclaration(EnumDeclaration node) {
2688 SimpleIdentifier enumName = node.name; 2694 SimpleIdentifier enumName = node.name;
2689 ClassElementImpl enumElement = new ClassElementImpl.forNode(enumName); 2695 ClassElementImpl enumElement = new ClassElementImpl.forNode(enumName);
2690 enumElement.enum2 = true; 2696 enumElement.enum2 = true;
2697 _setDocRange(enumElement, node);
2691 InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement); 2698 InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement);
2692 enumElement.type = enumType; 2699 enumElement.type = enumType;
2693 // The equivalent code for enums in the spec shows a single constructor, 2700 // The equivalent code for enums in the spec shows a single constructor,
2694 // but that constructor is not callable (since it is a compile-time error 2701 // but that constructor is not callable (since it is a compile-time error
2695 // to subclass, mix-in, implement, or explicitly instantiate an enum). So 2702 // to subclass, mix-in, implement, or explicitly instantiate an enum). So
2696 // we represent this as having no constructors. 2703 // we represent this as having no constructors.
2697 enumElement.constructors = ConstructorElement.EMPTY_LIST; 2704 enumElement.constructors = ConstructorElement.EMPTY_LIST;
2698 _currentHolder.addEnum(enumElement); 2705 _currentHolder.addEnum(enumElement);
2699 enumName.staticElement = enumElement; 2706 enumName.staticElement = enumElement;
2700 return super.visitEnumDeclaration(node); 2707 return super.visitEnumDeclaration(node);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2753 _visitChildren(holder, node); 2760 _visitChildren(holder, node);
2754 } finally { 2761 } finally {
2755 _inFunction = wasInFunction; 2762 _inFunction = wasInFunction;
2756 } 2763 }
2757 FunctionBody body = expression.body; 2764 FunctionBody body = expression.body;
2758 sc.Token property = node.propertyKeyword; 2765 sc.Token property = node.propertyKeyword;
2759 if (property == null || _inFunction) { 2766 if (property == null || _inFunction) {
2760 SimpleIdentifier functionName = node.name; 2767 SimpleIdentifier functionName = node.name;
2761 FunctionElementImpl element = 2768 FunctionElementImpl element =
2762 new FunctionElementImpl.forNode(functionName); 2769 new FunctionElementImpl.forNode(functionName);
2770 _setDocRange(element, node);
2763 if (node.externalKeyword != null) { 2771 if (node.externalKeyword != null) {
2764 element.external = true; 2772 element.external = true;
2765 } 2773 }
2766 element.functions = holder.functions; 2774 element.functions = holder.functions;
2767 element.labels = holder.labels; 2775 element.labels = holder.labels;
2768 element.localVariables = holder.localVariables; 2776 element.localVariables = holder.localVariables;
2769 element.parameters = holder.parameters; 2777 element.parameters = holder.parameters;
2770 element.typeParameters = holder.typeParameters; 2778 element.typeParameters = holder.typeParameters;
2771 if (body.isAsynchronous) { 2779 if (body.isAsynchronous) {
2772 element.asynchronous = true; 2780 element.asynchronous = true;
(...skipping 26 matching lines...) Expand all
2799 .getTopLevelVariable(propertyName) as TopLevelVariableElementImpl; 2807 .getTopLevelVariable(propertyName) as TopLevelVariableElementImpl;
2800 if (variable == null) { 2808 if (variable == null) {
2801 variable = new TopLevelVariableElementImpl(node.name.name, -1); 2809 variable = new TopLevelVariableElementImpl(node.name.name, -1);
2802 variable.final2 = true; 2810 variable.final2 = true;
2803 variable.synthetic = true; 2811 variable.synthetic = true;
2804 _currentHolder.addTopLevelVariable(variable); 2812 _currentHolder.addTopLevelVariable(variable);
2805 } 2813 }
2806 if (node.isGetter) { 2814 if (node.isGetter) {
2807 PropertyAccessorElementImpl getter = 2815 PropertyAccessorElementImpl getter =
2808 new PropertyAccessorElementImpl.forNode(propertyNameNode); 2816 new PropertyAccessorElementImpl.forNode(propertyNameNode);
2817 _setDocRange(getter, node);
2809 if (node.externalKeyword != null) { 2818 if (node.externalKeyword != null) {
2810 getter.external = true; 2819 getter.external = true;
2811 } 2820 }
2812 getter.functions = holder.functions; 2821 getter.functions = holder.functions;
2813 getter.labels = holder.labels; 2822 getter.labels = holder.labels;
2814 getter.localVariables = holder.localVariables; 2823 getter.localVariables = holder.localVariables;
2815 if (body.isAsynchronous) { 2824 if (body.isAsynchronous) {
2816 getter.asynchronous = true; 2825 getter.asynchronous = true;
2817 } 2826 }
2818 if (body.isGenerator) { 2827 if (body.isGenerator) {
2819 getter.generator = true; 2828 getter.generator = true;
2820 } 2829 }
2821 getter.variable = variable; 2830 getter.variable = variable;
2822 getter.getter = true; 2831 getter.getter = true;
2823 getter.static = true; 2832 getter.static = true;
2824 variable.getter = getter; 2833 variable.getter = getter;
2825 if (node.returnType == null) { 2834 if (node.returnType == null) {
2826 getter.hasImplicitReturnType = true; 2835 getter.hasImplicitReturnType = true;
2827 } 2836 }
2828 _currentHolder.addAccessor(getter); 2837 _currentHolder.addAccessor(getter);
2829 expression.element = getter; 2838 expression.element = getter;
2830 propertyNameNode.staticElement = getter; 2839 propertyNameNode.staticElement = getter;
2831 } else { 2840 } else {
2832 PropertyAccessorElementImpl setter = 2841 PropertyAccessorElementImpl setter =
2833 new PropertyAccessorElementImpl.forNode(propertyNameNode); 2842 new PropertyAccessorElementImpl.forNode(propertyNameNode);
2843 _setDocRange(setter, node);
2834 if (node.externalKeyword != null) { 2844 if (node.externalKeyword != null) {
2835 setter.external = true; 2845 setter.external = true;
2836 } 2846 }
2837 setter.functions = holder.functions; 2847 setter.functions = holder.functions;
2838 setter.labels = holder.labels; 2848 setter.labels = holder.labels;
2839 setter.localVariables = holder.localVariables; 2849 setter.localVariables = holder.localVariables;
2840 setter.parameters = holder.parameters; 2850 setter.parameters = holder.parameters;
2841 if (body.isAsynchronous) { 2851 if (body.isAsynchronous) {
2842 setter.asynchronous = true; 2852 setter.asynchronous = true;
2843 } 2853 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2910 2920
2911 @override 2921 @override
2912 Object visitFunctionTypeAlias(FunctionTypeAlias node) { 2922 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
2913 ElementHolder holder = new ElementHolder(); 2923 ElementHolder holder = new ElementHolder();
2914 _visitChildren(holder, node); 2924 _visitChildren(holder, node);
2915 SimpleIdentifier aliasName = node.name; 2925 SimpleIdentifier aliasName = node.name;
2916 List<ParameterElement> parameters = holder.parameters; 2926 List<ParameterElement> parameters = holder.parameters;
2917 List<TypeParameterElement> typeParameters = holder.typeParameters; 2927 List<TypeParameterElement> typeParameters = holder.typeParameters;
2918 FunctionTypeAliasElementImpl element = 2928 FunctionTypeAliasElementImpl element =
2919 new FunctionTypeAliasElementImpl.forNode(aliasName); 2929 new FunctionTypeAliasElementImpl.forNode(aliasName);
2930 _setDocRange(element, node);
2920 element.parameters = parameters; 2931 element.parameters = parameters;
2921 element.typeParameters = typeParameters; 2932 element.typeParameters = typeParameters;
2922 FunctionTypeImpl type = new FunctionTypeImpl.forTypedef(element); 2933 FunctionTypeImpl type = new FunctionTypeImpl.forTypedef(element);
2923 type.typeArguments = _createTypeParameterTypes(typeParameters); 2934 type.typeArguments = _createTypeParameterTypes(typeParameters);
2924 element.type = type; 2935 element.type = type;
2925 _currentHolder.addTypeAlias(element); 2936 _currentHolder.addTypeAlias(element);
2926 aliasName.staticElement = element; 2937 aliasName.staticElement = element;
2927 holder.validate(); 2938 holder.validate();
2928 return null; 2939 return null;
2929 } 2940 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2981 FunctionBody body = node.body; 2992 FunctionBody body = node.body;
2982 if (property == null) { 2993 if (property == null) {
2983 SimpleIdentifier methodName = node.name; 2994 SimpleIdentifier methodName = node.name;
2984 String nameOfMethod = methodName.name; 2995 String nameOfMethod = methodName.name;
2985 if (nameOfMethod == sc.TokenType.MINUS.lexeme && 2996 if (nameOfMethod == sc.TokenType.MINUS.lexeme &&
2986 node.parameters.parameters.length == 0) { 2997 node.parameters.parameters.length == 0) {
2987 nameOfMethod = "unary-"; 2998 nameOfMethod = "unary-";
2988 } 2999 }
2989 MethodElementImpl element = 3000 MethodElementImpl element =
2990 new MethodElementImpl(nameOfMethod, methodName.offset); 3001 new MethodElementImpl(nameOfMethod, methodName.offset);
3002 _setDocRange(element, node);
2991 element.abstract = node.isAbstract; 3003 element.abstract = node.isAbstract;
2992 if (node.externalKeyword != null) { 3004 if (node.externalKeyword != null) {
2993 element.external = true; 3005 element.external = true;
2994 } 3006 }
2995 element.functions = holder.functions; 3007 element.functions = holder.functions;
2996 element.labels = holder.labels; 3008 element.labels = holder.labels;
2997 element.localVariables = holder.localVariables; 3009 element.localVariables = holder.localVariables;
2998 element.parameters = holder.parameters; 3010 element.parameters = holder.parameters;
2999 element.static = isStatic; 3011 element.static = isStatic;
3000 element.typeParameters = holder.typeParameters; 3012 element.typeParameters = holder.typeParameters;
(...skipping 16 matching lines...) Expand all
3017 if (field == null) { 3029 if (field == null) {
3018 field = new FieldElementImpl(node.name.name, -1); 3030 field = new FieldElementImpl(node.name.name, -1);
3019 field.final2 = true; 3031 field.final2 = true;
3020 field.static = isStatic; 3032 field.static = isStatic;
3021 field.synthetic = true; 3033 field.synthetic = true;
3022 _currentHolder.addField(field); 3034 _currentHolder.addField(field);
3023 } 3035 }
3024 if (node.isGetter) { 3036 if (node.isGetter) {
3025 PropertyAccessorElementImpl getter = 3037 PropertyAccessorElementImpl getter =
3026 new PropertyAccessorElementImpl.forNode(propertyNameNode); 3038 new PropertyAccessorElementImpl.forNode(propertyNameNode);
3039 _setDocRange(getter, node);
3027 if (node.externalKeyword != null) { 3040 if (node.externalKeyword != null) {
3028 getter.external = true; 3041 getter.external = true;
3029 } 3042 }
3030 getter.functions = holder.functions; 3043 getter.functions = holder.functions;
3031 getter.labels = holder.labels; 3044 getter.labels = holder.labels;
3032 getter.localVariables = holder.localVariables; 3045 getter.localVariables = holder.localVariables;
3033 if (body.isAsynchronous) { 3046 if (body.isAsynchronous) {
3034 getter.asynchronous = true; 3047 getter.asynchronous = true;
3035 } 3048 }
3036 if (body.isGenerator) { 3049 if (body.isGenerator) {
3037 getter.generator = true; 3050 getter.generator = true;
3038 } 3051 }
3039 getter.variable = field; 3052 getter.variable = field;
3040 getter.abstract = node.isAbstract; 3053 getter.abstract = node.isAbstract;
3041 getter.getter = true; 3054 getter.getter = true;
3042 getter.static = isStatic; 3055 getter.static = isStatic;
3043 field.getter = getter; 3056 field.getter = getter;
3044 if (node.returnType == null) { 3057 if (node.returnType == null) {
3045 getter.hasImplicitReturnType = true; 3058 getter.hasImplicitReturnType = true;
3046 } 3059 }
3047 _currentHolder.addAccessor(getter); 3060 _currentHolder.addAccessor(getter);
3048 propertyNameNode.staticElement = getter; 3061 propertyNameNode.staticElement = getter;
3049 } else { 3062 } else {
3050 PropertyAccessorElementImpl setter = 3063 PropertyAccessorElementImpl setter =
3051 new PropertyAccessorElementImpl.forNode(propertyNameNode); 3064 new PropertyAccessorElementImpl.forNode(propertyNameNode);
3065 _setDocRange(setter, node);
3052 if (node.externalKeyword != null) { 3066 if (node.externalKeyword != null) {
3053 setter.external = true; 3067 setter.external = true;
3054 } 3068 }
3055 setter.functions = holder.functions; 3069 setter.functions = holder.functions;
3056 setter.labels = holder.labels; 3070 setter.labels = holder.labels;
3057 setter.localVariables = holder.localVariables; 3071 setter.localVariables = holder.localVariables;
3058 setter.parameters = holder.parameters; 3072 setter.parameters = holder.parameters;
3059 if (body.isAsynchronous) { 3073 if (body.isAsynchronous) {
3060 setter.asynchronous = true; 3074 setter.asynchronous = true;
3061 } 3075 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3178 VariableElementImpl element; 3192 VariableElementImpl element;
3179 if (_inFieldContext) { 3193 if (_inFieldContext) {
3180 SimpleIdentifier fieldName = node.name; 3194 SimpleIdentifier fieldName = node.name;
3181 FieldElementImpl field; 3195 FieldElementImpl field;
3182 if ((isConst || isFinal) && hasInitializer) { 3196 if ((isConst || isFinal) && hasInitializer) {
3183 field = new ConstFieldElementImpl.forNode(fieldName); 3197 field = new ConstFieldElementImpl.forNode(fieldName);
3184 } else { 3198 } else {
3185 field = new FieldElementImpl.forNode(fieldName); 3199 field = new FieldElementImpl.forNode(fieldName);
3186 } 3200 }
3187 element = field; 3201 element = field;
3202 if (node.parent.parent is FieldDeclaration) {
3203 _setDocRange(element, node.parent.parent);
3204 }
3188 if ((node.parent as VariableDeclarationList).type == null) { 3205 if ((node.parent as VariableDeclarationList).type == null) {
3189 field.hasImplicitType = true; 3206 field.hasImplicitType = true;
3190 } 3207 }
3191 _currentHolder.addField(field); 3208 _currentHolder.addField(field);
3192 fieldName.staticElement = field; 3209 fieldName.staticElement = field;
3193 } else if (_inFunction) { 3210 } else if (_inFunction) {
3194 SimpleIdentifier variableName = node.name; 3211 SimpleIdentifier variableName = node.name;
3195 LocalVariableElementImpl variable; 3212 LocalVariableElementImpl variable;
3196 if (isConst && hasInitializer) { 3213 if (isConst && hasInitializer) {
3197 variable = new ConstLocalVariableElementImpl.forNode(variableName); 3214 variable = new ConstLocalVariableElementImpl.forNode(variableName);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
3343 return parent.body; 3360 return parent.body;
3344 } else if (parent is MethodDeclaration) { 3361 } else if (parent is MethodDeclaration) {
3345 return parent.body; 3362 return parent.body;
3346 } 3363 }
3347 parent = parent.parent; 3364 parent = parent.parent;
3348 } 3365 }
3349 return null; 3366 return null;
3350 } 3367 }
3351 3368
3352 /** 3369 /**
3370 * If the given [node] has a documentation comment, remember its range
3371 * into the given [element].
3372 */
3373 void _setDocRange(ElementImpl element, AnnotatedNode node) {
3374 Comment comment = node.documentationComment;
3375 if (comment != null && comment.isDocumentation) {
3376 element.setDocRange(comment.offset, comment.length);
3377 }
3378 }
3379
3380 /**
3353 * Sets the visible source range for formal parameter. 3381 * Sets the visible source range for formal parameter.
3354 */ 3382 */
3355 void _setParameterVisibleRange( 3383 void _setParameterVisibleRange(
3356 FormalParameter node, ParameterElementImpl element) { 3384 FormalParameter node, ParameterElementImpl element) {
3357 FunctionBody body = _getFunctionBody(node); 3385 FunctionBody body = _getFunctionBody(node);
3358 if (body != null) { 3386 if (body != null) {
3359 element.setVisibleRange(body.offset, body.length); 3387 element.setVisibleRange(body.offset, body.length);
3360 } 3388 }
3361 } 3389 }
3362 3390
(...skipping 9350 matching lines...) Expand 10 before | Expand all | Expand 10 after
12713 } 12741 }
12714 } else if (statement is FunctionDeclarationStatement) { 12742 } else if (statement is FunctionDeclarationStatement) {
12715 FunctionDeclarationStatement fds = statement; 12743 FunctionDeclarationStatement fds = statement;
12716 scope.hide(fds.functionDeclaration.element); 12744 scope.hide(fds.functionDeclaration.element);
12717 } 12745 }
12718 } 12746 }
12719 } 12747 }
12720 } 12748 }
12721 12749
12722 /** 12750 /**
12751 * Implementation of [TypeSystem] using the strong mode rules.
12752 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
12753 */
12754 class StrongTypeSystemImpl implements TypeSystem {
12755 final _specTypeSystem = new TypeSystemImpl();
12756
12757 StrongTypeSystemImpl();
12758
12759 @override
12760 DartType getLeastUpperBound(
12761 TypeProvider typeProvider, DartType type1, DartType type2) {
12762 // TODO(leafp): Implement a strong mode version of this.
12763 return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2);
12764 }
12765
12766 // TODO(leafp): Document the rules in play here
12767 @override
12768 bool isAssignableTo(DartType fromType, DartType toType) {
12769 // An actual subtype
12770 if (isSubtypeOf(fromType, toType)) {
12771 return true;
12772 }
12773
12774 // Don't allow implicit downcasts between function types
12775 // and call method objects, as these will almost always fail.
12776 if ((fromType is FunctionType && _getCallMethodType(toType) != null) ||
12777 (toType is FunctionType && _getCallMethodType(fromType) != null)) {
12778 return false;
12779 }
12780
12781 // If the subtype relation goes the other way, allow the implicit downcast.
12782 // TODO(leafp): Emit warnings and hints for these in some way.
12783 // TODO(leafp): Consider adding a flag to disable these? Or just rely on
12784 // --warnings-as-errors?
12785 if (isSubtypeOf(toType, fromType) ||
12786 _specTypeSystem.isAssignableTo(toType, fromType)) {
12787 // TODO(leafp): error if type is known to be exact (literal,
12788 // instance creation).
12789 // TODO(leafp): Warn on composite downcast.
12790 // TODO(leafp): hint on object/dynamic downcast.
12791 // TODO(leafp): Consider allowing assignment casts.
12792 return true;
12793 }
12794
12795 return false;
12796 }
12797
12798 @override
12799 bool isSubtypeOf(DartType leftType, DartType rightType) {
12800 return _isSubtypeOf(leftType, rightType, null);
12801 }
12802
12803 FunctionType _getCallMethodType(DartType t) {
12804 if (t is InterfaceType) {
12805 ClassElement element = t.element;
12806 InheritanceManager manager = new InheritanceManager(element.library);
12807 FunctionType callType = manager.lookupMemberType(t, "call");
12808 return callType;
12809 }
12810 return null;
12811 }
12812
12813 // Given a type t, if t is an interface type with a call method
12814 // defined, return the function type for the call method, otherwise
12815 // return null.
12816 _GuardedSubtypeChecker<DartType> _guard(
12817 _GuardedSubtypeChecker<DartType> check) {
12818 return (DartType t1, DartType t2, Set<Element> visited) {
12819 Element element = t1.element;
12820 if (visited == null) {
12821 visited = new HashSet<Element>();
12822 }
12823 if (element == null || !visited.add(element)) {
12824 return false;
12825 }
12826 try {
12827 return check(t1, t2, visited);
12828 } finally {
12829 visited.remove(element);
12830 }
12831 };
12832 }
12833
12834 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
12835 return (t.isDynamic && dynamicIsBottom) || t.isBottom;
12836 }
12837
12838 // Guard against loops in the class hierarchy
12839 /**
12840 * Check that [f1] is a subtype of [f2].
12841 * [fuzzyArrows] indicates whether or not the f1 and f2 should be
12842 * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
12843 * as bottom).
12844 */
12845 bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
12846 {bool fuzzyArrows: true}) {
12847 final r1s = f1.normalParameterTypes;
12848 final o1s = f1.optionalParameterTypes;
12849 final n1s = f1.namedParameterTypes;
12850 final r2s = f2.normalParameterTypes;
12851 final o2s = f2.optionalParameterTypes;
12852 final n2s = f2.namedParameterTypes;
12853 final ret1 = f1.returnType;
12854 final ret2 = f2.returnType;
12855
12856 // A -> B <: C -> D if C <: A and
12857 // either D is void or B <: D
12858 if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) {
12859 return false;
12860 }
12861
12862 // Reject if one has named and the other has optional
12863 if (n1s.length > 0 && o2s.length > 0) {
12864 return false;
12865 }
12866 if (n2s.length > 0 && o1s.length > 0) {
12867 return false;
12868 }
12869
12870 // Rebind _isSubtypeOf for convenience
12871 _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) =>
12872 _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows);
12873
12874 // f2 has named parameters
12875 if (n2s.length > 0) {
12876 // Check that every named parameter in f2 has a match in f1
12877 for (String k2 in n2s.keys) {
12878 if (!n1s.containsKey(k2)) {
12879 return false;
12880 }
12881 if (!parameterSubtype(n2s[k2], n1s[k2])) {
12882 return false;
12883 }
12884 }
12885 }
12886 // If we get here, we either have no named parameters,
12887 // or else the named parameters match and we have no optional
12888 // parameters
12889
12890 // If f1 has more required parameters, reject
12891 if (r1s.length > r2s.length) {
12892 return false;
12893 }
12894
12895 // If f2 has more required + optional parameters, reject
12896 if (r2s.length + o2s.length > r1s.length + o1s.length) {
12897 return false;
12898 }
12899
12900 // The parameter lists must look like the following at this point
12901 // where rrr is a region of required, and ooo is a region of optionals.
12902 // f1: rrr ooo ooo ooo
12903 // f2: rrr rrr ooo
12904 int rr = r1s.length; // required in both
12905 int or = r2s.length - r1s.length; // optional in f1, required in f2
12906 int oo = o2s.length; // optional in both
12907
12908 for (int i = 0; i < rr; ++i) {
12909 if (!parameterSubtype(r2s[i], r1s[i])) {
12910 return false;
12911 }
12912 }
12913 for (int i = 0, j = rr; i < or; ++i, ++j) {
12914 if (!parameterSubtype(r2s[j], o1s[i])) {
12915 return false;
12916 }
12917 }
12918 for (int i = or, j = 0; i < oo; ++i, ++j) {
12919 if (!parameterSubtype(o2s[j], o1s[i])) {
12920 return false;
12921 }
12922 }
12923 return true;
12924 }
12925
12926 bool _isInterfaceSubtypeOf(
12927 InterfaceType i1, InterfaceType i2, Set<Element> visited) {
12928 // Guard recursive calls
12929 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype =
12930 _guard(_isInterfaceSubtypeOf);
12931
12932 if (i1 == i2) {
12933 return true;
12934 }
12935
12936 if (i1.element == i2.element) {
12937 List<DartType> tArgs1 = i1.typeArguments;
12938 List<DartType> tArgs2 = i2.typeArguments;
12939
12940 assert(tArgs1.length == tArgs2.length);
12941
12942 for (int i = 0; i < tArgs1.length; i++) {
12943 DartType t1 = tArgs1[i];
12944 DartType t2 = tArgs2[i];
12945 if (!isSubtypeOf(t1, t2)) {
12946 return false;
12947 }
12948 }
12949 return true;
12950 }
12951
12952 if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
12953 return true;
12954 }
12955
12956 if (i1.isObject) {
12957 return false;
12958 }
12959
12960 if (guardedInterfaceSubtype(i1.superclass, i2, visited)) {
12961 return true;
12962 }
12963
12964 for (final parent in i1.interfaces) {
12965 if (guardedInterfaceSubtype(parent, i2, visited)) {
12966 return true;
12967 }
12968 }
12969
12970 for (final parent in i1.mixins) {
12971 if (guardedInterfaceSubtype(parent, i2, visited)) {
12972 return true;
12973 }
12974 }
12975
12976 return false;
12977 }
12978
12979 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
12980 {bool dynamicIsBottom: false}) {
12981 // Guard recursive calls
12982 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf);
12983
12984 if (t1 == t2) {
12985 return true;
12986 }
12987
12988 // The types are void, dynamic, bottom, interface types, function types
12989 // and type parameters. We proceed by eliminating these different classes
12990 // from consideration.
12991
12992 // Trivially true.
12993 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
12994 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
12995 return true;
12996 }
12997
12998 // Trivially false.
12999 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
13000 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
13001 return false;
13002 }
13003
13004 // S <: T where S is a type variable
13005 // T is not dynamic or object (handled above)
13006 // S != T (handled above)
13007 // So only true if bound of S is S' and
13008 // S' <: T
13009 if (t1 is TypeParameterType) {
13010 DartType bound = t1.element.bound;
13011 if (bound == null) return false;
13012 return guardedSubtype(bound, t2, visited);
13013 }
13014
13015 if (t2 is TypeParameterType) {
13016 return false;
13017 }
13018
13019 if (t1.isVoid || t2.isVoid) {
13020 return false;
13021 }
13022
13023 // We've eliminated void, dynamic, bottom, and type parameters. The only
13024 // cases are the combinations of interface type and function type.
13025
13026 // A function type can only subtype an interface type if
13027 // the interface type is Function
13028 if (t1 is FunctionType && t2 is InterfaceType) {
13029 return t2.isDartCoreFunction;
13030 }
13031
13032 // An interface type can only subtype a function type if
13033 // the interface type declares a call method with a type
13034 // which is a super type of the function type.
13035 if (t1 is InterfaceType && t2 is FunctionType) {
13036 var callType = _getCallMethodType(t1);
13037 return (callType != null) && _isFunctionSubtypeOf(callType, t2);
13038 }
13039
13040 // Two interface types
13041 if (t1 is InterfaceType && t2 is InterfaceType) {
13042 return _isInterfaceSubtypeOf(t1, t2, visited);
13043 }
13044
13045 return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
13046 }
13047
13048 // TODO(leafp): Document the rules in play here
13049 bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
13050 return (t.isDynamic && !dynamicIsBottom) || t.isObject;
13051 }
13052 }
13053
13054 /**
12723 * Instances of this class manage the knowledge of what the set of subtypes are for a given type. 13055 * Instances of this class manage the knowledge of what the set of subtypes are for a given type.
12724 */ 13056 */
12725 class SubtypeManager { 13057 class SubtypeManager {
12726 /** 13058 /**
12727 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype s of the 13059 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype s of the
12728 * key. 13060 * key.
12729 */ 13061 */
12730 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap = 13062 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap =
12731 new HashMap<ClassElement, HashSet<ClassElement>>(); 13063 new HashMap<ClassElement, HashSet<ClassElement>>();
12732 13064
(...skipping 2213 matching lines...) Expand 10 before | Expand all | Expand 10 after
14946 15278
14947 /** 15279 /**
14948 * The interface `TypeSystem` defines the behavior of an object representing 15280 * The interface `TypeSystem` defines the behavior of an object representing
14949 * the type system. This provides a common location to put methods that act on 15281 * the type system. This provides a common location to put methods that act on
14950 * types but may need access to more global data structures, and it paves the 15282 * types but may need access to more global data structures, and it paves the
14951 * way for a possible future where we may wish to make the type system 15283 * way for a possible future where we may wish to make the type system
14952 * pluggable. 15284 * pluggable.
14953 */ 15285 */
14954 abstract class TypeSystem { 15286 abstract class TypeSystem {
14955 /** 15287 /**
14956 * Create either a strong mode or regular type system based on context.
14957 */
14958 static TypeSystem create(AnalysisContext context) {
14959 return (context.analysisOptions.strongMode)
14960 ? new StrongTypeSystemImpl()
14961 : new TypeSystemImpl();
14962 }
14963
14964 /**
14965 * Compute the least upper bound of two types. 15288 * Compute the least upper bound of two types.
14966 */ 15289 */
14967 DartType getLeastUpperBound( 15290 DartType getLeastUpperBound(
14968 TypeProvider typeProvider, DartType type1, DartType type2); 15291 TypeProvider typeProvider, DartType type1, DartType type2);
14969 15292
14970 /** 15293 /**
14971 * Return `true` if the [leftType] is assignable to the [rightType] (that is, 15294 * Return `true` if the [leftType] is assignable to the [rightType] (that is,
14972 * if leftType <==> rightType). 15295 * if leftType <==> rightType).
14973 */ 15296 */
14974 bool isAssignableTo(DartType leftType, DartType rightType); 15297 bool isAssignableTo(DartType leftType, DartType rightType);
14975 15298
14976 /** 15299 /**
14977 * Return `true` if the [leftType] is a subtype of the [rightType] (that is, 15300 * Return `true` if the [leftType] is a subtype of the [rightType] (that is,
14978 * if leftType <: rightType). 15301 * if leftType <: rightType).
14979 */ 15302 */
14980 bool isSubtypeOf(DartType leftType, DartType rightType); 15303 bool isSubtypeOf(DartType leftType, DartType rightType);
15304
15305 /**
15306 * Create either a strong mode or regular type system based on context.
15307 */
15308 static TypeSystem create(AnalysisContext context) {
15309 return (context.analysisOptions.strongMode)
15310 ? new StrongTypeSystemImpl()
15311 : new TypeSystemImpl();
15312 }
14981 } 15313 }
14982 15314
14983 /** 15315 /**
14984 * Implementation of [TypeSystem] using the rules in the Dart specification. 15316 * Implementation of [TypeSystem] using the rules in the Dart specification.
14985 */ 15317 */
14986 class TypeSystemImpl implements TypeSystem { 15318 class TypeSystemImpl implements TypeSystem {
14987 TypeSystemImpl(); 15319 TypeSystemImpl();
14988 15320
14989 @override 15321 @override
14990 DartType getLeastUpperBound( 15322 DartType getLeastUpperBound(
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
15070 bool isAssignableTo(DartType leftType, DartType rightType) { 15402 bool isAssignableTo(DartType leftType, DartType rightType) {
15071 return leftType.isAssignableTo(rightType); 15403 return leftType.isAssignableTo(rightType);
15072 } 15404 }
15073 15405
15074 @override 15406 @override
15075 bool isSubtypeOf(DartType leftType, DartType rightType) { 15407 bool isSubtypeOf(DartType leftType, DartType rightType) {
15076 return leftType.isSubtypeOf(rightType); 15408 return leftType.isSubtypeOf(rightType);
15077 } 15409 }
15078 } 15410 }
15079 15411
15080 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
15081 typedef bool _SubtypeChecker<T>(T t1, T t2);
15082
15083 /**
15084 * Implementation of [TypeSystem] using the strong mode rules.
15085 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
15086 */
15087 class StrongTypeSystemImpl implements TypeSystem {
15088 StrongTypeSystemImpl();
15089
15090 final _specTypeSystem = new TypeSystemImpl();
15091
15092 @override
15093 DartType getLeastUpperBound(
15094 TypeProvider typeProvider, DartType type1, DartType type2) {
15095 // TODO(leafp): Implement a strong mode version of this.
15096 return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2);
15097 }
15098
15099 // TODO(leafp): Document the rules in play here
15100 @override
15101 bool isAssignableTo(DartType fromType, DartType toType) {
15102 // An actual subtype
15103 if (isSubtypeOf(fromType, toType)) {
15104 return true;
15105 }
15106
15107 // Don't allow implicit downcasts between function types
15108 // and call method objects, as these will almost always fail.
15109 if ((fromType is FunctionType && _getCallMethodType(toType) != null) ||
15110 (toType is FunctionType && _getCallMethodType(fromType) != null)) {
15111 return false;
15112 }
15113
15114 // If the subtype relation goes the other way, allow the implicit downcast.
15115 // TODO(leafp): Emit warnings and hints for these in some way.
15116 // TODO(leafp): Consider adding a flag to disable these? Or just rely on
15117 // --warnings-as-errors?
15118 if (isSubtypeOf(toType, fromType) ||
15119 _specTypeSystem.isAssignableTo(toType, fromType)) {
15120 // TODO(leafp): error if type is known to be exact (literal,
15121 // instance creation).
15122 // TODO(leafp): Warn on composite downcast.
15123 // TODO(leafp): hint on object/dynamic downcast.
15124 // TODO(leafp): Consider allowing assignment casts.
15125 return true;
15126 }
15127
15128 return false;
15129 }
15130
15131 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
15132 return (t.isDynamic && dynamicIsBottom) || t.isBottom;
15133 }
15134
15135 bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
15136 return (t.isDynamic && !dynamicIsBottom) || t.isObject;
15137 }
15138
15139 // Given a type t, if t is an interface type with a call method
15140 // defined, return the function type for the call method, otherwise
15141 // return null.
15142 FunctionType _getCallMethodType(DartType t) {
15143 if (t is InterfaceType) {
15144 ClassElement element = t.element;
15145 InheritanceManager manager = new InheritanceManager(element.library);
15146 FunctionType callType = manager.lookupMemberType(t, "call");
15147 return callType;
15148 }
15149 return null;
15150 }
15151
15152 /**
15153 * Check that [f1] is a subtype of [f2].
15154 * [fuzzyArrows] indicates whether or not the f1 and f2 should be
15155 * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
15156 * as bottom).
15157 */
15158 bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
15159 {bool fuzzyArrows: true}) {
15160 final r1s = f1.normalParameterTypes;
15161 final o1s = f1.optionalParameterTypes;
15162 final n1s = f1.namedParameterTypes;
15163 final r2s = f2.normalParameterTypes;
15164 final o2s = f2.optionalParameterTypes;
15165 final n2s = f2.namedParameterTypes;
15166 final ret1 = f1.returnType;
15167 final ret2 = f2.returnType;
15168
15169 // A -> B <: C -> D if C <: A and
15170 // either D is void or B <: D
15171 if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) {
15172 return false;
15173 }
15174
15175 // Reject if one has named and the other has optional
15176 if (n1s.length > 0 && o2s.length > 0) {
15177 return false;
15178 }
15179 if (n2s.length > 0 && o1s.length > 0) {
15180 return false;
15181 }
15182
15183 // Rebind _isSubtypeOf for convenience
15184 _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) =>
15185 _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows);
15186
15187 // f2 has named parameters
15188 if (n2s.length > 0) {
15189 // Check that every named parameter in f2 has a match in f1
15190 for (String k2 in n2s.keys) {
15191 if (!n1s.containsKey(k2)) {
15192 return false;
15193 }
15194 if (!parameterSubtype(n2s[k2], n1s[k2])) {
15195 return false;
15196 }
15197 }
15198 }
15199 // If we get here, we either have no named parameters,
15200 // or else the named parameters match and we have no optional
15201 // parameters
15202
15203 // If f1 has more required parameters, reject
15204 if (r1s.length > r2s.length) {
15205 return false;
15206 }
15207
15208 // If f2 has more required + optional parameters, reject
15209 if (r2s.length + o2s.length > r1s.length + o1s.length) {
15210 return false;
15211 }
15212
15213 // The parameter lists must look like the following at this point
15214 // where rrr is a region of required, and ooo is a region of optionals.
15215 // f1: rrr ooo ooo ooo
15216 // f2: rrr rrr ooo
15217 int rr = r1s.length; // required in both
15218 int or = r2s.length - r1s.length; // optional in f1, required in f2
15219 int oo = o2s.length; // optional in both
15220
15221 for (int i = 0; i < rr; ++i) {
15222 if (!parameterSubtype(r2s[i], r1s[i])) {
15223 return false;
15224 }
15225 }
15226 for (int i = 0, j = rr; i < or; ++i, ++j) {
15227 if (!parameterSubtype(r2s[j], o1s[i])) {
15228 return false;
15229 }
15230 }
15231 for (int i = or, j = 0; i < oo; ++i, ++j) {
15232 if (!parameterSubtype(o2s[j], o1s[i])) {
15233 return false;
15234 }
15235 }
15236 return true;
15237 }
15238
15239 // Guard against loops in the class hierarchy
15240 _GuardedSubtypeChecker<DartType> _guard(
15241 _GuardedSubtypeChecker<DartType> check) {
15242 return (DartType t1, DartType t2, Set<Element> visited) {
15243 Element element = t1.element;
15244 if (visited == null) {
15245 visited = new HashSet<Element>();
15246 }
15247 if (element == null || !visited.add(element)) {
15248 return false;
15249 }
15250 try {
15251 return check(t1, t2, visited);
15252 } finally {
15253 visited.remove(element);
15254 }
15255 };
15256 }
15257
15258 bool _isInterfaceSubtypeOf(
15259 InterfaceType i1, InterfaceType i2, Set<Element> visited) {
15260 // Guard recursive calls
15261 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype =
15262 _guard(_isInterfaceSubtypeOf);
15263
15264 if (i1 == i2) {
15265 return true;
15266 }
15267
15268 if (i1.element == i2.element) {
15269 List<DartType> tArgs1 = i1.typeArguments;
15270 List<DartType> tArgs2 = i2.typeArguments;
15271
15272 assert(tArgs1.length == tArgs2.length);
15273
15274 for (int i = 0; i < tArgs1.length; i++) {
15275 DartType t1 = tArgs1[i];
15276 DartType t2 = tArgs2[i];
15277 if (!isSubtypeOf(t1, t2)) {
15278 return false;
15279 }
15280 }
15281 return true;
15282 }
15283
15284 if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
15285 return true;
15286 }
15287
15288 if (i1.isObject) {
15289 return false;
15290 }
15291
15292 if (guardedInterfaceSubtype(i1.superclass, i2, visited)) {
15293 return true;
15294 }
15295
15296 for (final parent in i1.interfaces) {
15297 if (guardedInterfaceSubtype(parent, i2, visited)) {
15298 return true;
15299 }
15300 }
15301
15302 for (final parent in i1.mixins) {
15303 if (guardedInterfaceSubtype(parent, i2, visited)) {
15304 return true;
15305 }
15306 }
15307
15308 return false;
15309 }
15310
15311 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
15312 {bool dynamicIsBottom: false}) {
15313 // Guard recursive calls
15314 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf);
15315
15316 if (t1 == t2) {
15317 return true;
15318 }
15319
15320 // The types are void, dynamic, bottom, interface types, function types
15321 // and type parameters. We proceed by eliminating these different classes
15322 // from consideration.
15323
15324 // Trivially true.
15325 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
15326 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
15327 return true;
15328 }
15329
15330 // Trivially false.
15331 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
15332 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
15333 return false;
15334 }
15335
15336 // S <: T where S is a type variable
15337 // T is not dynamic or object (handled above)
15338 // S != T (handled above)
15339 // So only true if bound of S is S' and
15340 // S' <: T
15341 if (t1 is TypeParameterType) {
15342 DartType bound = t1.element.bound;
15343 if (bound == null) return false;
15344 return guardedSubtype(bound, t2, visited);
15345 }
15346
15347 if (t2 is TypeParameterType) {
15348 return false;
15349 }
15350
15351 if (t1.isVoid || t2.isVoid) {
15352 return false;
15353 }
15354
15355 // We've eliminated void, dynamic, bottom, and type parameters. The only
15356 // cases are the combinations of interface type and function type.
15357
15358 // A function type can only subtype an interface type if
15359 // the interface type is Function
15360 if (t1 is FunctionType && t2 is InterfaceType) {
15361 return t2.isDartCoreFunction;
15362 }
15363
15364 // An interface type can only subtype a function type if
15365 // the interface type declares a call method with a type
15366 // which is a super type of the function type.
15367 if (t1 is InterfaceType && t2 is FunctionType) {
15368 var callType = _getCallMethodType(t1);
15369 return (callType != null) && _isFunctionSubtypeOf(callType, t2);
15370 }
15371
15372 // Two interface types
15373 if (t1 is InterfaceType && t2 is InterfaceType) {
15374 return _isInterfaceSubtypeOf(t1, t2, visited);
15375 }
15376
15377 return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
15378 }
15379
15380 // TODO(leafp): Document the rules in play here
15381 @override
15382 bool isSubtypeOf(DartType leftType, DartType rightType) {
15383 return _isSubtypeOf(leftType, rightType, null);
15384 }
15385 }
15386
15387 /** 15412 /**
15388 * Instances of the class [UnusedLocalElementsVerifier] traverse an element 15413 * Instances of the class [UnusedLocalElementsVerifier] traverse an element
15389 * structure looking for cases of [HintCode.UNUSED_ELEMENT], 15414 * structure looking for cases of [HintCode.UNUSED_ELEMENT],
15390 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. 15415 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
15391 */ 15416 */
15392 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { 15417 class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
15393 /** 15418 /**
15394 * The error listener to which errors will be reported. 15419 * The error listener to which errors will be reported.
15395 */ 15420 */
15396 final AnalysisErrorListener _errorListener; 15421 final AnalysisErrorListener _errorListener;
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
15946 nonFields.add(node); 15971 nonFields.add(node);
15947 return null; 15972 return null;
15948 } 15973 }
15949 15974
15950 @override 15975 @override
15951 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 15976 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
15952 15977
15953 @override 15978 @override
15954 Object visitWithClause(WithClause node) => null; 15979 Object visitWithClause(WithClause node) => null;
15955 } 15980 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/engine.dart ('k') | pkg/analyzer/lib/src/generated/testing/ast_factory.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698