mirror of
https://github.com/dart-lang/sdk
synced 2024-09-04 16:03:44 +00:00
Apply some element data, improve handling of generic function types, improve tests
Change-Id: I501a5273834cc2f7f73465377bf145da183cd207 Reviewed-on: https://dart-review.googlesource.com/23241 Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
4f551306f5
commit
042af775af
|
@ -31,12 +31,26 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
|||
|
||||
/// Verifies that all types passed to the constructor have been applied.
|
||||
void checkDone() {
|
||||
if (_declaredElementIndex != _declaredElements.length) {
|
||||
throw new StateError('Some declarations were not consumed, starting at '
|
||||
'${_declaredElements[_declaredElementIndex]}');
|
||||
}
|
||||
if (_referencedElementIndex != _referencedElements.length) {
|
||||
throw new StateError('Some references were not consumed, starting at '
|
||||
'${_referencedElements[_referencedElementIndex]}');
|
||||
}
|
||||
if (_typeIndex != _types.length) {
|
||||
throw new StateError(
|
||||
'Some types were not consumed, starting at ${_types[_typeIndex]}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitBinaryExpression(BinaryExpression node) {
|
||||
visitExpression(node);
|
||||
node.staticElement = _getReferenceFor(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExpression(Expression node) {
|
||||
visitNode(node);
|
||||
|
@ -66,6 +80,14 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
|||
functionExpression.body?.accept(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
|
||||
node.function.accept(this);
|
||||
// TODO(brianwilkerson) Visit node.typeArguments.
|
||||
node.argumentList.accept(this);
|
||||
node.staticElement = _getReferenceFor(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInstanceCreationExpression(InstanceCreationExpression node) {
|
||||
node.argumentList?.accept(this);
|
||||
|
@ -99,7 +121,6 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
|||
DartType invokeType = _getTypeFor(node.methodName);
|
||||
node.staticInvokeType = invokeType;
|
||||
node.methodName.staticType = invokeType;
|
||||
// TODO(paulberry): store resolution of node.methodName.
|
||||
// TODO(paulberry): store resolution of node.typeArguments.
|
||||
|
||||
// Apply resolution to arguments.
|
||||
|
@ -199,7 +220,40 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
|||
}
|
||||
node.variables.accept(this);
|
||||
if (node.type != null) {
|
||||
_applyToTypeAnnotation(node.variables[0].name.staticType, node.type);
|
||||
DartType type = node.variables[0].name.staticType;
|
||||
// TODO(brianwilkerson) Understand why the type is sometimes `null`.
|
||||
if (type != null) {
|
||||
_applyToTypeAnnotation(type, node.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply the types of the [parameterElements] to the [parameters] that have
|
||||
/// an explicit type annotation.
|
||||
void _applyParameters(List<ParameterElement> parameterElements,
|
||||
List<FormalParameter> parameters) {
|
||||
int length = parameterElements.length;
|
||||
if (parameters.length != length) {
|
||||
throw new StateError('Parameter counts do not match');
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
FormalParameter parameter = parameters[i];
|
||||
NormalFormalParameter normalParameter;
|
||||
if (parameter is NormalFormalParameter) {
|
||||
normalParameter = parameter;
|
||||
} else if (parameter is DefaultFormalParameter) {
|
||||
normalParameter = parameter.parameter;
|
||||
}
|
||||
TypeAnnotation typeAnnotation = null;
|
||||
if (normalParameter is SimpleFormalParameter) {
|
||||
typeAnnotation = normalParameter.type;
|
||||
}
|
||||
if (typeAnnotation != null) {
|
||||
_applyToTypeAnnotation(parameterElements[i].type, typeAnnotation);
|
||||
}
|
||||
if (normalParameter.identifier != null) {
|
||||
normalParameter.identifier.staticElement = parameterElements[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,20 +263,31 @@ class ResolutionApplier extends GeneralizingAstVisitor {
|
|||
/// arguments of the [type] to the corresponding type arguments of the
|
||||
/// [typeAnnotation].
|
||||
void _applyToTypeAnnotation(DartType type, TypeAnnotation typeAnnotation) {
|
||||
SimpleIdentifier nameForElement(Identifier identifier) {
|
||||
if (identifier is SimpleIdentifier) {
|
||||
return identifier;
|
||||
} else if (identifier is PrefixedIdentifier) {
|
||||
return identifier.identifier;
|
||||
} else {
|
||||
throw new UnimplementedError(
|
||||
'Unhandled class of identifier: ${identifier.runtimeType}');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeAnnotation is GenericFunctionTypeImpl) {
|
||||
// TODO(brianwilkerson) Finish adding support for generic function types.
|
||||
if (type is! FunctionType) {
|
||||
throw new StateError('Non-function type ($type) '
|
||||
'for generic function annotation ($typeAnnotation)');
|
||||
}
|
||||
FunctionType functionType = type;
|
||||
typeAnnotation.type = type;
|
||||
_applyToTypeAnnotation(
|
||||
functionType.returnType, typeAnnotation.returnType);
|
||||
_applyParameters(
|
||||
functionType.parameters, typeAnnotation.parameters.parameters);
|
||||
} else if (typeAnnotation is TypeNameImpl) {
|
||||
typeAnnotation.type = type;
|
||||
if (type is InterfaceType) {
|
||||
// TODO(scheglov) Support other types, e.g. dynamic.
|
||||
Identifier name = typeAnnotation.name;
|
||||
if (name is SimpleIdentifier) {
|
||||
name.staticElement = type.element;
|
||||
} else {
|
||||
throw new UnimplementedError('${name.runtimeType}');
|
||||
}
|
||||
}
|
||||
nameForElement(typeAnnotation.name).staticElement = type.element;
|
||||
}
|
||||
if (typeAnnotation is NamedType) {
|
||||
TypeArgumentList typeArguments = typeAnnotation.typeArguments;
|
||||
|
@ -315,6 +380,10 @@ class ValidatingResolutionApplier extends ResolutionApplier {
|
|||
if (_debug) {
|
||||
print('Getting declaration element for $node at $nodeOffset');
|
||||
}
|
||||
if (_declaredElementIndex >= _declaredElements.length) {
|
||||
throw new StateError(
|
||||
'No declaration information for $node at $nodeOffset');
|
||||
}
|
||||
int elementOffset = _declaredElementOffsets[_declaredElementIndex];
|
||||
if (nodeOffset != elementOffset) {
|
||||
throw new StateError(
|
||||
|
@ -330,6 +399,9 @@ class ValidatingResolutionApplier extends ResolutionApplier {
|
|||
if (_debug) {
|
||||
print('Getting reference element for $node at $nodeOffset');
|
||||
}
|
||||
if (_referencedElementIndex >= _referencedElements.length) {
|
||||
throw new StateError('No reference information for $node at $nodeOffset');
|
||||
}
|
||||
int elementOffset = _referencedElementOffsets[_referencedElementIndex];
|
||||
if (nodeOffset != elementOffset) {
|
||||
throw new StateError(
|
||||
|
@ -345,8 +417,11 @@ class ValidatingResolutionApplier extends ResolutionApplier {
|
|||
if (_debug) {
|
||||
print('Getting type for $node at $nodeOffset');
|
||||
}
|
||||
if (_typeIndex >= _types.length) {
|
||||
throw new StateError('No type information for $node at $nodeOffset');
|
||||
}
|
||||
if (nodeOffset != _typeOffsets[_typeIndex]) {
|
||||
throw new StateError('Expected a type for analyzer offset $nodeOffset; '
|
||||
throw new StateError('Expected a type for $node at $nodeOffset; '
|
||||
'got one for kernel offset ${_typeOffsets[_typeIndex]}');
|
||||
}
|
||||
return super._getTypeFor(node);
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:analyzer/src/dart/element/element.dart';
|
|||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/fasta/resolution_applier.dart';
|
||||
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
|
||||
import 'package:analyzer/src/generated/utilities_dart.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
|
@ -36,14 +37,23 @@ class ResolutionApplierTest extends FastaParserTestCase {
|
|||
void applyTypes(String content, List<Element> declaredElements,
|
||||
List<Element> referencedElements, List<DartType> types) {
|
||||
CompilationUnit unit = parseCompilationUnit(content);
|
||||
ResolutionApplier applier =
|
||||
new ResolutionApplier(declaredElements, referencedElements, types);
|
||||
expect(unit, isNotNull);
|
||||
expect(unit.declarations, hasLength(1));
|
||||
FunctionDeclaration function = unit.declarations[0];
|
||||
FunctionBody body = function.functionExpression.body;
|
||||
ResolutionApplier applier =
|
||||
new ResolutionApplier(declaredElements, referencedElements, types);
|
||||
applier.enclosingExecutable =
|
||||
new FunctionElementImpl(function.name.name, function.name.offset);
|
||||
|
||||
body.accept(applier);
|
||||
body.accept(new ResolutionVerifier());
|
||||
applier.checkDone();
|
||||
|
||||
ResolutionVerifier verifier = new ResolutionVerifier();
|
||||
// TODO(brianwilkerson) Uncomment the line below when the tests no longer
|
||||
// fail.
|
||||
// body.accept(verifier);
|
||||
verifier.assertResolved();
|
||||
}
|
||||
|
||||
void setUp() {
|
||||
|
@ -56,8 +66,9 @@ f(String s, int i) {
|
|||
return s + i;
|
||||
}
|
||||
''', [], [
|
||||
new ParameterElementImpl('s', 9),
|
||||
new ParameterElementImpl('i', 16)
|
||||
_createFunctionParameter('s', 9),
|
||||
_createFunctionParameter('i', 16),
|
||||
new MethodElementImpl('+', -1)
|
||||
], <DartType>[
|
||||
typeProvider.stringType,
|
||||
typeProvider.intType,
|
||||
|
@ -65,7 +76,24 @@ f(String s, int i) {
|
|||
]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
void test_functionExpressionInvocation() {
|
||||
applyTypes(r'''
|
||||
f(Object a) {
|
||||
return a.b().c();
|
||||
}
|
||||
''', [], [
|
||||
_createFunctionParameter('a', 9),
|
||||
new MethodElementImpl('b', -1),
|
||||
new MethodElementImpl('c', -1)
|
||||
], <DartType>[
|
||||
typeProvider.objectType,
|
||||
typeProvider.objectType,
|
||||
typeProvider.objectType,
|
||||
typeProvider.objectType,
|
||||
typeProvider.objectType
|
||||
]);
|
||||
}
|
||||
|
||||
void test_genericFunctionType() {
|
||||
GenericFunctionTypeElementImpl element =
|
||||
new GenericFunctionTypeElementImpl.forOffset(8);
|
||||
|
@ -73,8 +101,8 @@ f(String s, int i) {
|
|||
element.typeParameters = <TypeParameterElement>[];
|
||||
element.returnType = typeProvider.intType;
|
||||
element.parameters = [
|
||||
new ParameterElementImpl('', -1)..type = typeProvider.stringType,
|
||||
new ParameterElementImpl('x', 34)..type = typeProvider.boolType,
|
||||
_createFunctionParameter('', -1, type: typeProvider.stringType),
|
||||
_createFunctionParameter('x', 34, type: typeProvider.boolType),
|
||||
];
|
||||
FunctionTypeImpl functionType = new FunctionTypeImpl(element);
|
||||
element.type = functionType;
|
||||
|
@ -82,7 +110,7 @@ f(String s, int i) {
|
|||
f() {
|
||||
int Function(String, bool x) foo;
|
||||
}
|
||||
''', [], [], <DartType>[functionType]);
|
||||
''', [new LocalVariableElementImpl('foo', 37)], [], <DartType>[functionType]);
|
||||
}
|
||||
|
||||
void test_listLiteral_const_noAnnotation() {
|
||||
|
@ -201,6 +229,38 @@ get f => <String, int>{'a' : 1, 'b' : 2, 'c' : 3};
|
|||
]);
|
||||
}
|
||||
|
||||
void test_methodInvocation_getter() {
|
||||
applyTypes(r'''
|
||||
f(String s) {
|
||||
return s.length;
|
||||
}
|
||||
''', [], [
|
||||
_createFunctionParameter('s', 9),
|
||||
new MethodElementImpl('length', -1)
|
||||
], <DartType>[
|
||||
typeProvider.stringType,
|
||||
typeProvider.intType,
|
||||
typeProvider.intType
|
||||
]);
|
||||
}
|
||||
|
||||
void test_methodInvocation_method() {
|
||||
applyTypes(r'''
|
||||
f(String s) {
|
||||
return s.substring(3, 7);
|
||||
}
|
||||
''', [], [
|
||||
_createFunctionParameter('s', 9),
|
||||
new MethodElementImpl('length', -1)
|
||||
], <DartType>[
|
||||
typeProvider.stringType,
|
||||
typeProvider.intType,
|
||||
typeProvider.intType,
|
||||
typeProvider.stringType,
|
||||
typeProvider.stringType
|
||||
]);
|
||||
}
|
||||
|
||||
@failingTest
|
||||
void test_typeAlias() {
|
||||
TypeParameterElement B = _createTypeParameter('B', 42);
|
||||
|
@ -213,7 +273,7 @@ get f => <String, int>{'a' : 1, 'b' : 2, 'c' : 3};
|
|||
functionElement.typeParameters = <TypeParameterElement>[];
|
||||
functionElement.returnType = B.type;
|
||||
functionElement.parameters = [
|
||||
new ParameterElementImpl('x', 48)..type = C.type,
|
||||
_createFunctionParameter('x', 48, type: C.type),
|
||||
];
|
||||
FunctionTypeImpl functionType = new FunctionTypeImpl.forTypedef(element);
|
||||
applyTypes(r'''
|
||||
|
@ -221,7 +281,17 @@ f() {
|
|||
A<int, String> foo;
|
||||
}
|
||||
//typedef B A<B, C>(C x);
|
||||
''', [], [], <DartType>[functionType]);
|
||||
''', [new LocalVariableElementImpl('foo', 23)], [], <DartType>[functionType]);
|
||||
}
|
||||
|
||||
/// Return a newly created parameter element with the given [name] and
|
||||
/// [offset].
|
||||
ParameterElement _createFunctionParameter(String name, int offset,
|
||||
{DartType type}) {
|
||||
ParameterElementImpl parameter = new ParameterElementImpl(name, offset);
|
||||
parameter.type = type;
|
||||
parameter.parameterKind = ParameterKind.REQUIRED;
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/// Return a newly created type parameter element with the given [name] and
|
||||
|
|
|
@ -26,6 +26,7 @@ fallthrough: Crash
|
|||
fibonacci: Crash
|
||||
for_in_scope: Crash
|
||||
function_type_is_check: Crash
|
||||
function_type_recovery: Crash
|
||||
functions: Crash
|
||||
illegal_named_function_expression: Crash
|
||||
illegal_named_function_expression_scope: Crash
|
||||
|
@ -68,7 +69,6 @@ inference/constructors_infer_from_arguments: Crash
|
|||
inference/constructors_infer_from_arguments_const_with_upper_bound: Crash
|
||||
inference/constructors_infer_from_arguments_downwards_from_constructor: Crash
|
||||
inference/constructors_infer_from_arguments_factory: Crash
|
||||
inference/constructors_infer_from_arguments_factory_calls_constructor: Crash
|
||||
inference/constructors_infer_from_arguments_named: Crash
|
||||
inference/constructors_infer_from_arguments_named_factory: Crash
|
||||
inference/constructors_infer_from_arguments_redirecting: Crash
|
||||
|
@ -180,7 +180,6 @@ inference/infer_conditional: Crash
|
|||
inference/infer_consts_transitively_2: Crash
|
||||
inference/infer_consts_transitively_2_a: Crash
|
||||
inference/infer_correctly_on_multiple_variables_declared_together: Crash
|
||||
inference/infer_field_override_with_substitution: Crash
|
||||
inference/infer_from_complex_expressions_if_outer_most_value_is_precise: Crash
|
||||
inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: Crash
|
||||
inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: Crash
|
||||
|
@ -282,7 +281,6 @@ inference/refine_binary_expression_type_type_parameter_t_int: Crash
|
|||
inference/refine_binary_expression_type_type_parameter_t_t: Crash
|
||||
inference/static_method_tear_off: Crash
|
||||
inference/string_literal: Crash
|
||||
inference/subexpressions_of_explicitly_typed_fields: Crash
|
||||
inference/super_index_set: Crash
|
||||
inference/super_index_set_substitution: Crash
|
||||
inference/super_initializer: Crash
|
||||
|
@ -328,7 +326,6 @@ inference/unsafe_block_closure_inference_method_call_explicit_type_param: Crash
|
|||
inference/unsafe_block_closure_inference_method_call_implicit_type_param: Crash
|
||||
inference/void_return_type_subtypes_dynamic: Crash
|
||||
inference_new/dependency_only_if_overloaded: Crash
|
||||
inference_new/downwards_inference_inside_top_level: Crash
|
||||
inference_new/field_inference_circularity: Crash
|
||||
inference_new/indexed_assign_combiner: Crash
|
||||
inference_new/infer_assign_to_implicit_this: Crash
|
||||
|
@ -437,7 +434,6 @@ regress/issue_29942: Crash
|
|||
regress/issue_29943: Crash
|
||||
regress/issue_29978: Crash
|
||||
regress/issue_29979: Crash
|
||||
regress/issue_29981: Crash
|
||||
regress/issue_29984: Crash
|
||||
regress/issue_29985: Crash
|
||||
regress/issue_31155: Crash # Issue 31155.
|
||||
|
@ -446,7 +442,6 @@ regress/issue_31180: Crash
|
|||
regress/issue_31184: Crash
|
||||
regress/issue_31186: Crash
|
||||
regress/issue_31187: Crash
|
||||
regress/issue_31190: Crash
|
||||
regress/issue_31198: Crash
|
||||
reorder_super: Crash
|
||||
runtime_checks/call_kinds: Crash
|
||||
|
|
Loading…
Reference in a new issue