diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index f3c39fc99d9..85e699d837c 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart @@ -1060,31 +1060,6 @@ class ClassElementImpl extends AbstractClassElementImpl return _type; } - @override - List get typeParameters { - if (_typeParameterElements != null) return _typeParameterElements; - - if (linkedNode != null) { - var context = enclosingUnit.linkedContext; - var containerRef = reference.getChild('@typeParameter'); - var typeParameters = context.getTypeParameters2(linkedNode); - if (typeParameters == null) { - return _typeParameterElements = const []; - } - return _typeParameterElements = typeParameters.typeParameters.map((node) { - var name = node.name.name; - var reference = containerRef.getChild(name); - if (reference.element == null) { - reference.node2 = node; - TypeParameterElementImpl.forLinkedNode(this, reference, node); - } - return reference.element as TypeParameterElementImpl; - }).toList(); - } - - return super.typeParameters; - } - /// Set the type parameters defined for this class to the given /// [typeParameters]. void set typeParameters(List typeParameters) { @@ -9243,7 +9218,8 @@ class TypeParameterElementImpl extends ElementImpl @override String get name { if (linkedNode != null) { - return reference.name; + TypeParameter node = this.linkedNode; + return node.name.name; } if (_unlinkedTypeParam != null) { return _unlinkedTypeParam.name; @@ -9317,20 +9293,14 @@ mixin TypeParameterizedElementMixin if (_typeParameterElements != null) return _typeParameterElements; if (linkedNode != null) { - var context = enclosingUnit.linkedContext; - var containerRef = reference.getChild('@typeParameter'); - var typeParameters = context.getTypeParameters2(linkedNode); + var typeParameters = linkedContext.getTypeParameters2(linkedNode); if (typeParameters == null) { return _typeParameterElements = const []; } return _typeParameterElements = typeParameters.typeParameters.map((node) { - var name = node.name.name; - var reference = containerRef.getChild(name); - if (reference.element == null) { - reference.node2 = node; - TypeParameterElementImpl.forLinkedNode(this, reference, node); - } - return reference.element as TypeParameterElementImpl; + TypeParameterElementImpl element = node.declaredElement; + element.enclosingElement = this; + return element; }).toList(); } diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart index b3fd95fdcff..dbf57f9a8b2 100644 --- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart +++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart @@ -8,6 +8,37 @@ import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_visitor.dart'; +/// Generates a fresh copy of the given type parameters, with their bounds +/// substituted to reference the new parameters. +/// +/// The returned object contains the fresh type parameter list as well as a +/// mapping to be used for replacing other types to use the new type parameters. +FreshTypeParameters getFreshTypeParameters( + List typeParameters) { + var freshParameters = new List.generate( + typeParameters.length, + (i) => new TypeParameterElementImpl(typeParameters[i].name, -1), + growable: true, + ); + + var map = {}; + for (int i = 0; i < typeParameters.length; ++i) { + map[typeParameters[i]] = new TypeParameterTypeImpl(freshParameters[i]); + } + + var substitution = Substitution.fromMap(map); + + for (int i = 0; i < typeParameters.length; ++i) { + var bound = typeParameters[i].bound; + if (bound != null) { + var newBound = substitution.substituteType(bound); + freshParameters[i].bound = newBound; + } + } + + return new FreshTypeParameters(freshParameters, substitution); +} + /// Returns a type where all occurrences of the given type parameters have been /// replaced with the corresponding types. /// @@ -27,6 +58,30 @@ DartType substitute( return Substitution.fromMap(substitution).substituteType(type); } +class FreshTypeParameters { + final List freshTypeParameters; + final Substitution substitution; + + FreshTypeParameters(this.freshTypeParameters, this.substitution); + + FunctionType applyToFunctionType(FunctionType type) { + return new FunctionTypeImpl.synthetic( + substitute(type.returnType), + freshTypeParameters, + type.parameters.map((parameter) { + return ParameterElementImpl.synthetic( + parameter.name, + substitute(parameter.type), + // ignore: deprecated_member_use_from_same_package + parameter.parameterKind, + ); + }).toList(), + ); + } + + DartType substitute(DartType type) => substitution.substituteType(type); +} + abstract class Substitution { static const Substitution empty = _NullSubstitution.instance; diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart index fd78d947488..e3d8d322104 100644 --- a/pkg/analyzer/lib/src/summary/format.dart +++ b/pkg/analyzer/lib/src/summary/format.dart @@ -8174,6 +8174,12 @@ class LinkedNodeBuilder extends Object return _variantField_16 ??= 0; } + @override + int get typeParameter_id { + assert(kind == idl.LinkedNodeKind.typeParameter); + return _variantField_16 ??= 0; + } + @override int get typeParameterList_rightBracket { assert(kind == idl.LinkedNodeKind.typeParameterList); @@ -8508,6 +8514,12 @@ class LinkedNodeBuilder extends Object _variantField_16 = value; } + set typeParameter_id(int value) { + assert(kind == idl.LinkedNodeKind.typeParameter); + assert(value == null || value >= 0); + _variantField_16 = value; + } + set typeParameterList_rightBracket(int value) { assert(kind == idl.LinkedNodeKind.typeParameterList); assert(value == null || value >= 0); @@ -10649,6 +10661,7 @@ class LinkedNodeBuilder extends Object LinkedNodeBuilder typeParameter_bound, int typeParameter_extendsKeyword, LinkedNodeBuilder typeParameter_name, + int typeParameter_id, int codeLength, int codeOffset, }) : _kind = idl.LinkedNodeKind.typeParameter, @@ -10657,6 +10670,7 @@ class LinkedNodeBuilder extends Object _variantField_6 = typeParameter_bound, _variantField_15 = typeParameter_extendsKeyword, _variantField_7 = typeParameter_name, + _variantField_16 = typeParameter_id, _variantField_34 = codeLength, _variantField_33 = codeOffset; @@ -14399,6 +14413,14 @@ class _LinkedNodeImpl extends Object return _variantField_16; } + @override + int get typeParameter_id { + assert(kind == idl.LinkedNodeKind.typeParameter); + _variantField_16 ??= + const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0); + return _variantField_16; + } + @override int get typeParameterList_rightBracket { assert(kind == idl.LinkedNodeKind.typeParameterList); @@ -16265,6 +16287,7 @@ abstract class _LinkedNodeMixin implements idl.LinkedNode { _result["typeParameter_extendsKeyword"] = typeParameter_extendsKeyword; if (typeParameter_name != null) _result["typeParameter_name"] = typeParameter_name.toJson(); + if (typeParameter_id != 0) _result["typeParameter_id"] = typeParameter_id; if (codeLength != 0) _result["codeLength"] = codeLength; if (codeOffset != 0) _result["codeOffset"] = codeOffset; } @@ -17689,6 +17712,7 @@ abstract class _LinkedNodeMixin implements idl.LinkedNode { "typeParameter_bound": typeParameter_bound, "typeParameter_extendsKeyword": typeParameter_extendsKeyword, "typeParameter_name": typeParameter_name, + "typeParameter_id": typeParameter_id, "codeLength": codeLength, "codeOffset": codeOffset, "isSynthetic": isSynthetic, @@ -18891,13 +18915,13 @@ class LinkedNodeTypeBuilder extends Object implements idl.LinkedNodeType { List _functionFormalParameters; LinkedNodeTypeBuilder _functionReturnType; - List _functionTypeParameters; + List _functionTypeParameters; int _genericTypeAliasReference; List _genericTypeAliasTypeArguments; int _interfaceClass; List _interfaceTypeArguments; idl.LinkedNodeTypeKind _kind; - int _typeParameterParameter; + int _typeParameterId; @override List get functionFormalParameters => @@ -18916,11 +18940,10 @@ class LinkedNodeTypeBuilder extends Object } @override - List get functionTypeParameters => _functionTypeParameters ??= []; + List get functionTypeParameters => + _functionTypeParameters ??= []; - /// References to [LinkedNodeReferences]. - set functionTypeParameters(List value) { - assert(value == null || value.every((e) => e >= 0)); + set functionTypeParameters(List value) { this._functionTypeParameters = value; } @@ -18965,24 +18988,23 @@ class LinkedNodeTypeBuilder extends Object } @override - int get typeParameterParameter => _typeParameterParameter ??= 0; + int get typeParameterId => _typeParameterId ??= 0; - /// Reference to a [LinkedNodeReferences]. - set typeParameterParameter(int value) { + set typeParameterId(int value) { assert(value == null || value >= 0); - this._typeParameterParameter = value; + this._typeParameterId = value; } LinkedNodeTypeBuilder( {List functionFormalParameters, LinkedNodeTypeBuilder functionReturnType, - List functionTypeParameters, + List functionTypeParameters, int genericTypeAliasReference, List genericTypeAliasTypeArguments, int interfaceClass, List interfaceTypeArguments, idl.LinkedNodeTypeKind kind, - int typeParameterParameter}) + int typeParameterId}) : _functionFormalParameters = functionFormalParameters, _functionReturnType = functionReturnType, _functionTypeParameters = functionTypeParameters, @@ -18991,12 +19013,13 @@ class LinkedNodeTypeBuilder extends Object _interfaceClass = interfaceClass, _interfaceTypeArguments = interfaceTypeArguments, _kind = kind, - _typeParameterParameter = typeParameterParameter; + _typeParameterId = typeParameterId; /// Flush [informative] data recursively. void flushInformative() { _functionFormalParameters?.forEach((b) => b.flushInformative()); _functionReturnType?.flushInformative(); + _functionTypeParameters?.forEach((b) => b.flushInformative()); _genericTypeAliasTypeArguments?.forEach((b) => b.flushInformative()); _interfaceTypeArguments?.forEach((b) => b.flushInformative()); } @@ -19018,7 +19041,7 @@ class LinkedNodeTypeBuilder extends Object } else { signature.addInt(this._functionTypeParameters.length); for (var x in this._functionTypeParameters) { - signature.addInt(x); + x?.collectApiSignature(signature); } } signature.addInt(this._interfaceClass ?? 0); @@ -19031,7 +19054,7 @@ class LinkedNodeTypeBuilder extends Object } } signature.addInt(this._kind == null ? 0 : this._kind.index); - signature.addInt(this._typeParameterParameter ?? 0); + signature.addInt(this._typeParameterId ?? 0); signature.addInt(this._genericTypeAliasReference ?? 0); if (this._genericTypeAliasTypeArguments == null) { signature.addInt(0); @@ -19058,8 +19081,8 @@ class LinkedNodeTypeBuilder extends Object offset_functionReturnType = _functionReturnType.finish(fbBuilder); } if (!(_functionTypeParameters == null || _functionTypeParameters.isEmpty)) { - offset_functionTypeParameters = - fbBuilder.writeListUint32(_functionTypeParameters); + offset_functionTypeParameters = fbBuilder.writeList( + _functionTypeParameters.map((b) => b.finish(fbBuilder)).toList()); } if (!(_genericTypeAliasTypeArguments == null || _genericTypeAliasTypeArguments.isEmpty)) { @@ -19097,8 +19120,8 @@ class LinkedNodeTypeBuilder extends Object if (_kind != null && _kind != idl.LinkedNodeTypeKind.bottom) { fbBuilder.addUint8(5, _kind.index); } - if (_typeParameterParameter != null && _typeParameterParameter != 0) { - fbBuilder.addUint32(6, _typeParameterParameter); + if (_typeParameterId != null && _typeParameterId != 0) { + fbBuilder.addUint32(6, _typeParameterId); } return fbBuilder.endTable(); } @@ -19122,13 +19145,13 @@ class _LinkedNodeTypeImpl extends Object List _functionFormalParameters; idl.LinkedNodeType _functionReturnType; - List _functionTypeParameters; + List _functionTypeParameters; int _genericTypeAliasReference; List _genericTypeAliasTypeArguments; int _interfaceClass; List _interfaceTypeArguments; idl.LinkedNodeTypeKind _kind; - int _typeParameterParameter; + int _typeParameterId; @override List get functionFormalParameters { @@ -19148,9 +19171,12 @@ class _LinkedNodeTypeImpl extends Object } @override - List get functionTypeParameters { + List get functionTypeParameters { _functionTypeParameters ??= - const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const []); + const fb.ListReader( + const _LinkedNodeTypeTypeParameterReader()) + .vTableGet( + _bc, _bcOffset, 2, const []); return _functionTypeParameters; } @@ -19191,10 +19217,10 @@ class _LinkedNodeTypeImpl extends Object } @override - int get typeParameterParameter { - _typeParameterParameter ??= + int get typeParameterId { + _typeParameterId ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0); - return _typeParameterParameter; + return _typeParameterId; } } @@ -19208,7 +19234,8 @@ abstract class _LinkedNodeTypeMixin implements idl.LinkedNodeType { if (functionReturnType != null) _result["functionReturnType"] = functionReturnType.toJson(); if (functionTypeParameters.isNotEmpty) - _result["functionTypeParameters"] = functionTypeParameters; + _result["functionTypeParameters"] = + functionTypeParameters.map((_value) => _value.toJson()).toList(); if (genericTypeAliasReference != 0) _result["genericTypeAliasReference"] = genericTypeAliasReference; if (genericTypeAliasTypeArguments.isNotEmpty) @@ -19221,8 +19248,7 @@ abstract class _LinkedNodeTypeMixin implements idl.LinkedNodeType { interfaceTypeArguments.map((_value) => _value.toJson()).toList(); if (kind != idl.LinkedNodeTypeKind.bottom) _result["kind"] = kind.toString().split('.')[1]; - if (typeParameterParameter != 0) - _result["typeParameterParameter"] = typeParameterParameter; + if (typeParameterId != 0) _result["typeParameterId"] = typeParameterId; return _result; } @@ -19236,7 +19262,7 @@ abstract class _LinkedNodeTypeMixin implements idl.LinkedNodeType { "interfaceClass": interfaceClass, "interfaceTypeArguments": interfaceTypeArguments, "kind": kind, - "typeParameterParameter": typeParameterParameter, + "typeParameterId": typeParameterId, }; @override @@ -19381,6 +19407,116 @@ abstract class _LinkedNodeTypeFormalParameterMixin String toString() => convert.json.encode(toJson()); } +class LinkedNodeTypeTypeParameterBuilder extends Object + with _LinkedNodeTypeTypeParameterMixin + implements idl.LinkedNodeTypeTypeParameter { + LinkedNodeTypeBuilder _bound; + String _name; + + @override + LinkedNodeTypeBuilder get bound => _bound; + + set bound(LinkedNodeTypeBuilder value) { + this._bound = value; + } + + @override + String get name => _name ??= ''; + + set name(String value) { + this._name = value; + } + + LinkedNodeTypeTypeParameterBuilder({LinkedNodeTypeBuilder bound, String name}) + : _bound = bound, + _name = name; + + /// Flush [informative] data recursively. + void flushInformative() { + _bound?.flushInformative(); + } + + /// Accumulate non-[informative] data into [signature]. + void collectApiSignature(api_sig.ApiSignature signature) { + signature.addString(this._name ?? ''); + signature.addBool(this._bound != null); + this._bound?.collectApiSignature(signature); + } + + fb.Offset finish(fb.Builder fbBuilder) { + fb.Offset offset_bound; + fb.Offset offset_name; + if (_bound != null) { + offset_bound = _bound.finish(fbBuilder); + } + if (_name != null) { + offset_name = fbBuilder.writeString(_name); + } + fbBuilder.startTable(); + if (offset_bound != null) { + fbBuilder.addOffset(1, offset_bound); + } + if (offset_name != null) { + fbBuilder.addOffset(0, offset_name); + } + return fbBuilder.endTable(); + } +} + +class _LinkedNodeTypeTypeParameterReader + extends fb.TableReader<_LinkedNodeTypeTypeParameterImpl> { + const _LinkedNodeTypeTypeParameterReader(); + + @override + _LinkedNodeTypeTypeParameterImpl createObject( + fb.BufferContext bc, int offset) => + new _LinkedNodeTypeTypeParameterImpl(bc, offset); +} + +class _LinkedNodeTypeTypeParameterImpl extends Object + with _LinkedNodeTypeTypeParameterMixin + implements idl.LinkedNodeTypeTypeParameter { + final fb.BufferContext _bc; + final int _bcOffset; + + _LinkedNodeTypeTypeParameterImpl(this._bc, this._bcOffset); + + idl.LinkedNodeType _bound; + String _name; + + @override + idl.LinkedNodeType get bound { + _bound ??= const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 1, null); + return _bound; + } + + @override + String get name { + _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, ''); + return _name; + } +} + +abstract class _LinkedNodeTypeTypeParameterMixin + implements idl.LinkedNodeTypeTypeParameter { + @override + Map toJson() { + Map _result = {}; + if (bound != null) _result["bound"] = bound.toJson(); + if (name != '') _result["name"] = name; + return _result; + } + + @override + Map toMap() => { + "bound": bound, + "name": name, + }; + + @override + String toString() => convert.json.encode(toJson()); +} + class LinkedNodeUnitBuilder extends Object with _LinkedNodeUnitMixin implements idl.LinkedNodeUnit { diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs index bb86ffb272d..dea7ce64537 100644 --- a/pkg/analyzer/lib/src/summary/format.fbs +++ b/pkg/analyzer/lib/src/summary/format.fbs @@ -406,8 +406,6 @@ enum LinkedNodeTypeKind : byte { function, - genericTypeAlias, - interface, typeParameter, @@ -1945,8 +1943,7 @@ table LinkedNodeType { functionReturnType:LinkedNodeType (id: 1); - /// References to [LinkedNodeReferences]. - functionTypeParameters:[uint] (id: 2); + functionTypeParameters:[LinkedNodeTypeTypeParameter] (id: 2); genericTypeAliasReference:uint (id: 7); @@ -1959,8 +1956,7 @@ table LinkedNodeType { kind:LinkedNodeTypeKind (id: 5); - /// Reference to a [LinkedNodeReferences]. - typeParameterParameter:uint (id: 6); + typeParameterId:uint (id: 6); } /// Information about a formal parameter in a function type. @@ -1972,6 +1968,13 @@ table LinkedNodeTypeFormalParameter { type:LinkedNodeType (id: 2); } +/// Information about a type parameter in a function type. +table LinkedNodeTypeTypeParameter { + bound:LinkedNodeType (id: 1); + + name:string (id: 0); +} + /// Information about a single library in a [LinkedNodeLibrary]. table LinkedNodeUnit { node:LinkedNode (id: 2); diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart index 4b897bc0ded..033e6ff6bef 100644 --- a/pkg/analyzer/lib/src/summary/idl.dart +++ b/pkg/analyzer/lib/src/summary/idl.dart @@ -2222,6 +2222,9 @@ abstract class LinkedNode extends base.SummaryClass { @VariantId(15, variant: LinkedNodeKind.typeParameter) int get typeParameter_extendsKeyword; + @VariantId(16, variant: LinkedNodeKind.typeParameter) + int get typeParameter_id; + @VariantId(7, variant: LinkedNodeKind.typeParameter) LinkedNode get typeParameter_name; @@ -2501,9 +2504,8 @@ abstract class LinkedNodeType extends base.SummaryClass { @Id(1) LinkedNodeType get functionReturnType; - /// References to [LinkedNodeReferences]. @Id(2) - List get functionTypeParameters; + List get functionTypeParameters; @Id(7) int get genericTypeAliasReference; @@ -2521,9 +2523,8 @@ abstract class LinkedNodeType extends base.SummaryClass { @Id(5) LinkedNodeTypeKind get kind; - /// Reference to a [LinkedNodeReferences]. @Id(6) - int get typeParameterParameter; + int get typeParameterId; } /// Information about a formal parameter in a function type. @@ -2543,12 +2544,20 @@ enum LinkedNodeTypeKind { bottom, dynamic_, function, - genericTypeAlias, interface, typeParameter, void_ } +/// Information about a type parameter in a function type. +abstract class LinkedNodeTypeTypeParameter extends base.SummaryClass { + @Id(1) + LinkedNodeType get bound; + + @Id(0) + String get name; +} + /// Information about a single library in a [LinkedNodeLibrary]. abstract class LinkedNodeUnit extends base.SummaryClass { @Id(2) diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart index e08c4f6a6ee..b9cc2d19980 100644 --- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart +++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart @@ -9,7 +9,6 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary2/lazy_ast.dart'; @@ -240,7 +239,7 @@ class AstBinaryReader { _getToken(data.classDeclaration_abstractKeyword), _getToken(data.classDeclaration_classKeyword), _readNode(data.namedCompilationUnitMember_name), - _readNodeLazy(data.classOrMixinDeclaration_typeParameters), + _readNode(data.classOrMixinDeclaration_typeParameters), _readNodeLazy(data.classDeclaration_extendsClause), _readNodeLazy(data.classDeclaration_withClause), _readNodeLazy(data.classOrMixinDeclaration_implementsClause), @@ -259,7 +258,7 @@ class AstBinaryReader { _readNodeListLazy(data.annotatedNode_metadata), _getToken(data.typeAlias_typedefKeyword), _readNode(data.namedCompilationUnitMember_name), - _readNodeLazy(data.classTypeAlias_typeParameters), + _readNode(data.classTypeAlias_typeParameters), _getToken(data.classTypeAlias_equals), _getToken(data.classTypeAlias_abstractKeyword), _readNodeLazy(data.classTypeAlias_superclass), @@ -618,7 +617,7 @@ class AstBinaryReader { _localParameters = thisLocalParameters; var node = astFactory.functionExpression( - _readNodeLazy(data.functionExpression_typeParameters), + _readNode(data.functionExpression_typeParameters), _readNodeLazy(data.functionExpression_formalParameters), _readNodeLazy(data.functionExpression_body), ); @@ -664,7 +663,7 @@ class AstBinaryReader { _getToken(data.typeAlias_typedefKeyword), _readNodeLazy(data.functionTypeAlias_returnType), _readNode(data.namedCompilationUnitMember_name), - _readNodeLazy(data.functionTypeAlias_typeParameters), + _readNode(data.functionTypeAlias_typeParameters), _readNodeLazy(data.functionTypeAlias_formalParameters), _getToken(data.typeAlias_semicolon), ); @@ -705,7 +704,7 @@ class AstBinaryReader { GenericFunctionTypeImpl node = astFactory.genericFunctionType( _readNodeLazy(data.genericFunctionType_returnType), _getToken(data.genericFunctionType_functionKeyword), - _readNodeLazy(data.genericFunctionType_typeParameters), + _readNode(data.genericFunctionType_typeParameters), _readNodeLazy(data.genericFunctionType_formalParameters), question: _getToken(data.genericFunctionType_question), ); @@ -720,7 +719,7 @@ class AstBinaryReader { _readNodeList(data.annotatedNode_metadata), _getToken(data.typeAlias_typedefKeyword), _readNode(data.namedCompilationUnitMember_name), - _readNodeLazy(data.genericTypeAlias_typeParameters), + _readNode(data.genericTypeAlias_typeParameters), _getToken(data.genericTypeAlias_equals), _readNodeLazy(data.genericTypeAlias_functionType), _getToken(data.typeAlias_semicolon), @@ -896,7 +895,7 @@ class AstBinaryReader { _getToken(data.methodDeclaration_propertyKeyword), _getToken(data.methodDeclaration_operatorKeyword), _readNode(data.methodDeclaration_name), - _readNodeLazy(data.methodDeclaration_typeParameters), + _readNode(data.methodDeclaration_typeParameters), _readNodeLazy(data.methodDeclaration_formalParameters), _readNodeLazy(data.methodDeclaration_body), ); @@ -920,7 +919,7 @@ class AstBinaryReader { _readNodeList(data.annotatedNode_metadata), _getToken(data.mixinDeclaration_mixinKeyword), _readNode(data.namedCompilationUnitMember_name), - _readNodeLazy(data.classOrMixinDeclaration_typeParameters), + _readNode(data.classOrMixinDeclaration_typeParameters), _readNodeLazy(data.mixinDeclaration_onClause), _readNodeLazy(data.classOrMixinDeclaration_implementsClause), _getToken(data.classOrMixinDeclaration_leftBracket), @@ -1256,6 +1255,7 @@ class AstBinaryReader { _readNodeLazy(data.typeParameter_bound), ); LazyTypeParameter.setData(node, data); + _unitContext.addTypeParameter(data.typeParameter_id, node); return node; } @@ -1588,57 +1588,6 @@ class AstBinaryReader { } DartType _readType(LinkedNodeType data) { - if (data == null) return null; - - switch (data.kind) { - case LinkedNodeTypeKind.bottom: - return BottomTypeImpl.instance; - case LinkedNodeTypeKind.dynamic_: - return DynamicTypeImpl.instance; - case LinkedNodeTypeKind.function: - return FunctionTypeImpl.synthetic( - _readType(data.functionReturnType), - _getElements(data.functionTypeParameters), - data.functionFormalParameters - .map((p) => ParameterElementImpl.synthetic( - p.name, _readType(p.type), _formalParameterKind(p.kind))) - .toList(), - ); - case LinkedNodeTypeKind.interface: - var element = _getElement(data.interfaceClass); - if (element != null) { - return InterfaceTypeImpl.explicit( - element, - _readTypes( - data.interfaceTypeArguments, - const [], - ), - ); - } - return DynamicTypeImpl.instance; - case LinkedNodeTypeKind.typeParameter: - var element = _getElement(data.typeParameterParameter); - // TODO(scheglov) Remove when references include all type parameters. - element ??= TypeParameterElementImpl('', -1); - return TypeParameterTypeImpl(element); - case LinkedNodeTypeKind.void_: - return VoidTypeImpl.instance; - default: - throw UnimplementedError('Type kind: ${data.kind}'); - } - } - - List _readTypes( - List dataList, - List ifEmpty, - ) { - if (dataList.isEmpty) return ifEmpty; - - var result = List(dataList.length); - for (var i = 0; i < dataList.length; ++i) { - var data = dataList[i]; - result[i] = _readType(data); - } - return result; + return _unitContext.readType(data); } } diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart index 0766c2450cb..9f70a6b53c2 100644 --- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart +++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart @@ -8,8 +8,6 @@ import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/ast/ast.dart'; -import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary2/lazy_ast.dart'; @@ -18,7 +16,7 @@ import 'package:analyzer/src/summary2/tokens_context.dart'; /// Serializer of fully resolved ASTs into flat buffers. class AstBinaryWriter extends ThrowingAstVisitor { - final LinkingBundleContext _linkingBundleContext; + final LinkingBundleContext _linkingContext; final TokensContext _tokensContext; /// This field is set temporary while visiting [FieldDeclaration] or @@ -26,7 +24,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { /// in these declarations. LinkedNodeVariablesDeclarationBuilder _variablesDeclaration; - AstBinaryWriter(this._linkingBundleContext, this._tokensContext); + AstBinaryWriter(this._linkingContext, this._tokensContext); @override LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) { @@ -94,7 +92,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { @override LinkedNodeBuilder visitAssignmentExpression(AssignmentExpression node) { return LinkedNodeBuilder.assignmentExpression( - assignmentExpression_element: _getReferenceIndex(node.staticElement), + assignmentExpression_element: _indexOfElement(node.staticElement), assignmentExpression_leftHandSide: node.leftHandSide.accept(this), assignmentExpression_operator: _getToken(node.operator), assignmentExpression_rightHandSide: node.rightHandSide.accept(this), @@ -114,7 +112,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { @override LinkedNodeBuilder visitBinaryExpression(BinaryExpression node) { return LinkedNodeBuilder.binaryExpression( - binaryExpression_element: _getReferenceIndex(node.staticElement), + binaryExpression_element: _indexOfElement(node.staticElement), binaryExpression_leftOperand: node.leftOperand.accept(this), binaryExpression_operator: _getToken(node.operator), binaryExpression_rightOperand: node.rightOperand.accept(this), @@ -303,7 +301,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { @override LinkedNodeBuilder visitConstructorName(ConstructorName node) { return LinkedNodeBuilder.constructorName( - constructorName_element: _getReferenceIndex(node.staticElement), + constructorName_element: _indexOfElement(node.staticElement), constructorName_name: node.name?.accept(this), constructorName_period: _getToken(node.period), constructorName_type: node.type.accept(this), @@ -695,7 +693,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { @override LinkedNodeBuilder visitIndexExpression(IndexExpression node) { return LinkedNodeBuilder.indexExpression( - indexExpression_element: _getReferenceIndex(node.staticElement), + indexExpression_element: _indexOfElement(node.staticElement), indexExpression_index: node.index.accept(this), indexExpression_leftBracket: _getToken(node.leftBracket), indexExpression_period: _getToken(node.period), @@ -931,7 +929,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { LinkedNodeBuilder visitPostfixExpression(PostfixExpression node) { return LinkedNodeBuilder.postfixExpression( expression_type: _writeType(node.staticType), - postfixExpression_element: _getReferenceIndex(node.staticElement), + postfixExpression_element: _indexOfElement(node.staticElement), postfixExpression_operand: node.operand.accept(this), postfixExpression_operator: _getToken(node.operator), ); @@ -951,7 +949,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { LinkedNodeBuilder visitPrefixExpression(PrefixExpression node) { return LinkedNodeBuilder.prefixExpression( expression_type: _writeType(node.staticType), - prefixExpression_element: _getReferenceIndex(node.staticElement), + prefixExpression_element: _indexOfElement(node.staticElement), prefixExpression_operand: node.operand.accept(this), prefixExpression_operator: _getToken(node.operator), ); @@ -977,7 +975,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { redirectingConstructorInvocation_constructorName: node.constructorName?.accept(this), redirectingConstructorInvocation_element: - _getReferenceIndex(node.staticElement), + _indexOfElement(node.staticElement), redirectingConstructorInvocation_period: _getToken(node.period), redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword), ); @@ -1053,7 +1051,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { } return LinkedNodeBuilder.simpleIdentifier( - simpleIdentifier_element: _getReferenceIndex(element), + simpleIdentifier_element: _indexOfElement(element), simpleIdentifier_token: _getToken(node.token), expression_type: _writeType(node.staticType), ); @@ -1092,8 +1090,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { superConstructorInvocation_arguments: node.argumentList.accept(this), superConstructorInvocation_constructorName: node.constructorName?.accept(this), - superConstructorInvocation_element: - _getReferenceIndex(node.staticElement), + superConstructorInvocation_element: _indexOfElement(node.staticElement), superConstructorInvocation_period: _getToken(node.period), superConstructorInvocation_superKeyword: _getToken(node.superKeyword), ); @@ -1222,6 +1219,9 @@ class AstBinaryWriter extends ThrowingAstVisitor { typeParameter_name: node.name.accept(this)); _storeDeclaration(builder, node); _storeCodeOffsetLength(builder, node); + builder.typeParameter_id = _linkingContext.idOfTypeParameter( + node.declaredElement, + ); return builder; } @@ -1307,21 +1307,6 @@ class AstBinaryWriter extends ThrowingAstVisitor { return node.accept(this); } - int _getReferenceIndex(Element element) { - if (element == null) return 0; - - if (element is Member) { - element = (element as Member).baseElement; - } - - var reference = (element as ElementImpl).reference; - if (identical(element, DynamicElementImpl.instance)) { - reference = _linkingBundleContext.dynamicReference; - } - - return _linkingBundleContext.indexOfReference(reference); - } - int _getToken(Token token) { return _tokensContext.indexOfToken(token); } @@ -1335,6 +1320,10 @@ class AstBinaryWriter extends ThrowingAstVisitor { return result; } + int _indexOfElement(Element element) { + return _linkingContext.indexOfElement(element); + } + void _storeAnnotatedNode(LinkedNodeBuilder builder, AnnotatedNode node) { builder ..annotatedNode_comment = node.documentationComment?.accept(this) @@ -1517,7 +1506,7 @@ class AstBinaryWriter extends ThrowingAstVisitor { builder ..uriBasedDirective_uri = node.uri.accept(this) ..uriBasedDirective_uriContent = node.uriContent - ..uriBasedDirective_uriElement = _getReferenceIndex(node.uriElement); + ..uriBasedDirective_uriElement = _indexOfElement(node.uriElement); } void _writeActualReturnType(LinkedNodeBuilder builder, AstNode node) { @@ -1545,6 +1534,6 @@ class AstBinaryWriter extends ThrowingAstVisitor { } LinkedNodeTypeBuilder _writeType(DartType type) { - return _linkingBundleContext.writeType(type); + return _linkingContext.writeType(type); } } diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart index 73393588776..f32037197e6 100644 --- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart +++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart @@ -299,6 +299,7 @@ class SourceLibraryBuilder { var unitRef = reference.getChild('@unit'); var unitReference = unitRef.getChild(unitContext.uriStr); var resolver = ReferenceResolver( + linker.linkingBundleContext, nodesToBuildType, linker.elementFactory, element, diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart index 21076aaadf8..9c7c1cc890a 100644 --- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart +++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart @@ -45,7 +45,6 @@ class LazyClassDeclaration { bool _hasImplementsClause = false; bool _hasMembers = false; bool _hasMetadata = false; - bool _hasTypeParameters = false; bool _hasWithClause = false; LazyClassDeclaration(this.data); @@ -123,19 +122,6 @@ class LazyClassDeclaration { } } - static void readTypeParameters( - AstBinaryReader reader, - ClassDeclaration node, - ) { - var lazy = LazyClassDeclaration.get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.classOrMixinDeclaration_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void readWithClause( AstBinaryReader reader, ClassDeclaration node, @@ -163,7 +149,6 @@ class LazyClassTypeAlias { bool _hasImplementsClause = false; bool _hasMetadata = false; bool _hasSuperclass = false; - bool _hasTypeParameters = false; bool _hasWithClause = false; LazyClassTypeAlias(this.data); @@ -228,19 +213,6 @@ class LazyClassTypeAlias { } } - static void readTypeParameters( - AstBinaryReader reader, - ClassTypeAlias node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.classTypeAlias_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void readWithClause( AstBinaryReader reader, ClassTypeAlias node, @@ -635,6 +607,7 @@ class LazyFunctionDeclaration { AstBinaryReader reader, FunctionDeclaration node, ) { + readFunctionExpression(reader, node); if (reader.isLazy) { var lazy = get(node); if (!lazy._hasReturnType) { @@ -698,7 +671,6 @@ class LazyFunctionExpression { bool _hasBody = false; bool _hasFormalParameters = false; - bool _hasTypeParameters = false; LazyFunctionExpression(this.data); @@ -732,19 +704,6 @@ class LazyFunctionExpression { } } - static void readTypeParameters( - AstBinaryReader reader, - FunctionExpression node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.functionExpression_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void setData(FunctionExpression node, LinkedNode data) { node.setProperty(_key, LazyFunctionExpression(data)); } @@ -759,7 +718,6 @@ class LazyFunctionTypeAlias { bool _hasFormalParameters = false; bool _hasMetadata = false; bool _hasReturnType = false; - bool _hasTypeParameters = false; LazyFunctionTypeAlias(this.data); @@ -823,19 +781,6 @@ class LazyFunctionTypeAlias { } } - static void readTypeParameters( - AstBinaryReader reader, - FunctionTypeAlias node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.functionTypeAlias_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void setData(FunctionTypeAlias node, LinkedNode data) { node.setProperty(_key, LazyFunctionTypeAlias(data)); } @@ -895,7 +840,6 @@ class LazyGenericTypeAlias { bool _hasDocumentationComment = false; bool _hasFunction = false; - bool _hasTypeParameters = false; LazyGenericTypeAlias(this.data); @@ -929,19 +873,6 @@ class LazyGenericTypeAlias { } } - static void readTypeParameters( - AstBinaryReader reader, - GenericTypeAlias node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.genericTypeAlias_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void setData(GenericTypeAlias node, LinkedNode data) { node.setProperty(_key, LazyGenericTypeAlias(data)); } @@ -957,7 +888,6 @@ class LazyMethodDeclaration { bool _hasFormalParameters = false; bool _hasMetadata = false; bool _hasReturnType = false; - bool _hasTypeParameters = false; LazyMethodDeclaration(this.data); @@ -1034,19 +964,6 @@ class LazyMethodDeclaration { } } - static void readTypeParameters( - AstBinaryReader reader, - MethodDeclaration node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.methodDeclaration_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void setData(MethodDeclaration node, LinkedNode data) { node.setProperty(_key, LazyMethodDeclaration(data)); } @@ -1061,7 +978,6 @@ class LazyMixinDeclaration { bool _hasOnClause = false; bool _hasImplementsClause = false; bool _hasMembers = false; - bool _hasTypeParameters = false; LazyMixinDeclaration(this.data); @@ -1123,19 +1039,6 @@ class LazyMixinDeclaration { } } - static void readTypeParameters( - AstBinaryReader reader, - MixinDeclarationImpl node, - ) { - var lazy = get(node); - if (lazy != null && !lazy._hasTypeParameters) { - node.typeParameters = reader.readNode( - lazy.data.classOrMixinDeclaration_typeParameters, - ); - lazy._hasTypeParameters = true; - } - } - static void setData(MixinDeclaration node, LinkedNode data) { node.setProperty(_key, LazyMixinDeclaration(data)); } diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart index 88f86555c47..f81e2c4d45d 100644 --- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart +++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart @@ -82,52 +82,6 @@ class LinkedBundleContext { return result; } - InterfaceType getInterfaceType(LinkedNodeType linkedType) { - var type = getType(linkedType); - if (type is InterfaceType && !type.element.isEnum) { - return type; - } - return null; - } - - DartType getType(LinkedNodeType linkedType) { - var kind = linkedType.kind; - if (kind == LinkedNodeTypeKind.dynamic_) { - return DynamicTypeImpl.instance; - } else if (kind == LinkedNodeTypeKind.genericTypeAlias) { - var reference = referenceOfIndex(linkedType.genericTypeAliasReference); - return GenericTypeAliasElementImpl.typeAfterSubstitution( - elementFactory.elementOfReference(reference), - linkedType.genericTypeAliasTypeArguments.map(getType).toList(), - ); - } else if (kind == LinkedNodeTypeKind.function) { - var returnType = getType(linkedType.functionReturnType); - var formalParameters = linkedType.functionFormalParameters.map((p) { - return ParameterElementImpl.synthetic( - p.name, - getType(p.type), - _formalParameterKind(p.kind), - ); - }).toList(); - return FunctionElementImpl.synthetic(formalParameters, returnType).type; - } else if (kind == LinkedNodeTypeKind.interface) { - var reference = referenceOfIndex(linkedType.interfaceClass); - Element element = elementFactory.elementOfReference(reference); - return InterfaceTypeImpl.explicit( - element, - linkedType.interfaceTypeArguments.map(getType).toList(), - ); - } else if (kind == LinkedNodeTypeKind.typeParameter) { - var reference = referenceOfIndex(linkedType.typeParameterParameter); - Element element = elementFactory.elementOfReference(reference); - return TypeParameterTypeImpl(element); - } else if (kind == LinkedNodeTypeKind.void_) { - return VoidTypeImpl.instance; - } else { - throw UnimplementedError('$kind'); - } - } - Reference referenceOfIndex(int index) { var reference = _references[index]; if (reference != null) return reference; @@ -147,16 +101,6 @@ class LinkedBundleContext { return reference; } - - ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) { - if (kind == LinkedNodeFormalParameterKind.optionalNamed) { - return ParameterKind.NAMED; - } - if (kind == LinkedNodeFormalParameterKind.optionalPositional) { - return ParameterKind.POSITIONAL; - } - return ParameterKind.REQUIRED; - } } class LinkedLibraryContext { diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart index e16238fc689..88344cbb96b 100644 --- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart +++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart @@ -152,11 +152,6 @@ class _ElementRequest { return _typeAlias(unit, reference); } - if (parentName == '@typeParameter') { - var enclosing = elementOfReference(parent2) as TypeParameterizedElement; - return _typeParameter(enclosing, reference); - } - if (parentName == '@unit') { elementOfReference(parent2); // Creating a library fills all its units. @@ -296,14 +291,6 @@ class _ElementRequest { return reference.element; } - Element _typeParameter( - TypeParameterizedElement enclosing, Reference reference) { - enclosing.typeParameters; - // Requesting type parameters sets elements for all their references. - assert(reference.element != null); - return reference.element; - } - /// Index nodes for which we choose to create elements individually, /// for example [ClassDeclaration], so that its [Reference] has the node, /// and we can call the [ClassElementImpl] constructor. diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart index 4d82d2d5e66..8a906fe077e 100644 --- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart +++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart @@ -3,8 +3,10 @@ // BSD-style license that can be found in the LICENSE file. 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/element/element.dart'; +import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart'; @@ -27,6 +29,17 @@ class LinkedUnitContext { CompilationUnit _unit; bool _hasDirectivesRead = false; + /// Mapping from identifiers to real or synthetic type parameters. + /// + /// Real type parameters have corresponding [TypeParameter] nodes, and are + /// referenced from other AST nodes. + /// + /// Synthetic type parameters are added when [readType] begins reading a + /// [FunctionType], and removed when reading is done. + final Map _typeParameters = {}; + + int _nextSyntheticTypeParameterId = 0x10000; + LinkedUnitContext(this.bundleContext, this.libraryContext, this.indexInLibrary, this.uriStr, this.data, {CompilationUnit unit}) @@ -59,6 +72,15 @@ class LinkedUnitContext { return _unit; } + /// Every [TypeParameter] node has [TypeParameterElement], which is created + /// during reading of this node. All type parameter nodes are read before + /// any nodes that reference them (bounds are read lazily later). + void addTypeParameter(int id, TypeParameter node) { + var element = TypeParameterElementImpl.forLinkedNode(null, null, node); + _typeParameters[id] = element; + node.name.staticElement = element; + } + /// Return the absolute URI referenced in the [directive]. Uri directiveUri(Uri libraryUri, UriBasedDirective directive) { var relativeUriStr = directive.uri.stringValue; @@ -269,7 +291,11 @@ class LinkedUnitContext { } InterfaceType getInterfaceType(LinkedNodeType linkedType) { - return bundleContext.getInterfaceType(linkedType); + var type = readType(linkedType); + if (type is InterfaceType && !type.element.isEnum) { + return type; + } + return null; } List getLibraryMetadata(CompilationUnit unit) { @@ -460,10 +486,8 @@ class LinkedUnitContext { TypeParameterList getTypeParameters2(AstNode node) { if (node is ClassDeclaration) { - LazyClassDeclaration.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is ClassTypeAlias) { - LazyClassTypeAlias.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is ConstructorDeclaration) { return null; @@ -471,21 +495,16 @@ class LinkedUnitContext { LazyFunctionDeclaration.readFunctionExpression(_astReader, node); return getTypeParameters2(node.functionExpression); } else if (node is FunctionExpression) { - LazyFunctionExpression.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is FunctionTypeAlias) { - LazyFunctionTypeAlias.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is GenericFunctionType) { return node.typeParameters; } else if (node is GenericTypeAlias) { - LazyGenericTypeAlias.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is MethodDeclaration) { - LazyMethodDeclaration.readTypeParameters(_astReader, node); return node.typeParameters; } else if (node is MixinDeclaration) { - LazyMixinDeclaration.readTypeParameters(_astReader, node); return node.typeParameters; } else { throw UnimplementedError('${node.runtimeType}'); @@ -671,6 +690,58 @@ class LinkedUnitContext { return _astReader.readNode(linkedNode); } + DartType readType(LinkedNodeType linkedType) { + if (linkedType == null) return null; + + var kind = linkedType.kind; + if (kind == LinkedNodeTypeKind.bottom) { + return BottomTypeImpl.instance; + } else if (kind == LinkedNodeTypeKind.dynamic_) { + return DynamicTypeImpl.instance; + } else if (kind == LinkedNodeTypeKind.function) { + var typeParameterDataList = linkedType.functionTypeParameters; + + var typeParameters = []; + for (var typeParameterData in typeParameterDataList) { + var element = TypeParameterElementImpl(typeParameterData.name, -1); + typeParameters.add(element); + _typeParameters[_nextSyntheticTypeParameterId++] = element; + } + + var returnType = readType(linkedType.functionReturnType); + var formalParameters = linkedType.functionFormalParameters.map((p) { + var type = readType(p.type); + var kind = _formalParameterKind(p.kind); + return ParameterElementImpl.synthetic(p.name, type, kind); + }).toList(); + + for (var i = 0; i < typeParameterDataList.length; ++i) { + _typeParameters.remove(--_nextSyntheticTypeParameterId); + } + + return FunctionTypeImpl.synthetic( + returnType, + typeParameters, + formalParameters, + ); + } else if (kind == LinkedNodeTypeKind.interface) { + var element = bundleContext.elementOfIndex(linkedType.interfaceClass); + return InterfaceTypeImpl.explicit( + element, + linkedType.interfaceTypeArguments.map(readType).toList(), + ); + } else if (kind == LinkedNodeTypeKind.typeParameter) { + var id = linkedType.typeParameterId; + var element = _typeParameters[id]; + assert(element != null); + return TypeParameterTypeImpl(element); + } else if (kind == LinkedNodeTypeKind.void_) { + return VoidTypeImpl.instance; + } else { + throw UnimplementedError('$kind'); + } + } + void setReturnType(LinkedNodeBuilder node, DartType type) { throw UnimplementedError(); // var typeData = bundleContext.linking.writeType(type); @@ -693,6 +764,16 @@ class LinkedUnitContext { } } + ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) { + if (kind == LinkedNodeFormalParameterKind.optionalNamed) { + return ParameterKind.NAMED; + } + if (kind == LinkedNodeFormalParameterKind.optionalPositional) { + return ParameterKind.POSITIONAL; + } + return ParameterKind.REQUIRED; + } + List _getClassOrMixinMembers(ClassOrMixinDeclaration node) { if (node is ClassDeclaration) { LazyClassDeclaration.readMembers(_astReader, node); diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart index 6a9fc441dac..06d86cea489 100644 --- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart +++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart @@ -5,7 +5,9 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/element.dart'; +import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; +import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/summary/format.dart'; import 'package:analyzer/src/summary/idl.dart'; @@ -28,8 +30,35 @@ class LinkingBundleContext { name: [''], ); + final Map _typeParameters = Map.identity(); + int _nextTypeParameterId = 1; + int _nextSyntheticTypeParameterId = 0x10000; + LinkingBundleContext(this.dynamicReference); + void addTypeParameter(TypeParameterElement element) { + _typeParameters[element] = _nextTypeParameterId++; + } + + int idOfTypeParameter(TypeParameterElement element) { + return _typeParameters[element]; + } + + int indexOfElement(Element element) { + if (element == null) return 0; + + if (identical(element, DynamicElementImpl.instance)) { + return indexOfReference(dynamicReference); + } + + if (element is Member) { + element = (element as Member).baseElement; + } + + var reference = (element as ElementImpl).reference; + return indexOfReference(reference); + } + int indexOfReference(Reference reference) { if (reference == null) return 0; if (reference.parent == null) return 0; @@ -56,29 +85,18 @@ class LinkingBundleContext { kind: LinkedNodeTypeKind.dynamic_, ); } else if (type is FunctionType) { - return LinkedNodeTypeBuilder( - kind: LinkedNodeTypeKind.function, - functionFormalParameters: type.parameters - .map((p) => LinkedNodeTypeFormalParameterBuilder( - // ignore: deprecated_member_use_from_same_package - kind: _formalParameterKind(p.parameterKind), - name: p.name, - type: writeType(p.type), - )) - .toList(), - functionReturnType: writeType(type.returnType), - functionTypeParameters: _getReferences(type.typeParameters), - ); + return _writeFunctionType(type); } else if (type is InterfaceType) { return LinkedNodeTypeBuilder( kind: LinkedNodeTypeKind.interface, - interfaceClass: _getReferenceIndex(type.element), + interfaceClass: indexOfElement(type.element), interfaceTypeArguments: type.typeArguments.map(writeType).toList(), ); } else if (type is TypeParameterType) { + TypeParameterElementImpl element = type.element; return LinkedNodeTypeBuilder( kind: LinkedNodeTypeKind.typeParameter, - typeParameterParameter: _getReferenceIndex(type.element), + typeParameterId: _typeParameters[element], ); } else if (type is VoidType) { return LinkedNodeTypeBuilder( @@ -89,7 +107,9 @@ class LinkingBundleContext { } } - LinkedNodeFormalParameterKind _formalParameterKind(ParameterKind kind) { + LinkedNodeFormalParameterKind _formalParameterKind(ParameterElement p) { + // ignore: deprecated_member_use_from_same_package + var kind = p.parameterKind; if (kind == ParameterKind.NAMED) { return LinkedNodeFormalParameterKind.optionalNamed; } @@ -99,19 +119,57 @@ class LinkingBundleContext { return LinkedNodeFormalParameterKind.required; } - int _getReferenceIndex(Element element) { - if (element == null) return 0; + FunctionType _toSyntheticFunctionType(FunctionType type) { + var typeParameters = type.typeFormals; - var reference = (element as ElementImpl).reference; - return indexOfReference(reference); + if (typeParameters.isEmpty) return type; + + var onlySyntheticTypeParameters = typeParameters.every((e) { + return e is TypeParameterElementImpl && e.linkedNode == null; + }); + if (onlySyntheticTypeParameters) return type; + + var parameters = getFreshTypeParameters(typeParameters); + return parameters.applyToFunctionType(type); } - List _getReferences(List elements) { - var result = List(elements.length); - for (var i = 0; i < elements.length; ++i) { - var element = elements[i]; - result[i] = _getReferenceIndex(element); + LinkedNodeTypeBuilder _writeFunctionType(FunctionType type) { + type = _toSyntheticFunctionType(type); + + var typeParameterBuilders = []; + + var typeParameters = type.typeFormals; + for (var i = 0; i < typeParameters.length; ++i) { + var typeParameter = typeParameters[i]; + _typeParameters[typeParameter] = _nextSyntheticTypeParameterId++; + typeParameterBuilders.add( + LinkedNodeTypeTypeParameterBuilder(name: typeParameter.name), + ); } + + for (var i = 0; i < typeParameters.length; ++i) { + var typeParameter = typeParameters[i]; + typeParameterBuilders[i].bound = writeType(typeParameter.bound); + } + + var result = LinkedNodeTypeBuilder( + kind: LinkedNodeTypeKind.function, + functionFormalParameters: type.parameters + .map((p) => LinkedNodeTypeFormalParameterBuilder( + kind: _formalParameterKind(p), + name: p.name, + type: writeType(p.type), + )) + .toList(), + functionReturnType: writeType(type.returnType), + functionTypeParameters: typeParameterBuilders, + ); + + for (var typeParameter in typeParameters) { + _typeParameters.remove(typeParameter); + --_nextSyntheticTypeParameterId; + } + return result; } } diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart index 7f8af39ee86..989ab17c06a 100644 --- a/pkg/analyzer/lib/src/summary2/reference.dart +++ b/pkg/analyzer/lib/src/summary2/reference.dart @@ -71,8 +71,6 @@ class Reference { bool get isTypeAlias => parent != null && parent.name == '@typeAlias'; - bool get isTypeParameter => parent != null && parent.name == '@typeParameter'; - int get numOfChildren => _children != null ? _children.length : 0; /// Return the child with the given name, or `null` if does not exist. diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart index 28bb3357dfd..ddf98704c36 100644 --- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart +++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart @@ -10,6 +10,7 @@ import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/resolver/scope.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary2/linked_element_factory.dart'; +import 'package:analyzer/src/summary2/linking_bundle_context.dart'; import 'package:analyzer/src/summary2/linking_node_scope.dart'; import 'package:analyzer/src/summary2/reference.dart'; import 'package:analyzer/src/summary2/type_builder.dart'; @@ -510,6 +511,7 @@ import 'package:analyzer/src/summary2/type_builder.dart'; /// the type is set, otherwise we keep it empty, so we will attempt to infer /// it later). class ReferenceResolver extends ThrowingAstVisitor { + final LinkingBundleContext linkingContext; final NodesToBuildType nodesToBuildType; final LinkedElementFactory elementFactory; final LibraryElement _libraryElement; @@ -518,6 +520,7 @@ class ReferenceResolver extends ThrowingAstVisitor { Scope scope; ReferenceResolver( + this.linkingContext, this.nodesToBuildType, this.elementFactory, this._libraryElement, @@ -536,6 +539,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@class').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = ClassElementImpl.forLinkedNode( outerReference.element, reference, @@ -564,6 +568,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@class').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = ClassElementImpl.forLinkedNode( outerReference.element, reference, @@ -654,6 +659,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@function').getChild(name); + _createTypeParameterElements(node.functionExpression.typeParameters); var element = FunctionElementImpl.forLinkedNode( outerReference.element, reference, @@ -685,6 +691,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@typeAlias').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = GenericTypeAliasElementImpl.forLinkedNode( outerReference.element, reference, @@ -719,6 +726,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = '${outerReference.numOfChildren}'; reference = reference.getChild(name); + _createTypeParameterElements(node.typeParameters); var element = GenericFunctionTypeElementImpl.forLinkedNode( outerReference.element, reference, @@ -744,6 +752,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@typeAlias').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = GenericTypeAliasElementImpl.forLinkedNode( outerReference.element, reference, @@ -772,6 +781,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@method').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = MethodElementImpl.forLinkedNode( outerReference.element, reference, @@ -798,6 +808,7 @@ class ReferenceResolver extends ThrowingAstVisitor { var name = node.name.name; reference = reference.getChild('@class').getChild(name); + _createTypeParameterElements(node.typeParameters); var element = ClassElementImpl.forLinkedNode( outerReference.element, reference, @@ -879,4 +890,18 @@ class ReferenceResolver extends ThrowingAstVisitor { void visitWithClause(WithClause node) { node.mixinTypes.accept(this); } + + void _createTypeParameterElement(TypeParameter node) { + var element = TypeParameterElementImpl.forLinkedNode(null, null, node); + node.name.staticElement = element; + linkingContext.addTypeParameter(element); + } + + void _createTypeParameterElements(TypeParameterList typeParameterList) { + if (typeParameterList == null) return; + + for (var typeParameter in typeParameterList.typeParameters) { + _createTypeParameterElement(typeParameter); + } + } } diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart index 13a6dc40c06..b92d04b6dd1 100644 --- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart +++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart @@ -231,9 +231,9 @@ class SimplyBoundedNode extends graph.Node { var element = TypeBuilder.typeNameElementIndex(type.typeName_name); var reference = _walker.bundleContext.referenceOfIndex(element); - if (reference.isTypeParameter) { - return allowTypeParameters; - } +// if (reference.isTypeParameter) { +// return allowTypeParameters; +// } var arguments = type.typeName_typeArguments; if (arguments == null) { diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart index 358818130ae..70939354683 100644 --- a/pkg/analyzer/lib/src/summary2/type_builder.dart +++ b/pkg/analyzer/lib/src/summary2/type_builder.dart @@ -9,7 +9,6 @@ import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_algebra.dart'; -import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:analyzer/src/summary/idl.dart'; import 'package:analyzer/src/summary2/lazy_ast.dart'; import 'package:analyzer/src/summary2/linking_bundle_context.dart'; @@ -70,21 +69,28 @@ class TypeBuilder { } } - DartType _buildFunctionType( + FunctionType _buildFunctionType( + TypeParameterList typeParameterList, TypeAnnotation returnTypeNode, FormalParameterList parameterList, ) { var returnType = returnTypeNode?.type ?? _dynamicType; - // TODO(scheglov) type parameters - var typeParameters = const []; + List typeParameters; + if (typeParameterList != null) { + typeParameters = typeParameterList.typeParameters + .map((p) => p.declaredElement) + .toList(); + } else { + typeParameters = const []; + } - var formalParameters = parameterList.parameters.map((p) { - // TODO(scheglov) other types and kinds + var formalParameters = parameterList.parameters.map((parameter) { return ParameterElementImpl.synthetic( - (p as SimpleFormalParameter).identifier.name, - LazyAst.getType(p), - ParameterKind.REQUIRED, + parameter.identifier.name, + LazyAst.getType(parameter), + // ignore: deprecated_member_use_from_same_package + parameter.kind, ); }).toList(); @@ -96,8 +102,11 @@ class TypeBuilder { } void _buildGenericFunctionType(GenericFunctionTypeImpl node) { - // TODO(scheglov) Type parameters? - node.type = _buildFunctionType(node.returnType, node.parameters); + node.type = _buildFunctionType( + node.typeParameters, + node.returnType, + node.parameters, + ); } void _buildTypeName(TypeName node) { @@ -214,7 +223,11 @@ class TypeBuilder { void _fieldFormalParameter(FieldFormalParameter node) { var parameterList = node.parameters; if (parameterList != null) { - var type = _buildFunctionType(node.type, parameterList); + var type = _buildFunctionType( + node.typeParameters, + node.type, + parameterList, + ); LazyAst.setType(node, type); } else { LazyAst.setType(node, node.type?.type ?? _dynamicType); @@ -222,7 +235,11 @@ class TypeBuilder { } void _functionTypedFormalParameter(FunctionTypedFormalParameter node) { - var type = _buildFunctionType(node.returnType, node.parameters); + var type = _buildFunctionType( + node.typeParameters, + node.returnType, + node.parameters, + ); LazyAst.setType(node, type); } diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart index 313fe5dc0b7..3be71f3cbe0 100644 --- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart +++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart @@ -306,12 +306,6 @@ T max(T a, T b) => null; .test_const_parameterDefaultValue_initializingFormal_functionTyped(); } - @override - @failingTest - test_const_reference_topLevelFunction_generic() async { - await super.test_const_reference_topLevelFunction_generic(); - } - @override @failingTest test_const_reference_topLevelVariable_imported() async { @@ -512,12 +506,6 @@ T max(T a, T b) => null; await super.test_infer_generic_typedef_complex(); } - @override - @failingTest - test_infer_generic_typedef_simple() async { - await super.test_infer_generic_typedef_simple(); - } - @override @failingTest test_inference_issue_32394() async { @@ -848,12 +836,6 @@ T max(T a, T b) => null; await super.test_typedef_generic(); } - @override - @failingTest - test_typedef_generic_asFieldType() async { - await super.test_typedef_generic_asFieldType(); - } - @override @failingTest test_typedef_notSimplyBounded_dependency_via_param_type_new_style_name_included() async { @@ -943,12 +925,6 @@ T max(T a, T b) => null; await super.test_unresolved_import(); } - @override - @failingTest - test_unused_type_parameter() async { - await super.test_unused_type_parameter(); - } - @override @failingTest test_variable_propagatedType_final_dep_inLib() async {