Add optional FunctionType.positionalParameterNames and use them to resynthesize function-type formal parameters in Analyzer.

This will be also used as an alternative approach to support of
typedefs in Analyzer. The previous one was reverted in
e431e93e87, because it caused problems
during storing parameters of generic Function(s).

R=ahe@google.com, brianwilkerson@google.com, sigmund@google.com
BUG=

Review-Url: https://codereview.chromium.org/2985293002 .
This commit is contained in:
Konstantin Shcheglov 2017-07-31 14:09:18 -07:00
parent 41fb3c6d16
commit 66663f7fd6
9 changed files with 85 additions and 54 deletions

View file

@ -8216,9 +8216,6 @@ class ParameterElementImpl extends VariableElementImpl
@override
DartType get type {
if (_kernel != null) {
return _type ??= enclosingUnit._kernelContext.getType(this, _kernel.type);
}
_resynthesizeTypeAndParameters();
return super.type;
}
@ -8330,6 +8327,36 @@ class ParameterElementImpl extends VariableElementImpl
* been build yet, build them and remember in the corresponding fields.
*/
void _resynthesizeTypeAndParameters() {
if (_kernel != null && _type == null) {
kernel.DartType type = _kernel.type;
_type = enclosingUnit._kernelContext.getType(this, type);
if (type is kernel.FunctionType) {
_parameters = new List<ParameterElement>(
type.positionalParameters.length + type.namedParameters.length);
int index = 0;
for (int i = 0; i < type.positionalParameters.length; i++) {
String name = i < type.positionalParameterNames.length
? type.positionalParameterNames[i]
: null;
_parameters[index++] = new ParameterElementImpl.forKernel(
enclosingElement,
new kernel.VariableDeclaration(name,
type: type.positionalParameters[i]),
i < type.requiredParameterCount
? ParameterKind.REQUIRED
: ParameterKind.POSITIONAL);
}
for (int i = 0; i < type.namedParameters.length; i++) {
_parameters[index++] = new ParameterElementImpl.forKernel(
enclosingElement,
new kernel.VariableDeclaration(type.namedParameters[i].name,
type: type.namedParameters[i].type),
ParameterKind.NAMED);
}
} else {
_parameters = const <ParameterElement>[];
}
}
if (_unlinkedParam != null && _declaredType == null && _type == null) {
if (_unlinkedParam.isFunctionTyped) {
CompilationUnitElementImpl enclosingUnit = this.enclosingUnit;

View file

@ -6753,12 +6753,24 @@ class C extends D {
}
''');
if (isStrongMode) {
checkElementText(library, r'''
if (isSharedFrontEnd) {
// Front-end copies FunctionType instances, which means that if it has
// parameter names in superclass, then we have names also in the
// subclass.
checkElementText(library, r'''
import 'a.dart';
class C extends D {
void f(int x, int g(String s)) {}
}
''');
} else {
checkElementText(library, r'''
import 'a.dart';
class C extends D {
void f(int x, (String) int g) {}
}
''');
}
} else {
checkElementText(library, r'''
import 'a.dart';

View file

@ -467,29 +467,19 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_function_entry_point_in_part();
}
@failingTest
test_function_parameter_parameters() async {
await super.test_function_parameter_parameters();
}
@failingTest
test_function_type_parameter_with_function_typed_parameter() async {
await super.test_function_type_parameter_with_function_typed_parameter();
}
@failingTest
test_futureOr_const() async {
await super.test_futureOr_const();
}
@failingTest
test_genericFunction_asFunctionTypedParameterReturnType() async {
await super.test_genericFunction_asFunctionTypedParameterReturnType();
test_genericFunction_asGenericFunctionReturnType() async {
await super.test_genericFunction_asGenericFunctionReturnType();
}
@failingTest
test_genericFunction_asGenericFunctionReturnType() async {
await super.test_genericFunction_asGenericFunctionReturnType();
test_genericFunction_asParameterType() async {
await super.test_genericFunction_asParameterType();
}
@failingTest
@ -579,17 +569,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
.test_inferred_type_refers_to_method_function_typed_parameter_type();
}
@failingTest
test_inferred_type_refers_to_nested_function_typed_param() async {
await super.test_inferred_type_refers_to_nested_function_typed_param();
}
@failingTest
test_inferred_type_refers_to_nested_function_typed_param_named() async {
await super
.test_inferred_type_refers_to_nested_function_typed_param_named();
}
@failingTest
test_inferred_type_refers_to_setter_function_typed_parameter_type() async {
await super
@ -601,12 +580,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_inferredType_definedInSdkLibraryPart();
}
@failingTest
test_inferredType_usesSyntheticFunctionType_functionTypedParam() async {
await super
.test_inferredType_usesSyntheticFunctionType_functionTypedParam();
}
@failingTest
test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
await super.test_instantiateToBounds_boundRefersToEarlierTypeArgument();
@ -774,11 +747,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_metadata_typeParameter_ofTypedef();
}
@failingTest
test_method_type_parameter_with_function_typed_parameter() async {
await super.test_method_type_parameter_with_function_typed_parameter();
}
@failingTest
test_parameter_checked() async {
await super.test_parameter_checked();
@ -799,16 +767,6 @@ class ResynthesizeKernelStrongTest extends ResynthesizeTest {
await super.test_parameter_covariant_inherited();
}
@failingTest
test_parameter_parameters() async {
await super.test_parameter_parameters();
}
@failingTest
test_parameter_parameters_in_generic_class() async {
await super.test_parameter_parameters_in_generic_class();
}
@failingTest
test_parts() async {
await super.test_parts();

View file

@ -41,6 +41,7 @@ class KernelFunctionTypeBuilder extends FunctionTypeBuilder
DartType builtReturnType =
returnType?.build(library) ?? const DynamicType();
List<DartType> positionalParameters = <DartType>[];
List<String> positionalParameterNames = <String>[];
List<NamedType> namedParameters;
int requiredParameterCount = 0;
if (formals != null) {
@ -48,6 +49,7 @@ class KernelFunctionTypeBuilder extends FunctionTypeBuilder
DartType type = formal.type?.build(library) ?? const DynamicType();
if (formal.isPositional) {
positionalParameters.add(type);
positionalParameterNames.add(formal.name ?? '');
if (formal.isRequired) requiredParameterCount++;
} else if (formal.isNamed) {
namedParameters ??= <NamedType>[];
@ -68,7 +70,8 @@ class KernelFunctionTypeBuilder extends FunctionTypeBuilder
return new FunctionType(positionalParameters, builtReturnType,
namedParameters: namedParameters ?? const <NamedType>[],
typeParameters: typeParameters ?? const <TypeParameter>[],
requiredParameterCount: requiredParameterCount);
requiredParameterCount: requiredParameterCount,
positionalParameterNames: positionalParameterNames);
}
Supertype buildSupertype(LibraryBuilder library) {

View file

@ -4095,13 +4095,20 @@ class FunctionType extends DartType {
final int requiredParameterCount;
final List<DartType> positionalParameters;
final List<NamedType> namedParameters; // Must be sorted.
/// The optional names of [positionalParameters], not `null`, but might be
/// empty if information is not available.
@informative
final List<String> positionalParameterNames;
final DartType returnType;
int _hashCode;
FunctionType(List<DartType> positionalParameters, this.returnType,
{this.namedParameters: const <NamedType>[],
this.typeParameters: const <TypeParameter>[],
int requiredParameterCount})
int requiredParameterCount,
this.positionalParameterNames: const <String>[]})
: this.positionalParameters = positionalParameters,
this.requiredParameterCount =
requiredParameterCount ?? positionalParameters.length;

View file

@ -1163,17 +1163,21 @@ class BinaryBuilder {
var totalParameterCount = readUInt();
var positional = readDartTypeList();
var named = readNamedTypeList();
var positionalNames = readStringReferenceList();
assert(positional.length + named.length == totalParameterCount);
var returnType = readDartType();
typeParameterStack.length = typeParameterStackHeight;
return new FunctionType(positional, returnType,
typeParameters: typeParameters,
requiredParameterCount: requiredParameterCount,
namedParameters: named);
namedParameters: named,
positionalParameterNames: positionalNames);
case Tag.SimpleFunctionType:
var positional = readDartTypeList();
var positionalNames = readStringReferenceList();
var returnType = readDartType();
return new FunctionType(positional, returnType);
return new FunctionType(positional, returnType,
positionalParameterNames: positionalNames);
case Tag.TypeParameterType:
int index = readUInt();
readUInt(); // offset of parameter list in the binary.

View file

@ -1119,6 +1119,7 @@ class BinaryPrinter extends Visitor {
node.namedParameters.isEmpty) {
writeByte(Tag.SimpleFunctionType);
writeNodeList(node.positionalParameters);
writeStringReferenceList(node.positionalParameterNames);
writeNode(node.returnType);
} else {
writeByte(Tag.FunctionType);
@ -1129,6 +1130,7 @@ class BinaryPrinter extends Visitor {
node.positionalParameters.length + node.namedParameters.length);
writeNodeList(node.positionalParameters);
writeNodeList(node.namedParameters);
writeStringReferenceList(node.positionalParameterNames);
writeNode(node.returnType);
_typeParameterIndexer.exit(node.typeParameters);
}
@ -1389,6 +1391,12 @@ class StringIndexer extends RecursiveVisitor<Null> {
super.visitField(node);
}
@override
visitFunctionType(FunctionType node) {
node.positionalParameterNames.forEach(put);
super.visitFunctionType(node);
}
visitNamedExpression(NamedExpression node) {
put(node.name);
node.visitChildren(this);

View file

@ -1095,6 +1095,7 @@ void StreamingScopeBuilder::VisitFunctionType(bool simple) {
}
}
builder_->SkipListOfStrings(); // read positional parameter names.
VisitDartType(); // read return type.
}
@ -1570,6 +1571,8 @@ void StreamingDartTypeTranslator::BuildFunctionType(bool simple) {
}
}
builder_->SkipListOfStrings(); // read positional parameter names.
BuildTypeInternal(); // read return type.
if (result_.IsMalformed()) {
result_ = AbstractType::dynamic_type().raw();
@ -3807,6 +3810,7 @@ void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) {
}
}
SkipListOfStrings(); // read positional parameter names.
SkipDartType(); // read return type.
}
@ -3824,6 +3828,13 @@ void StreamingFlowGraphBuilder::SkipListOfDartTypes() {
}
}
void StreamingFlowGraphBuilder::SkipListOfStrings() {
intptr_t list_length = ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {
SkipStringReference(); // read ith string index.
}
}
void StreamingFlowGraphBuilder::SkipListOfVariableDeclarations() {
intptr_t list_length = ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {

View file

@ -403,6 +403,7 @@ class StreamingFlowGraphBuilder {
void SkipFunctionType(bool simple);
void SkipListOfExpressions();
void SkipListOfDartTypes();
void SkipListOfStrings();
void SkipListOfVariableDeclarations();
void SkipTypeParametersList();
void SkipExpression();