Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: pkg/analyzer/test/generated/static_type_analyzer_test.dart

Issue 1782463002: Split resolver_test.dart into smaller files. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/test/generated/static_type_analyzer_test.dart
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..61910204a99a5b966b4acdb9e721199fb2f0b6a0
--- /dev/null
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -0,0 +1,1619 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.generated.static_type_analyzer_test;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.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/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/static_type_analyzer.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+import 'analysis_context_factory.dart';
+import 'resolver_test_case.dart';
+import 'test_support.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(StaticTypeAnalyzerTest);
+ runReflectiveTests(StaticTypeAnalyzer2Test);
+}
+
+@reflectiveTest
+class StaticTypeAnalyzerTest extends EngineTestCase {
+ /**
+ * The error listener to which errors will be reported.
+ */
+ GatheringErrorListener _listener;
+
+ /**
+ * The resolver visitor used to create the analyzer.
+ */
+ ResolverVisitor _visitor;
+
+ /**
+ * The analyzer being used to analyze the test cases.
+ */
+ StaticTypeAnalyzer _analyzer;
+
+ /**
+ * The type provider used to access the types.
+ */
+ TestTypeProvider _typeProvider;
+
+ /**
+ * The type system used to analyze the test cases.
+ */
+ TypeSystem get _typeSystem => _visitor.typeSystem;
+
+ void fail_visitFunctionExpressionInvocation() {
+ fail("Not yet tested");
+ _listener.assertNoErrors();
+ }
+
+ void fail_visitMethodInvocation() {
+ fail("Not yet tested");
+ _listener.assertNoErrors();
+ }
+
+ void fail_visitSimpleIdentifier() {
+ fail("Not yet tested");
+ _listener.assertNoErrors();
+ }
+
+ @override
+ void setUp() {
+ super.setUp();
+ _listener = new GatheringErrorListener();
+ _analyzer = _createAnalyzer();
+ }
+
+ void test_flatten_derived() {
+ // class Derived<T> extends Future<T> { ... }
+ ClassElementImpl derivedClass =
+ ElementFactory.classElement2('Derived', ['T']);
+ derivedClass.supertype = _typeProvider.futureType
+ .instantiate([derivedClass.typeParameters[0].type]);
+ InterfaceType intType = _typeProvider.intType;
+ DartType dynamicType = _typeProvider.dynamicType;
+ InterfaceType derivedIntType = derivedClass.type.instantiate([intType]);
+ // flatten(Derived) = dynamic
+ InterfaceType derivedDynamicType =
+ derivedClass.type.instantiate([dynamicType]);
+ expect(_flatten(derivedDynamicType), dynamicType);
+ // flatten(Derived<int>) = int
+ expect(_flatten(derivedIntType), intType);
+ // flatten(Derived<Derived>) = Derived
+ expect(_flatten(derivedClass.type.instantiate([derivedDynamicType])),
+ derivedDynamicType);
+ // flatten(Derived<Derived<int>>) = Derived<int>
+ expect(_flatten(derivedClass.type.instantiate([derivedIntType])),
+ derivedIntType);
+ }
+
+ void test_flatten_inhibit_recursion() {
+ // class A extends B
+ // class B extends A
+ ClassElementImpl classA = ElementFactory.classElement2('A', []);
+ ClassElementImpl classB = ElementFactory.classElement2('B', []);
+ classA.supertype = classB.type;
+ classB.supertype = classA.type;
+ // flatten(A) = A and flatten(B) = B, since neither class contains Future
+ // in its class hierarchy. Even though there is a loop in the class
+ // hierarchy, flatten() should terminate.
+ expect(_flatten(classA.type), classA.type);
+ expect(_flatten(classB.type), classB.type);
+ }
+
+ void test_flatten_related_derived_types() {
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType numType = _typeProvider.numType;
+ // class Derived<T> extends Future<T>
+ ClassElementImpl derivedClass =
+ ElementFactory.classElement2('Derived', ['T']);
+ derivedClass.supertype = _typeProvider.futureType
+ .instantiate([derivedClass.typeParameters[0].type]);
+ InterfaceType derivedType = derivedClass.type;
+ // class A extends Derived<int> implements Derived<num> { ... }
+ ClassElementImpl classA =
+ ElementFactory.classElement('A', derivedType.instantiate([intType]));
+ classA.interfaces = <InterfaceType>[
+ derivedType.instantiate([numType])
+ ];
+ // class B extends Future<num> implements Future<int> { ... }
+ ClassElementImpl classB =
+ ElementFactory.classElement('B', derivedType.instantiate([numType]));
+ classB.interfaces = <InterfaceType>[
+ derivedType.instantiate([intType])
+ ];
+ // flatten(A) = flatten(B) = int, since int is more specific than num.
+ // The code in flatten() that inhibits infinite recursion shouldn't be
+ // fooled by the fact that Derived appears twice in the type hierarchy.
+ expect(_flatten(classA.type), intType);
+ expect(_flatten(classB.type), intType);
+ }
+
+ void test_flatten_related_types() {
+ InterfaceType futureType = _typeProvider.futureType;
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType numType = _typeProvider.numType;
+ // class A extends Future<int> implements Future<num> { ... }
+ ClassElementImpl classA =
+ ElementFactory.classElement('A', futureType.instantiate([intType]));
+ classA.interfaces = <InterfaceType>[
+ futureType.instantiate([numType])
+ ];
+ // class B extends Future<num> implements Future<int> { ... }
+ ClassElementImpl classB =
+ ElementFactory.classElement('B', futureType.instantiate([numType]));
+ classB.interfaces = <InterfaceType>[
+ futureType.instantiate([intType])
+ ];
+ // flatten(A) = flatten(B) = int, since int is more specific than num.
+ expect(_flatten(classA.type), intType);
+ expect(_flatten(classB.type), intType);
+ }
+
+ void test_flatten_simple() {
+ InterfaceType intType = _typeProvider.intType;
+ DartType dynamicType = _typeProvider.dynamicType;
+ InterfaceType futureDynamicType = _typeProvider.futureDynamicType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate([intType]);
+ InterfaceType futureFutureDynamicType =
+ _typeProvider.futureType.instantiate([futureDynamicType]);
+ InterfaceType futureFutureIntType =
+ _typeProvider.futureType.instantiate([futureIntType]);
+ // flatten(int) = int
+ expect(_flatten(intType), intType);
+ // flatten(dynamic) = dynamic
+ expect(_flatten(dynamicType), dynamicType);
+ // flatten(Future) = dynamic
+ expect(_flatten(futureDynamicType), dynamicType);
+ // flatten(Future<int>) = int
+ expect(_flatten(futureIntType), intType);
+ // flatten(Future<Future>) = dynamic
+ expect(_flatten(futureFutureDynamicType), dynamicType);
+ // flatten(Future<Future<int>>) = int
+ expect(_flatten(futureFutureIntType), intType);
+ }
+
+ void test_flatten_unrelated_types() {
+ InterfaceType futureType = _typeProvider.futureType;
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType stringType = _typeProvider.stringType;
+ // class A extends Future<int> implements Future<String> { ... }
+ ClassElementImpl classA =
+ ElementFactory.classElement('A', futureType.instantiate([intType]));
+ classA.interfaces = <InterfaceType>[
+ futureType.instantiate([stringType])
+ ];
+ // class B extends Future<String> implements Future<int> { ... }
+ ClassElementImpl classB =
+ ElementFactory.classElement('B', futureType.instantiate([stringType]));
+ classB.interfaces = <InterfaceType>[
+ futureType.instantiate([intType])
+ ];
+ // flatten(A) = A and flatten(B) = B, since neither string nor int is more
+ // specific than the other.
+ expect(_flatten(classA.type), classA.type);
+ expect(_flatten(classB.type), classB.type);
+ }
+
+ void test_visitAdjacentStrings() {
+ // "a" "b"
+ Expression node = AstFactory
+ .adjacentStrings([_resolvedString("a"), _resolvedString("b")]);
+ expect(_analyze(node), same(_typeProvider.stringType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAsExpression() {
+ // class A { ... this as B ... }
+ // class B extends A {}
+ ClassElement superclass = ElementFactory.classElement2("A");
+ InterfaceType superclassType = superclass.type;
+ ClassElement subclass = ElementFactory.classElement("B", superclassType);
+ Expression node = AstFactory.asExpression(
+ AstFactory.thisExpression(), AstFactory.typeName(subclass));
+ expect(_analyze3(node, superclassType), same(subclass.type));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAssignmentExpression_compound() {
+ // i += 1
+ InterfaceType numType = _typeProvider.numType;
+ SimpleIdentifier identifier = _resolvedVariable(_typeProvider.intType, "i");
+ AssignmentExpression node = AstFactory.assignmentExpression(
+ identifier, TokenType.PLUS_EQ, _resolvedInteger(1));
+ MethodElement plusMethod = getMethod(numType, "+");
+ node.staticElement = plusMethod;
+ expect(_analyze(node), same(numType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAssignmentExpression_compoundIfNull_differentTypes() {
+ // double d; d ??= 0
+ Expression node = AstFactory.assignmentExpression(
+ _resolvedVariable(_typeProvider.doubleType, 'd'),
+ TokenType.QUESTION_QUESTION_EQ,
+ _resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.numType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAssignmentExpression_compoundIfNull_sameTypes() {
+ // int i; i ??= 0
+ Expression node = AstFactory.assignmentExpression(
+ _resolvedVariable(_typeProvider.intType, 'i'),
+ TokenType.QUESTION_QUESTION_EQ,
+ _resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAssignmentExpression_simple() {
+ // i = 0
+ InterfaceType intType = _typeProvider.intType;
+ Expression node = AstFactory.assignmentExpression(
+ _resolvedVariable(intType, "i"), TokenType.EQ, _resolvedInteger(0));
+ expect(_analyze(node), same(intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAwaitExpression_flattened() {
+ // await e, where e has type Future<Future<int>>
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[intType]);
+ InterfaceType futureFutureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[futureIntType]);
+ Expression node =
+ AstFactory.awaitExpression(_resolvedVariable(futureFutureIntType, 'e'));
+ expect(_analyze(node), same(intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitAwaitExpression_simple() {
+ // await e, where e has type Future<int>
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[intType]);
+ Expression node =
+ AstFactory.awaitExpression(_resolvedVariable(futureIntType, 'e'));
+ expect(_analyze(node), same(intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_equals() {
+ // 2 == 3
+ Expression node = AstFactory.binaryExpression(
+ _resolvedInteger(2), TokenType.EQ_EQ, _resolvedInteger(3));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_ifNull() {
+ // 1 ?? 1.5
+ Expression node = AstFactory.binaryExpression(
+ _resolvedInteger(1), TokenType.QUESTION_QUESTION, _resolvedDouble(1.5));
+ expect(_analyze(node), same(_typeProvider.numType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_logicalAnd() {
+ // false && true
+ Expression node = AstFactory.binaryExpression(
+ AstFactory.booleanLiteral(false),
+ TokenType.AMPERSAND_AMPERSAND,
+ AstFactory.booleanLiteral(true));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_logicalOr() {
+ // false || true
+ Expression node = AstFactory.binaryExpression(
+ AstFactory.booleanLiteral(false),
+ TokenType.BAR_BAR,
+ AstFactory.booleanLiteral(true));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_minusID_propagated() {
+ // a - b
+ BinaryExpression node = AstFactory.binaryExpression(
+ _propagatedVariable(_typeProvider.intType, 'a'),
+ TokenType.MINUS,
+ _propagatedVariable(_typeProvider.doubleType, 'b'));
+ node.propagatedElement = getMethod(_typeProvider.numType, "+");
+ _analyze(node);
+ expect(node.propagatedType, same(_typeProvider.doubleType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_notEquals() {
+ // 2 != 3
+ Expression node = AstFactory.binaryExpression(
+ _resolvedInteger(2), TokenType.BANG_EQ, _resolvedInteger(3));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_plusID() {
+ // 1 + 2.0
+ BinaryExpression node = AstFactory.binaryExpression(
+ _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0));
+ node.staticElement = getMethod(_typeProvider.numType, "+");
+ expect(_analyze(node), same(_typeProvider.doubleType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_plusII() {
+ // 1 + 2
+ BinaryExpression node = AstFactory.binaryExpression(
+ _resolvedInteger(1), TokenType.PLUS, _resolvedInteger(2));
+ node.staticElement = getMethod(_typeProvider.numType, "+");
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_plusII_propagated() {
+ // a + b
+ BinaryExpression node = AstFactory.binaryExpression(
+ _propagatedVariable(_typeProvider.intType, 'a'),
+ TokenType.PLUS,
+ _propagatedVariable(_typeProvider.intType, 'b'));
+ node.propagatedElement = getMethod(_typeProvider.numType, "+");
+ _analyze(node);
+ expect(node.propagatedType, same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_slash() {
+ // 2 / 2
+ BinaryExpression node = AstFactory.binaryExpression(
+ _resolvedInteger(2), TokenType.SLASH, _resolvedInteger(2));
+ node.staticElement = getMethod(_typeProvider.numType, "/");
+ expect(_analyze(node), same(_typeProvider.doubleType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_star_notSpecial() {
+ // class A {
+ // A operator *(double value);
+ // }
+ // (a as A) * 2.0
+ ClassElementImpl classA = ElementFactory.classElement2("A");
+ InterfaceType typeA = classA.type;
+ MethodElement operator =
+ ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]);
+ classA.methods = <MethodElement>[operator];
+ BinaryExpression node = AstFactory.binaryExpression(
+ AstFactory.asExpression(
+ AstFactory.identifier3("a"), AstFactory.typeName(classA)),
+ TokenType.PLUS,
+ _resolvedDouble(2.0));
+ node.staticElement = operator;
+ expect(_analyze(node), same(typeA));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_starID() {
+ // 1 * 2.0
+ BinaryExpression node = AstFactory.binaryExpression(
+ _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0));
+ node.staticElement = getMethod(_typeProvider.numType, "*");
+ expect(_analyze(node), same(_typeProvider.doubleType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBooleanLiteral_false() {
+ // false
+ Expression node = AstFactory.booleanLiteral(false);
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitBooleanLiteral_true() {
+ // true
+ Expression node = AstFactory.booleanLiteral(true);
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitCascadeExpression() {
+ // a..length
+ Expression node = AstFactory.cascadeExpression(
+ _resolvedString("a"), [AstFactory.propertyAccess2(null, "length")]);
+ expect(_analyze(node), same(_typeProvider.stringType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitConditionalExpression_differentTypes() {
+ // true ? 1.0 : 0
+ Expression node = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(true),
+ _resolvedDouble(1.0),
+ _resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.numType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitConditionalExpression_sameTypes() {
+ // true ? 1 : 0
+ Expression node = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(true),
+ _resolvedInteger(1),
+ _resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitDoubleLiteral() {
+ // 4.33
+ Expression node = AstFactory.doubleLiteral(4.33);
+ expect(_analyze(node), same(_typeProvider.doubleType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_async_block() {
+ // () async {}
+ BlockFunctionBody body = AstFactory.blockFunctionBody2();
+ body.keyword = TokenFactory.tokenFromString('async');
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(
+ _typeProvider.futureDynamicType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_async_expression() {
+ // () async => e, where e has type int
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[intType]);
+ Expression expression = _resolvedVariable(intType, 'e');
+ ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression);
+ body.keyword = TokenFactory.tokenFromString('async');
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(futureIntType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_async_expression_flatten() {
+ // () async => e, where e has type Future<int>
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[intType]);
+ Expression expression = _resolvedVariable(futureIntType, 'e');
+ ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression);
+ body.keyword = TokenFactory.tokenFromString('async');
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(futureIntType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_async_expression_flatten_twice() {
+ // () async => e, where e has type Future<Future<int>>
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType futureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[intType]);
+ InterfaceType futureFutureIntType =
+ _typeProvider.futureType.instantiate(<DartType>[futureIntType]);
+ Expression expression = _resolvedVariable(futureFutureIntType, 'e');
+ ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression);
+ body.keyword = TokenFactory.tokenFromString('async');
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(futureIntType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_generator_async() {
+ // () async* {}
+ BlockFunctionBody body = AstFactory.blockFunctionBody2();
+ body.keyword = TokenFactory.tokenFromString('async');
+ body.star = TokenFactory.tokenFromType(TokenType.STAR);
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(
+ _typeProvider.streamDynamicType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_generator_sync() {
+ // () sync* {}
+ BlockFunctionBody body = AstFactory.blockFunctionBody2();
+ body.keyword = TokenFactory.tokenFromString('sync');
+ body.star = TokenFactory.tokenFromType(TokenType.STAR);
+ FunctionExpression node =
+ _resolvedFunctionExpression(AstFactory.formalParameterList([]), body);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(
+ _typeProvider.iterableDynamicType, null, null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_named_block() {
+ // ({p1 : 0, p2 : 0}) {}
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.namedFormalParameter(
+ AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0));
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.namedFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.blockFunctionBody2());
+ _analyze5(p1);
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>();
+ expectedNamedTypes["p1"] = dynamicType;
+ expectedNamedTypes["p2"] = dynamicType;
+ _assertFunctionType(
+ dynamicType, null, null, expectedNamedTypes, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_named_expression() {
+ // ({p : 0}) -> 0;
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p = AstFactory.namedFormalParameter(
+ AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0));
+ _setType(p, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p]),
+ AstFactory.expressionFunctionBody(_resolvedInteger(0)));
+ _analyze5(p);
+ DartType resultType = _analyze(node);
+ Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>();
+ expectedNamedTypes["p"] = dynamicType;
+ _assertFunctionType(
+ _typeProvider.intType, null, null, expectedNamedTypes, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normal_block() {
+ // (p1, p2) {}
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.simpleFormalParameter3("p1");
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.simpleFormalParameter3("p2");
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.blockFunctionBody2());
+ _analyze5(p1);
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(dynamicType, <DartType>[dynamicType, dynamicType], null,
+ null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normal_expression() {
+ // (p1, p2) -> 0
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p = AstFactory.simpleFormalParameter3("p");
+ _setType(p, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p]),
+ AstFactory.expressionFunctionBody(_resolvedInteger(0)));
+ _analyze5(p);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(
+ _typeProvider.intType, <DartType>[dynamicType], null, null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normalAndNamed_block() {
+ // (p1, {p2 : 0}) {}
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.simpleFormalParameter3("p1");
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.namedFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.blockFunctionBody2());
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>();
+ expectedNamedTypes["p2"] = dynamicType;
+ _assertFunctionType(dynamicType, <DartType>[dynamicType], null,
+ expectedNamedTypes, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normalAndNamed_expression() {
+ // (p1, {p2 : 0}) -> 0
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.simpleFormalParameter3("p1");
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.namedFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.expressionFunctionBody(_resolvedInteger(0)));
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>();
+ expectedNamedTypes["p2"] = dynamicType;
+ _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null,
+ expectedNamedTypes, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normalAndPositional_block() {
+ // (p1, [p2 = 0]) {}
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.simpleFormalParameter3("p1");
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.positionalFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.blockFunctionBody2());
+ _analyze5(p1);
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(dynamicType, <DartType>[dynamicType],
+ <DartType>[dynamicType], null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_normalAndPositional_expression() {
+ // (p1, [p2 = 0]) -> 0
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.simpleFormalParameter3("p1");
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.positionalFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.expressionFunctionBody(_resolvedInteger(0)));
+ _analyze5(p1);
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType],
+ <DartType>[dynamicType], null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_positional_block() {
+ // ([p1 = 0, p2 = 0]) {}
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p1 = AstFactory.positionalFormalParameter(
+ AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0));
+ _setType(p1, dynamicType);
+ FormalParameter p2 = AstFactory.positionalFormalParameter(
+ AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0));
+ _setType(p2, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p1, p2]),
+ AstFactory.blockFunctionBody2());
+ _analyze5(p1);
+ _analyze5(p2);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(dynamicType, null, <DartType>[dynamicType, dynamicType],
+ null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitFunctionExpression_positional_expression() {
+ // ([p1 = 0, p2 = 0]) -> 0
+ DartType dynamicType = _typeProvider.dynamicType;
+ FormalParameter p = AstFactory.positionalFormalParameter(
+ AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0));
+ _setType(p, dynamicType);
+ FunctionExpression node = _resolvedFunctionExpression(
+ AstFactory.formalParameterList([p]),
+ AstFactory.expressionFunctionBody(_resolvedInteger(0)));
+ _analyze5(p);
+ DartType resultType = _analyze(node);
+ _assertFunctionType(
+ _typeProvider.intType, null, <DartType>[dynamicType], null, resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIndexExpression_getter() {
+ // List a;
+ // a[2]
+ InterfaceType listType = _typeProvider.listType;
+ SimpleIdentifier identifier = _resolvedVariable(listType, "a");
+ IndexExpression node =
+ AstFactory.indexExpression(identifier, _resolvedInteger(2));
+ MethodElement indexMethod = listType.element.methods[0];
+ node.staticElement = indexMethod;
+ expect(_analyze(node), same(listType.typeArguments[0]));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIndexExpression_setter() {
+ // List a;
+ // a[2] = 0
+ InterfaceType listType = _typeProvider.listType;
+ SimpleIdentifier identifier = _resolvedVariable(listType, "a");
+ IndexExpression node =
+ AstFactory.indexExpression(identifier, _resolvedInteger(2));
+ MethodElement indexMethod = listType.element.methods[1];
+ node.staticElement = indexMethod;
+ AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0));
+ expect(_analyze(node), same(listType.typeArguments[0]));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIndexExpression_typeParameters() {
+ // List<int> list = ...
+ // list[0]
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType listType = _typeProvider.listType;
+ // (int) -> E
+ MethodElement methodElement = getMethod(listType, "[]");
+ // "list" has type List<int>
+ SimpleIdentifier identifier = AstFactory.identifier3("list");
+ InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
+ identifier.staticType = listOfIntType;
+ // list[0] has MethodElement element (int) -> E
+ IndexExpression indexExpression =
+ AstFactory.indexExpression(identifier, AstFactory.integer(0));
+ MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType);
+ indexExpression.staticElement = indexMethod;
+ // analyze and assert result of the index expression
+ expect(_analyze(indexExpression), same(intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIndexExpression_typeParameters_inSetterContext() {
+ // List<int> list = ...
+ // list[0] = 0;
+ InterfaceType intType = _typeProvider.intType;
+ InterfaceType listType = _typeProvider.listType;
+ // (int, E) -> void
+ MethodElement methodElement = getMethod(listType, "[]=");
+ // "list" has type List<int>
+ SimpleIdentifier identifier = AstFactory.identifier3("list");
+ InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
+ identifier.staticType = listOfIntType;
+ // list[0] has MethodElement element (int) -> E
+ IndexExpression indexExpression =
+ AstFactory.indexExpression(identifier, AstFactory.integer(0));
+ MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType);
+ indexExpression.staticElement = indexMethod;
+ // list[0] should be in a setter context
+ AstFactory.assignmentExpression(
+ indexExpression, TokenType.EQ, AstFactory.integer(0));
+ // analyze and assert result of the index expression
+ expect(_analyze(indexExpression), same(intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitInstanceCreationExpression_named() {
+ // new C.m()
+ ClassElementImpl classElement = ElementFactory.classElement2("C");
+ String constructorName = "m";
+ ConstructorElementImpl constructor =
+ ElementFactory.constructorElement2(classElement, constructorName);
+ constructor.returnType = classElement.type;
+ FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor);
+ constructor.type = constructorType;
+ classElement.constructors = <ConstructorElement>[constructor];
+ InstanceCreationExpression node = AstFactory.instanceCreationExpression2(
+ null,
+ AstFactory.typeName(classElement),
+ [AstFactory.identifier3(constructorName)]);
+ node.staticElement = constructor;
+ expect(_analyze(node), same(classElement.type));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitInstanceCreationExpression_typeParameters() {
+ // new C<I>()
+ ClassElementImpl elementC = ElementFactory.classElement2("C", ["E"]);
+ ClassElementImpl elementI = ElementFactory.classElement2("I");
+ ConstructorElementImpl constructor =
+ ElementFactory.constructorElement2(elementC, null);
+ elementC.constructors = <ConstructorElement>[constructor];
+ constructor.returnType = elementC.type;
+ FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor);
+ constructor.type = constructorType;
+ TypeName typeName =
+ AstFactory.typeName(elementC, [AstFactory.typeName(elementI)]);
+ typeName.type = elementC.type.instantiate(<DartType>[elementI.type]);
+ InstanceCreationExpression node =
+ AstFactory.instanceCreationExpression2(null, typeName);
+ node.staticElement = constructor;
+ InterfaceType interfaceType = _analyze(node) as InterfaceType;
+ List<DartType> typeArgs = interfaceType.typeArguments;
+ expect(typeArgs.length, 1);
+ expect(typeArgs[0], elementI.type);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitInstanceCreationExpression_unnamed() {
+ // new C()
+ ClassElementImpl classElement = ElementFactory.classElement2("C");
+ ConstructorElementImpl constructor =
+ ElementFactory.constructorElement2(classElement, null);
+ constructor.returnType = classElement.type;
+ FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor);
+ constructor.type = constructorType;
+ classElement.constructors = <ConstructorElement>[constructor];
+ InstanceCreationExpression node = AstFactory.instanceCreationExpression2(
+ null, AstFactory.typeName(classElement));
+ node.staticElement = constructor;
+ expect(_analyze(node), same(classElement.type));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIntegerLiteral() {
+ // 42
+ Expression node = _resolvedInteger(42);
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIsExpression_negated() {
+ // a is! String
+ Expression node = AstFactory.isExpression(
+ _resolvedString("a"), true, AstFactory.typeName4("String"));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitIsExpression_notNegated() {
+ // a is String
+ Expression node = AstFactory.isExpression(
+ _resolvedString("a"), false, AstFactory.typeName4("String"));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitListLiteral_empty() {
+ // []
+ Expression node = AstFactory.listLiteral();
+ DartType resultType = _analyze(node);
+ _assertType2(
+ _typeProvider.listType
+ .instantiate(<DartType>[_typeProvider.dynamicType]),
+ resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitListLiteral_nonEmpty() {
+ // [0]
+ Expression node = AstFactory.listLiteral([_resolvedInteger(0)]);
+ DartType resultType = _analyze(node);
+ _assertType2(
+ _typeProvider.listType
+ .instantiate(<DartType>[_typeProvider.dynamicType]),
+ resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitMapLiteral_empty() {
+ // {}
+ Expression node = AstFactory.mapLiteral2();
+ DartType resultType = _analyze(node);
+ _assertType2(
+ _typeProvider.mapType.instantiate(
+ <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]),
+ resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitMapLiteral_nonEmpty() {
+ // {"k" : 0}
+ Expression node = AstFactory
+ .mapLiteral2([AstFactory.mapLiteralEntry("k", _resolvedInteger(0))]);
+ DartType resultType = _analyze(node);
+ _assertType2(
+ _typeProvider.mapType.instantiate(
+ <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]),
+ resultType);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitMethodInvocation_then() {
+ // then()
+ Expression node = AstFactory.methodInvocation(null, "then");
+ _analyze(node);
+ _listener.assertNoErrors();
+ }
+
+ void test_visitNamedExpression() {
+ // n: a
+ Expression node = AstFactory.namedExpression2("n", _resolvedString("a"));
+ expect(_analyze(node), same(_typeProvider.stringType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitNullLiteral() {
+ // null
+ Expression node = AstFactory.nullLiteral();
+ expect(_analyze(node), same(_typeProvider.bottomType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitParenthesizedExpression() {
+ // (0)
+ Expression node = AstFactory.parenthesizedExpression(_resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPostfixExpression_minusMinus() {
+ // 0--
+ PostfixExpression node = AstFactory.postfixExpression(
+ _resolvedInteger(0), TokenType.MINUS_MINUS);
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPostfixExpression_plusPlus() {
+ // 0++
+ PostfixExpression node =
+ AstFactory.postfixExpression(_resolvedInteger(0), TokenType.PLUS_PLUS);
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixedIdentifier_getter() {
+ DartType boolType = _typeProvider.boolType;
+ PropertyAccessorElementImpl getter =
+ ElementFactory.getterElement("b", false, boolType);
+ PrefixedIdentifier node = AstFactory.identifier5("a", "b");
+ node.identifier.staticElement = getter;
+ expect(_analyze(node), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixedIdentifier_setter() {
+ DartType boolType = _typeProvider.boolType;
+ FieldElementImpl field =
+ ElementFactory.fieldElement("b", false, false, false, boolType);
+ PropertyAccessorElement setter = field.setter;
+ PrefixedIdentifier node = AstFactory.identifier5("a", "b");
+ node.identifier.staticElement = setter;
+ expect(_analyze(node), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixedIdentifier_variable() {
+ VariableElementImpl variable = ElementFactory.localVariableElement2("b");
+ variable.type = _typeProvider.boolType;
+ PrefixedIdentifier node = AstFactory.identifier5("a", "b");
+ node.identifier.staticElement = variable;
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_bang() {
+ // !0
+ PrefixExpression node =
+ AstFactory.prefixExpression(TokenType.BANG, _resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_minus() {
+ // -0
+ PrefixExpression node =
+ AstFactory.prefixExpression(TokenType.MINUS, _resolvedInteger(0));
+ MethodElement minusMethod = getMethod(_typeProvider.numType, "-");
+ node.staticElement = minusMethod;
+ expect(_analyze(node), same(_typeProvider.numType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_minusMinus() {
+ // --0
+ PrefixExpression node =
+ AstFactory.prefixExpression(TokenType.MINUS_MINUS, _resolvedInteger(0));
+ MethodElement minusMethod = getMethod(_typeProvider.numType, "-");
+ node.staticElement = minusMethod;
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_not() {
+ // !true
+ Expression node = AstFactory.prefixExpression(
+ TokenType.BANG, AstFactory.booleanLiteral(true));
+ expect(_analyze(node), same(_typeProvider.boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_plusPlus() {
+ // ++0
+ PrefixExpression node =
+ AstFactory.prefixExpression(TokenType.PLUS_PLUS, _resolvedInteger(0));
+ MethodElement plusMethod = getMethod(_typeProvider.numType, "+");
+ node.staticElement = plusMethod;
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPrefixExpression_tilde() {
+ // ~0
+ PrefixExpression node =
+ AstFactory.prefixExpression(TokenType.TILDE, _resolvedInteger(0));
+ MethodElement tildeMethod = getMethod(_typeProvider.intType, "~");
+ node.staticElement = tildeMethod;
+ expect(_analyze(node), same(_typeProvider.intType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPropertyAccess_propagated_getter() {
+ DartType boolType = _typeProvider.boolType;
+ PropertyAccessorElementImpl getter =
+ ElementFactory.getterElement("b", false, boolType);
+ PropertyAccess node =
+ AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b");
+ node.propertyName.propagatedElement = getter;
+ expect(_analyze2(node, false), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPropertyAccess_propagated_setter() {
+ DartType boolType = _typeProvider.boolType;
+ FieldElementImpl field =
+ ElementFactory.fieldElement("b", false, false, false, boolType);
+ PropertyAccessorElement setter = field.setter;
+ PropertyAccess node =
+ AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b");
+ node.propertyName.propagatedElement = setter;
+ expect(_analyze2(node, false), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPropertyAccess_static_getter() {
+ DartType boolType = _typeProvider.boolType;
+ PropertyAccessorElementImpl getter =
+ ElementFactory.getterElement("b", false, boolType);
+ PropertyAccess node =
+ AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b");
+ node.propertyName.staticElement = getter;
+ expect(_analyze(node), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitPropertyAccess_static_setter() {
+ DartType boolType = _typeProvider.boolType;
+ FieldElementImpl field =
+ ElementFactory.fieldElement("b", false, false, false, boolType);
+ PropertyAccessorElement setter = field.setter;
+ PropertyAccess node =
+ AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b");
+ node.propertyName.staticElement = setter;
+ expect(_analyze(node), same(boolType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitSimpleIdentifier_dynamic() {
+ // "dynamic"
+ SimpleIdentifier identifier = AstFactory.identifier3('dynamic');
+ DynamicElementImpl element = DynamicElementImpl.instance;
+ identifier.staticElement = element;
+ identifier.staticType = _typeProvider.typeType;
+ expect(_analyze(identifier), same(_typeProvider.typeType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitSimpleStringLiteral() {
+ // "a"
+ Expression node = _resolvedString("a");
+ expect(_analyze(node), same(_typeProvider.stringType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitStringInterpolation() {
+ // "a${'b'}c"
+ Expression node = AstFactory.string([
+ AstFactory.interpolationString("a", "a"),
+ AstFactory.interpolationExpression(_resolvedString("b")),
+ AstFactory.interpolationString("c", "c")
+ ]);
+ expect(_analyze(node), same(_typeProvider.stringType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitSuperExpression() {
+ // super
+ InterfaceType superType = ElementFactory.classElement2("A").type;
+ InterfaceType thisType = ElementFactory.classElement("B", superType).type;
+ Expression node = AstFactory.superExpression();
+ expect(_analyze3(node, thisType), same(thisType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitSymbolLiteral() {
+ expect(_analyze(AstFactory.symbolLiteral(["a"])),
+ same(_typeProvider.symbolType));
+ }
+
+ void test_visitThisExpression() {
+ // this
+ InterfaceType thisType = ElementFactory
+ .classElement("B", ElementFactory.classElement2("A").type)
+ .type;
+ Expression node = AstFactory.thisExpression();
+ expect(_analyze3(node, thisType), same(thisType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitThrowExpression_withoutValue() {
+ // throw
+ Expression node = AstFactory.throwExpression();
+ expect(_analyze(node), same(_typeProvider.bottomType));
+ _listener.assertNoErrors();
+ }
+
+ void test_visitThrowExpression_withValue() {
+ // throw 0
+ Expression node = AstFactory.throwExpression2(_resolvedInteger(0));
+ expect(_analyze(node), same(_typeProvider.bottomType));
+ _listener.assertNoErrors();
+ }
+
+ /**
+ * Return the type associated with the given expression after the static type analyzer has
+ * computed a type for it.
+ *
+ * @param node the expression with which the type is associated
+ * @return the type associated with the expression
+ */
+ DartType _analyze(Expression node) => _analyze4(node, null, true);
+
+ /**
+ * Return the type associated with the given expression after the static or propagated type
+ * analyzer has computed a type for it.
+ *
+ * @param node the expression with which the type is associated
+ * @param useStaticType `true` if the static type is being requested, and `false` if
+ * the propagated type is being requested
+ * @return the type associated with the expression
+ */
+ DartType _analyze2(Expression node, bool useStaticType) =>
+ _analyze4(node, null, useStaticType);
+
+ /**
+ * Return the type associated with the given expression after the static type analyzer has
+ * computed a type for it.
+ *
+ * @param node the expression with which the type is associated
+ * @param thisType the type of 'this'
+ * @return the type associated with the expression
+ */
+ DartType _analyze3(Expression node, InterfaceType thisType) =>
+ _analyze4(node, thisType, true);
+
+ /**
+ * Return the type associated with the given expression after the static type analyzer has
+ * computed a type for it.
+ *
+ * @param node the expression with which the type is associated
+ * @param thisType the type of 'this'
+ * @param useStaticType `true` if the static type is being requested, and `false` if
+ * the propagated type is being requested
+ * @return the type associated with the expression
+ */
+ DartType _analyze4(
+ Expression node, InterfaceType thisType, bool useStaticType) {
+ try {
+ _analyzer.thisType = thisType;
+ } catch (exception) {
+ throw new IllegalArgumentException(
+ "Could not set type of 'this'", exception);
+ }
+ node.accept(_analyzer);
+ if (useStaticType) {
+ return node.staticType;
+ } else {
+ return node.propagatedType;
+ }
+ }
+
+ /**
+ * Return the type associated with the given parameter after the static type analyzer has computed
+ * a type for it.
+ *
+ * @param node the parameter with which the type is associated
+ * @return the type associated with the parameter
+ */
+ DartType _analyze5(FormalParameter node) {
+ node.accept(_analyzer);
+ return (node.identifier.staticElement as ParameterElement).type;
+ }
+
+ /**
+ * Assert that the actual type is a function type with the expected characteristics.
+ *
+ * @param expectedReturnType the expected return type of the function
+ * @param expectedNormalTypes the expected types of the normal parameters
+ * @param expectedOptionalTypes the expected types of the optional parameters
+ * @param expectedNamedTypes the expected types of the named parameters
+ * @param actualType the type being tested
+ */
+ void _assertFunctionType(
+ DartType expectedReturnType,
+ List<DartType> expectedNormalTypes,
+ List<DartType> expectedOptionalTypes,
+ Map<String, DartType> expectedNamedTypes,
+ DartType actualType) {
+ EngineTestCase.assertInstanceOf(
+ (obj) => obj is FunctionType, FunctionType, actualType);
+ FunctionType functionType = actualType as FunctionType;
+ List<DartType> normalTypes = functionType.normalParameterTypes;
+ if (expectedNormalTypes == null) {
+ expect(normalTypes, hasLength(0));
+ } else {
+ int expectedCount = expectedNormalTypes.length;
+ expect(normalTypes, hasLength(expectedCount));
+ for (int i = 0; i < expectedCount; i++) {
+ expect(normalTypes[i], same(expectedNormalTypes[i]));
+ }
+ }
+ List<DartType> optionalTypes = functionType.optionalParameterTypes;
+ if (expectedOptionalTypes == null) {
+ expect(optionalTypes, hasLength(0));
+ } else {
+ int expectedCount = expectedOptionalTypes.length;
+ expect(optionalTypes, hasLength(expectedCount));
+ for (int i = 0; i < expectedCount; i++) {
+ expect(optionalTypes[i], same(expectedOptionalTypes[i]));
+ }
+ }
+ Map<String, DartType> namedTypes = functionType.namedParameterTypes;
+ if (expectedNamedTypes == null) {
+ expect(namedTypes, hasLength(0));
+ } else {
+ expect(namedTypes, hasLength(expectedNamedTypes.length));
+ expectedNamedTypes.forEach((String name, DartType type) {
+ expect(namedTypes[name], same(type));
+ });
+ }
+ expect(functionType.returnType, equals(expectedReturnType));
+ }
+
+ void _assertType(
+ InterfaceTypeImpl expectedType, InterfaceTypeImpl actualType) {
+ expect(actualType.displayName, expectedType.displayName);
+ expect(actualType.element, expectedType.element);
+ List<DartType> expectedArguments = expectedType.typeArguments;
+ int length = expectedArguments.length;
+ List<DartType> actualArguments = actualType.typeArguments;
+ expect(actualArguments, hasLength(length));
+ for (int i = 0; i < length; i++) {
+ _assertType2(expectedArguments[i], actualArguments[i]);
+ }
+ }
+
+ void _assertType2(DartType expectedType, DartType actualType) {
+ if (expectedType is InterfaceTypeImpl) {
+ EngineTestCase.assertInstanceOf(
+ (obj) => obj is InterfaceTypeImpl, InterfaceTypeImpl, actualType);
+ _assertType(expectedType, actualType as InterfaceTypeImpl);
+ }
+ // TODO(brianwilkerson) Compare other kinds of types then make this a shared
+ // utility method.
+ }
+
+ /**
+ * Create the analyzer used by the tests.
+ *
+ * @return the analyzer to be used by the tests
+ */
+ StaticTypeAnalyzer _createAnalyzer() {
+ InternalAnalysisContext context = AnalysisContextFactory.contextWithCore();
+ FileBasedSource source =
+ new FileBasedSource(FileUtilities2.createFile("/lib.dart"));
+ CompilationUnitElementImpl definingCompilationUnit =
+ new CompilationUnitElementImpl("lib.dart");
+ definingCompilationUnit.librarySource =
+ definingCompilationUnit.source = source;
+ LibraryElementImpl definingLibrary =
+ new LibraryElementImpl.forNode(context, null);
+ definingLibrary.definingCompilationUnit = definingCompilationUnit;
+ _typeProvider = new TestTypeProvider(context);
+ _visitor = new ResolverVisitor(
+ definingLibrary, source, _typeProvider, _listener,
+ nameScope: new LibraryScope(definingLibrary, _listener));
+ _visitor.overrideManager.enterScope();
+ try {
+ return _visitor.typeAnalyzer;
+ } catch (exception) {
+ throw new IllegalArgumentException(
+ "Could not create analyzer", exception);
+ }
+ }
+
+ DartType _flatten(DartType type) => type.flattenFutures(_typeSystem);
+
+ /**
+ * Return a simple identifier that has been resolved to a variable element with the given type.
+ *
+ * @param type the type of the variable being represented
+ * @param variableName the name of the variable
+ * @return a simple identifier that has been resolved to a variable element with the given type
+ */
+ SimpleIdentifier _propagatedVariable(
+ InterfaceType type, String variableName) {
+ SimpleIdentifier identifier = AstFactory.identifier3(variableName);
+ VariableElementImpl element =
+ ElementFactory.localVariableElement(identifier);
+ element.type = type;
+ identifier.staticType = _typeProvider.dynamicType;
+ identifier.propagatedElement = element;
+ identifier.propagatedType = type;
+ return identifier;
+ }
+
+ /**
+ * Return an integer literal that has been resolved to the correct type.
+ *
+ * @param value the value of the literal
+ * @return an integer literal that has been resolved to the correct type
+ */
+ DoubleLiteral _resolvedDouble(double value) {
+ DoubleLiteral literal = AstFactory.doubleLiteral(value);
+ literal.staticType = _typeProvider.doubleType;
+ return literal;
+ }
+
+ /**
+ * Create a function expression that has an element associated with it, where the element has an
+ * incomplete type associated with it (just like the one
+ * [ElementBuilder.visitFunctionExpression] would have built if we had
+ * run it).
+ *
+ * @param parameters the parameters to the function
+ * @param body the body of the function
+ * @return a resolved function expression
+ */
+ FunctionExpression _resolvedFunctionExpression(
+ FormalParameterList parameters, FunctionBody body) {
+ List<ParameterElement> parameterElements = new List<ParameterElement>();
+ for (FormalParameter parameter in parameters.parameters) {
+ ParameterElementImpl element =
+ new ParameterElementImpl.forNode(parameter.identifier);
+ element.parameterKind = parameter.kind;
+ element.type = _typeProvider.dynamicType;
+ parameter.identifier.staticElement = element;
+ parameterElements.add(element);
+ }
+ FunctionExpression node = AstFactory.functionExpression2(parameters, body);
+ FunctionElementImpl element = new FunctionElementImpl.forNode(null);
+ element.parameters = parameterElements;
+ element.type = new FunctionTypeImpl(element);
+ node.element = element;
+ return node;
+ }
+
+ /**
+ * Return an integer literal that has been resolved to the correct type.
+ *
+ * @param value the value of the literal
+ * @return an integer literal that has been resolved to the correct type
+ */
+ IntegerLiteral _resolvedInteger(int value) {
+ IntegerLiteral literal = AstFactory.integer(value);
+ literal.staticType = _typeProvider.intType;
+ return literal;
+ }
+
+ /**
+ * Return a string literal that has been resolved to the correct type.
+ *
+ * @param value the value of the literal
+ * @return a string literal that has been resolved to the correct type
+ */
+ SimpleStringLiteral _resolvedString(String value) {
+ SimpleStringLiteral string = AstFactory.string2(value);
+ string.staticType = _typeProvider.stringType;
+ return string;
+ }
+
+ /**
+ * Return a simple identifier that has been resolved to a variable element with the given type.
+ *
+ * @param type the type of the variable being represented
+ * @param variableName the name of the variable
+ * @return a simple identifier that has been resolved to a variable element with the given type
+ */
+ SimpleIdentifier _resolvedVariable(InterfaceType type, String variableName) {
+ SimpleIdentifier identifier = AstFactory.identifier3(variableName);
+ VariableElementImpl element =
+ ElementFactory.localVariableElement(identifier);
+ element.type = type;
+ identifier.staticElement = element;
+ identifier.staticType = type;
+ return identifier;
+ }
+
+ /**
+ * Set the type of the given parameter to the given type.
+ *
+ * @param parameter the parameter whose type is to be set
+ * @param type the new type of the given parameter
+ */
+ void _setType(FormalParameter parameter, DartType type) {
+ SimpleIdentifier identifier = parameter.identifier;
+ Element element = identifier.staticElement;
+ if (element is! ParameterElement) {
+ element = new ParameterElementImpl.forNode(identifier);
+ identifier.staticElement = element;
+ }
+ (element as ParameterElementImpl).type = type;
+ }
+}
+
+/**
+ * Like [StaticTypeAnalyzerTest], but as end-to-end tests.
+ */
+@reflectiveTest
+class StaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared {
+ void test_FunctionExpressionInvocation_block() {
+ String code = r'''
+main() {
+ var foo = (() { return 1; })();
+}
+''';
+ resolveTestUnit(code);
+ expectInitializerType('foo', 'dynamic', isNull);
+ }
+
+ void test_FunctionExpressionInvocation_curried() {
+ String code = r'''
+typedef int F();
+F f() => null;
+main() {
+ var foo = f()();
+}
+''';
+ resolveTestUnit(code);
+ expectInitializerType('foo', 'int', isNull);
+ }
+
+ void test_FunctionExpressionInvocation_expression() {
+ String code = r'''
+main() {
+ var foo = (() => 1)();
+}
+''';
+ resolveTestUnit(code);
+ expectInitializerType('foo', 'int', isNull);
+ }
+
+ void test_MethodInvocation_nameType_localVariable() {
+ String code = r"""
+typedef Foo();
+main() {
+ Foo foo;
+ foo();
+}
+""";
+ resolveTestUnit(code);
+ // "foo" should be resolved to the "Foo" type
+ expectIdentifierType("foo();", new isInstanceOf<FunctionType>());
+ }
+
+ void test_MethodInvocation_nameType_parameter_FunctionTypeAlias() {
+ String code = r"""
+typedef Foo();
+main(Foo foo) {
+ foo();
+}
+""";
+ resolveTestUnit(code);
+ // "foo" should be resolved to the "Foo" type
+ expectIdentifierType("foo();", new isInstanceOf<FunctionType>());
+ }
+
+ void test_MethodInvocation_nameType_parameter_propagatedType() {
+ String code = r"""
+typedef Foo();
+main(p) {
+ if (p is Foo) {
+ p();
+ }
+}
+""";
+ resolveTestUnit(code);
+ expectIdentifierType("p()", DynamicTypeImpl.instance,
+ predicate((type) => type.name == 'Foo'));
+ }
+
+ void test_staticMethods_classTypeParameters() {
+ String code = r'''
+class C<T> {
+ static void m() => null;
+}
+main() {
+ print(C.m);
+}
+''';
+ resolveTestUnit(code);
+ expectFunctionType('m);', '() → void');
+ }
+
+ void test_staticMethods_classTypeParameters_genericMethod() {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableGenericMethods = true;
+ resetWithOptions(options);
+ String code = r'''
+class C<T> {
+ static void m<S>(S s) {
+ void f<U>(S s, U u) {}
+ print(f);
+ }
+}
+main() {
+ print(C.m);
+}
+''';
+ resolveTestUnit(code);
+ // C - m
+ TypeParameterType typeS;
+ {
+ expectFunctionType('m);', '<S>(S) → void',
+ elementTypeParams: '[S]', typeFormals: '[S]');
+
+ FunctionTypeImpl type = findIdentifier('m);').staticType;
+ typeS = type.typeFormals[0].type;
+ type = type.instantiate([DynamicTypeImpl.instance]);
+ expect(type.toString(), '(dynamic) → void');
+ expect(type.typeParameters.toString(), '[S]');
+ expect(type.typeArguments, [DynamicTypeImpl.instance]);
+ expect(type.typeFormals, isEmpty);
+ }
+ // C - m - f
+ {
+ expectFunctionType('f);', '<U>(S, U) → void',
+ elementTypeParams: '[U]',
+ typeParams: '[S]',
+ typeArgs: '[S]',
+ typeFormals: '[U]');
+
+ FunctionTypeImpl type = findIdentifier('f);').staticType;
+ type = type.instantiate([DynamicTypeImpl.instance]);
+ expect(type.toString(), '(S, dynamic) → void');
+ expect(type.typeParameters.toString(), '[S, U]');
+ expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
+ expect(type.typeFormals, isEmpty);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698