// Copyright (c) 2014, 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. import 'package:analyzer/src/error/codes.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../src/dart/resolution/context_collection_resolution.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(StrictModeTest); defineReflectiveTests(TypePropagationTest); }); } /// The class `StrictModeTest` contains tests to ensure that the correct errors /// and warnings are reported when the analysis engine is run in strict mode. @reflectiveTest class StrictModeTest extends PubPackageResolutionTest { test_assert_is() async { await assertErrorsInCode( r''' int f(num n) { assert (n is int); return n & 0x0F; }''', [error(CompileTimeErrorCode.undefinedOperator, 47, 1)], ); } test_conditional_and_is() async { await assertNoErrorsInCode(r''' int f(num n) { return (n is int && n > 0) ? n & 0x0F : 0; }'''); } test_conditional_is() async { await assertNoErrorsInCode(r''' int f(num n) { return (n is int) ? n & 0x0F : 0; }'''); } test_conditional_isNot() async { await assertNoErrorsInCode(r''' int f(num n) { return (n is! int) ? 0 : n & 0x0F; } '''); } test_conditional_or_is() async { await assertNoErrorsInCode(r''' int f(num n) { return (n is! int || n < 0) ? 0 : n & 0x0F; } '''); } test_for() async { await assertNoErrorsInCode(r''' void f(List list) { num sum = 0; // ignore: unused_local_variable for (int i = 0; i < list.length; i++) { sum += list[i]; } } '''); } test_forEach() async { await assertErrorsInCode( r''' void f(List list) { num sum = 0; // ignore: unused_local_variable for (num n in list) { sum += n & 0x0F; } } ''', [error(CompileTimeErrorCode.undefinedOperator, 110, 1)], ); } test_if_and_is() async { await assertNoErrorsInCode(r''' int f(num n) { if (n is int && n > 0) { return n & 0x0F; } return 0; }'''); } test_if_is() async { await assertNoErrorsInCode(r''' int f(num n) { if (n is int) { return n & 0x0F; } return 0; }'''); } test_if_isNot() async { await assertNoErrorsInCode(r''' int f(num n) { if (n is! int) { return 0; } else { return n & 0x0F; } } '''); } test_if_isNot_abrupt() async { await assertNoErrorsInCode(r''' int f(num n) { if (n is! int) { return 0; } return n & 0x0F; } '''); } test_if_or_is() async { await assertNoErrorsInCode(r''' int f(num n) { if (n is! int || n < 0) { return 0; } else { return n & 0x0F; } } '''); } test_localVar() async { await assertErrorsInCode( r''' int f() { num n = 1234; return n & 0x0F; }''', [error(CompileTimeErrorCode.undefinedOperator, 37, 1)], ); } } @reflectiveTest class TypePropagationTest extends PubPackageResolutionTest { test_assignment_null() async { await resolveTestCode(r''' main() { int v; // declare v = null; return v; // return } '''); var node = findNode.simple('v; // return'); assertResolvedNodeText(node, r''' SimpleIdentifier token: v element: v@15 staticType: int '''); } test_initializer_hasStaticType() async { await resolveTestCode(r''' f() { int v = 0; return v; }'''); var node = findNode.simple('v;'); assertResolvedNodeText(node, r''' SimpleIdentifier token: v element: v@12 staticType: int '''); } test_initializer_hasStaticType_parameterized() async { await resolveTestCode(r''' f() { List v = []; return v; }'''); var node = findNode.simple('v;'); assertResolvedNodeText(node, r''' SimpleIdentifier token: v element: v@18 staticType: List '''); } test_initializer_null() async { await resolveTestCode(r''' main() { int v = null; return v; }'''); var node = findNode.simple('v;'); assertResolvedNodeText(node, r''' SimpleIdentifier token: v element: v@15 staticType: int '''); } test_invocation_target_prefixed() async { newFile('$testPackageLibPath/a.dart', r''' int max(int x, int y) => 0; '''); await resolveTestCode(''' import 'a.dart' as helper; main() { helper.max(10, 10); // marker }'''); var node = findNode.simple('max(10, 10)'); assertResolvedNodeText(node, r''' SimpleIdentifier token: max element: package:test/a.dart::@function::max staticType: int Function(int, int) '''); } test_is_subclass() async { await resolveTestCode(r''' class A {} class B extends A { B m() => this; } A f(A p) { if (p is B) { return p.m(); } return p; }'''); var node = findNode.methodInvocation('p.m()'); assertResolvedNodeText(node, r''' MethodInvocation target: SimpleIdentifier token: p element: ::@function::f::@formalParameter::p staticType: B operator: . methodName: SimpleIdentifier token: m element: ::@class::B::@method::m staticType: B Function() argumentList: ArgumentList leftParenthesis: ( rightParenthesis: ) staticInvokeType: B Function() staticType: B '''); } test_mutatedOutsideScope() async { // https://code.google.com/p/dart/issues/detail?id=22732 await assertNoErrorsInCode(r''' class Base { } class Derived extends Base { get y => null; } class C { void f(Base x) { x = Base(); if (x is Derived) { print(x.y); // BAD } x = Base(); } } void g(Base x) { x = Base(); if (x is Derived) { print(x.y); // GOOD } x = Base(); } '''); } test_objectAccessInference_disabled_for_library_prefix() async { newFile('$testPackageLibPath/a.dart', ''' dynamic get hashCode => 42; '''); await assertNoErrorsInCode(''' import 'a.dart' as helper; main() { helper.hashCode; }'''); assertTypeDynamic(findNode.prefixed('helper.hashCode')); } test_objectAccessInference_disabled_for_local_getter() async { await assertNoErrorsInCode(''' dynamic get hashCode => null; main() { hashCode; // marker }'''); assertTypeDynamic(findNode.simple('hashCode; // marker')); } test_objectMethodInference_disabled_for_library_prefix() async { newFile('$testPackageLibPath/a.dart', ''' dynamic toString = (int x) => x + 42; '''); await assertNoErrorsInCode(''' import 'a.dart' as helper; main() { helper.toString(); }'''); assertTypeDynamic( findNode.functionExpressionInvocation('helper.toString()'), ); } test_objectMethodInference_disabled_for_local_function() async { await resolveTestCode(''' main() { dynamic toString = () => null; toString(); // marker }'''); var node = findNode.simple('toString(); // marker'); assertResolvedNodeText(node, r''' SimpleIdentifier token: toString element: toString@19 staticType: dynamic '''); } @failingTest test_propagatedReturnType_functionExpression() async { // TODO(scheglov): disabled because we don't resolve function expression await resolveTestCode(r''' main() { var v = (() {return 42;})(); }'''); assertTypeDynamic(findNode.simple('v = ')); } }