Skip to content

Commit 26129cc

Browse files
scheglovwhesse
authored andcommitted
Fix for summarization of generic function type aliases and support for resynthesizing.
This is based on your CL https://codereview.chromium.org/2808093004/ and includes fixes for summarization and resynthesis. [email protected] BUG= #29237 Review-Url: https://codereview.chromium.org/2814443005 .
1 parent 2a6a0cf commit 26129cc

14 files changed

+277
-44
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
7272
/**
7373
* The version of data format, should be incremented on every format change.
7474
*/
75-
static const int DATA_VERSION = 28;
75+
static const int DATA_VERSION = 29;
7676

7777
/**
7878
* The number of exception contexts allowed to write. Once this field is

pkg/analyzer/lib/src/dart/element/element.dart

+21
Original file line numberDiff line numberDiff line change
@@ -5233,6 +5233,27 @@ class GenericTypeAliasElementImpl extends ElementImpl
52335233
return null;
52345234
}
52355235

5236+
/**
5237+
* Return the type of the function defined by this typedef after substituting
5238+
* the given [typeArguments] for the type parameters defined for this typedef
5239+
* (but not the type parameters defined by the function). If the number of
5240+
* [typeArguments] does not match the number of type parameters, then
5241+
* `dynamic` will be used in place of each of the type arguments.
5242+
*/
5243+
FunctionType typeAfterSubstitution(List<DartType> typeArguments) {
5244+
FunctionType functionType = function.type;
5245+
List<TypeParameterElement> parameterElements = typeParameters;
5246+
List<DartType> parameterTypes =
5247+
TypeParameterTypeImpl.getTypes(parameterElements);
5248+
int parameterCount = parameterTypes.length;
5249+
if (typeArguments == null ||
5250+
parameterElements.length != typeArguments.length) {
5251+
DartType dynamicType = DynamicElementImpl.instance.type;
5252+
typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
5253+
}
5254+
return functionType.substitute2(typeArguments, parameterTypes);
5255+
}
5256+
52365257
@override
52375258
void visitChildren(ElementVisitor visitor) {
52385259
super.visitChildren(visitor);

pkg/analyzer/lib/src/dart/element/handle.dart

+39
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,45 @@ class FunctionTypeAliasElementHandle extends ElementHandle
669669
FunctionTypeAlias computeNode() => actualElement.computeNode();
670670
}
671671

672+
/**
673+
* A handle to a [GenericTypeAliasElement].
674+
*/
675+
class GenericTypeAliasElementHandle extends ElementHandle
676+
implements GenericTypeAliasElement {
677+
GenericTypeAliasElementHandle(
678+
ElementResynthesizer resynthesizer, ElementLocation location)
679+
: super(resynthesizer, location);
680+
681+
@override
682+
GenericTypeAliasElement get actualElement =>
683+
super.actualElement as GenericTypeAliasElement;
684+
685+
@override
686+
CompilationUnitElement get enclosingElement =>
687+
super.enclosingElement as CompilationUnitElement;
688+
689+
@override
690+
GenericFunctionTypeElement get function => actualElement.function;
691+
692+
@override
693+
ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
694+
695+
@override
696+
List<ParameterElement> get parameters => actualElement.parameters;
697+
698+
@override
699+
DartType get returnType => actualElement.returnType;
700+
701+
@override
702+
FunctionType get type => actualElement.type;
703+
704+
@override
705+
List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
706+
707+
@override
708+
FunctionTypeAlias computeNode() => actualElement.computeNode();
709+
}
710+
672711
/**
673712
* A handle to an [ImportElement].
674713
*/

pkg/analyzer/lib/src/generated/resolver.dart

+10-23
Original file line numberDiff line numberDiff line change
@@ -8466,31 +8466,18 @@ class TypeNameResolver {
84668466
return undefinedType;
84678467
} else if (type is FunctionType) {
84688468
Element element = type.element;
8469-
if (annotation is TypeName && element is GenericTypeAliasElement) {
8470-
List<TypeParameterElement> parameterElements = element.typeParameters;
8471-
FunctionType functionType = element.function.type;
8472-
if (parameterElements.isNotEmpty) {
8473-
List<DartType> parameterTypes =
8474-
TypeParameterTypeImpl.getTypes(parameterElements);
8475-
int parameterCount = parameterTypes.length;
8476-
TypeArgumentList argumentList = annotation.typeArguments;
8477-
List<DartType> typeArguments;
8478-
if (argumentList != null) {
8479-
List<TypeAnnotation> arguments = argumentList.arguments;
8480-
int argumentCount = arguments.length;
8481-
if (argumentCount == parameterCount) {
8482-
typeArguments = new List<DartType>(parameterCount);
8483-
for (int i = 0; i < parameterCount; i++) {
8484-
typeArguments[i] = _getType(arguments[i]);
8485-
}
8486-
}
8469+
if (annotation is TypeName && element is GenericTypeAliasElementImpl) {
8470+
TypeArgumentList argumentList = annotation.typeArguments;
8471+
List<DartType> typeArguments = null;
8472+
if (argumentList != null) {
8473+
List<TypeAnnotation> arguments = argumentList.arguments;
8474+
int argumentCount = arguments.length;
8475+
typeArguments = new List<DartType>(argumentCount);
8476+
for (int i = 0; i < argumentCount; i++) {
8477+
typeArguments[i] = _getType(arguments[i]);
84878478
}
8488-
typeArguments ??=
8489-
new List<DartType>.filled(parameterCount, dynamicType);
8490-
functionType =
8491-
functionType.substitute2(typeArguments, parameterTypes);
84928479
}
8493-
return functionType;
8480+
return element.typeAfterSubstitution(typeArguments);
84948481
}
84958482
}
84968483
return type;

pkg/analyzer/lib/src/summary/idl.dart

+6-1
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,12 @@ enum ReferenceKind {
11321132
/**
11331133
* The entity being referred to does not exist.
11341134
*/
1135-
unresolved
1135+
unresolved,
1136+
1137+
/**
1138+
* The entity is a typedef expressed using generic function type syntax.
1139+
*/
1140+
genericFunctionTypedef
11361141
}
11371142

11381143
/**

pkg/analyzer/lib/src/summary/prelink.dart

+12-4
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,18 @@ class _Prelinker {
383383
executable.typeParameters.length));
384384
}
385385
for (UnlinkedTypedef typedef in unit.typedefs) {
386-
privateNamespace.add(
387-
typedef.name,
388-
new _Meaning(unitNum, ReferenceKind.typedef, 0,
389-
typedef.typeParameters.length));
386+
ReferenceKind kind;
387+
switch (typedef.style) {
388+
case TypedefStyle.functionType:
389+
kind = ReferenceKind.typedef;
390+
break;
391+
case TypedefStyle.genericFunctionType:
392+
kind = ReferenceKind.genericFunctionTypedef;
393+
break;
394+
}
395+
assert(kind != null);
396+
privateNamespace.add(typedef.name,
397+
new _Meaning(unitNum, kind, 0, typedef.typeParameters.length));
390398
}
391399
for (UnlinkedVariable variable in unit.variables) {
392400
privateNamespace.add(variable.name,

pkg/analyzer/lib/src/summary/public_namespace_computer.dart

+6
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ class _PublicNamespaceVisitor extends RecursiveAstVisitor {
176176
node.typeParameters?.typeParameters?.length ?? 0);
177177
}
178178

179+
@override
180+
visitGenericTypeAlias(GenericTypeAlias node) {
181+
addNameIfPublic(node.name.name, ReferenceKind.genericFunctionTypedef,
182+
node.typeParameters?.typeParameters?.length ?? 0);
183+
}
184+
179185
@override
180186
visitPartDirective(PartDirective node) {
181187
parts.add(node.uri.stringValue ?? '');

pkg/analyzer/lib/src/summary/resynthesize.dart

+13
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,9 @@ class _LibraryResynthesizer {
938938
case ReferenceKind.typedef:
939939
return new FunctionTypeAliasElementHandle(
940940
summaryResynthesizer, location);
941+
case ReferenceKind.genericFunctionTypedef:
942+
return new GenericTypeAliasElementHandle(
943+
summaryResynthesizer, location);
941944
case ReferenceKind.topLevelFunction:
942945
return new FunctionElementHandle(summaryResynthesizer, location);
943946
case ReferenceKind.topLevelPropertyAccessor:
@@ -1314,6 +1317,11 @@ class _ReferenceInfo {
13141317
}
13151318
// Done.
13161319
return type;
1320+
} else if (element is GenericTypeAliasElementHandle) {
1321+
GenericTypeAliasElementImpl actualElement = element.actualElement;
1322+
List<DartType> argumentTypes =
1323+
new List.generate(numTypeArguments, getTypeArgument);
1324+
return actualElement.typeAfterSubstitution(argumentTypes);
13171325
} else if (element is FunctionTypedElement) {
13181326
if (element is FunctionTypeAliasElementHandle) {
13191327
List<DartType> typeArguments;
@@ -1839,6 +1847,11 @@ class _UnitResynthesizer {
18391847
summaryResynthesizer, location);
18401848
isDeclarableType = true;
18411849
break;
1850+
case ReferenceKind.genericFunctionTypedef:
1851+
element = new GenericTypeAliasElementHandle(
1852+
summaryResynthesizer, location);
1853+
isDeclarableType = true;
1854+
break;
18421855
case ReferenceKind.variable:
18431856
Element enclosingElement = enclosingInfo.element;
18441857
if (enclosingElement is ExecutableElement) {

pkg/analyzer/lib/src/summary/summarize_ast.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -799,11 +799,11 @@ class _SummarizeAstVisitor extends RecursiveAstVisitor {
799799
scopes.add(typeParameterScope);
800800
EntityRefBuilder b = new EntityRefBuilder();
801801
b.entityKind = EntityRefKind.genericFunctionType;
802+
b.typeParameters =
803+
serializeTypeParameters(node.typeParameters, typeParameterScope);
802804
b.syntheticReturnType = node.returnType == null
803805
? serializeDynamic()
804806
: serializeTypeName(node.returnType);
805-
b.typeParameters =
806-
serializeTypeParameters(node.typeParameters, typeParameterScope);
807807
b.syntheticParams = node.parameters.parameters
808808
.map((FormalParameter p) => p.accept(this) as UnlinkedParamBuilder)
809809
.toList();

pkg/analyzer/test/generated/non_error_resolver_driver_test.dart

-5
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,4 @@ main() {
1616
class NonErrorResolverTest_Driver extends NonErrorResolverTest {
1717
@override
1818
bool get enableNewAnalysisDriver => true;
19-
20-
@failingTest
21-
test_genericTypeAlias_fieldAndReturnType() async {
22-
return super.test_genericTypeAlias_fieldAndReturnType();
23-
}
2419
}

pkg/analyzer/test/generated/non_error_resolver_test.dart

+43-1
Original file line numberDiff line numberDiff line change
@@ -2158,7 +2158,7 @@ class B extends A implements Function {
21582158
verify([source]);
21592159
}
21602160

2161-
test_genericTypeAlias_fieldAndReturnType() async {
2161+
test_genericTypeAlias_fieldAndReturnType_noTypeParameters() async {
21622162
Source source = addSource(r'''
21632163
typedef Foo = int Function<T>(T x);
21642164
int foo<T>(T x) => 3;
@@ -2167,6 +2167,48 @@ void test1() {
21672167
bar()<String>("hello");
21682168
}
21692169
2170+
class A {
2171+
Foo f;
2172+
void test() {
2173+
f<String>("hello");
2174+
}
2175+
}
2176+
''');
2177+
await computeAnalysisResult(source);
2178+
assertNoErrors(source);
2179+
verify([source]);
2180+
}
2181+
2182+
test_genericTypeAlias_fieldAndReturnType_typeParameters_arguments() async {
2183+
Source source = addSource(r'''
2184+
typedef Foo<S> = S Function<T>(T x);
2185+
int foo<T>(T x) => 3;
2186+
Foo<int> bar() => foo;
2187+
void test1() {
2188+
bar()<String>("hello");
2189+
}
2190+
2191+
class A {
2192+
Foo<int> f;
2193+
void test() {
2194+
f<String>("hello");
2195+
}
2196+
}
2197+
''');
2198+
await computeAnalysisResult(source);
2199+
assertNoErrors(source);
2200+
verify([source]);
2201+
}
2202+
2203+
test_genericTypeAlias_fieldAndReturnType_typeParameters_noArguments() async {
2204+
Source source = addSource(r'''
2205+
typedef Foo<S> = S Function<T>(T x);
2206+
int foo<T>(T x) => 3;
2207+
Foo bar() => foo;
2208+
void test1() {
2209+
bar()<String>("hello");
2210+
}
2211+
21702212
class A {
21712213
Foo f;
21722214
void test() {

pkg/analyzer/test/src/summary/element_text.dart

+18-5
Original file line numberDiff line numberDiff line change
@@ -442,13 +442,26 @@ class _ElementWriter {
442442
writeDocumentation(e);
443443
writeMetadata(e, '', '\n');
444444

445-
buffer.write('typedef ');
446-
writeType2(e.returnType);
445+
if (e is GenericTypeAliasElement) {
446+
buffer.write('typedef ');
447+
writeName(e);
448+
writeTypeParameterElements(e.typeParameters);
447449

448-
writeName(e);
450+
buffer.write(' = ');
449451

450-
writeTypeParameterElements(e.typeParameters);
451-
writeParameterElements(e.parameters);
452+
writeType(e.function.returnType);
453+
buffer.write(' Function');
454+
writeTypeParameterElements(e.function.typeParameters);
455+
writeParameterElements(e.function.parameters);
456+
} else {
457+
buffer.write('typedef ');
458+
writeType2(e.returnType);
459+
460+
writeName(e);
461+
462+
writeTypeParameterElements(e.typeParameters);
463+
writeParameterElements(e.parameters);
464+
}
452465

453466
buffer.writeln(';');
454467
}

pkg/analyzer/test/src/summary/resynthesize_common.dart

+44-2
Original file line numberDiff line numberDiff line change
@@ -13860,8 +13860,50 @@ typedef dynamic F();
1386013860
}
1386113861

1386213862
test_typedef_generic() {
13863-
checkLibrary(
13864-
'typedef F<T> = Function<S>(List<S> list, Function<A>(A), T);');
13863+
var library = checkLibrary(
13864+
'typedef F<T> = int Function<S>(List<S> list, num Function<A>(A), T);');
13865+
if (isStrongMode) {
13866+
checkElementText(
13867+
library,
13868+
r'''
13869+
typedef F<T> = int Function<S>(List<S> list, <A>(A) → num , T );
13870+
''');
13871+
} else {
13872+
checkElementText(
13873+
library,
13874+
r'''
13875+
typedef F<T> = int Function<S>(List<S> list, <A>(A) → num , T );
13876+
''');
13877+
}
13878+
}
13879+
13880+
test_typedef_generic_asFieldType() {
13881+
shouldCompareLibraryElements = false;
13882+
var library = checkLibrary(r'''
13883+
typedef Foo<S> = S Function<T>(T x);
13884+
class A {
13885+
Foo<int> f;
13886+
}
13887+
''');
13888+
if (isStrongMode) {
13889+
checkElementText(
13890+
library,
13891+
r'''
13892+
typedef Foo<S> = S Function<T>(T x);
13893+
class A {
13894+
<T>(T) → int f;
13895+
}
13896+
''');
13897+
} else {
13898+
checkElementText(
13899+
library,
13900+
r'''
13901+
typedef Foo<S> = S Function<T>(T x);
13902+
class A {
13903+
<T>(T) → int f;
13904+
}
13905+
''');
13906+
}
1386513907
}
1386613908

1386713909
test_typedef_parameter_parameters() {

0 commit comments

Comments
 (0)