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

Unified Diff: pkg/analyzer/test/generated/simple_resolver_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/simple_resolver_test.dart
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..12fc55000cb5763abb7dcef034ac040cdea76e17
--- /dev/null
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -0,0 +1,1762 @@
+// 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.simple_resolver_test;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+import 'resolver_test_case.dart';
+import 'test_support.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(SimpleResolverTest);
+}
+
+@reflectiveTest
+class SimpleResolverTest extends ResolverTestCase {
+ void fail_getter_and_setter_fromMixins_property_access() {
+ // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
+ // a SimpleIdentifier that's inside a property access. This bug should be
+ // fixed.
+ Source source = addSource('''
+class B {}
+class M1 {
+ get x => null;
+ set x(value) {}
+}
+class M2 {
+ get x => null;
+ set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+ new C().x += 1;
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that both the getter and setter for "x" in "new C().x" refer to
+ // the accessors defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ AssignmentExpression assignment = stmt.expression;
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ expect(
+ propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
+ expect(
+ propertyAccess
+ .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
+ 'M2');
+ }
+
+ void fail_staticInvocation() {
+ Source source = addSource(r'''
+class A {
+ static int get g => (a,b) => 0;
+}
+class B {
+ f() {
+ A.g(1,0);
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_argumentResolution_required_matching() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, 3);
+ }
+ void g(a, b, c) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2]);
+ }
+
+ void test_argumentResolution_required_tooFew() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2);
+ }
+ void g(a, b, c) {}
+}''');
+ _validateArgumentResolution(source, [0, 1]);
+ }
+
+ void test_argumentResolution_required_tooMany() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, 3);
+ }
+ void g(a, b) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, -1]);
+ }
+
+ void test_argumentResolution_requiredAndNamed_extra() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, c: 3, d: 4);
+ }
+ void g(a, b, {c}) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2, -1]);
+ }
+
+ void test_argumentResolution_requiredAndNamed_matching() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, c: 3);
+ }
+ void g(a, b, {c}) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2]);
+ }
+
+ void test_argumentResolution_requiredAndNamed_missing() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, d: 3);
+ }
+ void g(a, b, {c, d}) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 3]);
+ }
+
+ void test_argumentResolution_requiredAndPositional_fewer() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, 3);
+ }
+ void g(a, b, [c, d]) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2]);
+ }
+
+ void test_argumentResolution_requiredAndPositional_matching() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, 3, 4);
+ }
+ void g(a, b, [c, d]) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2, 3]);
+ }
+
+ void test_argumentResolution_requiredAndPositional_more() {
+ Source source = addSource(r'''
+class A {
+ void f() {
+ g(1, 2, 3, 4);
+ }
+ void g(a, b, [c]) {}
+}''');
+ _validateArgumentResolution(source, [0, 1, 2, -1]);
+ }
+
+ void test_argumentResolution_setter_propagated() {
+ Source source = addSource(r'''
+main() {
+ var a = new A();
+ a.sss = 0;
+}
+class A {
+ set sss(x) {}
+}''');
+ LibraryElement library = resolve2(source);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ // find "a.sss = 0"
+ AssignmentExpression assignment;
+ {
+ FunctionElement mainElement = unit.functions[0];
+ FunctionBody mainBody = mainElement.computeNode().functionExpression.body;
+ Statement statement = (mainBody as BlockFunctionBody).block.statements[1];
+ ExpressionStatement expressionStatement =
+ statement as ExpressionStatement;
+ assignment = expressionStatement.expression as AssignmentExpression;
+ }
+ // get parameter
+ Expression rhs = assignment.rightHandSide;
+ expect(rhs.staticParameterElement, isNull);
+ ParameterElement parameter = rhs.propagatedParameterElement;
+ expect(parameter, isNotNull);
+ expect(parameter.displayName, "x");
+ // validate
+ ClassElement classA = unit.types[0];
+ PropertyAccessorElement setter = classA.accessors[0];
+ expect(setter.parameters[0], same(parameter));
+ }
+
+ void test_argumentResolution_setter_propagated_propertyAccess() {
+ Source source = addSource(r'''
+main() {
+ var a = new A();
+ a.b.sss = 0;
+}
+class A {
+ B b = new B();
+}
+class B {
+ set sss(x) {}
+}''');
+ LibraryElement library = resolve2(source);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ // find "a.b.sss = 0"
+ AssignmentExpression assignment;
+ {
+ FunctionElement mainElement = unit.functions[0];
+ FunctionBody mainBody = mainElement.computeNode().functionExpression.body;
+ Statement statement = (mainBody as BlockFunctionBody).block.statements[1];
+ ExpressionStatement expressionStatement =
+ statement as ExpressionStatement;
+ assignment = expressionStatement.expression as AssignmentExpression;
+ }
+ // get parameter
+ Expression rhs = assignment.rightHandSide;
+ expect(rhs.staticParameterElement, isNull);
+ ParameterElement parameter = rhs.propagatedParameterElement;
+ expect(parameter, isNotNull);
+ expect(parameter.displayName, "x");
+ // validate
+ ClassElement classB = unit.types[1];
+ PropertyAccessorElement setter = classB.accessors[0];
+ expect(setter.parameters[0], same(parameter));
+ }
+
+ void test_argumentResolution_setter_static() {
+ Source source = addSource(r'''
+main() {
+ A a = new A();
+ a.sss = 0;
+}
+class A {
+ set sss(x) {}
+}''');
+ LibraryElement library = resolve2(source);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ // find "a.sss = 0"
+ AssignmentExpression assignment;
+ {
+ FunctionElement mainElement = unit.functions[0];
+ FunctionBody mainBody = mainElement.computeNode().functionExpression.body;
+ Statement statement = (mainBody as BlockFunctionBody).block.statements[1];
+ ExpressionStatement expressionStatement =
+ statement as ExpressionStatement;
+ assignment = expressionStatement.expression as AssignmentExpression;
+ }
+ // get parameter
+ Expression rhs = assignment.rightHandSide;
+ ParameterElement parameter = rhs.staticParameterElement;
+ expect(parameter, isNotNull);
+ expect(parameter.displayName, "x");
+ // validate
+ ClassElement classA = unit.types[0];
+ PropertyAccessorElement setter = classA.accessors[0];
+ expect(setter.parameters[0], same(parameter));
+ }
+
+ void test_argumentResolution_setter_static_propertyAccess() {
+ Source source = addSource(r'''
+main() {
+ A a = new A();
+ a.b.sss = 0;
+}
+class A {
+ B b = new B();
+}
+class B {
+ set sss(x) {}
+}''');
+ LibraryElement library = resolve2(source);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ // find "a.b.sss = 0"
+ AssignmentExpression assignment;
+ {
+ FunctionElement mainElement = unit.functions[0];
+ FunctionBody mainBody = mainElement.computeNode().functionExpression.body;
+ Statement statement = (mainBody as BlockFunctionBody).block.statements[1];
+ ExpressionStatement expressionStatement =
+ statement as ExpressionStatement;
+ assignment = expressionStatement.expression as AssignmentExpression;
+ }
+ // get parameter
+ Expression rhs = assignment.rightHandSide;
+ ParameterElement parameter = rhs.staticParameterElement;
+ expect(parameter, isNotNull);
+ expect(parameter.displayName, "x");
+ // validate
+ ClassElement classB = unit.types[1];
+ PropertyAccessorElement setter = classB.accessors[0];
+ expect(setter.parameters[0], same(parameter));
+ }
+
+ void test_breakTarget_labeled() {
+ // Verify that the target of the label is correctly found and is recorded
+ // as the unlabeled portion of the statement.
+ String text = r'''
+void f() {
+ loop1: while (true) {
+ loop2: for (int i = 0; i < 10; i++) {
+ break loop1;
+ break loop2;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ WhileStatement whileStatement = EngineTestCase.findNode(
+ unit, text, 'while (true)', (n) => n is WhileStatement);
+ ForStatement forStatement =
+ EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
+ BreakStatement break1 = EngineTestCase.findNode(
+ unit, text, 'break loop1', (n) => n is BreakStatement);
+ BreakStatement break2 = EngineTestCase.findNode(
+ unit, text, 'break loop2', (n) => n is BreakStatement);
+ expect(break1.target, same(whileStatement));
+ expect(break2.target, same(forStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakFromDo() {
+ String text = r'''
+void f() {
+ do {
+ break;
+ } while (true);
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ DoStatement doStatement =
+ EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, same(doStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakFromFor() {
+ String text = r'''
+void f() {
+ for (int i = 0; i < 10; i++) {
+ break;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ ForStatement forStatement =
+ EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, same(forStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakFromForEach() {
+ String text = r'''
+void f() {
+ for (x in []) {
+ break;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ ForEachStatement forStatement = EngineTestCase.findNode(
+ unit, text, 'for', (n) => n is ForEachStatement);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, same(forStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakFromSwitch() {
+ String text = r'''
+void f() {
+ while (true) {
+ switch (0) {
+ case 0:
+ break;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ SwitchStatement switchStatement = EngineTestCase.findNode(
+ unit, text, 'switch', (n) => n is SwitchStatement);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, same(switchStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakFromWhile() {
+ String text = r'''
+void f() {
+ while (true) {
+ break;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ WhileStatement whileStatement = EngineTestCase.findNode(
+ unit, text, 'while', (n) => n is WhileStatement);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, same(whileStatement));
+ }
+
+ void test_breakTarget_unlabeledBreakToOuterFunction() {
+ // Verify that unlabeled break statements can't resolve to loops in an
+ // outer function.
+ String text = r'''
+void f() {
+ while (true) {
+ void g() {
+ break;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ BreakStatement breakStatement = EngineTestCase.findNode(
+ unit, text, 'break', (n) => n is BreakStatement);
+ expect(breakStatement.target, isNull);
+ }
+
+ void test_class_definesCall() {
+ Source source = addSource(r'''
+class A {
+ int call(int x) { return x; }
+}
+int f(A a) {
+ return a(0);
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_class_extends_implements() {
+ Source source = addSource(r'''
+class A extends B implements C {}
+class B {}
+class C {}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_commentReference_class() {
+ Source source = addSource(r'''
+f() {}
+/** [A] [new A] [A.n] [new A.n] [m] [f] */
+class A {
+ A() {}
+ A.n() {}
+ m() {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_commentReference_parameter() {
+ Source source = addSource(r'''
+class A {
+ A() {}
+ A.n() {}
+ /** [e] [f] */
+ m(e, f()) {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_commentReference_singleLine() {
+ Source source = addSource(r'''
+/// [A]
+class A {}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_continueTarget_labeled() {
+ // Verify that the target of the label is correctly found and is recorded
+ // as the unlabeled portion of the statement.
+ String text = r'''
+void f() {
+ loop1: while (true) {
+ loop2: for (int i = 0; i < 10; i++) {
+ continue loop1;
+ continue loop2;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ WhileStatement whileStatement = EngineTestCase.findNode(
+ unit, text, 'while (true)', (n) => n is WhileStatement);
+ ForStatement forStatement =
+ EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
+ ContinueStatement continue1 = EngineTestCase.findNode(
+ unit, text, 'continue loop1', (n) => n is ContinueStatement);
+ ContinueStatement continue2 = EngineTestCase.findNode(
+ unit, text, 'continue loop2', (n) => n is ContinueStatement);
+ expect(continue1.target, same(whileStatement));
+ expect(continue2.target, same(forStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueFromDo() {
+ String text = r'''
+void f() {
+ do {
+ continue;
+ } while (true);
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ DoStatement doStatement =
+ EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, same(doStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueFromFor() {
+ String text = r'''
+void f() {
+ for (int i = 0; i < 10; i++) {
+ continue;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ ForStatement forStatement =
+ EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, same(forStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueFromForEach() {
+ String text = r'''
+void f() {
+ for (x in []) {
+ continue;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ ForEachStatement forStatement = EngineTestCase.findNode(
+ unit, text, 'for', (n) => n is ForEachStatement);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, same(forStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueFromWhile() {
+ String text = r'''
+void f() {
+ while (true) {
+ continue;
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ WhileStatement whileStatement = EngineTestCase.findNode(
+ unit, text, 'while', (n) => n is WhileStatement);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, same(whileStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueSkipsSwitch() {
+ String text = r'''
+void f() {
+ while (true) {
+ switch (0) {
+ case 0:
+ continue;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ WhileStatement whileStatement = EngineTestCase.findNode(
+ unit, text, 'while', (n) => n is WhileStatement);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, same(whileStatement));
+ }
+
+ void test_continueTarget_unlabeledContinueToOuterFunction() {
+ // Verify that unlabeled continue statements can't resolve to loops in an
+ // outer function.
+ String text = r'''
+void f() {
+ while (true) {
+ void g() {
+ continue;
+ }
+ }
+}
+''';
+ CompilationUnit unit = resolveSource(text);
+ ContinueStatement continueStatement = EngineTestCase.findNode(
+ unit, text, 'continue', (n) => n is ContinueStatement);
+ expect(continueStatement.target, isNull);
+ }
+
+ void test_empty() {
+ Source source = addSource("");
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_entryPoint_exported() {
+ addNamedSource(
+ "/two.dart",
+ r'''
+library two;
+main() {}''');
+ Source source = addNamedSource(
+ "/one.dart",
+ r'''
+library one;
+export 'two.dart';''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ FunctionElement main = library.entryPoint;
+ expect(main, isNotNull);
+ expect(main.library, isNot(same(library)));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_entryPoint_local() {
+ Source source = addNamedSource(
+ "/one.dart",
+ r'''
+library one;
+main() {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ FunctionElement main = library.entryPoint;
+ expect(main, isNotNull);
+ expect(main.library, same(library));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_entryPoint_none() {
+ Source source = addNamedSource("/one.dart", "library one;");
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ expect(library.entryPoint, isNull);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_enum_externalLibrary() {
+ addNamedSource(
+ "/my_lib.dart",
+ r'''
+library my_lib;
+enum EEE {A, B, C}''');
+ Source source = addSource(r'''
+import 'my_lib.dart';
+main() {
+ EEE e = null;
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_extractedMethodAsConstant() {
+ Source source = addSource(r'''
+abstract class Comparable<T> {
+ int compareTo(T other);
+ static int compare(Comparable a, Comparable b) => a.compareTo(b);
+}
+class A {
+ void sort([compare = Comparable.compare]) {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_fieldFormalParameter() {
+ Source source = addSource(r'''
+class A {
+ int x;
+ A(this.x) {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_forEachLoops_nonConflicting() {
+ Source source = addSource(r'''
+f() {
+ List list = [1,2,3];
+ for (int x in list) {}
+ for (int x in list) {}
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_forLoops_nonConflicting() {
+ Source source = addSource(r'''
+f() {
+ for (int i = 0; i < 3; i++) {
+ }
+ for (int i = 0; i < 3; i++) {
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_functionTypeAlias() {
+ Source source = addSource(r'''
+typedef bool P(e);
+class A {
+ P p;
+ m(e) {
+ if (p(e)) {}
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_getter_and_setter_fromMixins_bare_identifier() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ get x => null;
+ set x(value) {}
+}
+class M2 {
+ get x => null;
+ set x(value) {}
+}
+class C extends B with M1, M2 {
+ void f() {
+ x += 1;
+ }
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that both the getter and setter for "x" in C.f() refer to the
+ // accessors defined in M2.
+ ClassElement classC = library.definingCompilationUnit.types[3];
+ MethodDeclaration f = classC.getMethod('f').computeNode();
+ BlockFunctionBody body = f.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ AssignmentExpression assignment = stmt.expression;
+ SimpleIdentifier leftHandSide = assignment.leftHandSide;
+ expect(leftHandSide.staticElement.enclosingElement.name, 'M2');
+ expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name,
+ 'M2');
+ }
+
+ void test_getter_fromMixins_bare_identifier() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ get x => null;
+}
+class M2 {
+ get x => null;
+}
+class C extends B with M1, M2 {
+ f() {
+ return x;
+ }
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the getter for "x" in C.f() refers to the getter defined in
+ // M2.
+ ClassElement classC = library.definingCompilationUnit.types[3];
+ MethodDeclaration f = classC.getMethod('f').computeNode();
+ BlockFunctionBody body = f.body;
+ ReturnStatement stmt = body.block.statements[0];
+ SimpleIdentifier x = stmt.expression;
+ expect(x.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_getter_fromMixins_property_access() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ get x => null;
+}
+class M2 {
+ get x => null;
+}
+class C extends B with M1, M2 {}
+void main() {
+ var y = new C().x;
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the getter for "x" in "new C().x" refers to the getter
+ // defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ VariableDeclarationStatement stmt = body.block.statements[0];
+ PropertyAccess propertyAccess = stmt.variables.variables[0].initializer;
+ expect(
+ propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_getterAndSetterWithDifferentTypes() {
+ Source source = addSource(r'''
+class A {
+ int get f => 0;
+ void set f(String s) {}
+}
+g (A a) {
+ a.f = a.f.toString();
+}''');
+ computeLibrarySourceErrors(source);
+ assertErrors(
+ source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
+ verify([source]);
+ }
+
+ void test_hasReferenceToSuper() {
+ Source source = addSource(r'''
+class A {}
+class B {toString() => super.toString();}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<ClassElement> classes = unit.types;
+ expect(classes, hasLength(2));
+ expect(classes[0].hasReferenceToSuper, isFalse);
+ expect(classes[1].hasReferenceToSuper, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_import_hide() {
+ addNamedSource(
+ "/lib1.dart",
+ r'''
+library lib1;
+set foo(value) {}
+class A {}''');
+ addNamedSource(
+ "/lib2.dart",
+ r'''
+library lib2;
+set foo(value) {}''');
+ Source source = addNamedSource(
+ "/lib3.dart",
+ r'''
+import 'lib1.dart' hide foo;
+import 'lib2.dart';
+
+main() {
+ foo = 0;
+}
+A a;''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_import_prefix() {
+ addNamedSource(
+ "/two.dart",
+ r'''
+library two;
+f(int x) {
+ return x * x;
+}''');
+ Source source = addNamedSource(
+ "/one.dart",
+ r'''
+library one;
+import 'two.dart' as _two;
+main() {
+ _two.f(0);
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_import_spaceInUri() {
+ addNamedSource(
+ "/sub folder/lib.dart",
+ r'''
+library lib;
+foo() {}''');
+ Source source = addNamedSource(
+ "/app.dart",
+ r'''
+import 'sub folder/lib.dart';
+
+main() {
+ foo();
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_indexExpression_typeParameters() {
+ Source source = addSource(r'''
+f() {
+ List<int> a;
+ a[0];
+ List<List<int>> b;
+ b[0][0];
+ List<List<List<int>>> c;
+ c[0][0][0];
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_indexExpression_typeParameters_invalidAssignmentWarning() {
+ Source source = addSource(r'''
+f() {
+ List<List<int>> b;
+ b[0][0] = 'hi';
+}''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ verify([source]);
+ }
+
+ void test_indirectOperatorThroughCall() {
+ Source source = addSource(r'''
+class A {
+ B call() { return new B(); }
+}
+
+class B {
+ int operator [](int i) { return i; }
+}
+
+A f = new A();
+
+g(int x) {}
+
+main() {
+ g(f()[0]);
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_invoke_dynamicThroughGetter() {
+ Source source = addSource(r'''
+class A {
+ List get X => [() => 0];
+ m(A a) {
+ X.last;
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_badSuperclass() {
+ Source source = addSource(r'''
+class A extends B {}
+class B {}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isFalse);
+ assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+ verify([source]);
+ }
+
+ void test_isValidMixin_badSuperclass_withSuperMixins() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+ Source source = addSource(r'''
+class A extends B {}
+class B {}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_constructor() {
+ Source source = addSource(r'''
+class A {
+ A() {}
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isFalse);
+ assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+ verify([source]);
+ }
+
+ void test_isValidMixin_constructor_withSuperMixins() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+ Source source = addSource(r'''
+class A {
+ A() {}
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isFalse);
+ assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+ verify([source]);
+ }
+
+ void test_isValidMixin_factoryConstructor() {
+ Source source = addSource(r'''
+class A {
+ factory A() => null;
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_factoryConstructor_withSuperMixins() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+ Source source = addSource(r'''
+class A {
+ factory A() => null;
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_super() {
+ Source source = addSource(r'''
+class A {
+ toString() {
+ return super.toString();
+ }
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isFalse);
+ assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
+ verify([source]);
+ }
+
+ void test_isValidMixin_super_withSuperMixins() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+ Source source = addSource(r'''
+class A {
+ toString() {
+ return super.toString();
+ }
+}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_valid() {
+ Source source = addSource('''
+class A {}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_isValidMixin_valid_withSuperMixins() {
+ resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+ Source source = addSource('''
+class A {}
+class C = Object with A;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ ClassElement a = unit.getType('A');
+ expect(a.isValidMixin, isTrue);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_labels_switch() {
+ Source source = addSource(r'''
+void doSwitch(int target) {
+ switch (target) {
+ l0: case 0:
+ continue l1;
+ l1: case 1:
+ continue l0;
+ default:
+ continue l1;
+ }
+}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_localVariable_types_invoked() {
+ Source source = addSource(r'''
+const A = null;
+main() {
+ var myVar = (int p) => 'foo';
+ myVar(42);
+}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, library);
+ expect(unit, isNotNull);
+ List<bool> found = [false];
+ List<CaughtException> thrownException = new List<CaughtException>(1);
+ unit.accept(new _SimpleResolverTest_localVariable_types_invoked(
+ this, found, thrownException));
+ if (thrownException[0] != null) {
+ throw new AnalysisException(
+ "Exception", new CaughtException(thrownException[0], null));
+ }
+ expect(found[0], isTrue);
+ }
+
+ void test_metadata_class() {
+ Source source = addSource(r'''
+const A = null;
+@A class C<A> {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unitElement = library.definingCompilationUnit;
+ expect(unitElement, isNotNull);
+ List<ClassElement> classes = unitElement.types;
+ expect(classes, hasLength(1));
+ List<ElementAnnotation> annotations = classes[0].metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = resolveCompilationUnit(source, library);
+ NodeList<CompilationUnitMember> declarations = unit.declarations;
+ expect(declarations, hasLength(2));
+ Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+ .variables
+ .variables[0]
+ .name
+ .staticElement;
+ EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
+ PropertyInducingElement, expectedElement);
+ expectedElement = (expectedElement as PropertyInducingElement).getter;
+ Element actualElement =
+ (declarations[1] as ClassDeclaration).metadata[0].name.staticElement;
+ expect(actualElement, same(expectedElement));
+ }
+
+ void test_metadata_field() {
+ Source source = addSource(r'''
+const A = null;
+class C {
+ @A int f;
+}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<ClassElement> classes = unit.types;
+ expect(classes, hasLength(1));
+ FieldElement field = classes[0].fields[0];
+ List<ElementAnnotation> annotations = field.metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_fieldFormalParameter() {
+ Source source = addSource(r'''
+const A = null;
+class C {
+ int f;
+ C(@A this.f);
+}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<ClassElement> classes = unit.types;
+ expect(classes, hasLength(1));
+ List<ConstructorElement> constructors = classes[0].constructors;
+ expect(constructors, hasLength(1));
+ List<ParameterElement> parameters = constructors[0].parameters;
+ expect(parameters, hasLength(1));
+ List<ElementAnnotation> annotations = parameters[0].metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_function() {
+ Source source = addSource(r'''
+const A = null;
+@A f() {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<FunctionElement> functions = unit.functions;
+ expect(functions, hasLength(1));
+ List<ElementAnnotation> annotations = functions[0].metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_functionTypedParameter() {
+ Source source = addSource(r'''
+const A = null;
+f(@A int p(int x)) {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<FunctionElement> functions = unit.functions;
+ expect(functions, hasLength(1));
+ List<ParameterElement> parameters = functions[0].parameters;
+ expect(parameters, hasLength(1));
+ List<ElementAnnotation> annotations1 = parameters[0].metadata;
+ expect(annotations1, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_libraryDirective() {
+ Source source = addSource(r'''
+@A library lib;
+const A = null;''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ List<ElementAnnotation> annotations = library.metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_method() {
+ Source source = addSource(r'''
+const A = null;
+class C {
+ @A void m() {}
+}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<ClassElement> classes = unit.types;
+ expect(classes, hasLength(1));
+ MethodElement method = classes[0].methods[0];
+ List<ElementAnnotation> annotations = method.metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_namedParameter() {
+ Source source = addSource(r'''
+const A = null;
+f({@A int p : 0}) {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<FunctionElement> functions = unit.functions;
+ expect(functions, hasLength(1));
+ List<ParameterElement> parameters = functions[0].parameters;
+ expect(parameters, hasLength(1));
+ List<ElementAnnotation> annotations1 = parameters[0].metadata;
+ expect(annotations1, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_positionalParameter() {
+ Source source = addSource(r'''
+const A = null;
+f([@A int p = 0]) {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<FunctionElement> functions = unit.functions;
+ expect(functions, hasLength(1));
+ List<ParameterElement> parameters = functions[0].parameters;
+ expect(parameters, hasLength(1));
+ List<ElementAnnotation> annotations1 = parameters[0].metadata;
+ expect(annotations1, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_simpleParameter() {
+ Source source = addSource(r'''
+const A = null;
+f(@A p1, @A int p2) {}''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unit = library.definingCompilationUnit;
+ expect(unit, isNotNull);
+ List<FunctionElement> functions = unit.functions;
+ expect(functions, hasLength(1));
+ List<ParameterElement> parameters = functions[0].parameters;
+ expect(parameters, hasLength(2));
+ List<ElementAnnotation> annotations1 = parameters[0].metadata;
+ expect(annotations1, hasLength(1));
+ List<ElementAnnotation> annotations2 = parameters[1].metadata;
+ expect(annotations2, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_metadata_typedef() {
+ Source source = addSource(r'''
+const A = null;
+@A typedef F<A>();''');
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ CompilationUnitElement unitElement = library.definingCompilationUnit;
+ expect(unitElement, isNotNull);
+ List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases;
+ expect(aliases, hasLength(1));
+ List<ElementAnnotation> annotations = aliases[0].metadata;
+ expect(annotations, hasLength(1));
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = resolveCompilationUnit(source, library);
+ NodeList<CompilationUnitMember> declarations = unit.declarations;
+ expect(declarations, hasLength(2));
+ Element expectedElement = (declarations[0] as TopLevelVariableDeclaration)
+ .variables
+ .variables[0]
+ .name
+ .staticElement;
+ EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement,
+ PropertyInducingElement, expectedElement);
+ expectedElement = (expectedElement as PropertyInducingElement).getter;
+ Element actualElement =
+ (declarations[1] as FunctionTypeAlias).metadata[0].name.staticElement;
+ expect(actualElement, same(expectedElement));
+ }
+
+ void test_method_fromMixin() {
+ Source source = addSource(r'''
+class B {
+ bar() => 1;
+}
+class A {
+ foo() => 2;
+}
+
+class C extends B with A {
+ bar() => super.bar();
+ foo() => super.foo();
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_method_fromMixins() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ void f() {}
+}
+class M2 {
+ void f() {}
+}
+class C extends B with M1, M2 {}
+void main() {
+ new C().f();
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the "f" in "new C().f()" refers to the "f" defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ MethodInvocation expr = stmt.expression;
+ expect(expr.methodName.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_method_fromMixins_bare_identifier() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ void f() {}
+}
+class M2 {
+ void f() {}
+}
+class C extends B with M1, M2 {
+ void g() {
+ f();
+ }
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the call to f() in C.g() refers to the method defined in M2.
+ ClassElement classC = library.definingCompilationUnit.types[3];
+ MethodDeclaration g = classC.getMethod('g').computeNode();
+ BlockFunctionBody body = g.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ MethodInvocation invocation = stmt.expression;
+ SimpleIdentifier methodName = invocation.methodName;
+ expect(methodName.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_method_fromMixins_invked_from_outside_class() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ void f() {}
+}
+class M2 {
+ void f() {}
+}
+class C extends B with M1, M2 {}
+void main() {
+ new C().f();
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the call to f() in "new C().f()" refers to the method
+ // defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ MethodInvocation invocation = stmt.expression;
+ expect(invocation.methodName.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_method_fromSuperclassMixin() {
+ Source source = addSource(r'''
+class A {
+ void m1() {}
+}
+class B extends Object with A {
+}
+class C extends B {
+}
+f(C c) {
+ c.m1();
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_methodCascades() {
+ Source source = addSource(r'''
+class A {
+ void m1() {}
+ void m2() {}
+ void m() {
+ A a = new A();
+ a..m1()
+ ..m2();
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_methodCascades_withSetter() {
+ Source source = addSource(r'''
+class A {
+ String name;
+ void m1() {}
+ void m2() {}
+ void m() {
+ A a = new A();
+ a..m1()
+ ..name = 'name'
+ ..m2();
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ // failing with error code: INVOCATION_OF_NON_FUNCTION
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_resolveAgainstNull() {
+ Source source = addSource(r'''
+f(var p) {
+ return null == p;
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ }
+
+ void test_setter_fromMixins_bare_identifier() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ set x(value) {}
+}
+class M2 {
+ set x(value) {}
+}
+class C extends B with M1, M2 {
+ void f() {
+ x = 1;
+ }
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the setter for "x" in C.f() refers to the setter defined in
+ // M2.
+ ClassElement classC = library.definingCompilationUnit.types[3];
+ MethodDeclaration f = classC.getMethod('f').computeNode();
+ BlockFunctionBody body = f.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ AssignmentExpression assignment = stmt.expression;
+ SimpleIdentifier leftHandSide = assignment.leftHandSide;
+ expect(leftHandSide.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_setter_fromMixins_property_access() {
+ Source source = addSource('''
+class B {}
+class M1 {
+ set x(value) {}
+}
+class M2 {
+ set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+ new C().x = 1;
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that the setter for "x" in "new C().x" refers to the setter
+ // defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ AssignmentExpression assignment = stmt.expression;
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ expect(
+ propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
+ }
+
+ void test_setter_inherited() {
+ Source source = addSource(r'''
+class A {
+ int get x => 0;
+ set x(int p) {}
+}
+class B extends A {
+ int get x => super.x == null ? 0 : super.x;
+ int f() => x = 1;
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ void test_setter_static() {
+ Source source = addSource(r'''
+set s(x) {
+}
+
+main() {
+ s = 123;
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ /**
+ * Resolve the given source and verify that the arguments in a specific method invocation were
+ * correctly resolved.
+ *
+ * The source is expected to be source for a compilation unit, the first declaration is expected
+ * to be a class, the first member of which is expected to be a method with a block body, and the
+ * first statement in the body is expected to be an expression statement whose expression is a
+ * method invocation. It is the arguments to that method invocation that are tested. The method
+ * invocation can contain errors.
+ *
+ * The arguments were resolved correctly if the number of expressions in the list matches the
+ * length of the array of indices and if, for each index in the array of indices, the parameter to
+ * which the argument expression was resolved is the parameter in the invoked method's list of
+ * parameters at that index. Arguments that should not be resolved to a parameter because of an
+ * error can be denoted by including a negative index in the array of indices.
+ *
+ * @param source the source to be resolved
+ * @param indices the array of indices used to associate arguments with parameters
+ * @throws Exception if the source could not be resolved or if the structure of the source is not
+ * valid
+ */
+ void _validateArgumentResolution(Source source, List<int> indices) {
+ LibraryElement library = resolve2(source);
+ expect(library, isNotNull);
+ ClassElement classElement = library.definingCompilationUnit.types[0];
+ List<ParameterElement> parameters = classElement.methods[1].parameters;
+ CompilationUnit unit = resolveCompilationUnit(source, library);
+ expect(unit, isNotNull);
+ ClassDeclaration classDeclaration =
+ unit.declarations[0] as ClassDeclaration;
+ MethodDeclaration methodDeclaration =
+ classDeclaration.members[0] as MethodDeclaration;
+ Block block = (methodDeclaration.body as BlockFunctionBody).block;
+ ExpressionStatement statement = block.statements[0] as ExpressionStatement;
+ MethodInvocation invocation = statement.expression as MethodInvocation;
+ NodeList<Expression> arguments = invocation.argumentList.arguments;
+ int argumentCount = arguments.length;
+ expect(argumentCount, indices.length);
+ for (int i = 0; i < argumentCount; i++) {
+ Expression argument = arguments[i];
+ ParameterElement element = argument.staticParameterElement;
+ int index = indices[i];
+ if (index < 0) {
+ expect(element, isNull);
+ } else {
+ expect(element, same(parameters[index]));
+ }
+ }
+ }
+}
+
+class _SimpleResolverTest_localVariable_types_invoked
+ extends RecursiveAstVisitor<Object> {
+ final SimpleResolverTest test;
+
+ List<bool> found;
+
+ List<CaughtException> thrownException;
+
+ _SimpleResolverTest_localVariable_types_invoked(
+ this.test, this.found, this.thrownException)
+ : super();
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ if (node.name == "myVar" && node.parent is MethodInvocation) {
+ try {
+ found[0] = true;
+ // check static type
+ DartType staticType = node.staticType;
+ expect(staticType, same(test.typeProvider.dynamicType));
+ // check propagated type
+ FunctionType propagatedType = node.propagatedType as FunctionType;
+ expect(propagatedType.returnType, test.typeProvider.stringType);
+ } on AnalysisException catch (e, stackTrace) {
+ thrownException[0] = new CaughtException(e, stackTrace);
+ }
+ }
+ return null;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698