Index: pkg/analyzer/lib/src/summary/link.dart |
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart |
index 279bd780d13e5e1955230935e4ce58d711dacac8..8e84971dd880055b7de2d236082b5d14255a712e 100644 |
--- a/pkg/analyzer/lib/src/summary/link.dart |
+++ b/pkg/analyzer/lib/src/summary/link.dart |
@@ -58,13 +58,18 @@ |
* checks. E.g. see [ReferenceableElementForLink.asConstructor]. |
*/ |
+import 'package:analyzer/dart/ast/ast.dart'; |
import 'package:analyzer/dart/element/element.dart'; |
import 'package:analyzer/dart/element/type.dart'; |
+import 'package:analyzer/src/dart/constant/value.dart'; |
+import 'package:analyzer/src/dart/element/element.dart'; |
import 'package:analyzer/src/dart/element/type.dart'; |
+import 'package:analyzer/src/generated/resolver.dart'; |
import 'package:analyzer/src/generated/utilities_dart.dart'; |
import 'package:analyzer/src/summary/format.dart'; |
import 'package:analyzer/src/summary/idl.dart'; |
import 'package:analyzer/src/summary/prelink.dart'; |
+import 'package:analyzer/src/task/strong_mode.dart'; |
/** |
* Link together the build unit consisting of [libraryUris], using |
@@ -72,12 +77,17 @@ import 'package:analyzer/src/summary/prelink.dart'; |
* build units, and [getUnit] to fetch the [UnlinkedUnit] objects from |
* both this build unit and other build units. |
* |
+ * The [strong] flag controls whether type inference is performed in strong |
+ * mode or spec mode. Note that in spec mode, the only types that are inferred |
+ * are the types of initializing formals, which are inferred from the types of |
+ * the corresponding fields. |
+ * |
* A map is returned whose keys are the URIs of the libraries in this |
* build unit, and whose values are the corresponding |
* [LinkedLibraryBuilder]s. |
*/ |
Map<String, LinkedLibraryBuilder> link(Set<String> libraryUris, |
- GetDependencyCallback getDependency, GetUnitCallback getUnit) { |
+ GetDependencyCallback getDependency, GetUnitCallback getUnit, bool strong) { |
Map<String, LinkedLibraryBuilder> linkedLibraries = |
<String, LinkedLibraryBuilder>{}; |
for (String absoluteUri in libraryUris) { |
@@ -89,7 +99,7 @@ Map<String, LinkedLibraryBuilder> link(Set<String> libraryUris, |
getRelativeUnit, |
(String relativeUri) => getRelativeUnit(relativeUri)?.publicNamespace); |
} |
- relink(linkedLibraries, getDependency, getUnit); |
+ relink(linkedLibraries, getDependency, getUnit, strong); |
return linkedLibraries; |
} |
@@ -100,10 +110,39 @@ Map<String, LinkedLibraryBuilder> link(Set<String> libraryUris, |
* objects from other build units, and [getUnit] to fetch the |
* [UnlinkedUnit] objects from both this build unit and other build |
* units. |
+ * |
+ * The [strong] flag controls whether type inference is performed in strong |
+ * mode or spec mode. Note that in spec mode, the only types that are inferred |
+ * are the types of initializing formals, which are inferred from the types of |
+ * the corresponding fields. |
*/ |
void relink(Map<String, LinkedLibraryBuilder> libraries, |
- GetDependencyCallback getDependency, GetUnitCallback getUnit) { |
- new _Linker(libraries, getDependency, getUnit).link(); |
+ GetDependencyCallback getDependency, GetUnitCallback getUnit, bool strong) { |
+ new _Linker(libraries, getDependency, getUnit, strong).link(); |
+} |
+ |
+/** |
+ * Create an [EntityRefBuilder] representing the given [type], in a form |
+ * suitable for inclusion in [LinkedUnit.types]. [compilationUnit] is the |
+ * compilation unit in which the type will be used. If [slot] is provided, it |
+ * is stored in [EntityRefBuilder.slot]. |
+ */ |
+EntityRefBuilder _createLinkedType( |
+ DartType type, CompilationUnitElementInBuildUnit compilationUnit, |
+ {int slot}) { |
+ EntityRefBuilder result = new EntityRefBuilder(slot: slot); |
+ if (type is InterfaceType) { |
+ ClassElementForLink element = type.element; |
+ int dependency = compilationUnit.library.addDependency(element.library); |
+ result.reference = compilationUnit.addReference(dependency, element.name, |
+ element.typeParameters.length, element.enclosingElement.unitNum); |
+ if (element.typeParameters.isNotEmpty) { |
+ // TODO(paulberry): implement. |
+ throw new UnimplementedError(); |
+ } |
+ return result; |
+ } |
+ throw new UnimplementedError('${type.runtimeType}'); |
} |
/** |
@@ -123,10 +162,18 @@ typedef UnlinkedUnit GetUnitCallback(String absoluteUri); |
* during linking. |
*/ |
abstract class ClassElementForLink |
- implements ClassElement, ReferenceableElementForLink { |
+ implements ClassElementImpl, ReferenceableElementForLink { |
Map<String, ReferenceableElementForLink> _containedNames; |
@override |
+ final CompilationUnitElementForLink enclosingElement; |
+ |
+ @override |
+ bool hasBeenInferred = false; |
+ |
+ ClassElementForLink(this.enclosingElement); |
+ |
+ @override |
ConstructorElementForLink get asConstructor => unnamedConstructor; |
@override |
@@ -149,6 +196,9 @@ abstract class ClassElementForLink |
bool get isObject; |
@override |
+ LibraryElementForLink get library => enclosingElement.library; |
+ |
+ @override |
String get name; |
@override |
@@ -183,6 +233,11 @@ abstract class ClassElementForLink |
@override |
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
+ |
+ /** |
+ * Throw away any information produced by a previous call to [link]. |
+ */ |
+ void unlink(); |
} |
/** |
@@ -196,18 +251,27 @@ class ClassElementForLink_Class extends ClassElementForLink |
*/ |
final UnlinkedClass _unlinkedClass; |
- @override |
- final CompilationUnitElementForLink enclosingElement; |
- |
List<ConstructorElementForLink> _constructors; |
ConstructorElementForLink _unnamedConstructor; |
bool _unnamedConstructorComputed = false; |
List<FieldElementForLink_ClassField> _fields; |
InterfaceType _supertype; |
InterfaceType _type; |
+ List<TypeParameterElementForLink> _typeParameters; |
List<TypeParameterType> _typeParameterTypes; |
+ List<MethodElementForLink> _methods; |
+ List<InterfaceType> _mixins; |
+ List<InterfaceType> _interfaces; |
- ClassElementForLink_Class(this.enclosingElement, this._unlinkedClass); |
+ ClassElementForLink_Class( |
+ CompilationUnitElementForLink enclosingElement, this._unlinkedClass) |
+ : super(enclosingElement); |
+ |
+ @override |
+ List<PropertyAccessorElement> get accessors { |
+ // TODO(paulberry): implement |
+ return const []; |
+ } |
@override |
List<ConstructorElementForLink> get constructors { |
@@ -239,9 +303,35 @@ class ClassElementForLink_Class extends ClassElementForLink |
} |
@override |
+ List<InterfaceType> get interfaces => _interfaces ??= |
+ _unlinkedClass.interfaces.map(_computeInterfaceType).toList(); |
+ |
+ @override |
bool get isObject => _unlinkedClass.hasNoSupertype; |
@override |
+ LibraryElementForLink get library => enclosingElement.library; |
+ |
+ @override |
+ List<MethodElementForLink> get methods { |
+ if (_methods == null) { |
+ _methods = <MethodElementForLink>[]; |
+ for (UnlinkedExecutable unlinkedExecutable |
+ in _unlinkedClass.executables) { |
+ if (unlinkedExecutable.kind == |
+ UnlinkedExecutableKind.functionOrMethod) { |
+ _methods.add(new MethodElementForLink(this, unlinkedExecutable)); |
+ } |
+ } |
+ } |
+ return _methods; |
+ } |
+ |
+ @override |
+ List<InterfaceType> get mixins => |
+ _mixins ??= _unlinkedClass.mixins.map(_computeInterfaceType).toList(); |
+ |
+ @override |
String get name => _unlinkedClass.name; |
@override |
@@ -249,7 +339,17 @@ class ClassElementForLink_Class extends ClassElementForLink |
if (isObject) { |
return null; |
} |
- return _supertype ??= _computeSupertype(); |
+ return _supertype ??= _computeInterfaceType(_unlinkedClass.supertype); |
+ } |
+ |
+ @override |
+ List<TypeParameterElementForLink> get typeParameters { |
+ if (_typeParameters == null) { |
+ _typeParameters = _unlinkedClass.typeParameters |
+ .map((UnlinkedTypeParam p) => new TypeParameterElementForLink(p)) |
+ .toList(); |
+ } |
+ return _typeParameters; |
} |
/** |
@@ -258,9 +358,8 @@ class ClassElementForLink_Class extends ClassElementForLink |
*/ |
List<TypeParameterType> get typeParameterTypes { |
if (_typeParameterTypes == null) { |
- _typeParameterTypes = _unlinkedClass.typeParameters |
- .map((UnlinkedTypeParam p) => |
- new TypeParameterTypeImpl(new TypeParameterElementForLink(p))) |
+ _typeParameterTypes = typeParameters |
+ .map((TypeParameterElementForLink e) => new TypeParameterTypeImpl(e)) |
.toList(); |
} |
return _typeParameterTypes; |
@@ -310,12 +409,25 @@ class ClassElementForLink_Class extends ClassElementForLink |
for (ConstructorElementForLink constructorElement in constructors) { |
constructorElement.link(linkedUnit); |
} |
+ for (MethodElementForLink methodElement in methods) { |
+ methodElement.link(linkedUnit); |
+ } |
} |
- InterfaceType _computeSupertype() { |
+ @override |
+ void unlink() { |
+ hasBeenInferred = false; |
+ for (MethodElementForLink methodElement in methods) { |
+ methodElement.unlink(); |
+ } |
+ } |
+ |
+ /** |
+ * Convert [typeRef] into an [InterfaceType]. |
+ */ |
+ InterfaceType _computeInterfaceType(EntityRef typeRef) { |
if (_unlinkedClass.supertype != null) { |
- DartType supertype = |
- enclosingElement._resolveTypeRef(_unlinkedClass.supertype, this); |
+ DartType supertype = enclosingElement._resolveTypeRef(typeRef, this); |
if (supertype is InterfaceType) { |
return supertype; |
} |
@@ -323,7 +435,7 @@ class ClassElementForLink_Class extends ClassElementForLink |
// happen in the event of erroneous code) just fall through and pretend |
// the supertype is `Object`. |
} |
- return enclosingElement.enclosingElement._linker.objectType; |
+ return enclosingElement.enclosingElement._linker.typeProvider.objectType; |
} |
} |
@@ -340,7 +452,15 @@ class ClassElementForLink_Enum extends ClassElementForLink { |
InterfaceType _type; |
List<FieldElementForLink_EnumField> _fields; |
- ClassElementForLink_Enum(this._unlinkedEnum); |
+ ClassElementForLink_Enum( |
+ CompilationUnitElementForLink enclosingElement, this._unlinkedEnum) |
+ : super(enclosingElement); |
+ |
+ @override |
+ List<PropertyAccessorElement> get accessors { |
+ // TODO(paulberry): do we need to include synthetic accessors? |
+ return const []; |
+ } |
@override |
List<ConstructorElementForLink> get constructors => const []; |
@@ -361,12 +481,24 @@ class ClassElementForLink_Enum extends ClassElementForLink { |
} |
@override |
+ List<InterfaceType> get interfaces => const []; |
+ |
+ @override |
bool get isObject => false; |
@override |
+ List<MethodElement> get methods => const []; |
+ |
+ @override |
+ List<InterfaceType> get mixins => const []; |
+ |
+ @override |
String get name => _unlinkedEnum.name; |
@override |
+ InterfaceType get supertype => library._linker.typeProvider.objectType; |
+ |
+ @override |
ConstructorElementForLink get unnamedConstructor => null; |
@override |
@@ -376,6 +508,9 @@ class ClassElementForLink_Enum extends ClassElementForLink { |
@override |
void link(LinkedUnitBuilder linkedUnit) {} |
+ |
+ @override |
+ void unlink() {} |
} |
/** |
@@ -396,25 +531,30 @@ abstract class CompilationUnitElementForLink implements CompilationUnitElement { |
final List<ReferenceableElementForLink> _references; |
List<ClassElementForLink_Class> _types; |
+ |
Map<String, ReferenceableElementForLink> _containedNames; |
List<TopLevelVariableElementForLink> _topLevelVariables; |
List<ClassElementForLink_Enum> _enums; |
- @override |
- final LibraryElementForLink enclosingElement; |
+ /** |
+ * Index of this unit in the list of units in the enclosing library. |
+ */ |
+ final int unitNum; |
- CompilationUnitElementForLink( |
- this.enclosingElement, UnlinkedUnit unlinkedUnit) |
+ CompilationUnitElementForLink(UnlinkedUnit unlinkedUnit, this.unitNum) |
: _references = new List<ReferenceableElementForLink>( |
unlinkedUnit.references.length), |
_unlinkedUnit = unlinkedUnit; |
@override |
+ LibraryElementForLink get enclosingElement; |
+ |
+ @override |
List<ClassElementForLink_Enum> get enums { |
if (_enums == null) { |
_enums = <ClassElementForLink_Enum>[]; |
for (UnlinkedEnum unlinkedEnum in _unlinkedUnit.enums) { |
- _enums.add(new ClassElementForLink_Enum(unlinkedEnum)); |
+ _enums.add(new ClassElementForLink_Enum(this, unlinkedEnum)); |
} |
} |
return _enums; |
@@ -427,6 +567,9 @@ abstract class CompilationUnitElementForLink implements CompilationUnitElement { |
bool get isInBuildUnit; |
@override |
+ LibraryElementForLink get library => enclosingElement; |
+ |
+ @override |
List<TopLevelVariableElementForLink> get topLevelVariables { |
if (_topLevelVariables == null) { |
_topLevelVariables = <TopLevelVariableElementForLink>[]; |
@@ -554,18 +697,59 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink { |
@override |
final LinkedUnitBuilder _linkedUnit; |
- CompilationUnitElementInBuildUnit(LibraryElementInBuildUnit libraryElement, |
- UnlinkedUnit unlinkedUnit, this._linkedUnit) |
- : super(libraryElement, unlinkedUnit); |
+ @override |
+ final LibraryElementInBuildUnit enclosingElement; |
+ |
+ CompilationUnitElementInBuildUnit(this.enclosingElement, |
+ UnlinkedUnit unlinkedUnit, this._linkedUnit, int unitNum) |
+ : super(unlinkedUnit, unitNum); |
@override |
bool get isInBuildUnit => true; |
+ @override |
+ LibraryElementInBuildUnit get library => enclosingElement; |
+ |
+ /** |
+ * If this compilation unit already has a reference in its references table |
+ * matching [dependency], [name], [numTypeParameters], and [unitNum], return |
+ * its index. Otherwise add a new reference to table and return its index. |
+ */ |
+ int addReference( |
+ int dependency, String name, int numTypeParameters, int unitNum) { |
+ List<LinkedReferenceBuilder> linkedReferences = _linkedUnit.references; |
+ List<UnlinkedReference> unlinkedReferences = _unlinkedUnit.references; |
+ for (int i = 0; i < linkedReferences.length; i++) { |
+ LinkedReferenceBuilder linkedReference = linkedReferences[i]; |
+ if (linkedReference.dependency == dependency && |
+ (i < unlinkedReferences.length |
+ ? unlinkedReferences[i].name |
+ : linkedReference.name) == |
+ name && |
+ linkedReference.numTypeParameters == numTypeParameters && |
+ linkedReference.unit == unitNum) { |
+ return i; |
+ } |
+ } |
+ int result = linkedReferences.length; |
+ linkedReferences.add(new LinkedReferenceBuilder( |
+ dependency: dependency, |
+ name: name, |
+ numTypeParameters: numTypeParameters, |
+ unit: unitNum)); |
+ return result; |
+ } |
+ |
/** |
* Perform type inference and const cycle detection on this |
* compilation unit. |
*/ |
void link() { |
+ if (library._linker.strongMode) { |
+ new InstanceMemberInferrer(enclosingElement._linker.typeProvider, |
+ enclosingElement.inheritanceManager) |
+ .inferCompilationUnit(this); |
+ } |
for (ClassElementForLink classElement in types) { |
classElement.link(_linkedUnit); |
} |
@@ -578,6 +762,9 @@ class CompilationUnitElementInBuildUnit extends CompilationUnitElementForLink { |
_linkedUnit.constCycles.clear(); |
_linkedUnit.references.length = _unlinkedUnit.references.length; |
_linkedUnit.types.clear(); |
+ for (ClassElementForLink classElement in types) { |
+ classElement.unlink(); |
+ } |
} |
} |
@@ -589,9 +776,12 @@ class CompilationUnitElementInDependency extends CompilationUnitElementForLink { |
@override |
final LinkedUnit _linkedUnit; |
- CompilationUnitElementInDependency(LibraryElementInDependency libraryElement, |
- UnlinkedUnit unlinkedUnit, this._linkedUnit) |
- : super(libraryElement, unlinkedUnit); |
+ @override |
+ final LibraryElementInDependency enclosingElement; |
+ |
+ CompilationUnitElementInDependency(this.enclosingElement, |
+ UnlinkedUnit unlinkedUnit, this._linkedUnit, int unitNum) |
+ : super(unlinkedUnit, unitNum); |
@override |
bool get isInBuildUnit => false; |
@@ -818,7 +1008,7 @@ class ConstParameterNode extends ConstNode { |
* during linking. |
*/ |
class ConstructorElementForLink |
- implements ConstructorElement, ReferenceableElementForLink { |
+ implements ConstructorElementImpl, ReferenceableElementForLink { |
/** |
* The unlinked representation of the constructor in the summary. |
*/ |
@@ -1096,6 +1286,9 @@ class FieldElementForLink_EnumField extends FieldElementForLink |
bool get isStatic => true; |
@override |
+ bool get isSynthetic => false; |
+ |
+ @override |
String get name => |
unlinkedEnumValue == null ? 'values' : unlinkedEnumValue.name; |
@@ -1112,6 +1305,23 @@ class FieldElementForLink_EnumField extends FieldElementForLink |
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
} |
+class FunctionElementForLink_Initializer implements FunctionElementImpl { |
+ @override |
+ DartType get returnType { |
+ // TODO(paulberry): for type inference, compute and return the type of the |
+ // initializer expression. |
+ return DynamicTypeImpl.instance; |
+ } |
+ |
+ @override |
+ void set returnType(DartType newType) { |
+ // TODO(paulberry): store inferred type. |
+ } |
+ |
+ @override |
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
+} |
+ |
/** |
* Element representing a library resynthesied from a summary during |
* linking. The type parameter, [UnitElement], represents the type |
@@ -1134,15 +1344,25 @@ abstract class LibraryElementForLink< |
final Map<String, ReferenceableElementForLink> _containedNames = |
<String, ReferenceableElementForLink>{}; |
final List<LibraryElementForLink> _dependencies = <LibraryElementForLink>[]; |
+ UnlinkedUnit _definingUnlinkedUnit; |
LibraryElementForLink(this._linker, this._absoluteUri) { |
_dependencies.length = _linkedLibrary.dependencies.length; |
} |
+ /** |
+ * Get the [UnlinkedUnit] for the defining compilation unit of this library. |
+ */ |
+ UnlinkedUnit get definingUnlinkedUnit => |
+ _definingUnlinkedUnit ??= _linker.getUnit(_absoluteUri.toString()); |
+ |
+ @override |
+ Element get enclosingElement => null; |
+ |
@override |
List<UnitElement> get units { |
if (_units == null) { |
- UnlinkedUnit definingUnit = _linker.getUnit(_absoluteUri.toString()); |
+ UnlinkedUnit definingUnit = definingUnlinkedUnit; |
_units = <UnitElement>[_makeUnitElement(definingUnit, 0)]; |
int numParts = definingUnit.parts.length; |
for (int i = 0; i < numParts; i++) { |
@@ -1169,7 +1389,7 @@ abstract class LibraryElementForLink< |
* [name]. If no name is found, return the singleton instance of |
* [UndefinedElementForLink]. |
*/ |
- ReferenceableElementForLink getContainedName(name) => |
+ ReferenceableElementForLink getContainedName(String name) => |
_containedNames.putIfAbsent(name, () { |
for (UnitElement unit in units) { |
ReferenceableElementForLink element = unit.getContainedName(name); |
@@ -1207,11 +1427,38 @@ class LibraryElementInBuildUnit |
@override |
final LinkedLibraryBuilder _linkedLibrary; |
+ InheritanceManager _inheritanceManager; |
+ |
LibraryElementInBuildUnit( |
_Linker linker, Uri absoluteUri, this._linkedLibrary) |
: super(linker, absoluteUri); |
/** |
+ * Get the inheritance manager for this library (creating it if necessary). |
+ */ |
+ InheritanceManager get inheritanceManager => |
+ _inheritanceManager ??= new InheritanceManager(this); |
+ |
+ /** |
+ * If this library already has a dependency in its dependencies table matching |
+ * [library], return its index. Otherwise add a new dependency to table and |
+ * return its index. |
+ */ |
+ int addDependency(LibraryElementForLink library) { |
+ for (int i = 0; i < _linkedLibrary.dependencies.length; i++) { |
+ if (identical(_getDependency(i), library)) { |
+ return i; |
+ } |
+ } |
+ int result = _linkedLibrary.dependencies.length; |
+ _linkedLibrary.dependencies.add(new LinkedDependencyBuilder( |
+ parts: library.definingUnlinkedUnit.publicNamespace.parts, |
+ uri: library._absoluteUri.toString())); |
+ _dependencies.add(library); |
+ return result; |
+ } |
+ |
+ /** |
* Perform type inference and const cycle detection on this library. |
*/ |
void link() { |
@@ -1235,7 +1482,7 @@ class LibraryElementInBuildUnit |
CompilationUnitElementInBuildUnit _makeUnitElement( |
UnlinkedUnit unlinkedUnit, int i) => |
new CompilationUnitElementInBuildUnit( |
- this, unlinkedUnit, _linkedLibrary.units[i]); |
+ this, unlinkedUnit, _linkedLibrary.units[i], i); |
} |
/** |
@@ -1255,7 +1502,120 @@ class LibraryElementInDependency |
CompilationUnitElementInDependency _makeUnitElement( |
UnlinkedUnit unlinkedUnit, int i) => |
new CompilationUnitElementInDependency( |
- this, unlinkedUnit, _linkedLibrary.units[i]); |
+ this, unlinkedUnit, _linkedLibrary.units[i], i); |
+} |
+ |
+/** |
+ * Element representing a method resynthesized from a summary during linking. |
+ */ |
+class MethodElementForLink implements MethodElementImpl, TypeParameterContext { |
+ /** |
+ * The unlinked representation of the method in the summary. |
+ */ |
+ final UnlinkedExecutable _unlinkedExecutable; |
+ |
+ DartType _declaredReturnType; |
+ DartType _inferredReturnType; |
+ FunctionTypeImpl _type; |
+ List<TypeParameterElementForLink> _typeParameters; |
+ |
+ @override |
+ final ClassElementForLink_Class enclosingElement; |
+ |
+ MethodElementForLink(this.enclosingElement, this._unlinkedExecutable); |
+ |
+ @override |
+ bool get hasImplicitReturnType => _unlinkedExecutable.returnType == null; |
+ |
+ @override |
+ bool get isStatic => _unlinkedExecutable.isStatic; |
+ |
+ @override |
+ bool get isSynthetic => false; |
+ |
+ @override |
+ ElementKind get kind => ElementKind.METHOD; |
+ |
+ @override |
+ LibraryElementForLink get library => enclosingElement.library; |
+ |
+ @override |
+ String get name => _unlinkedExecutable.name; |
+ |
+ @override |
+ List<ParameterElementForLink> get parameters { |
+ // TODO(paulberry): implement. |
+ return const []; |
+ } |
+ |
+ @override |
+ DartType get returnType { |
+ if (_inferredReturnType != null) { |
+ return _inferredReturnType; |
+ } else if (_declaredReturnType == null) { |
+ if (_unlinkedExecutable.returnType == null) { |
+ _declaredReturnType = DynamicTypeImpl.instance; |
+ } else { |
+ _declaredReturnType = enclosingElement.enclosingElement |
+ ._resolveTypeRef(_unlinkedExecutable.returnType, this); |
+ } |
+ } |
+ return _declaredReturnType; |
+ } |
+ |
+ @override |
+ void set returnType(DartType inferredType) { |
+ assert(_inferredReturnType == null); |
+ _inferredReturnType = inferredType; |
+ } |
+ |
+ @override |
+ FunctionTypeImpl get type => _type ??= new FunctionTypeImpl(this); |
+ |
+ @override |
+ List<TypeParameterElementForLink> get typeParameters { |
+ if (_typeParameters == null) { |
+ _typeParameters = _unlinkedExecutable.typeParameters |
+ .map((UnlinkedTypeParam p) => new TypeParameterElementForLink(p)) |
+ .toList(); |
+ } |
+ return _typeParameters; |
+ } |
+ |
+ @override |
+ TypeParameterType getTypeParameterType(int index) { |
+ // TODO(paulberry): implement. |
+ throw new UnimplementedError(); |
+ } |
+ |
+ @override |
+ bool isAccessibleIn(LibraryElement library) => |
+ !Identifier.isPrivateName(name) || identical(this.library, library); |
+ |
+ /** |
+ * Store the results of type inference for this method in [linkedUnit]. |
+ */ |
+ void link(LinkedUnitBuilder linkedUnit) { |
+ int slot = _unlinkedExecutable.inferredReturnTypeSlot; |
+ if (slot != 0) { |
+ DartType inferredReturnType = returnType; |
+ if (!inferredReturnType.isDynamic) { |
+ linkedUnit.types.add(_createLinkedType( |
+ inferredReturnType, enclosingElement.enclosingElement, |
+ slot: slot)); |
+ } |
+ } |
+ } |
+ |
+ @override |
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
+ |
+ /** |
+ * Throw away any information produced by type inference. |
+ */ |
+ void unlink() { |
+ _inferredReturnType = null; |
+ } |
} |
/** |
@@ -1439,6 +1799,150 @@ class TypeParameterElementForLink implements TypeParameterElement { |
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
} |
+class TypeProviderForLink implements TypeProvider { |
+ final _Linker _linker; |
+ |
+ InterfaceType _boolType; |
+ InterfaceType _deprecatedType; |
+ InterfaceType _doubleType; |
+ InterfaceType _functionType; |
+ InterfaceType _futureDynamicType; |
+ InterfaceType _futureNullType; |
+ InterfaceType _futureType; |
+ InterfaceType _intType; |
+ InterfaceType _iterableDynamicType; |
+ InterfaceType _iterableType; |
+ InterfaceType _listType; |
+ InterfaceType _mapType; |
+ InterfaceType _nullType; |
+ InterfaceType _numType; |
+ InterfaceType _objectType; |
+ InterfaceType _stackTraceType; |
+ InterfaceType _streamDynamicType; |
+ InterfaceType _streamType; |
+ InterfaceType _stringType; |
+ InterfaceType _symbolType; |
+ InterfaceType _typeType; |
+ |
+ TypeProviderForLink(this._linker); |
+ |
+ @override |
+ InterfaceType get boolType => |
+ _boolType ??= _buildInterfaceType(_linker.coreLibrary, 'bool'); |
+ |
+ @override |
+ DartType get bottomType => BottomTypeImpl.instance; |
+ |
+ @override |
+ InterfaceType get deprecatedType => _deprecatedType ??= |
+ _buildInterfaceType(_linker.coreLibrary, 'Deprecated'); |
+ |
+ @override |
+ InterfaceType get doubleType => |
+ _doubleType ??= _buildInterfaceType(_linker.coreLibrary, 'double'); |
+ |
+ @override |
+ DartType get dynamicType => DynamicTypeImpl.instance; |
+ |
+ @override |
+ InterfaceType get functionType => |
+ _functionType ??= _buildInterfaceType(_linker.coreLibrary, 'Function'); |
+ |
+ @override |
+ InterfaceType get futureDynamicType => |
+ _futureDynamicType ??= futureType.instantiate(<DartType>[dynamicType]); |
+ |
+ @override |
+ InterfaceType get futureNullType => |
+ _futureNullType ??= futureType.instantiate(<DartType>[nullType]); |
+ |
+ @override |
+ InterfaceType get futureType => |
+ _futureType ??= _buildInterfaceType(_linker.asyncLibrary, 'Future'); |
+ |
+ @override |
+ InterfaceType get intType => |
+ _intType ??= _buildInterfaceType(_linker.coreLibrary, 'int'); |
+ |
+ @override |
+ InterfaceType get iterableDynamicType => _iterableDynamicType ??= |
+ iterableType.instantiate(<DartType>[dynamicType]); |
+ |
+ @override |
+ InterfaceType get iterableType => |
+ _iterableType ??= _buildInterfaceType(_linker.coreLibrary, 'Iterable'); |
+ |
+ @override |
+ InterfaceType get listType => |
+ _listType ??= _buildInterfaceType(_linker.coreLibrary, 'List'); |
+ |
+ @override |
+ InterfaceType get mapType => |
+ _mapType ??= _buildInterfaceType(_linker.coreLibrary, 'Map'); |
+ |
+ @override |
+ List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[ |
+ nullType, |
+ numType, |
+ intType, |
+ doubleType, |
+ boolType, |
+ stringType |
+ ]; |
+ |
+ @override |
+ DartObjectImpl get nullObject { |
+ // TODO(paulberry): implement if needed |
+ throw new UnimplementedError(); |
+ } |
+ |
+ @override |
+ InterfaceType get nullType => |
+ _nullType ??= _buildInterfaceType(_linker.coreLibrary, 'Null'); |
+ |
+ @override |
+ InterfaceType get numType => |
+ _numType ??= _buildInterfaceType(_linker.coreLibrary, 'num'); |
+ |
+ @override |
+ InterfaceType get objectType => |
+ _objectType ??= _buildInterfaceType(_linker.coreLibrary, 'Object'); |
+ |
+ @override |
+ InterfaceType get stackTraceType => _stackTraceType ??= |
+ _buildInterfaceType(_linker.coreLibrary, 'StackTrace'); |
+ |
+ @override |
+ InterfaceType get streamDynamicType => |
+ _streamDynamicType ??= streamType.instantiate(<DartType>[dynamicType]); |
+ |
+ @override |
+ InterfaceType get streamType => |
+ _streamType ??= _buildInterfaceType(_linker.asyncLibrary, 'Stream'); |
+ |
+ @override |
+ InterfaceType get stringType => |
+ _stringType ??= _buildInterfaceType(_linker.coreLibrary, 'String'); |
+ |
+ @override |
+ InterfaceType get symbolType => |
+ _symbolType ??= _buildInterfaceType(_linker.coreLibrary, 'Symbol'); |
+ |
+ @override |
+ InterfaceType get typeType => |
+ _typeType ??= _buildInterfaceType(_linker.coreLibrary, 'Type'); |
+ |
+ @override |
+ DartType get undefinedType => UndefinedTypeImpl.instance; |
+ |
+ InterfaceType _buildInterfaceType( |
+ LibraryElementForLink library, String name) { |
+ return library |
+ .getContainedName(name) |
+ .buildType((int i) => DynamicTypeImpl.instance, const []); |
+ } |
+} |
+ |
/** |
* Singleton element used for unresolved references. |
*/ |
@@ -1468,7 +1972,7 @@ class UndefinedElementForLink implements ReferenceableElementForLink { |
* summary during linking. |
*/ |
class VariableElementForLink |
- implements VariableElement, ReferenceableElementForLink { |
+ implements VariableElementImpl, ReferenceableElementForLink { |
/** |
* The unlinked representation of the variable in the summary. |
*/ |
@@ -1481,6 +1985,8 @@ class VariableElementForLink |
*/ |
ConstNode _constNode; |
+ FunctionElementForLink_Initializer _initializer; |
+ |
/** |
* The compilation unit in which this variable appears. |
*/ |
@@ -1499,6 +2005,13 @@ class VariableElementForLink |
ConstVariableNode get asConstVariable => _constNode; |
@override |
+ bool get hasImplicitType => unlinkedVariable.type != null; |
+ |
+ @override |
+ FunctionElementForLink_Initializer get initializer => |
+ _initializer ??= new FunctionElementForLink_Initializer(); |
+ |
+ @override |
bool get isConst => unlinkedVariable.isConst; |
@override |
@@ -1508,9 +2021,17 @@ class VariableElementForLink |
bool get isStatic; |
@override |
+ bool get isSynthetic => false; |
+ |
+ @override |
String get name => unlinkedVariable.name; |
@override |
+ void set type(DartType newType) { |
+ // TODO(paulberry): store inferred type. |
+ } |
+ |
+ @override |
DartType buildType(DartType getTypeArgument(int i), |
List<int> implicitFunctionTypeIndices) => |
DynamicTypeImpl.instance; |
@@ -1554,11 +2075,17 @@ class _Linker { |
final List<LibraryElementInBuildUnit> _librariesInBuildUnit = |
<LibraryElementInBuildUnit>[]; |
- InterfaceType _objectType; |
+ /** |
+ * Indicates whether type inference should use strong mode rules. |
+ */ |
+ final bool strongMode; |
+ |
LibraryElementForLink _coreLibrary; |
+ LibraryElementForLink _asyncLibrary; |
+ TypeProviderForLink _typeProvider; |
_Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency, |
- this.getUnit) { |
+ this.getUnit, this.strongMode) { |
// Create elements for the libraries to be linked. The rest of |
// the element model will be created on demand. |
linkedLibraries |
@@ -1570,17 +2097,22 @@ class _Linker { |
} |
/** |
+ * Get the library element for `dart:async`. |
+ */ |
+ LibraryElementForLink get asyncLibrary => |
+ _asyncLibrary ??= getLibrary(Uri.parse('dart:async')); |
+ |
+ /** |
* Get the library element for `dart:core`. |
*/ |
LibraryElementForLink get coreLibrary => |
_coreLibrary ??= getLibrary(Uri.parse('dart:core')); |
/** |
- * Get the `InterfaceType` for the type `Object`. |
+ * Get an instance of [TypeProvider] for use during linking. |
*/ |
- InterfaceType get objectType => _objectType ??= coreLibrary |
- .getContainedName('Object') |
- .buildType((int i) => DynamicTypeImpl.instance, const []); |
+ TypeProviderForLink get typeProvider => |
+ _typeProvider ??= new TypeProviderForLink(this); |
/** |
* Get the library element for the library having the given [uri]. |
@@ -1595,6 +2127,7 @@ class _Linker { |
* in the build unit being linked. |
*/ |
void link() { |
+ // TODO(paulberry): link library cycles in appropriate dependency order. |
for (LibraryElementInBuildUnit library in _librariesInBuildUnit) { |
library.link(); |
} |