From d2a1bdff4a2b53ef627152fda9f720e754ce7def Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Wed, 12 Apr 2017 09:35:53 -0700 Subject: [PATCH] Pass ElementImpl as a context for resynthesizing types. We need to do this in order to associate resynthesized GenericFunctionTypeElementImpl instances with these enclosing ElementImpl instances. The same enclosing ElementImpl can also be used to get the TypeParameterizedElementMixin for accessing type parameters. R=brianwilkerson@google.com, paulberry@google.com BUG= Review-Url: https://codereview.chromium.org/2813543007 . --- .../lib/src/dart/element/element.dart | 69 ++++++++--------- pkg/analyzer/lib/src/summary/link.dart | 41 ++++++---- .../lib/src/summary/resynthesize.dart | 57 ++++++-------- .../test/src/summary/resynthesize_common.dart | 76 +++++++++++++++++++ 4 files changed, 155 insertions(+), 88 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index f5b2df67ad4..fadc2e2efbb 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -724,7 +724,7 @@ class ClassElementImpl extends AbstractClassElementImpl if (_unlinkedClass != null && _interfaces == null) { ResynthesizerContext context = enclosingUnit.resynthesizerContext; _interfaces = _unlinkedClass.interfaces - .map((EntityRef t) => context.resolveTypeRef(t, this)) + .map((EntityRef t) => context.resolveTypeRef(this, t)) .where(_isClassInterfaceType) .toList(growable: false); } @@ -831,7 +831,7 @@ class ClassElementImpl extends AbstractClassElementImpl if (_unlinkedClass != null && _mixins == null) { ResynthesizerContext context = enclosingUnit.resynthesizerContext; _mixins = _unlinkedClass.mixins - .map((EntityRef t) => context.resolveTypeRef(t, this)) + .map((EntityRef t) => context.resolveTypeRef(this, t)) .where(_isClassInterfaceType) .toList(growable: false); } @@ -865,7 +865,7 @@ class ClassElementImpl extends AbstractClassElementImpl if (_unlinkedClass != null && _supertype == null) { if (_unlinkedClass.supertype != null) { DartType type = enclosingUnit.resynthesizerContext - .resolveTypeRef(_unlinkedClass.supertype, this); + .resolveTypeRef(this, _unlinkedClass.supertype); if (_isClassInterfaceType(type)) { _supertype = type; } else { @@ -3879,10 +3879,10 @@ abstract class ExecutableElementImpl extends ElementImpl _returnType == null) { bool isSetter = serializedExecutable.kind == UnlinkedExecutableKind.setter; - _returnType = enclosingUnit.resynthesizerContext.resolveLinkedType( - serializedExecutable.inferredReturnTypeSlot, typeParameterContext); + _returnType = enclosingUnit.resynthesizerContext + .resolveLinkedType(this, serializedExecutable.inferredReturnTypeSlot); _declaredReturnType = enclosingUnit.resynthesizerContext.resolveTypeRef( - serializedExecutable.returnType, typeParameterContext, + this, serializedExecutable.returnType, defaultVoid: isSetter && context.analysisOptions.strongMode, declaredType: true); } @@ -4572,7 +4572,7 @@ class FunctionElementImpl_forLUB extends FunctionElementImpl { @override DartType get returnType { return _returnType ??= enclosingUnit.resynthesizerContext - .resolveTypeRef(_entityRef.syntheticReturnType, typeParameterContext); + .resolveTypeRef(this, _entityRef.syntheticReturnType); } @override @@ -4736,7 +4736,7 @@ class FunctionTypeAliasElementImpl extends ElementImpl DartType get returnType { if (_unlinkedTypedef != null && _returnType == null) { _returnType = enclosingUnit.resynthesizerContext.resolveTypeRef( - _unlinkedTypedef.returnType, this, + this, _unlinkedTypedef.returnType, declaredType: true); } return _returnType; @@ -4858,11 +4858,6 @@ class GenericFunctionTypeElementImpl extends ElementImpl */ EntityRef _entityRef; - /** - * The enclosing type parameter context. - */ - TypeParameterizedElementMixin _typeParameterContext; - /** * The declared return type of the function. */ @@ -4889,13 +4884,13 @@ class GenericFunctionTypeElementImpl extends ElementImpl * Initialize from serialized information. */ GenericFunctionTypeElementImpl.forSerialized( - this._entityRef, this._typeParameterContext) - : super.forSerialized(null); + ElementImpl enclosingElement, this._entityRef) + : super.forSerialized(enclosingElement); @override - TypeParameterizedElementMixin get enclosingTypeParameterContext => - _typeParameterContext ?? - (enclosingElement as ElementImpl).typeParameterContext; + TypeParameterizedElementMixin get enclosingTypeParameterContext { + return _enclosingElement.typeParameterContext; + } @override String get identifier => '-'; @@ -4928,7 +4923,7 @@ class GenericFunctionTypeElementImpl extends ElementImpl DartType get returnType { if (_entityRef != null && _returnType == null) { _returnType = enclosingUnit.resynthesizerContext.resolveTypeRef( - _entityRef.syntheticReturnType, typeParameterContext, + this, _entityRef.syntheticReturnType, defaultVoid: false, declaredType: true); } return _returnType; @@ -5102,7 +5097,7 @@ class GenericTypeAliasElementImpl extends ElementImpl GenericFunctionTypeElement get function { if (_function == null && _unlinkedTypedef != null) { DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef( - _unlinkedTypedef.returnType, this, + this, _unlinkedTypedef.returnType, declaredType: true); if (type is FunctionType) { Element element = type.element; @@ -7280,11 +7275,10 @@ abstract class NonParameterVariableElementImpl extends VariableElementImpl { @override DartType get type { if (_unlinkedVariable != null && _declaredType == null && _type == null) { - _type = enclosingUnit.resynthesizerContext.resolveLinkedType( - _unlinkedVariable.inferredTypeSlot, typeParameterContext); - declaredType = enclosingUnit.resynthesizerContext.resolveTypeRef( - _unlinkedVariable.type, typeParameterContext, - declaredType: true); + _type = enclosingUnit.resynthesizerContext + .resolveLinkedType(this, _unlinkedVariable.inferredTypeSlot); + declaredType = enclosingUnit.resynthesizerContext + .resolveTypeRef(this, _unlinkedVariable.type, declaredType: true); } return super.type; } @@ -7786,18 +7780,17 @@ class ParameterElementImpl extends VariableElementImpl parameterTypeElement.shareParameters(subParameters); } parameterTypeElement.returnType = enclosingUnit.resynthesizerContext - .resolveTypeRef(_unlinkedParam.type, typeParameterContext); + .resolveTypeRef(this, _unlinkedParam.type); FunctionTypeImpl parameterType = new FunctionTypeImpl.elementWithNameAndArgs(parameterTypeElement, null, typeParameterContext.allTypeParameterTypes, false); parameterTypeElement.type = parameterType; _type = parameterType; } else { - _type = enclosingUnit.resynthesizerContext.resolveLinkedType( - _unlinkedParam.inferredTypeSlot, typeParameterContext); - declaredType = enclosingUnit.resynthesizerContext.resolveTypeRef( - _unlinkedParam.type, typeParameterContext, - declaredType: true); + _type = enclosingUnit.resynthesizerContext + .resolveLinkedType(this, _unlinkedParam.inferredTypeSlot); + declaredType = enclosingUnit.resynthesizerContext + .resolveTypeRef(this, _unlinkedParam.type, declaredType: true); } } } @@ -8294,8 +8287,8 @@ abstract class PropertyInducingElementImpl @override DartType get propagatedType { if (_unlinkedVariable != null && _propagatedType == null) { - _propagatedType = enclosingUnit.resynthesizerContext.resolveLinkedType( - _unlinkedVariable.propagatedTypeSlot, typeParameterContext); + _propagatedType = enclosingUnit.resynthesizerContext + .resolveLinkedType(this, _unlinkedVariable.propagatedTypeSlot); } return _propagatedType; } @@ -8370,14 +8363,13 @@ abstract class ResynthesizerContext { * unresolved, return `null`. */ ConstructorElement resolveConstructorRef( - TypeParameterizedElementMixin typeParameterContext, EntityRef entry); + ElementImpl context, EntityRef entry); /** * Build the appropriate [DartType] object corresponding to a slot id in the * [LinkedUnit.types] table. */ - DartType resolveLinkedType( - int slot, TypeParameterizedElementMixin typeParameterContext); + DartType resolveLinkedType(ElementImpl context, int slot); /** * Resolve an [EntityRef] into a type. If the reference is @@ -8386,8 +8378,7 @@ abstract class ResynthesizerContext { * TODO(paulberry): or should we have a class representing an * unresolved type, for consistency with the full element model? */ - DartType resolveTypeRef( - EntityRef type, TypeParameterizedElementMixin typeParameterContext, + DartType resolveTypeRef(ElementImpl context, EntityRef type, {bool defaultVoid: false, bool instantiateToBoundsAllowed: true, bool declaredType: false}); @@ -8589,7 +8580,7 @@ class TypeParameterElementImpl extends ElementImpl return null; } return _bound ??= enclosingUnit.resynthesizerContext.resolveTypeRef( - _unlinkedTypeParam.bound, enclosingElement, + this, _unlinkedTypeParam.bound, instantiateToBoundsAllowed: false, declaredType: true); } return _bound; diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart index 3a674d4b9ee..b7f77030f27 100644 --- a/pkg/analyzer/lib/src/summary/link.dart +++ b/pkg/analyzer/lib/src/summary/link.dart @@ -683,7 +683,7 @@ class ClassElementForLink_Class extends ClassElementForLink */ InterfaceType _computeInterfaceType(EntityRef typeRef) { if (typeRef != null) { - DartType type = enclosingElement.resolveTypeRef(typeRef, this); + DartType type = enclosingElement.resolveTypeRef(this, typeRef); if (type is InterfaceType && !type.element.isEnum) { return type; } @@ -1076,8 +1076,7 @@ abstract class CompilationUnitElementForLink } @override - DartType resolveTypeRef( - EntityRef type, TypeParameterizedElementMixin typeParameterContext, + DartType resolveTypeRef(ElementImpl context, EntityRef type, {bool defaultVoid: false, bool instantiateToBoundsAllowed: true, bool declaredType: false}) { @@ -1089,7 +1088,8 @@ abstract class CompilationUnitElementForLink } } if (type.paramReference != 0) { - return typeParameterContext.getTypeParameterType(type.paramReference); + return context.typeParameterContext + .getTypeParameterType(type.paramReference); } else if (type.syntheticReturnType != null) { // TODO(paulberry): implement. throw new UnimplementedError(); @@ -1099,7 +1099,7 @@ abstract class CompilationUnitElementForLink } else { DartType getTypeArgument(int i) { if (i < type.typeArguments.length) { - return resolveTypeRef(type.typeArguments[i], typeParameterContext); + return resolveTypeRef(context, type.typeArguments[i]); } else if (!instantiateToBoundsAllowed) { // Do not allow buildType to instantiate the bounds; force dynamic. return DynamicTypeImpl.instance; @@ -1409,7 +1409,7 @@ class CompilationUnitElementInDependency extends CompilationUnitElementForLink { DartType getLinkedType( int slot, TypeParameterizedElementMixin typeParameterContext) { if (slot < _linkedTypeRefs.length) { - return resolveTypeRef(_linkedTypeRefs[slot], typeParameterContext); + return resolveTypeRef(this, _linkedTypeRefs[slot]); } else { return DynamicTypeImpl.instance; } @@ -1832,7 +1832,7 @@ abstract class ExecutableElementForLink extends Object return null; } else { return _declaredReturnType ??= - compilationUnit.resolveTypeRef(_unlinkedExecutable.returnType, this); + compilationUnit.resolveTypeRef(this, _unlinkedExecutable.returnType); } } @@ -2327,8 +2327,7 @@ class ExprTypeComputer { if (ref.typeArguments.isNotEmpty) { return constructorElement.enclosingClass.buildType((int i) { if (i < ref.typeArguments.length) { - return unit.resolveTypeRef( - ref.typeArguments[i], function.typeParameterContext); + return unit.resolveTypeRef(function, ref.typeArguments[i]); } else { return null; } @@ -2528,7 +2527,7 @@ class ExprTypeComputer { DartType _getNextTypeRef() { EntityRef ref = _getNextRef(); - return unit.resolveTypeRef(ref, function.typeParameterContext); + return unit.resolveTypeRef(function, ref); } List _getTypeArguments() { @@ -2885,7 +2884,7 @@ class FunctionElementForLink_FunctionTypedParam extends Object _returnType = DynamicTypeImpl.instance; } else { _returnType = enclosingElement.compilationUnit.resolveTypeRef( - enclosingElement._unlinkedParam.type, typeParameterContext); + enclosingElement, enclosingElement._unlinkedParam.type); } } return _returnType; @@ -3200,7 +3199,7 @@ class FunctionTypeAliasElementForLink extends Object @override DartType get returnType => _returnType ??= - enclosingElement.resolveTypeRef(_unlinkedTypedef.returnType, this); + enclosingElement.resolveTypeRef(this, _unlinkedTypedef.returnType); @override TypeParameterizedElementMixin get typeParameterContext => this; @@ -4199,8 +4198,8 @@ class ParameterElementForLink implements ParameterElementImpl { _declaredType = DynamicTypeImpl.instance; } } else { - _declaredType = compilationUnit.resolveTypeRef( - _unlinkedParam.type, _typeParameterContext); + _declaredType = + compilationUnit.resolveTypeRef(this, _unlinkedParam.type); } } return _declaredType; @@ -4212,6 +4211,11 @@ class ParameterElementForLink implements ParameterElementImpl { _inferredType = inferredType; } + @override + TypeParameterizedElementMixin get typeParameterContext { + return _typeParameterContext; + } + /** * Store the results of type inference for this parameter in * [compilationUnit]. @@ -5186,8 +5190,8 @@ abstract class VariableElementForLink if (unlinkedVariable.type == null) { return null; } else { - return _declaredType ??= compilationUnit.resolveTypeRef( - unlinkedVariable.type, _typeParameterContext); + return _declaredType ??= + compilationUnit.resolveTypeRef(this, unlinkedVariable.type); } } @@ -5285,6 +5289,11 @@ abstract class VariableElementForLink // TODO(paulberry): store inferred type. } + @override + TypeParameterizedElementMixin get typeParameterContext { + return _typeParameterContext; + } + /** * The context in which type parameters should be interpreted, or `null` if * there are no type parameters in scope. diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart index 32ce287f805..234f46a3550 100644 --- a/pkg/analyzer/lib/src/summary/resynthesize.dart +++ b/pkg/analyzer/lib/src/summary/resynthesize.dart @@ -594,8 +594,7 @@ class _ConstExprBuilder { */ TypeAnnotation _newTypeName() { EntityRef typeRef = uc.references[refPtr++]; - DartType type = - resynthesizer.buildType(typeRef, context?.typeParameterContext); + DartType type = resynthesizer.buildType(context, typeRef); return _buildTypeAst(type); } @@ -643,7 +642,7 @@ class _ConstExprBuilder { return; } InterfaceType definingType = resynthesizer._createConstructorDefiningType( - context?.typeParameterContext, info, ref.typeArguments); + context, info, ref.typeArguments); constructorElement = resynthesizer._getConstructorForInfo(definingType, info); typeNode = _buildTypeAst(definingType); @@ -1439,24 +1438,21 @@ class _ResynthesizerContext implements ResynthesizerContext { @override ConstructorElement resolveConstructorRef( - TypeParameterizedElementMixin typeParameterContext, EntityRef entry) { - return _unitResynthesizer._getConstructorForEntry( - typeParameterContext, entry); + ElementImpl context, EntityRef entry) { + return _unitResynthesizer._getConstructorForEntry(context, entry); } @override - DartType resolveLinkedType( - int slot, TypeParameterizedElementMixin typeParameterContext) { - return _unitResynthesizer.buildLinkedType(slot, typeParameterContext); + DartType resolveLinkedType(ElementImpl context, int slot) { + return _unitResynthesizer.buildLinkedType(context, slot); } @override - DartType resolveTypeRef( - EntityRef type, TypeParameterizedElementMixin typeParameterContext, + DartType resolveTypeRef(ElementImpl context, EntityRef type, {bool defaultVoid: false, bool instantiateToBoundsAllowed: true, bool declaredType: false}) { - return _unitResynthesizer.buildType(type, typeParameterContext, + return _unitResynthesizer.buildType(context, type, defaultVoid: defaultVoid, instantiateToBoundsAllowed: instantiateToBoundsAllowed, declaredType: declaredType); @@ -1625,8 +1621,7 @@ class _UnitResynthesizer { * Build the appropriate [DartType] object corresponding to a slot id in the * [LinkedUnit.types] table. */ - DartType buildLinkedType( - int slot, TypeParameterizedElementMixin typeParameterContext) { + DartType buildLinkedType(ElementImpl context, int slot) { if (slot == 0) { // A slot id of 0 means there is no [DartType] object to build. return null; @@ -1637,7 +1632,7 @@ class _UnitResynthesizer { // stored in this slot. return null; } - return buildType(type, typeParameterContext); + return buildType(context, type); } /** @@ -1646,8 +1641,7 @@ class _UnitResynthesizer { * deserialized, so handles are used to avoid having to deserialize other * libraries in the process. */ - DartType buildType( - EntityRef type, TypeParameterizedElementMixin typeParameterContext, + DartType buildType(ElementImpl context, EntityRef type, {bool defaultVoid: false, bool instantiateToBoundsAllowed: true, bool declaredType: false}) { @@ -1659,20 +1653,20 @@ class _UnitResynthesizer { } } if (type.paramReference != 0) { - return typeParameterContext.getTypeParameterType(type.paramReference); + return context.typeParameterContext + .getTypeParameterType(type.paramReference); } else if (type.entityKind == EntityRefKind.genericFunctionType) { GenericFunctionTypeElement element = - new GenericFunctionTypeElementImpl.forSerialized( - type, typeParameterContext); + new GenericFunctionTypeElementImpl.forSerialized(context, type); return element.type; } else if (type.syntheticReturnType != null) { - FunctionElementImpl element = - new FunctionElementImpl_forLUB(unit, typeParameterContext, type); + FunctionElementImpl element = new FunctionElementImpl_forLUB( + unit, context.typeParameterContext, type); return element.type; } else { DartType getTypeArgument(int i) { if (i < type.typeArguments.length) { - return buildType(type.typeArguments[i], typeParameterContext, + return buildType(context, type.typeArguments[i], declaredType: declaredType); } else { return DynamicTypeImpl.instance; @@ -1929,18 +1923,15 @@ class _UnitResynthesizer { * [typeArgumentRefs] to the given linked [info]. Return [DynamicTypeImpl] * if the [info] is unresolved. */ - DartType _createConstructorDefiningType( - TypeParameterizedElementMixin typeParameterContext, - _ReferenceInfo info, - List typeArgumentRefs) { + DartType _createConstructorDefiningType(ElementImpl context, + _ReferenceInfo info, List typeArgumentRefs) { bool isClass = info.element is ClassElement; _ReferenceInfo classInfo = isClass ? info : info.enclosing; if (classInfo == null) { return DynamicTypeImpl.instance; } - List typeArguments = typeArgumentRefs - .map((t) => buildType(t, typeParameterContext)) - .toList(); + List typeArguments = + typeArgumentRefs.map((t) => buildType(context, t)).toList(); return classInfo.buildType(true, typeArguments.length, (i) { if (i < typeArguments.length) { return typeArguments[i]; @@ -1954,10 +1945,10 @@ class _UnitResynthesizer { * Return the [ConstructorElement] corresponding to the given [entry]. */ ConstructorElement _getConstructorForEntry( - TypeParameterizedElementMixin typeParameterContext, EntityRef entry) { + ElementImpl context, EntityRef entry) { _ReferenceInfo info = getReferenceInfo(entry.reference); - DartType type = _createConstructorDefiningType( - typeParameterContext, info, entry.typeArguments); + DartType type = + _createConstructorDefiningType(context, info, entry.typeArguments); if (type is InterfaceType) { return _getConstructorForInfo(type, info); } diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart index 748deea1f0e..aee2ada2824 100644 --- a/pkg/analyzer/test/src/summary/resynthesize_common.dart +++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart @@ -8549,6 +8549,82 @@ class C { } } + test_genericFunction_asFunctionReturnType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +int Function(int a, String b) f() => null; +'''); + checkElementText( + library, + r''' +(int, String) → int f() {} +'''); + } + + test_genericFunction_asFunctionTypedParameterReturnType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +void f(int Function(int a, String b) p(num c)) => null; +'''); + checkElementText( + library, + r''' +void f((num) → (int, String) → int p) {} +'''); + } + + test_genericFunction_asGenericFunctionReturnType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +typedef F = void Function(String a) Function(int b); +'''); + checkElementText( + library, + r''' +typedef F = (String) → void Function(int b); +'''); + } + + test_genericFunction_asMethodReturnType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +class C { + int Function(int a, String b) m() => null; +} +'''); + checkElementText( + library, + r''' +class C { + (int, String) → int m() {} +} +'''); + } + + test_genericFunction_asParameterType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +void f(int Function(int a, String b) p) => null; +'''); + checkElementText( + library, + r''' +void f((int, String) → int p) {} +'''); + } + + test_genericFunction_asTopLevelVariableType() { + shouldCompareLibraryElements = false; + var library = checkLibrary(r''' +int Function(int a, String b) v; +'''); + checkElementText( + library, + r''' +(int, String) → int v; +'''); + } + test_getElement_constructor_named() { String text = 'class C { C.named(); }'; Source source = addLibrarySource('/test.dart', text);