| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.resolver_test; | 5 library engine.resolver_test; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| (...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2202 m() { | 2202 m() { |
| 2203 var i = ''; | 2203 var i = ''; |
| 2204 n(i); | 2204 n(i); |
| 2205 } | 2205 } |
| 2206 n(int i) {}'''); | 2206 n(int i) {}'''); |
| 2207 resolve(source); | 2207 resolve(source); |
| 2208 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); | 2208 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 2209 verify([source]); | 2209 verify([source]); |
| 2210 } | 2210 } |
| 2211 | 2211 |
| 2212 void test_argumentTypeNotAssignable_unionTypeMethodMerge() { | |
| 2213 enableUnionTypes(false); | |
| 2214 Source source = addSource(r''' | |
| 2215 class A { | |
| 2216 int m(int x) => 0; | |
| 2217 } | |
| 2218 class B { | |
| 2219 String m(String x) => '0'; | |
| 2220 } | |
| 2221 f(A a, B b) { | |
| 2222 var ab; | |
| 2223 if (0 < 1) { | |
| 2224 ab = a; | |
| 2225 } else { | |
| 2226 ab = b; | |
| 2227 } | |
| 2228 ab.m(0.5); | |
| 2229 }'''); | |
| 2230 resolve(source); | |
| 2231 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); | |
| 2232 verify([source]); | |
| 2233 } | |
| 2234 | |
| 2235 void test_deadCode_deadBlock_conditionalElse() { | 2212 void test_deadCode_deadBlock_conditionalElse() { |
| 2236 Source source = addSource(r''' | 2213 Source source = addSource(r''' |
| 2237 f() { | 2214 f() { |
| 2238 true ? 1 : 2; | 2215 true ? 1 : 2; |
| 2239 }'''); | 2216 }'''); |
| 2240 resolve(source); | 2217 resolve(source); |
| 2241 assertErrors(source, [HintCode.DEAD_CODE]); | 2218 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2242 verify([source]); | 2219 verify([source]); |
| 2243 } | 2220 } |
| 2244 | 2221 |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2653 class A { | 2630 class A { |
| 2654 @deprecated | 2631 @deprecated |
| 2655 m() {} | 2632 m() {} |
| 2656 n() {m();} | 2633 n() {m();} |
| 2657 }'''); | 2634 }'''); |
| 2658 resolve(source); | 2635 resolve(source); |
| 2659 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | 2636 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2660 verify([source]); | 2637 verify([source]); |
| 2661 } | 2638 } |
| 2662 | 2639 |
| 2663 void test_deprecatedAnnotationUse_deprecatedMethodCalledOnUnionType() { | |
| 2664 enableUnionTypes(false); | |
| 2665 Source source = addSource(r''' | |
| 2666 class A { | |
| 2667 @deprecated f() => 0; | |
| 2668 } | |
| 2669 class B extends A {} | |
| 2670 main(A a, B b) { | |
| 2671 var x; | |
| 2672 if (0 < 1) { | |
| 2673 x = a; | |
| 2674 } else { | |
| 2675 x = b; | |
| 2676 } | |
| 2677 x.f(); // Here [x] has type [{A,B}] but we still want the deprecation warning. | |
| 2678 }'''); | |
| 2679 resolve(source); | |
| 2680 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
| 2681 verify([source]); | |
| 2682 } | |
| 2683 | |
| 2684 void test_deprecatedAnnotationUse_export() { | 2640 void test_deprecatedAnnotationUse_export() { |
| 2685 Source source = addSource("export 'deprecated_library.dart';"); | 2641 Source source = addSource("export 'deprecated_library.dart';"); |
| 2686 addNamedSource("/deprecated_library.dart", r''' | 2642 addNamedSource("/deprecated_library.dart", r''' |
| 2687 @deprecated | 2643 @deprecated |
| 2688 library deprecated_library; | 2644 library deprecated_library; |
| 2689 class A {}'''); | 2645 class A {}'''); |
| 2690 resolve(source); | 2646 resolve(source); |
| 2691 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | 2647 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2692 verify([source]); | 2648 verify([source]); |
| 2693 } | 2649 } |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3132 f(var a, var a2) { | 3088 f(var a, var a2) { |
| 3133 a = new A(); | 3089 a = new A(); |
| 3134 a2 = new A(); | 3090 a2 = new A(); |
| 3135 a += a2; | 3091 a += a2; |
| 3136 } | 3092 } |
| 3137 }'''); | 3093 }'''); |
| 3138 resolve(source); | 3094 resolve(source); |
| 3139 assertErrors(source, [HintCode.UNDEFINED_METHOD]); | 3095 assertErrors(source, [HintCode.UNDEFINED_METHOD]); |
| 3140 } | 3096 } |
| 3141 | 3097 |
| 3142 void test_undefinedMethod_unionType_noSuchMethod() { | |
| 3143 enableUnionTypes(false); | |
| 3144 Source source = addSource(r''' | |
| 3145 class A { | |
| 3146 int m(int x) => 0; | |
| 3147 } | |
| 3148 class B { | |
| 3149 String m() => '0'; | |
| 3150 } | |
| 3151 f(A a, B b) { | |
| 3152 var ab; | |
| 3153 if (0 < 1) { | |
| 3154 ab = a; | |
| 3155 } else { | |
| 3156 ab = b; | |
| 3157 } | |
| 3158 ab.n(); | |
| 3159 }'''); | |
| 3160 resolve(source); | |
| 3161 assertErrors(source, [HintCode.UNDEFINED_METHOD]); | |
| 3162 } | |
| 3163 | |
| 3164 void test_undefinedOperator_binaryExpression() { | 3098 void test_undefinedOperator_binaryExpression() { |
| 3165 Source source = addSource(r''' | 3099 Source source = addSource(r''' |
| 3166 class A {} | 3100 class A {} |
| 3167 f(var a) { | 3101 f(var a) { |
| 3168 if(a is A) { | 3102 if(a is A) { |
| 3169 a + 1; | 3103 a + 1; |
| 3170 } | 3104 } |
| 3171 }'''); | 3105 }'''); |
| 3172 resolve(source); | 3106 resolve(source); |
| 3173 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | 3107 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| (...skipping 3368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6542 if (message is Function) { | 6476 if (message is Function) { |
| 6543 message = dynamic_; | 6477 message = dynamic_; |
| 6544 } | 6478 } |
| 6545 int s = message; | 6479 int s = message; |
| 6546 }'''); | 6480 }'''); |
| 6547 resolve(source); | 6481 resolve(source); |
| 6548 assertNoErrors(source); | 6482 assertNoErrors(source); |
| 6549 verify([source]); | 6483 verify([source]); |
| 6550 } | 6484 } |
| 6551 | 6485 |
| 6552 void test_issue20904BuggyTypePromotionAtIfJoin_2() { | |
| 6553 // https://code.google.com/p/dart/issues/detail?id=20904 | |
| 6554 enableUnionTypes(false); | |
| 6555 Source source = addSource(r''' | |
| 6556 f(var message) { | |
| 6557 if (message is Function) { | |
| 6558 message = ''; | |
| 6559 } | |
| 6560 int s = message; | |
| 6561 }'''); | |
| 6562 resolve(source); | |
| 6563 assertNoErrors(source); | |
| 6564 verify([source]); | |
| 6565 } | |
| 6566 | |
| 6567 void test_issue20904BuggyTypePromotionAtIfJoin_3() { | 6486 void test_issue20904BuggyTypePromotionAtIfJoin_3() { |
| 6568 // https://code.google.com/p/dart/issues/detail?id=20904 | 6487 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6569 Source source = addSource(r''' | 6488 Source source = addSource(r''' |
| 6570 f(var message) { | 6489 f(var message) { |
| 6571 var dynamic_; | 6490 var dynamic_; |
| 6572 if (message is Function) { | 6491 if (message is Function) { |
| 6573 message = dynamic_; | 6492 message = dynamic_; |
| 6574 } else { | 6493 } else { |
| 6575 return; | 6494 return; |
| 6576 } | 6495 } |
| (...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7741 CompilationUnitElementImpl compilationUnit = | 7660 CompilationUnitElementImpl compilationUnit = |
| 7742 new CompilationUnitElementImpl(fileName); | 7661 new CompilationUnitElementImpl(fileName); |
| 7743 compilationUnit.source = _createNamedSource(fileName); | 7662 compilationUnit.source = _createNamedSource(fileName); |
| 7744 LibraryElementImpl library = new LibraryElementImpl.forNode( | 7663 LibraryElementImpl library = new LibraryElementImpl.forNode( |
| 7745 context, AstFactory.libraryIdentifier2([libraryName])); | 7664 context, AstFactory.libraryIdentifier2([libraryName])); |
| 7746 library.definingCompilationUnit = compilationUnit; | 7665 library.definingCompilationUnit = compilationUnit; |
| 7747 library.parts = sourcedCompilationUnits; | 7666 library.parts = sourcedCompilationUnits; |
| 7748 return library; | 7667 return library; |
| 7749 } | 7668 } |
| 7750 | 7669 |
| 7751 /** | |
| 7752 * Enable optionally strict union types for the current test. | |
| 7753 * | |
| 7754 * @param strictUnionTypes `true` if union types should be strict. | |
| 7755 */ | |
| 7756 void enableUnionTypes(bool strictUnionTypes) { | |
| 7757 AnalysisEngine.instance.enableUnionTypes = true; | |
| 7758 AnalysisEngine.instance.strictUnionTypes = strictUnionTypes; | |
| 7759 } | |
| 7760 | |
| 7761 Expression findTopLevelConstantExpression( | 7670 Expression findTopLevelConstantExpression( |
| 7762 CompilationUnit compilationUnit, String name) => | 7671 CompilationUnit compilationUnit, String name) => |
| 7763 findTopLevelDeclaration(compilationUnit, name).initializer; | 7672 findTopLevelDeclaration(compilationUnit, name).initializer; |
| 7764 | 7673 |
| 7765 VariableDeclaration findTopLevelDeclaration( | 7674 VariableDeclaration findTopLevelDeclaration( |
| 7766 CompilationUnit compilationUnit, String name) { | 7675 CompilationUnit compilationUnit, String name) { |
| 7767 for (CompilationUnitMember member in compilationUnit.declarations) { | 7676 for (CompilationUnitMember member in compilationUnit.declarations) { |
| 7768 if (member is TopLevelVariableDeclaration) { | 7677 if (member is TopLevelVariableDeclaration) { |
| 7769 for (VariableDeclaration variable in member.variables.variables) { | 7678 for (VariableDeclaration variable in member.variables.variables) { |
| 7770 if (variable.name.name == name) { | 7679 if (variable.name.name == name) { |
| 7771 return variable; | 7680 return variable; |
| 7772 } | 7681 } |
| 7773 } | 7682 } |
| 7774 } | 7683 } |
| 7775 } | 7684 } |
| 7776 return null; | 7685 return null; |
| 7777 // Not found | 7686 // Not found |
| 7778 } | 7687 } |
| 7779 | 7688 |
| 7780 /** | 7689 /** |
| 7781 * In the rare cases we want to group several tests into single "test_" method
, so need a way to | 7690 * In the rare cases we want to group several tests into single "test_" method
, so need a way to |
| 7782 * reset test instance to reuse it. | 7691 * reset test instance to reuse it. |
| 7783 */ | 7692 */ |
| 7784 void reset() { | 7693 void reset() { |
| 7785 analysisContext2 = AnalysisContextFactory.contextWithCore(); | 7694 analysisContext2 = AnalysisContextFactory.contextWithCore(); |
| 7786 // These defaults are duplicated for the editor in | |
| 7787 // editor/tools/plugins/com.google.dart.tools.core/.options . | |
| 7788 AnalysisEngine.instance.enableUnionTypes = false; | |
| 7789 AnalysisEngine.instance.strictUnionTypes = false; | |
| 7790 } | 7695 } |
| 7791 | 7696 |
| 7792 /** | 7697 /** |
| 7793 * Reset the analysis context to have the given options applied. | 7698 * Reset the analysis context to have the given options applied. |
| 7794 * | 7699 * |
| 7795 * @param options the analysis options to be applied to the context | 7700 * @param options the analysis options to be applied to the context |
| 7796 */ | 7701 */ |
| 7797 void resetWithOptions(AnalysisOptions options) { | 7702 void resetWithOptions(AnalysisOptions options) { |
| 7798 analysisContext2 = | 7703 analysisContext2 = |
| 7799 AnalysisContextFactory.contextWithCoreAndOptions(options); | 7704 AnalysisContextFactory.contextWithCoreAndOptions(options); |
| (...skipping 4828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12628 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; | 12533 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12629 InterfaceType typeA = classA.element.type; | 12534 InterfaceType typeA = classA.element.type; |
| 12630 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; | 12535 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12631 BlockFunctionBody body = | 12536 BlockFunctionBody body = |
| 12632 function.functionExpression.body as BlockFunctionBody; | 12537 function.functionExpression.body as BlockFunctionBody; |
| 12633 ReturnStatement statement = body.block.statements[1] as ReturnStatement; | 12538 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 12634 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; | 12539 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12635 expect(variableName.propagatedType, same(typeA)); | 12540 expect(variableName.propagatedType, same(typeA)); |
| 12636 } | 12541 } |
| 12637 | 12542 |
| 12638 void test_issue20904BuggyTypePromotionAtIfJoin_2() { | |
| 12639 // https://code.google.com/p/dart/issues/detail?id=20904 | |
| 12640 enableUnionTypes(false); | |
| 12641 String code = r''' | |
| 12642 f(var message) { | |
| 12643 if (message is Function) { | |
| 12644 message = ''; | |
| 12645 } | |
| 12646 message; // marker | |
| 12647 }'''; | |
| 12648 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; | |
| 12649 expect(typeProvider.stringType == t, isFalse); | |
| 12650 expect(typeProvider.functionType == t, isFalse); | |
| 12651 } | |
| 12652 | |
| 12653 void test_issue20904BuggyTypePromotionAtIfJoin_5() { | 12543 void test_issue20904BuggyTypePromotionAtIfJoin_5() { |
| 12654 // https://code.google.com/p/dart/issues/detail?id=20904 | 12544 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 12655 // | 12545 // |
| 12656 // This is not an example of the 20904 bug, but rather, | 12546 // This is not an example of the 20904 bug, but rather, |
| 12657 // an example of something that one obvious fix changes inadvertently: we | 12547 // an example of something that one obvious fix changes inadvertently: we |
| 12658 // want to avoid using type information from is-checks when it | 12548 // want to avoid using type information from is-checks when it |
| 12659 // loses precision. I can't see how to get a bad hint this way, since | 12549 // loses precision. I can't see how to get a bad hint this way, since |
| 12660 // it seems the propagated type is not used to generate hints when a | 12550 // it seems the propagated type is not used to generate hints when a |
| 12661 // more precise type would cause no hint. For example, for code like the | 12551 // more precise type would cause no hint. For example, for code like the |
| 12662 // following, when the propagated type of [x] is [A] -- as happens for the | 12552 // following, when the propagated type of [x] is [A] -- as happens for the |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12856 if (x) { | 12746 if (x) { |
| 12857 y = 0; | 12747 y = 0; |
| 12858 } else { | 12748 } else { |
| 12859 return y; | 12749 return y; |
| 12860 } | 12750 } |
| 12861 // Propagated type is [int] here: correct. | 12751 // Propagated type is [int] here: correct. |
| 12862 return y; // marker | 12752 return y; // marker |
| 12863 }''', null, typeProvider.intType); | 12753 }''', null, typeProvider.intType); |
| 12864 } | 12754 } |
| 12865 | 12755 |
| 12866 void test_mergePropagatedTypesAtJoinPoint_6() { | |
| 12867 // https://code.google.com/p/dart/issues/detail?id=19929 | |
| 12868 // | |
| 12869 // Labeled [break]s are unsafe for the purposes of | |
| 12870 // [isAbruptTerminationStatement]. | |
| 12871 // | |
| 12872 // This is tricky: the [break] jumps back above the [if], making | |
| 12873 // it into a loop of sorts. The [if] type-propagation code assumes | |
| 12874 // that [break] does not introduce a loop. | |
| 12875 enableUnionTypes(false); | |
| 12876 String code = r''' | |
| 12877 f() { | |
| 12878 var x = 0; | |
| 12879 var c = false; | |
| 12880 L: | |
| 12881 if (c) { | |
| 12882 } else { | |
| 12883 x = ''; | |
| 12884 c = true; | |
| 12885 break L; | |
| 12886 } | |
| 12887 x; // marker | |
| 12888 }'''; | |
| 12889 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; | |
| 12890 expect(typeProvider.intType.isSubtypeOf(t), isTrue); | |
| 12891 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); | |
| 12892 } | |
| 12893 | |
| 12894 void test_mutatedOutsideScope() { | 12756 void test_mutatedOutsideScope() { |
| 12895 // https://code.google.com/p/dart/issues/detail?id=22732 | 12757 // https://code.google.com/p/dart/issues/detail?id=22732 |
| 12896 Source source = addSource(r''' | 12758 Source source = addSource(r''' |
| 12897 class Base { | 12759 class Base { |
| 12898 } | 12760 } |
| 12899 | 12761 |
| 12900 class Derived extends Base { | 12762 class Derived extends Base { |
| 12901 get y => null; | 12763 get y => null; |
| 12902 } | 12764 } |
| 12903 | 12765 |
| (...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13785 // check propagated type | 13647 // check propagated type |
| 13786 FunctionType propagatedType = node.propagatedType as FunctionType; | 13648 FunctionType propagatedType = node.propagatedType as FunctionType; |
| 13787 expect(propagatedType.returnType, test.typeProvider.stringType); | 13649 expect(propagatedType.returnType, test.typeProvider.stringType); |
| 13788 } on AnalysisException catch (e, stackTrace) { | 13650 } on AnalysisException catch (e, stackTrace) { |
| 13789 thrownException[0] = new CaughtException(e, stackTrace); | 13651 thrownException[0] = new CaughtException(e, stackTrace); |
| 13790 } | 13652 } |
| 13791 } | 13653 } |
| 13792 return null; | 13654 return null; |
| 13793 } | 13655 } |
| 13794 } | 13656 } |
| OLD | NEW |