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

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

Issue 1407923009: move TypeSystem classes to their own file (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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 'package:analyzer/src/generated/scanner.dart';
10
11 import 'ast.dart'; 9 import 'ast.dart';
12 import 'constant.dart'; 10 import 'constant.dart';
13 import 'element.dart'; 11 import 'element.dart';
14 import 'element_resolver.dart'; 12 import 'element_resolver.dart';
15 import 'engine.dart'; 13 import 'engine.dart';
16 import 'error.dart'; 14 import 'error.dart';
17 import 'error_verifier.dart'; 15 import 'error_verifier.dart';
18 import 'html.dart' as ht; 16 import 'html.dart' as ht;
19 import 'java_core.dart'; 17 import 'java_core.dart';
20 import 'java_engine.dart'; 18 import 'java_engine.dart';
19 import 'scanner.dart';
21 import 'scanner.dart' as sc; 20 import 'scanner.dart' as sc;
22 import 'sdk.dart' show DartSdk, SdkLibrary; 21 import 'sdk.dart' show DartSdk, SdkLibrary;
23 import 'source.dart'; 22 import 'source.dart';
24 import 'static_type_analyzer.dart'; 23 import 'static_type_analyzer.dart';
24 import 'type_system.dart';
25 import 'utilities_dart.dart'; 25 import 'utilities_dart.dart';
26 26
27 export 'type_system.dart';
28
27 /** 29 /**
28 * Callback signature used by ImplicitConstructorBuilder to register 30 * Callback signature used by ImplicitConstructorBuilder to register
29 * computations to be performed, and their dependencies. A call to this 31 * computations to be performed, and their dependencies. A call to this
30 * callback indicates that [computation] may be used to compute implicit 32 * callback indicates that [computation] may be used to compute implicit
31 * constructors for [classElement], but that the computation may not be invoked 33 * constructors for [classElement], but that the computation may not be invoked
32 * until after implicit constructors have been built for [superclassElement]. 34 * until after implicit constructors have been built for [superclassElement].
33 */ 35 */
34 typedef void ImplicitConstructorBuilderCallback(ClassElement classElement, 36 typedef void ImplicitConstructorBuilderCallback(ClassElement classElement,
35 ClassElement superclassElement, void computation()); 37 ClassElement superclassElement, void computation());
36 38
37 typedef LibraryResolver LibraryResolverFactory(AnalysisContext context); 39 typedef LibraryResolver LibraryResolverFactory(AnalysisContext context);
38 40
39 typedef ResolverVisitor ResolverVisitorFactory( 41 typedef ResolverVisitor ResolverVisitorFactory(
40 Library library, Source source, TypeProvider typeProvider); 42 Library library, Source source, TypeProvider typeProvider);
41 43
42 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor); 44 typedef StaticTypeAnalyzer StaticTypeAnalyzerFactory(ResolverVisitor visitor);
43 45
44 typedef TypeResolverVisitor TypeResolverVisitorFactory( 46 typedef TypeResolverVisitor TypeResolverVisitorFactory(
45 Library library, Source source, TypeProvider typeProvider); 47 Library library, Source source, TypeProvider typeProvider);
46 48
47 typedef void VoidFunction(); 49 typedef void VoidFunction();
48 50
49 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
50
51 typedef bool _SubtypeChecker<T>(T t1, T t2);
52
53 /** 51 /**
54 * 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
55 * violations of Dart best practices. 53 * violations of Dart best practices.
56 */ 54 */
57 class BestPracticesVerifier extends RecursiveAstVisitor<Object> { 55 class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
58 // static String _HASHCODE_GETTER_NAME = "hashCode"; 56 // static String _HASHCODE_GETTER_NAME = "hashCode";
59 57
60 static String _NULL_TYPE_NAME = "Null"; 58 static String _NULL_TYPE_NAME = "Null";
61 59
62 static String _TO_INT_METHOD_NAME = "toInt"; 60 static String _TO_INT_METHOD_NAME = "toInt";
(...skipping 12736 matching lines...) Expand 10 before | Expand all | Expand 10 after
12799 } 12797 }
12800 } else if (statement is FunctionDeclarationStatement) { 12798 } else if (statement is FunctionDeclarationStatement) {
12801 FunctionDeclarationStatement fds = statement; 12799 FunctionDeclarationStatement fds = statement;
12802 scope.hide(fds.functionDeclaration.element); 12800 scope.hide(fds.functionDeclaration.element);
12803 } 12801 }
12804 } 12802 }
12805 } 12803 }
12806 } 12804 }
12807 12805
12808 /** 12806 /**
12809 * Implementation of [TypeSystem] using the strong mode rules.
12810 * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
12811 */
12812 class StrongTypeSystemImpl implements TypeSystem {
12813 final _specTypeSystem = new TypeSystemImpl();
12814
12815 StrongTypeSystemImpl();
12816
12817 @override
12818 DartType getLeastUpperBound(
12819 TypeProvider typeProvider, DartType type1, DartType type2) {
12820 // TODO(leafp): Implement a strong mode version of this.
12821 return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2);
12822 }
12823
12824 // TODO(leafp): Document the rules in play here
12825 @override
12826 bool isAssignableTo(DartType fromType, DartType toType) {
12827 // An actual subtype
12828 if (isSubtypeOf(fromType, toType)) {
12829 return true;
12830 }
12831
12832 // Don't allow implicit downcasts between function types
12833 // and call method objects, as these will almost always fail.
12834 if ((fromType is FunctionType && _getCallMethodType(toType) != null) ||
12835 (toType is FunctionType && _getCallMethodType(fromType) != null)) {
12836 return false;
12837 }
12838
12839 // If the subtype relation goes the other way, allow the implicit downcast.
12840 // TODO(leafp): Emit warnings and hints for these in some way.
12841 // TODO(leafp): Consider adding a flag to disable these? Or just rely on
12842 // --warnings-as-errors?
12843 if (isSubtypeOf(toType, fromType) ||
12844 _specTypeSystem.isAssignableTo(toType, fromType)) {
12845 // TODO(leafp): error if type is known to be exact (literal,
12846 // instance creation).
12847 // TODO(leafp): Warn on composite downcast.
12848 // TODO(leafp): hint on object/dynamic downcast.
12849 // TODO(leafp): Consider allowing assignment casts.
12850 return true;
12851 }
12852
12853 return false;
12854 }
12855
12856 @override
12857 bool isSubtypeOf(DartType leftType, DartType rightType) {
12858 return _isSubtypeOf(leftType, rightType, null);
12859 }
12860
12861 FunctionType _getCallMethodType(DartType t) {
12862 if (t is InterfaceType) {
12863 return t.lookUpInheritedMethod("call")?.type;
12864 }
12865 return null;
12866 }
12867
12868 // Given a type t, if t is an interface type with a call method
12869 // defined, return the function type for the call method, otherwise
12870 // return null.
12871 _GuardedSubtypeChecker<DartType> _guard(
12872 _GuardedSubtypeChecker<DartType> check) {
12873 return (DartType t1, DartType t2, Set<Element> visited) {
12874 Element element = t1.element;
12875 if (visited == null) {
12876 visited = new HashSet<Element>();
12877 }
12878 if (element == null || !visited.add(element)) {
12879 return false;
12880 }
12881 try {
12882 return check(t1, t2, visited);
12883 } finally {
12884 visited.remove(element);
12885 }
12886 };
12887 }
12888
12889 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
12890 return (t.isDynamic && dynamicIsBottom) || t.isBottom;
12891 }
12892
12893 // Guard against loops in the class hierarchy
12894 /**
12895 * Check that [f1] is a subtype of [f2].
12896 * [fuzzyArrows] indicates whether or not the f1 and f2 should be
12897 * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
12898 * as bottom).
12899 */
12900 bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2,
12901 {bool fuzzyArrows: true}) {
12902 final r1s = f1.normalParameterTypes;
12903 final o1s = f1.optionalParameterTypes;
12904 final n1s = f1.namedParameterTypes;
12905 final r2s = f2.normalParameterTypes;
12906 final o2s = f2.optionalParameterTypes;
12907 final n2s = f2.namedParameterTypes;
12908 final ret1 = f1.returnType;
12909 final ret2 = f2.returnType;
12910
12911 // A -> B <: C -> D if C <: A and
12912 // either D is void or B <: D
12913 if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) {
12914 return false;
12915 }
12916
12917 // Reject if one has named and the other has optional
12918 if (n1s.length > 0 && o2s.length > 0) {
12919 return false;
12920 }
12921 if (n2s.length > 0 && o1s.length > 0) {
12922 return false;
12923 }
12924
12925 // Rebind _isSubtypeOf for convenience
12926 _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) =>
12927 _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows);
12928
12929 // f2 has named parameters
12930 if (n2s.length > 0) {
12931 // Check that every named parameter in f2 has a match in f1
12932 for (String k2 in n2s.keys) {
12933 if (!n1s.containsKey(k2)) {
12934 return false;
12935 }
12936 if (!parameterSubtype(n2s[k2], n1s[k2])) {
12937 return false;
12938 }
12939 }
12940 }
12941 // If we get here, we either have no named parameters,
12942 // or else the named parameters match and we have no optional
12943 // parameters
12944
12945 // If f1 has more required parameters, reject
12946 if (r1s.length > r2s.length) {
12947 return false;
12948 }
12949
12950 // If f2 has more required + optional parameters, reject
12951 if (r2s.length + o2s.length > r1s.length + o1s.length) {
12952 return false;
12953 }
12954
12955 // The parameter lists must look like the following at this point
12956 // where rrr is a region of required, and ooo is a region of optionals.
12957 // f1: rrr ooo ooo ooo
12958 // f2: rrr rrr ooo
12959 int rr = r1s.length; // required in both
12960 int or = r2s.length - r1s.length; // optional in f1, required in f2
12961 int oo = o2s.length; // optional in both
12962
12963 for (int i = 0; i < rr; ++i) {
12964 if (!parameterSubtype(r2s[i], r1s[i])) {
12965 return false;
12966 }
12967 }
12968 for (int i = 0, j = rr; i < or; ++i, ++j) {
12969 if (!parameterSubtype(r2s[j], o1s[i])) {
12970 return false;
12971 }
12972 }
12973 for (int i = or, j = 0; i < oo; ++i, ++j) {
12974 if (!parameterSubtype(o2s[j], o1s[i])) {
12975 return false;
12976 }
12977 }
12978 return true;
12979 }
12980
12981 bool _isInterfaceSubtypeOf(
12982 InterfaceType i1, InterfaceType i2, Set<Element> visited) {
12983 // Guard recursive calls
12984 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype =
12985 _guard(_isInterfaceSubtypeOf);
12986
12987 if (i1 == i2) {
12988 return true;
12989 }
12990
12991 if (i1.element == i2.element) {
12992 List<DartType> tArgs1 = i1.typeArguments;
12993 List<DartType> tArgs2 = i2.typeArguments;
12994
12995 assert(tArgs1.length == tArgs2.length);
12996
12997 for (int i = 0; i < tArgs1.length; i++) {
12998 DartType t1 = tArgs1[i];
12999 DartType t2 = tArgs2[i];
13000 if (!isSubtypeOf(t1, t2)) {
13001 return false;
13002 }
13003 }
13004 return true;
13005 }
13006
13007 if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
13008 return true;
13009 }
13010
13011 if (i1.isObject) {
13012 return false;
13013 }
13014
13015 if (guardedInterfaceSubtype(i1.superclass, i2, visited)) {
13016 return true;
13017 }
13018
13019 for (final parent in i1.interfaces) {
13020 if (guardedInterfaceSubtype(parent, i2, visited)) {
13021 return true;
13022 }
13023 }
13024
13025 for (final parent in i1.mixins) {
13026 if (guardedInterfaceSubtype(parent, i2, visited)) {
13027 return true;
13028 }
13029 }
13030
13031 return false;
13032 }
13033
13034 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
13035 {bool dynamicIsBottom: false}) {
13036 // Guard recursive calls
13037 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf);
13038
13039 if (t1 == t2) {
13040 return true;
13041 }
13042
13043 // The types are void, dynamic, bottom, interface types, function types
13044 // and type parameters. We proceed by eliminating these different classes
13045 // from consideration.
13046
13047 // Trivially true.
13048 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
13049 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
13050 return true;
13051 }
13052
13053 // Trivially false.
13054 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
13055 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
13056 return false;
13057 }
13058
13059 // S <: T where S is a type variable
13060 // T is not dynamic or object (handled above)
13061 // S != T (handled above)
13062 // So only true if bound of S is S' and
13063 // S' <: T
13064 if (t1 is TypeParameterType) {
13065 DartType bound = t1.element.bound;
13066 if (bound == null) return false;
13067 return guardedSubtype(bound, t2, visited);
13068 }
13069
13070 if (t2 is TypeParameterType) {
13071 return false;
13072 }
13073
13074 if (t1.isVoid || t2.isVoid) {
13075 return false;
13076 }
13077
13078 // We've eliminated void, dynamic, bottom, and type parameters. The only
13079 // cases are the combinations of interface type and function type.
13080
13081 // A function type can only subtype an interface type if
13082 // the interface type is Function
13083 if (t1 is FunctionType && t2 is InterfaceType) {
13084 return t2.isDartCoreFunction;
13085 }
13086
13087 // An interface type can only subtype a function type if
13088 // the interface type declares a call method with a type
13089 // which is a super type of the function type.
13090 if (t1 is InterfaceType && t2 is FunctionType) {
13091 var callType = _getCallMethodType(t1);
13092 return (callType != null) && _isFunctionSubtypeOf(callType, t2);
13093 }
13094
13095 // Two interface types
13096 if (t1 is InterfaceType && t2 is InterfaceType) {
13097 return _isInterfaceSubtypeOf(t1, t2, visited);
13098 }
13099
13100 return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
13101 }
13102
13103 // TODO(leafp): Document the rules in play here
13104 bool _isTop(DartType t, {bool dynamicIsBottom: false}) {
13105 return (t.isDynamic && !dynamicIsBottom) || t.isObject;
13106 }
13107 }
13108
13109 /**
13110 * Instances of this class manage the knowledge of what the set of subtypes are for a given type. 12807 * Instances of this class manage the knowledge of what the set of subtypes are for a given type.
13111 */ 12808 */
13112 class SubtypeManager { 12809 class SubtypeManager {
13113 /** 12810 /**
13114 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype s of the 12811 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype s of the
13115 * key. 12812 * key.
13116 */ 12813 */
13117 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap = 12814 HashMap<ClassElement, HashSet<ClassElement>> _subtypeMap =
13118 new HashMap<ClassElement, HashSet<ClassElement>>(); 12815 new HashMap<ClassElement, HashSet<ClassElement>>();
13119 12816
(...skipping 2205 matching lines...) Expand 10 before | Expand all | Expand 10 after
15325 return identical(parent.type, node); 15022 return identical(parent.type, node);
15326 } 15023 }
15327 if (parent is SimpleFormalParameter) { 15024 if (parent is SimpleFormalParameter) {
15328 return identical(parent.type, node); 15025 return identical(parent.type, node);
15329 } 15026 }
15330 return false; 15027 return false;
15331 } 15028 }
15332 } 15029 }
15333 15030
15334 /** 15031 /**
15335 * The interface `TypeSystem` defines the behavior of an object representing
15336 * the type system. This provides a common location to put methods that act on
15337 * types but may need access to more global data structures, and it paves the
15338 * way for a possible future where we may wish to make the type system
15339 * pluggable.
15340 */
15341 abstract class TypeSystem {
15342 /**
15343 * Compute the least upper bound of two types.
15344 */
15345 DartType getLeastUpperBound(
15346 TypeProvider typeProvider, DartType type1, DartType type2);
15347
15348 /**
15349 * Return `true` if the [leftType] is assignable to the [rightType] (that is,
15350 * if leftType <==> rightType).
15351 */
15352 bool isAssignableTo(DartType leftType, DartType rightType);
15353
15354 /**
15355 * Return `true` if the [leftType] is a subtype of the [rightType] (that is,
15356 * if leftType <: rightType).
15357 */
15358 bool isSubtypeOf(DartType leftType, DartType rightType);
15359
15360 /**
15361 * Create either a strong mode or regular type system based on context.
15362 */
15363 static TypeSystem create(AnalysisContext context) {
15364 return (context.analysisOptions.strongMode)
15365 ? new StrongTypeSystemImpl()
15366 : new TypeSystemImpl();
15367 }
15368 }
15369
15370 /**
15371 * Implementation of [TypeSystem] using the rules in the Dart specification.
15372 */
15373 class TypeSystemImpl implements TypeSystem {
15374 TypeSystemImpl();
15375
15376 @override
15377 DartType getLeastUpperBound(
15378 TypeProvider typeProvider, DartType type1, DartType type2) {
15379 // The least upper bound relation is reflexive.
15380 if (identical(type1, type2)) {
15381 return type1;
15382 }
15383 // The least upper bound of dynamic and any type T is dynamic.
15384 if (type1.isDynamic) {
15385 return type1;
15386 }
15387 if (type2.isDynamic) {
15388 return type2;
15389 }
15390 // The least upper bound of void and any type T != dynamic is void.
15391 if (type1.isVoid) {
15392 return type1;
15393 }
15394 if (type2.isVoid) {
15395 return type2;
15396 }
15397 // The least upper bound of bottom and any type T is T.
15398 if (type1.isBottom) {
15399 return type2;
15400 }
15401 if (type2.isBottom) {
15402 return type1;
15403 }
15404 // Let U be a type variable with upper bound B. The least upper bound of U
15405 // and a type T is the least upper bound of B and T.
15406 while (type1 is TypeParameterType) {
15407 // TODO(paulberry): is this correct in the complex of F-bounded
15408 // polymorphism?
15409 DartType bound = (type1 as TypeParameterType).element.bound;
15410 if (bound == null) {
15411 bound = typeProvider.objectType;
15412 }
15413 type1 = bound;
15414 }
15415 while (type2 is TypeParameterType) {
15416 // TODO(paulberry): is this correct in the context of F-bounded
15417 // polymorphism?
15418 DartType bound = (type2 as TypeParameterType).element.bound;
15419 if (bound == null) {
15420 bound = typeProvider.objectType;
15421 }
15422 type2 = bound;
15423 }
15424 // The least upper bound of a function type and an interface type T is the
15425 // least upper bound of Function and T.
15426 if (type1 is FunctionType && type2 is InterfaceType) {
15427 type1 = typeProvider.functionType;
15428 }
15429 if (type2 is FunctionType && type1 is InterfaceType) {
15430 type2 = typeProvider.functionType;
15431 }
15432
15433 // At this point type1 and type2 should both either be interface types or
15434 // function types.
15435 if (type1 is InterfaceType && type2 is InterfaceType) {
15436 InterfaceType result =
15437 InterfaceTypeImpl.computeLeastUpperBound(type1, type2);
15438 if (result == null) {
15439 return typeProvider.dynamicType;
15440 }
15441 return result;
15442 } else if (type1 is FunctionType && type2 is FunctionType) {
15443 FunctionType result =
15444 FunctionTypeImpl.computeLeastUpperBound(type1, type2);
15445 if (result == null) {
15446 return typeProvider.functionType;
15447 }
15448 return result;
15449 } else {
15450 // Should never happen. As a defensive measure, return the dynamic type.
15451 assert(false);
15452 return typeProvider.dynamicType;
15453 }
15454 }
15455
15456 @override
15457 bool isAssignableTo(DartType leftType, DartType rightType) {
15458 return leftType.isAssignableTo(rightType);
15459 }
15460
15461 @override
15462 bool isSubtypeOf(DartType leftType, DartType rightType) {
15463 return leftType.isSubtypeOf(rightType);
15464 }
15465 }
15466
15467 /**
15468 * Instances of the class [UnusedLocalElementsVerifier] traverse an element 15032 * Instances of the class [UnusedLocalElementsVerifier] traverse an element
15469 * structure looking for cases of [HintCode.UNUSED_ELEMENT], 15033 * structure looking for cases of [HintCode.UNUSED_ELEMENT],
15470 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. 15034 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
15471 */ 15035 */
15472 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { 15036 class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
15473 /** 15037 /**
15474 * The error listener to which errors will be reported. 15038 * The error listener to which errors will be reported.
15475 */ 15039 */
15476 final AnalysisErrorListener _errorListener; 15040 final AnalysisErrorListener _errorListener;
15477 15041
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
16040 nonFields.add(node); 15604 nonFields.add(node);
16041 return null; 15605 return null;
16042 } 15606 }
16043 15607
16044 @override 15608 @override
16045 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 15609 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
16046 15610
16047 @override 15611 @override
16048 Object visitWithClause(WithClause node) => null; 15612 Object visitWithClause(WithClause node) => null;
16049 } 15613 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/constant.dart ('k') | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698