Skip to content

Commit c7dd9c1

Browse files
committed
Perform top-level inference using elements.
This is still not a valid implementation, because for example it does no inheritance inference, or ordering. But we need elements for inheritance, so this change is required. [email protected], [email protected] Change-Id: Ia290a9034cbda753af60e74f6d9120d9c38bf203 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98381 Reviewed-by: Brian Wilkerson <[email protected]>
1 parent cd34ec9 commit c7dd9c1

File tree

4 files changed

+160
-128
lines changed

4 files changed

+160
-128
lines changed

pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,7 @@ class SourceLibraryBuilder {
254254
}
255255

256256
void performTopLevelInference() {
257-
for (var unit in units) {
258-
TopLevelInference(linker, reference, unit).infer();
259-
}
257+
TopLevelInference(linker, reference).infer();
260258
}
261259

262260
void resolveConstructors() {

pkg/analyzer/lib/src/summary2/top_level_inference.dart

Lines changed: 148 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
6+
import 'package:analyzer/dart/element/element.dart';
67
import 'package:analyzer/dart/element/type.dart';
78
import 'package:analyzer/src/dart/element/element.dart';
89
import 'package:analyzer/src/dart/element/type.dart';
910
import 'package:analyzer/src/dart/resolver/scope.dart';
1011
import 'package:analyzer/src/summary/format.dart';
1112
import 'package:analyzer/src/summary/idl.dart';
1213
import 'package:analyzer/src/summary2/ast_resolver.dart';
13-
import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
1414
import 'package:analyzer/src/summary2/link.dart';
15+
import 'package:analyzer/src/summary2/linked_unit_context.dart';
1516
import 'package:analyzer/src/summary2/reference.dart';
1617

1718
DartType _dynamicIfNull(DartType type) {
@@ -21,116 +22,121 @@ DartType _dynamicIfNull(DartType type) {
2122
return type;
2223
}
2324

25+
/// TODO(scheglov) This is not a valid implementation of top-level inference.
26+
/// See https://bit.ly/2HYfAKg
27+
///
28+
/// In general inference of constructor field formal parameters should be
29+
/// interleaved with inference of fields. There are resynthesis tests that
30+
/// fail because of this limitation.
2431
class TopLevelInference {
2532
final Linker linker;
26-
final Reference libraryRef;
27-
final UnitBuilder unit;
33+
LibraryElementImpl _libraryElement;
34+
35+
Scope _libraryScope;
36+
Scope _nameScope;
37+
38+
LinkedUnitContext _linkedContext;
2839
CompilationUnitElementImpl unitElement;
2940

30-
TopLevelInference(this.linker, this.libraryRef, this.unit) {
31-
unitElement = linker.elementFactory.elementOfReference(
32-
libraryRef.getChild('@unit').getChild('${unit.uri}'),
33-
);
41+
TopLevelInference(this.linker, Reference libraryRef) {
42+
_libraryElement = linker.elementFactory.elementOfReference(libraryRef);
43+
_libraryScope = LibraryScope(_libraryElement);
44+
_nameScope = _libraryScope;
3445
}
3546

3647
void infer() {
48+
_setOmittedReturnTypes();
3749
_inferFieldsTemporary();
3850
_inferConstructorFieldFormals();
3951
}
4052

4153
void _inferConstructorFieldFormals() {
42-
_visitClassList((unitDeclaration) {
43-
var members = unitDeclaration.classOrMixinDeclaration_members;
44-
45-
var fields = <String, LinkedNodeType>{};
46-
_visitClassFields(unitDeclaration, (field) {
47-
var name = unit.context.getVariableName(field);
48-
var type = field.variableDeclaration_type2;
49-
if (type == null) {
50-
throw StateError('Field $name should have a type.');
54+
for (CompilationUnitElementImpl unit in _libraryElement.units) {
55+
this.unitElement = unit;
56+
_linkedContext = unit.linkedContext;
57+
58+
for (var class_ in unit.types) {
59+
var fields = <String, LinkedNodeType>{};
60+
for (FieldElementImpl field in class_.fields) {
61+
if (field.isSynthetic) continue;
62+
63+
var name = field.name;
64+
var type = field.linkedNode.variableDeclaration_type2;
65+
if (type == null) {
66+
throw StateError('Field $name should have a type.');
67+
}
68+
fields[name] ??= type;
5169
}
52-
fields[name] ??= type;
53-
});
54-
55-
for (var member in members) {
56-
if (member.kind == LinkedNodeKind.constructorDeclaration) {
57-
for (var parameter in member.constructorDeclaration_parameters
58-
.formalParameterList_parameters) {
59-
if (parameter.kind == LinkedNodeKind.defaultFormalParameter) {
60-
parameter = parameter.defaultFormalParameter_parameter;
61-
}
62-
if (parameter.kind == LinkedNodeKind.fieldFormalParameter &&
63-
parameter.fieldFormalParameter_type2 == null) {
64-
var name = unit.context.getSimpleName(
65-
parameter.normalFormalParameter_identifier,
66-
);
67-
var type = fields[name];
68-
if (type == null) {
69-
type = LinkedNodeTypeBuilder(
70-
kind: LinkedNodeTypeKind.dynamic_,
71-
);
70+
71+
for (ConstructorElementImpl constructor in class_.constructors) {
72+
for (ParameterElementImpl parameter in constructor.parameters) {
73+
if (parameter is FieldFormalParameterElement) {
74+
LinkedNodeBuilder parameterNode = parameter.linkedNode;
75+
if (parameterNode.kind == LinkedNodeKind.defaultFormalParameter) {
76+
parameterNode = parameterNode.defaultFormalParameter_parameter;
77+
}
78+
79+
if (parameterNode.fieldFormalParameter_type2 == null) {
80+
var name = parameter.name;
81+
var type = fields[name];
82+
if (type == null) {
83+
type = LinkedNodeTypeBuilder(
84+
kind: LinkedNodeTypeKind.dynamic_,
85+
);
86+
}
87+
parameterNode.fieldFormalParameter_type2 = type;
7288
}
73-
parameter.fieldFormalParameter_type2 = type;
7489
}
7590
}
7691
}
7792
}
78-
});
93+
}
7994
}
8095

8196
void _inferFieldsTemporary() {
82-
var unitDeclarations = unit.node.compilationUnit_declarations;
83-
for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
84-
if (unitDeclaration.kind == LinkedNodeKind.classDeclaration ||
85-
unitDeclaration.kind == LinkedNodeKind.mixinDeclaration) {
86-
_visitClassFields(unitDeclaration, (field) {
87-
// var name = unit.context.getVariableName(field);
88-
// TODO(scheglov) Use inheritance
89-
// TODO(scheglov) infer in the correct order
90-
if (field.variableDeclaration_type2 == null) {
91-
_inferVariableTypeFromInitializerTemporary(field);
92-
}
93-
});
94-
95-
var members = unitDeclaration.classOrMixinDeclaration_members;
96-
for (var member in members) {
97-
if (member.kind == LinkedNodeKind.methodDeclaration) {
98-
// TODO(scheglov) Use inheritance
99-
if (member.methodDeclaration_returnType2 == null) {
100-
if (unit.context.isSetter(member)) {
101-
member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
102-
kind: LinkedNodeTypeKind.void_,
103-
);
104-
} else {
105-
member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
106-
kind: LinkedNodeTypeKind.dynamic_,
107-
);
108-
}
109-
}
110-
}
111-
}
112-
} else if (unitDeclaration.kind == LinkedNodeKind.functionDeclaration) {
113-
if (unit.context.isSetter(unitDeclaration)) {
114-
unitDeclaration.functionDeclaration_returnType2 =
115-
LinkedNodeTypeBuilder(
116-
kind: LinkedNodeTypeKind.void_,
117-
);
118-
}
119-
} else if (unitDeclaration.kind ==
120-
LinkedNodeKind.topLevelVariableDeclaration) {
121-
var variableList =
122-
unitDeclaration.topLevelVariableDeclaration_variableList;
123-
for (var variable in variableList.variableDeclarationList_variables) {
124-
// TODO(scheglov) infer in the correct order
125-
if (variable.variableDeclaration_type2 == null ||
126-
unit.context.isConst(variable)) {
127-
_inferVariableTypeFromInitializerTemporary(variable);
128-
}
97+
for (CompilationUnitElementImpl unit in _libraryElement.units) {
98+
this.unitElement = unit;
99+
_linkedContext = unit.linkedContext;
100+
101+
for (var class_ in unit.types) {
102+
_inferFieldsTemporaryClass(class_);
103+
}
104+
105+
for (var mixin_ in unit.mixins) {
106+
_inferFieldsTemporaryClass(mixin_);
107+
}
108+
109+
for (TopLevelVariableElementImpl variable in unit.topLevelVariables) {
110+
if (variable.isSynthetic) continue;
111+
LinkedNodeBuilder variableNode = variable.linkedNode;
112+
if (variableNode.variableDeclaration_type2 == null ||
113+
_linkedContext.isConst(variableNode)) {
114+
_inferVariableTypeFromInitializerTemporary(variableNode);
129115
}
130116
}
131117
}
132118
}
133119

120+
void _inferFieldsTemporaryClass(ClassElement class_) {
121+
var prevScope = _nameScope;
122+
123+
_nameScope = TypeParameterScope(_nameScope, class_);
124+
_nameScope = ClassScope(_nameScope, class_);
125+
126+
for (FieldElementImpl field in class_.fields) {
127+
if (field.isSynthetic) continue;
128+
var fieldNode = field.linkedNode;
129+
130+
// TODO(scheglov) Use inheritance
131+
// TODO(scheglov) infer in the correct order
132+
if (fieldNode.variableDeclaration_type2 == null) {
133+
_inferVariableTypeFromInitializerTemporary(fieldNode);
134+
}
135+
}
136+
137+
_nameScope = prevScope;
138+
}
139+
134140
void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
135141
var unresolvedNode = node.variableDeclaration_initializer;
136142

@@ -141,15 +147,11 @@ class TopLevelInference {
141147
return;
142148
}
143149

144-
var expression = unit.context.readInitializer(unitElement, node);
150+
var expression = _linkedContext.readInitializer(unitElement, node);
145151
astFactory.expressionFunctionBody(null, null, expression, null);
146152

147-
// TODO(scheglov) can be shared for the whole library
148-
var libraryElement = linker.elementFactory.elementOfReference(libraryRef);
149-
var libraryScope = LibraryScope(libraryElement);
150-
var astResolver = AstResolver(linker, libraryElement, libraryScope);
151-
152-
var resolvedNode = astResolver.resolve(unit.context, expression);
153+
var astResolver = AstResolver(linker, _libraryElement, _nameScope);
154+
var resolvedNode = astResolver.resolve(_linkedContext, expression);
153155
node.variableDeclaration_initializer = resolvedNode;
154156

155157
if (node.variableDeclaration_type2 == null) {
@@ -163,26 +165,66 @@ class TopLevelInference {
163165
}
164166
}
165167

166-
void _visitClassFields(
167-
LinkedNode class_, void Function(LinkedNodeBuilder) f) {
168-
var members = class_.classOrMixinDeclaration_members;
168+
void _setOmittedReturnTypes() {
169+
for (CompilationUnitElementImpl unit in _libraryElement.units) {
170+
this.unitElement = unit;
171+
_linkedContext = unit.linkedContext;
172+
173+
for (var class_ in unit.types) {
174+
_setOmittedReturnTypesClass(class_);
175+
}
176+
177+
for (var mixin_ in unit.mixins) {
178+
_setOmittedReturnTypesClass(mixin_);
179+
}
180+
181+
for (FunctionElementImpl function in unit.functions) {
182+
LinkedNodeBuilder functionNode = function.linkedNode;
183+
if (functionNode.functionDeclaration_returnType == null) {
184+
functionNode.functionDeclaration_returnType2 = LinkedNodeTypeBuilder(
185+
kind: LinkedNodeTypeKind.dynamic_,
186+
);
187+
}
188+
}
169189

170-
for (var member in members) {
171-
if (member.kind == LinkedNodeKind.fieldDeclaration) {
172-
var variableList = member.fieldDeclaration_fields;
173-
for (var field in variableList.variableDeclarationList_variables) {
174-
f(field);
190+
for (PropertyAccessorElementImpl accessor in unit.accessors) {
191+
if (accessor.isSynthetic) continue;
192+
if (accessor.isSetter) {
193+
LinkedNodeBuilder node = accessor.linkedNode;
194+
if (node.functionDeclaration_returnType == null) {
195+
node.functionDeclaration_returnType2 = LinkedNodeTypeBuilder(
196+
kind: LinkedNodeTypeKind.void_,
197+
);
198+
}
175199
}
176200
}
177201
}
178202
}
179203

180-
void _visitClassList(void Function(LinkedNodeBuilder) f) {
181-
var unitDeclarations = unit.node.compilationUnit_declarations;
182-
for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
183-
if (unitDeclaration.kind == LinkedNodeKind.classDeclaration ||
184-
unitDeclaration.kind == LinkedNodeKind.mixinDeclaration) {
185-
f(unitDeclaration);
204+
void _setOmittedReturnTypesClass(ClassElement class_) {
205+
for (MethodElementImpl method in class_.methods) {
206+
LinkedNodeBuilder methodNode = method.linkedNode;
207+
if (methodNode.methodDeclaration_returnType == null) {
208+
methodNode.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
209+
kind: LinkedNodeTypeKind.dynamic_,
210+
);
211+
}
212+
}
213+
214+
for (PropertyAccessorElementImpl accessor in class_.accessors) {
215+
if (accessor.isSynthetic) continue;
216+
217+
LinkedNodeBuilder accessorNode = accessor.linkedNode;
218+
if (accessorNode.methodDeclaration_returnType != null) continue;
219+
220+
if (accessor.isSetter) {
221+
accessorNode.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
222+
kind: LinkedNodeTypeKind.void_,
223+
);
224+
} else {
225+
accessorNode.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
226+
kind: LinkedNodeTypeKind.dynamic_,
227+
);
186228
}
187229
}
188230
}

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,6 @@ T max<T extends num>(T a, T b) => null;
269269
await super.test_const_reference_topLevelVariable_imported_withPrefix();
270270
}
271271

272-
@override
273-
@failingTest
274-
test_const_reference_type_typeParameter() async {
275-
await super.test_const_reference_type_typeParameter();
276-
}
277-
278272
@override
279273
@failingTest
280274
test_const_topLevel_typedList_typedefArgument() async {
@@ -287,12 +281,6 @@ T max<T extends num>(T a, T b) => null;
287281
await super.test_constExpr_pushReference_field_simpleIdentifier();
288282
}
289283

290-
@override
291-
@failingTest
292-
test_constExpr_pushReference_staticMethod_simpleIdentifier() async {
293-
await super.test_constExpr_pushReference_staticMethod_simpleIdentifier();
294-
}
295-
296284
@override
297285
@failingTest
298286
test_constructor_redirected_factory_named_generic() async {
@@ -697,12 +685,6 @@ T max<T extends num>(T a, T b) => null;
697685
await super.test_syntheticFunctionType_genericClosure();
698686
}
699687

700-
@override
701-
@failingTest
702-
test_syntheticFunctionType_inGenericClass() async {
703-
await super.test_syntheticFunctionType_inGenericClass();
704-
}
705-
706688
@override
707689
@failingTest
708690
test_type_inference_based_on_loadLibrary() async {

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3733,14 +3733,24 @@ class C {
37333733
static m() {}
37343734
}
37353735
''');
3736-
checkElementText(library, r'''
3736+
if (isAstBasedSummary) {
3737+
checkElementText(library, r'''
3738+
class C {
3739+
static const () → dynamic a =
3740+
m/*location: test.dart;C;m*/;
3741+
static dynamic m() {}
3742+
}
3743+
''');
3744+
} else {
3745+
checkElementText(library, r'''
37373746
class C {
37383747
static const () → dynamic a =
37393748
C/*location: test.dart;C*/.
37403749
m/*location: test.dart;C;m*/;
37413750
static dynamic m() {}
37423751
}
37433752
''');
3753+
}
37443754
}
37453755

37463756
test_constructor_documented() async {

0 commit comments

Comments
 (0)