diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart index 2b5ff785b30..e901c24a909 100644 --- a/pkg/analyzer/test/generated/non_error_resolver_test.dart +++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart @@ -5,7 +5,6 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; -import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -2682,18 +2681,20 @@ class A { '''); } - @failingTest test_null_callOperator() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { null + 5; +// ^ +// [diag.invalidUseOfNullValue] An expression whose value is always 'null' can't be dereferenced. null == 5; +//^^^^^^^ +// [diag.unnecessaryNullComparisonNeverNullFalse] The operand can't be 'null', so the condition is always 'false'. null[0]; +// ^ +// [diag.invalidUseOfNullValue] An expression whose value is always 'null' can't be dereferenced. } -''', - [error(diag.undefinedMethod, 0, 0), error(diag.undefinedMethod, 0, 0)], - ); +'''); } test_optionalNew_rewrite() async { diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart index 323ccac5223..c605dab37cb 100644 --- a/pkg/analyzer/test/generated/strong_mode_test.dart +++ b/pkg/analyzer/test/generated/strong_mode_test.dart @@ -11,7 +11,6 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/dart/analysis/results.dart'; import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -328,17 +327,19 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { // variable if they are ordered right to left, when the variable // appears co- and contra-variantly, and that an error is issued // for the non-matching bound. - String code = r''' + var result = await resolveTestCodeWithDiagnostics(r''' typedef To Func1(From x); T f, S>(S x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'f' because it has a return type of 'T'. void test() { var x = f(3)(null); } - '''; - var result = await assertErrorsInCode(code, [ - error(diag.returnOfInvalidTypeFromFunction, 82, 4), - error(diag.unusedLocalVariable, 110, 1), - error(diag.couldNotInfer, 114, 1), - error(diag.argumentTypeNotAssignable, 119, 4), - ]); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'x' isn't used. +// ^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T'.\n\nTried to infer 'Object? Function(Never)' for 'T' which doesn't work:\n Type parameter 'T' is declared to extend 'S Function(S)' producing 'int Function(int)'.\n\nConsider passing explicit type argument(s) to the generic. +// ^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'Null' can't be assigned to the parameter type 'Never'. + '''); List statements = AstFinder.getStatementsInTopLevelFunction( result.unit, @@ -961,39 +962,36 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards1() async { // Test that downwards inference interacts correctly with FutureOr // parameters. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. Future test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); } test_futureOr_downwards2() async { // Test that downwards inference interacts correctly with FutureOr // parameters when the downwards context is FutureOr - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); } test_futureOr_downwards3() async { // Test that downwards inference correctly propagates into // arguments. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. Future test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); _isFutureOfInt( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1004,13 +1002,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards4() async { // Test that downwards inference interacts correctly with FutureOr // parameters when the downwards context is FutureOr - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); _isFutureOfInt( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1021,13 +1018,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards5() async { // Test that downwards inference correctly pins the type when it // comes from a FutureOr - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOf([_isNum])(invoke.staticType as InterfaceType); _isFutureOf([_isNum])( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1038,13 +1034,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards6() async { // Test that downwards inference doesn't decompose FutureOr // when instantiating type variables. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' T mk(T x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'T'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 42, 4)], - ); + '''); _isFutureOrOfInt(invoke.staticType as InterfaceType); _isFutureOfInt( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1055,13 +1050,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards7() async { // Test that downwards inference incorporates bounds correctly // when instantiating type variables. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' T mk>(T x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'T'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 64, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); _isFutureOfInt( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1074,13 +1068,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { // when instantiating type variables. // TODO(leafp): I think this should pass once the inference changes // that jmesserly is adding are landed. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' T mk>(T x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'T'. FutureOr test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 65, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); _isFutureOfInt( invoke.argumentList.arguments[0].argumentExpression.staticType @@ -1091,13 +1084,12 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_downwards9() async { // Test that downwards inference decomposes correctly with // other composite types - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' List mk(T x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'List'. FutureOr> test() => mk(3); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 48, 4)], - ); + '''); _isListOf(_isInt)(invoke.staticType as InterfaceType); _isInt(invoke.argumentList.arguments[0].argumentExpression.typeOrThrow); } @@ -1112,50 +1104,42 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_methods2() async { // Test that FutureOr does not have the constituent type methods - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' dynamic test(FutureOr x) => x.abs(); - ''', - expectedDiagnostics: [error(diag.undefinedMethod, 61, 3)], - ); +// ^^^ +// [diag.undefinedMethod] The method 'abs' isn't defined for the type 'FutureOr'. + '''); _isInvalidType(invoke.typeOrThrow); } test_futureOr_methods3() async { // Test that FutureOr does not have the Future type methods - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' dynamic test(FutureOr x) => x.then((x) => x); - ''', - expectedDiagnostics: [error(diag.undefinedMethod, 61, 4)], - ); +// ^^^^ +// [diag.undefinedMethod] The method 'then' isn't defined for the type 'FutureOr'. + '''); _isInvalidType(invoke.typeOrThrow); } test_futureOr_methods4() async { // Test that FutureOr does not have all methods - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' dynamic test(FutureOr x) => x.abs(); - ''', - expectedDiagnostics: [ - error(diag.uncheckedMethodInvocationOfNullableValue, 65, 3), - ], - ); +// ^^^ +// [diag.uncheckedMethodInvocationOfNullableValue] The method 'abs' can't be unconditionally invoked because the receiver can be 'null'. + '''); _isInvalidType(invoke.typeOrThrow); } test_futureOr_no_return() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) {}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1163,16 +1147,13 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { } test_futureOr_no_return_value() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) {return;}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1180,16 +1161,13 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { } test_futureOr_return_null() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) {return null;}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1199,40 +1177,35 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { test_futureOr_upwards1() async { // Test that upwards inference correctly prefers to instantiate type // variables with the "smaller" solution when both are possible. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' Future mk(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'Future'. dynamic test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 60, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); } test_futureOr_upwards2() async { // Test that upwards inference fails when the solution doesn't // match the bound. - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' T mk>(FutureOr x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'mk' because it has a return type of 'T'. dynamic test() => mk(new Future.value(42)); - ''', - expectedDiagnostics: [error(diag.returnOfInvalidTypeFromFunction, 75, 4)], - ); + '''); _isFutureOfInt(invoke.staticType as InterfaceType); } test_futureOrNull_no_return() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) {}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1240,16 +1213,13 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { } test_futureOrNull_no_return_value() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) {return;}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1257,16 +1227,13 @@ class StrongModeLocalInferenceTest extends PubPackageResolutionTest { } test_futureOrNull_return_null() async { - MethodInvocation invoke = await _testFutureOr( - r''' + MethodInvocation invoke = await _testFutureOr(r''' FutureOr mk(Future x) => x; Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. test() => f.then((int x) { return null;}); - ''', - expectedDiagnostics: [ - error(diag.notInitializedNonNullableVariable, 79, 1), - ], - ); + '''); _isFunction2Of(_isInt, _isNull)( invoke.argumentList.arguments[0].argumentExpression.typeOrThrow, ); @@ -1355,20 +1322,21 @@ void test() { } test_inference_error_arguments() async { - var code = r''' + var result = await resolveTestCodeWithDiagnostics(r''' typedef R F(T t); F g(F f) => (x) => f(f(x)); test() { var h = g((int x) => 42.0); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'h' isn't used. +// ^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T'.\n\nTried to infer 'double' for 'T' which doesn't work:\n Parameter 'f' declared as 'T Function(T)'\n but argument is 'double Function(int)'.\n\nConsider passing explicit type argument(s) to the generic. +// ^^^^^^^^^^^^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'double Function(int)' can't be assigned to the parameter type 'F'. } - '''; - var result = await assertErrorsInCode(code, [ - error(diag.unusedLocalVariable, 84, 1), - error(diag.couldNotInfer, 88, 1), - error(diag.argumentTypeNotAssignable, 90, 15), - ]); + '''); _expectInferenceError(result, r''' Couldn't infer type parameter 'T'. @@ -1382,21 +1350,23 @@ Consider passing explicit type argument(s) to the generic. } test_inference_error_arguments2() async { - var code = r''' + var result = await resolveTestCodeWithDiagnostics(r''' typedef R F(T t); F g(F a, F b) => (x) => a(b(x)); test() { var h = g((int x) => 42.0, (double x) => 42); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'h' isn't used. +// ^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T'.\n\nTried to infer 'num' for 'T' which doesn't work:\n Parameter 'a' declared as 'T Function(T)'\n but argument is 'double Function(int)'.\n Parameter 'b' declared as 'T Function(T)'\n but argument is 'int Function(double)'.\n\nConsider passing explicit type argument(s) to the generic. +// ^^^^^^^^^^^^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'double Function(int)' can't be assigned to the parameter type 'F'. +// ^^^^^^^^^^^^^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'int Function(double)' can't be assigned to the parameter type 'F'. } - '''; - var result = await assertErrorsInCode(code, [ - error(diag.unusedLocalVariable, 95, 1), - error(diag.couldNotInfer, 99, 1), - error(diag.argumentTypeNotAssignable, 101, 15), - error(diag.argumentTypeNotAssignable, 118, 16), - ]); + '''); _expectInferenceError(result, r''' Couldn't infer type parameter 'T'. @@ -1490,20 +1460,21 @@ test(Iterable values) { } test_inference_error_returnContext() async { - var code = r''' + var result = await resolveTestCodeWithDiagnostics(r''' typedef R F(T t); F g(T t) => (x) => t; test() { F h = g(42); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'h' isn't used. +// ^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T'.\n\nTried to infer 'num' for 'T' which doesn't work:\n Return type declared as 'T Function(T)'\n used where 'int Function(num)' is required.\n\nConsider passing explicit type argument(s) to the generic. +// ^^^^^ +// [diag.invalidAssignment] A value of type 'F' can't be assigned to a variable of type 'F'. } - '''; - var result = await assertErrorsInCode(code, [ - error(diag.unusedLocalVariable, 80, 1), - error(diag.couldNotInfer, 84, 1), - error(diag.invalidAssignment, 84, 5), - ]); + '''); _expectInferenceError(result, r''' Couldn't infer type parameter 'T'. @@ -3552,14 +3523,14 @@ class B { _isListOf(_isString)(exp.staticType as InterfaceType); } - /// Verifies the result has [diag.couldNotInfer] with + /// Verifies the result has a `could_not_infer` diagnostic with /// the expected [errorMessage]. void _expectInferenceError( TestResolvedUnitResult result, String errorMessage, ) { var errors = result.diagnostics - .where((e) => e.diagnosticCode == diag.couldNotInfer) + .where((e) => e.diagnosticCode.lowerCaseUniqueName == 'could_not_infer') .map((e) => e.message) .toList(); expect(errors.length, 1); @@ -3602,20 +3573,16 @@ class B { /// Helper method for testing `FutureOr`. /// - /// Validates that [code] produces [expectedDiagnostics]. It should define a - /// function "test", whose body is an expression that invokes a method. - /// Returns that invocation. - Future _testFutureOr( - String code, { - List expectedDiagnostics = const [], - }) async { + /// Validates that [code] defines a function "test", whose body is an + /// expression that invokes a method. Returns that invocation. + Future _testFutureOr(String code) async { var fullCode = """ import "dart:async"; $code """; - var result = await assertErrorsInCode(fullCode, expectedDiagnostics); + var result = await resolveTestCodeWithDiagnostics(fullCode); FunctionDeclaration test = AstFinder.getTopLevelFunction( result.unit, @@ -5088,24 +5055,18 @@ class D extends C {} test_instantiateToBounds_class_error_instantiation_malbounded() async { // Test that instance creations are strictly checked for malbounded default // types - var result = await assertErrorsInCode( - r''' + var result = await resolveTestCodeWithDiagnostics(r''' class C, T1 extends List> {} void test() { var c = new C(); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'c' isn't used. +// ^ +// [context 1] The raw type was instantiated as 'C, List>>', and is not regular-bounded. +// [diag.couldNotInfer] Couldn't infer type parameter 'T0'.\n\nTried to infer 'List' for 'T0' which doesn't work:\n Type parameter 'T0' is declared to extend 'List' producing 'List>>'.\n\nConsider passing explicit type argument(s) to the generic. +// [diag.typeArgumentNotMatchingBounds][context 1] 'List' doesn't conform to the bound 'List>>' of the type parameter 'T0'. } -''', - [ - error(diag.unusedLocalVariable, 73, 1), - error(diag.couldNotInfer, 81, 1), - error( - diag.typeArgumentNotMatchingBounds, - 81, - 1, - contextMessages: [message(testFile, 81, 1)], - ), - ], - ); +'''); _assertLocalVarType(result, 'c', 'C, List>>'); } @@ -5238,20 +5199,19 @@ void main() { test_instantiateToBounds_generic_function_error_malbounded() async { // Test that generic methods are strictly checked for malbounded default // types - var result = await assertErrorsInCode( - r''' + var result = await resolveTestCodeWithDiagnostics(r''' T0 f, T1 extends List>() {} +// ^ +// [diag.bodyMightCompleteNormally] The body might complete normally, causing 'null' to be returned, but the return type, 'T0', is a potentially non-nullable type. void g() { var c = f(); +// ^ +// [diag.unusedLocalVariable] The value of the local variable 'c' isn't used. +// ^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T0'.\n\nTried to infer 'List' for 'T0' which doesn't work:\n Type parameter 'T0' is declared to extend 'List' producing 'List>>'.\n\nConsider passing explicit type argument(s) to the generic. return; } -''', - [ - error(diag.bodyMightCompleteNormally, 3, 1), - error(diag.unusedLocalVariable, 69, 1), - error(diag.couldNotInfer, 73, 1), - ], - ); +'''); _assertLocalVarType(result, 'c', 'List'); } @@ -5419,19 +5379,30 @@ class C { } test_objectMethodOnFunctions_Anonymous() async { - await _objectMethodOnFunctions_helper2( - r''' + await _objectMethodOnFunctions_helper2(r''' void main() { var f = (x) => 3; // No errors, correct type var t0 = f.toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't0' isn't used. var t1 = f.toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't1' isn't used. var t2 = f.hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't2' isn't used. // Expressions, no errors, correct type var t3 = (f).toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't3' isn't used. var t4 = (f).toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't4' isn't used. var t5 = (f).hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't5' isn't used. // Cascades, no errors f..toString(); @@ -5443,81 +5414,99 @@ void main() { (f)..toString; (f)..hashCode; } -''', - [ - error(diag.unusedLocalVariable, 69, 2), - error(diag.unusedLocalVariable, 94, 2), - error(diag.unusedLocalVariable, 117, 2), - error(diag.unusedLocalVariable, 183, 2), - error(diag.unusedLocalVariable, 210, 2), - error(diag.unusedLocalVariable, 235, 2), - ], - ); +'''); } test_objectMethodOnFunctions_Function() async { - await _objectMethodOnFunctions_helper2( - r''' + await _objectMethodOnFunctions_helper2(r''' void main() { Function f; // No errors, correct type var t0 = f.toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't0' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t1 = f.toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't1' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t2 = f.hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't2' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Expressions, no errors, correct type var t3 = (f).toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't3' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t4 = (f).toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't4' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t5 = (f).hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't5' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Cascades, no errors f..toString(); +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. f..toString; +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. f..hashCode; +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Expression cascades, no errors (f)..toString(); +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. (f)..toString; +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. (f)..hashCode; +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. } -''', - [ - error(diag.unusedLocalVariable, 63, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 68, 1), - error(diag.unusedLocalVariable, 88, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 93, 1), - error(diag.unusedLocalVariable, 111, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 116, 1), - error(diag.unusedLocalVariable, 177, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 183, 1), - error(diag.unusedLocalVariable, 204, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 210, 1), - error(diag.unusedLocalVariable, 229, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 235, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 276, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 293, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 308, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 361, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 380, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 397, 1), - ], - ); +'''); } test_objectMethodOnFunctions_Static() async { - await _objectMethodOnFunctions_helper2( - r''' + await _objectMethodOnFunctions_helper2(r''' int f(int x) => null; +// ^^^^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Null' can't be returned from the function 'f' because it has a return type of 'int'. void main() { // No errors, correct type var t0 = f.toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't0' isn't used. var t1 = f.toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't1' isn't used. var t2 = f.hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't2' isn't used. // Expressions, no errors, correct type var t3 = (f).toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't3' isn't used. var t4 = (f).toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't4' isn't used. var t5 = (f).hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't5' isn't used. // Cascades, no errors f..toString(); @@ -5529,68 +5518,72 @@ void main() { (f)..toString; (f)..hashCode; } -''', - [ - error(diag.returnOfInvalidTypeFromFunction, 16, 4), - error(diag.unusedLocalVariable, 71, 2), - error(diag.unusedLocalVariable, 96, 2), - error(diag.unusedLocalVariable, 119, 2), - error(diag.unusedLocalVariable, 185, 2), - error(diag.unusedLocalVariable, 212, 2), - error(diag.unusedLocalVariable, 237, 2), - ], - ); +'''); } test_objectMethodOnFunctions_Typedef() async { - await _objectMethodOnFunctions_helper2( - r''' + await _objectMethodOnFunctions_helper2(r''' typedef bool Predicate(T object); void main() { Predicate f; // No errors, correct type var t0 = f.toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't0' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t1 = f.toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't1' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t2 = f.hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't2' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Expressions, no errors, correct type var t3 = (f).toString(); +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't3' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t4 = (f).toString; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't4' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. var t5 = (f).hashCode; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 't5' isn't used. +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Cascades, no errors f..toString(); +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. f..toString; +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. f..hashCode; +//^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. // Expression cascades, no errors (f)..toString(); +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. (f)..toString; +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. (f)..hashCode; +// ^ +// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. } -''', - [ - error(diag.unusedLocalVariable, 107, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 112, 1), - error(diag.unusedLocalVariable, 132, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 137, 1), - error(diag.unusedLocalVariable, 155, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 160, 1), - error(diag.unusedLocalVariable, 221, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 227, 1), - error(diag.unusedLocalVariable, 248, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 254, 1), - error(diag.unusedLocalVariable, 273, 2), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 279, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 320, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 337, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 352, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 405, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 424, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 441, 1), - ], - ); +'''); } test_returnOfInvalidType_object_void() async { @@ -5706,11 +5699,8 @@ main() { assertType(element.type, expectedType); } - Future _objectMethodOnFunctions_helper2( - String code, - List expectedDiagnostics, - ) async { - var result = await assertErrorsInCode(code, expectedDiagnostics); + Future _objectMethodOnFunctions_helper2(String code) async { + var result = await resolveTestCodeWithDiagnostics(code); _assertLocalVarType(result, 't0', "String"); _assertLocalVarType(result, 't1', "String Function()"); _assertLocalVarType(result, 't2', "int"); diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart index 87a5c7d1b66..762790ced2b 100644 --- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart +++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart @@ -4,8 +4,6 @@ import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -7688,19 +7686,18 @@ void main() { '''); } - @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/55467') test_listLiteral_expression_nonConstant() async { - await assertErrorsInCode( - ''' + // TODO(scheglov): https://github.com/dart-lang/sdk/issues/55467 + await resolveTestCodeWithDiagnostics(''' var b = 7; var x = const A([b]); +// ^ +// [diag.invalidConstant] Invalid constant value. class A { const A(List p); } -''', - [error(diag.nonConstantListElement, 28, 1)], - ); +'''); } test_redirectingConstructor_typeParameter() async { diff --git a/pkg/analyzer/test/src/dart/resolution/variance_test.dart b/pkg/analyzer/test/src/dart/resolution/variance_test.dart index e20686438cb..b591ff01778 100644 --- a/pkg/analyzer/test/src/dart/resolution/variance_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/variance_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import 'context_collection_resolution.dart'; @@ -80,8 +79,7 @@ InstanceCreationExpression } test_inference_inout_parameter() async { - var result = await assertErrorsInCode( - ''' + var result = await resolveTestCodeWithDiagnostics(r''' class Invariant {} class Exactly {} @@ -90,14 +88,14 @@ Exactly inferInvInv(Invariant x, Invariant y) => new Exactly(); main() { inferInvInv(Invariant(), Invariant()); +//^^^^^^^^^^^ +// [diag.couldNotInfer] Couldn't infer type parameter 'T'.\n\nTried to infer 'Object' for 'T' which doesn't work:\n Parameter 'x' declared as 'Invariant'\n but argument is 'Invariant'.\n Parameter 'y' declared as 'Invariant'\n but argument is 'Invariant'.\n\nConsider passing explicit type argument(s) to the generic. +// ^^^^^^^^^^^^^^^^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'Invariant' can't be assigned to the parameter type 'Invariant'. +// ^^^^^^^^^^^^^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'Invariant' can't be assigned to the parameter type 'Invariant'. } -''', - [ - error(diag.couldNotInfer, 147, 11), - error(diag.argumentTypeNotAssignable, 159, 19), - error(diag.argumentTypeNotAssignable, 180, 16), - ], - ); +'''); var node = result.findNode.methodInvocation('inferInvInv('); nodeTextConfiguration.skipArgumentList = true; diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart index 301e77fd9b0..1a11b14d291 100644 --- a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart +++ b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -175,34 +174,31 @@ void f() { } test_method_conflict_conflict_notSpecific_sameName() async { - var one = newFile('$testPackageLibPath/one.dart', ''' + var one = getFile('$testPackageLibPath/one.dart'); + var two = getFile('$testPackageLibPath/two.dart'); + + await resolveFilesWithDiagnostics({ + one: ''' extension E on int { void foo() {} } -'''); - var two = newFile('$testPackageLibPath/two.dart', ''' +// ^ +// [context 1] E is defined in /home/test/lib/one.dart +''', + two: ''' extension E on int { void foo() {} } -'''); - await assertErrorsInCode( - ''' +// ^ +// [context 2] E is defined in /home/test/lib/two.dart +''', + testFile: ''' // ignore_for_file: unused_import import 'one.dart'; import 'two.dart'; void f() { 0.foo(); +// ^^^ +// [diag.ambiguousExtensionMemberAccessTwo][context 1][context 2] A member named 'foo' is defined in 'extension E on int (where E is defined in /home/test/lib/one.dart)' and 'extension E on int (where E is defined in /home/test/lib/two.dart)', and neither is more specific. } ''', - [ - error( - diag.ambiguousExtensionMemberAccessTwo, - 87, - 3, - messageContains: [ - "'extension E on int (where E is defined in ${one.path})' and " - "'extension E on int (where E is defined in ${two.path})',", - ], - contextMessages: [message(one, 10, 1), message(two, 10, 1)], - ), - ], - ); + }); } test_method_conflict_conflict_notSpecific_sameName_invalidType() async { @@ -334,34 +330,36 @@ void f() { } test_method_triple_conflict_sameName() async { - var one = newFile('$testPackageLibPath/one.dart', ''' + var one = getFile('$testPackageLibPath/one.dart'); + var two = getFile('$testPackageLibPath/two.dart'); + var three = getFile('$testPackageLibPath/three.dart'); + + await resolveFilesWithDiagnostics({ + one: ''' extension E on int { void foo() {} } -'''); - var two = newFile('$testPackageLibPath/two.dart', ''' +// ^ +// [context 1] E is defined in /home/test/lib/one.dart +''', + two: ''' extension E on int { void foo() {} } -'''); - newFile('$testPackageLibPath/three.dart', ''' +// ^ +// [context 2] E is defined in /home/test/lib/two.dart +''', + three: ''' extension E1 on int { void foo() {} } -'''); - await assertErrorsInCode( - ''' +''', + testFile: ''' // ignore_for_file: unused_import import 'one.dart'; import 'two.dart'; import 'three.dart'; void f() { 0.foo(); +// ^^^ +// [diag.ambiguousExtensionMemberAccessThreeOrMore][context 1][context 2] A member named 'foo' is defined in extension 'E', extension 'E', and extension 'E1', and none are more specific. } ''', - [ - error( - diag.ambiguousExtensionMemberAccessThreeOrMore, - 108, - 3, - contextMessages: [message(one, 10, 1), message(two, 10, 1)], - ), - ], - ); + }); } test_noMoreSpecificExtension() async { diff --git a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart index ec958c143df..d1f27323981 100644 --- a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart +++ b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -283,19 +282,18 @@ class A { '''); } - @FailingTest(reason: 'Not yet implemented') + @SkippedTest() // TODO(scheglov): Not yet implemented. test_topLevelVariable_asExpression() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' import 'package:meta/meta.dart'; final f = v as Object; +// ^ +// [diag.assignmentOfDoNotStore] 'v' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable. @doNotStore String get v => ''; -''', - [error(diag.assignmentOfDoNotStore, 44, 1)], - ); +'''); } test_topLevelVariable_assignment_field() async { @@ -369,19 +367,18 @@ class A { '''); } - @FailingTest(reason: 'Not yet implemented') + @SkippedTest() // TODO(scheglov): Not yet implemented. test_topLevelVariable_cascadeExpression_target() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' import 'package:meta/meta.dart'; final f = v..runtimeType; +// ^ +// [diag.assignmentOfDoNotStore] 'v' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable. @doNotStore String get v => ''; -''', - [error(diag.assignmentOfDoNotStore, 44, 1)], - ); +'''); } test_topLevelVariable_conditionalExpression() async { @@ -401,21 +398,20 @@ String get v => ''; '''); } - @FailingTest(reason: 'Not yet implemented') + @SkippedTest() // TODO(scheglov): Not yet implemented. test_topLevelVariable_dotShorthandPropertyAccess() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' import 'package:meta/meta.dart'; final A f = .v; +// ^ +// [diag.assignmentOfDoNotStore] 'v' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable. class A { @doNotStore static A get v => A(); } -''', - [error(diag.assignmentOfDoNotStore, 47, 1)], - ); +'''); } test_topLevelVariable_forElement() async { @@ -531,19 +527,18 @@ String get v => ''; '''); } - @FailingTest(reason: 'Not yet implemented') + @SkippedTest() // TODO(scheglov): Not yet implemented. test_topLevelVariable_nullAssert() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' import 'package:meta/meta.dart'; final f = v!; +// ^ +// [diag.assignmentOfDoNotStore] 'v' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable. @doNotStore String? get v => ''; -''', - [error(diag.assignmentOfDoNotStore, 44, 1)], - ); +'''); } test_topLevelVariable_nullAwareElement() async { @@ -612,22 +607,21 @@ List get v => []; '''); } - @FailingTest(reason: 'Not yet implemented') + @SkippedTest() // TODO(scheglov): Not yet implemented. test_topLevelVariable_switchExpression_caseBody() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' import 'package:meta/meta.dart'; final f = switch (1 == 2) { true => v, +// ^ +// [diag.assignmentOfDoNotStore] 'v' is marked 'doNotStore' and shouldn't be assigned to a field or top-level variable. false => '', }; @doNotStore String? get v => ''; -''', - [error(diag.assignmentOfDoNotStore, 72, 1)], - ); +'''); } test_topLevelVariable_switchExpression_condition() async { diff --git a/pkg/analyzer/test/src/diagnostics/base_class_implemented_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/base_class_implemented_outside_of_library_test.dart index a897a4be691..054549715f7 100644 --- a/pkg/analyzer/test/src/diagnostics/base_class_implemented_outside_of_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/base_class_implemented_outside_of_library_test.dart @@ -2,8 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -40,71 +38,43 @@ base class Bar implements Foo {} } test_class_outside_sealed() async { - var a = newFile('$testPackageLibPath/a.dart', r''' -base class A {} -'''); + var a = getFile('$testPackageLibPath/a.dart'); - await assertErrorsInCode( - r''' + await resolveFilesWithDiagnostics({ + a: r''' +base class A {} +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B extends A {} base class C implements B {} +// ^ +// [diag.baseClassImplementedOutsideOfLibrary][context 1] The class 'A' can't be implemented outside of its library because it's a base class. ''', - [ - this.error( - diag.baseClassImplementedOutsideOfLibrary, - 69, - 1, - text: - "The class 'A' can't be implemented outside of its library because it's a base class.", - contextMessages: [ - contextMessage( - a, - 11, - 1, - textContains: [ - "The type 'B' is a subtype of 'A', and 'A' is defined here.", - ], - ), - ], - ), - ], - ); + }); } test_class_outside_sealed_noBase() async { // Instead of emitting [SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED], we // tell the user that they can't implement an indirect base supertype. - var a = newFile('$testPackageLibPath/a.dart', r''' -base class A {} -'''); + var a = getFile('$testPackageLibPath/a.dart'); - await assertErrorsInCode( - r''' + await resolveFilesWithDiagnostics({ + a: r''' +base class A {} +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B extends A {} class C implements B {} +// ^ +// [diag.baseClassImplementedOutsideOfLibrary][context 1] The class 'A' can't be implemented outside of its library because it's a base class. ''', - [ - this.error( - diag.baseClassImplementedOutsideOfLibrary, - 64, - 1, - text: - "The class 'A' can't be implemented outside of its library because it's a base class.", - contextMessages: [ - contextMessage( - a, - 11, - 1, - textContains: [ - "The type 'B' is a subtype of 'A', and 'A' is defined here.", - ], - ), - ], - ), - ], - ); + }); } test_class_outside_viaExtends() async { @@ -159,37 +129,23 @@ base class C = Object with M implements B; } test_classTypeAlias_outside() async { - var a = newFile('$testPackageLibPath/a.dart', r''' -base class A {} -'''); + var a = getFile('$testPackageLibPath/a.dart'); - await assertErrorsInCode( - r''' + await resolveFilesWithDiagnostics({ + a: r''' +base class A {} +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B extends A {} mixin M {} base class C = Object with M implements B; +// ^ +// [diag.baseClassImplementedOutsideOfLibrary][context 1] The class 'A' can't be implemented outside of its library because it's a base class. ''', - [ - this.error( - diag.baseClassImplementedOutsideOfLibrary, - 96, - 1, - text: - "The class 'A' can't be implemented outside of its library because it's a base class.", - contextMessages: [ - contextMessage( - a, - 11, - 1, - textContains: [ - "The type 'B' is a subtype of 'A', and 'A' is defined here.", - ], - ), - ], - ), - ], - ); + }); } test_enum_inside() async { diff --git a/pkg/analyzer/test/src/diagnostics/base_mixin_implemented_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/base_mixin_implemented_outside_of_library_test.dart index 05a8af1d760..878d164c28e 100644 --- a/pkg/analyzer/test/src/diagnostics/base_mixin_implemented_outside_of_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/base_mixin_implemented_outside_of_library_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -39,26 +38,23 @@ base class Bar implements Foo {} } test_class_outside_viaExtends() async { - var a = newFile('$testPackageLibPath/a.dart', r''' -base mixin A {} -'''); + var a = getFile('$testPackageLibPath/a.dart'); - await assertErrorsInCode( - r''' + await resolveFilesWithDiagnostics({ + a: r''' +base mixin A {} +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B extends Object with A {} class C implements B {} +// ^ +// [diag.baseMixinImplementedOutsideOfLibrary][context 1] The mixin 'A' can't be implemented outside of its library because it's a base mixin. ''', - [ - error( - diag.baseMixinImplementedOutsideOfLibrary, - 77, - 1, - contextMessages: [message(a, 11, 1)], - ), - ], - ); + }); } test_class_outside_viaTypedef_inside() async { diff --git a/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart b/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart index 82c59775076..1cdb2ad0916 100644 --- a/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart +++ b/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -52,27 +51,39 @@ enum E { } test_enum_method_nonNullable_blockBody_switchStatement_notNullable_notExhaustive() async { - await assertErrorsInCode( - r''' + if (_arePatternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' enum E { a, b; int get value { switch (this) { +// ^^^^^^ +// [diag.nonExhaustiveSwitchStatement] The type 'E' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'E.b'. case a: return 0; } } } -''', - [ - if (!_arePatternsEnabled) ...[ - error(diag.bodyMightCompleteNormally, 28, 5), - error(diag.missingEnumConstantInSwitch, 40, 13), - ] else - error(diag.nonExhaustiveSwitchStatement, 40, 6), - ], - ); +'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +enum E { + a, b; + + int get value { +// ^^^^^ +// [diag.bodyMightCompleteNormally] The body might complete normally, causing 'null' to be returned, but the return type, 'int', is a potentially non-nullable type. + switch (this) { +// ^^^^^^^^^^^^^ +// [diag.missingEnumConstantInSwitch] Missing case clause for 'b'. + case a: + return 0; + } + } +} +'''); + } } test_factoryConstructor_named_blockBody() async { @@ -188,30 +199,40 @@ int f(Foo foo) { } test_function_nonNullable_blockBody_switchStatement_notNullable_notExhaustive() async { - await assertErrorsInCode( - r''' + if (_arePatternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' enum Foo { a, b } int f(Foo foo) { switch (foo) { +//^^^^^^ +// [diag.nonExhaustiveSwitchStatement] The type 'Foo' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'Foo.b'. case Foo.a: return 0; } } -''', - [ - if (!_arePatternsEnabled) ...[ - error(diag.bodyMightCompleteNormally, 23, 1), - error(diag.missingEnumConstantInSwitch, 38, 12), - ] else - error(diag.nonExhaustiveSwitchStatement, 38, 6), - ], - ); +'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +enum Foo { a, b } + +int f(Foo foo) { +// ^ +// [diag.bodyMightCompleteNormally] The body might complete normally, causing 'null' to be returned, but the return type, 'int', is a potentially non-nullable type. + switch (foo) { +//^^^^^^^^^^^^ +// [diag.missingEnumConstantInSwitch] Missing case clause for 'b'. + case Foo.a: + return 0; + } +} +'''); + } } test_function_nonNullable_blockBody_switchStatement_notNullable_notExhaustive_enhanced() async { - await assertErrorsInCode( - r''' + if (_arePatternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' enum E { a, b; @@ -220,19 +241,33 @@ enum E { int f(E e) { switch (e) { +//^^^^^^ +// [diag.nonExhaustiveSwitchStatement] The type 'E' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'E.b'. case E.a: return 0; } } -''', - [ - if (!_arePatternsEnabled) ...[ - error(diag.bodyMightCompleteNormally, 47, 1), - error(diag.missingEnumConstantInSwitch, 58, 10), - ] else - error(diag.nonExhaustiveSwitchStatement, 58, 6), - ], - ); +'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +enum E { + a, b; + + static const c = 0; +} + +int f(E e) { +// ^ +// [diag.bodyMightCompleteNormally] The body might complete normally, causing 'null' to be returned, but the return type, 'int', is a potentially non-nullable type. + switch (e) { +//^^^^^^^^^^ +// [diag.missingEnumConstantInSwitch] Missing case clause for 'b'. + case E.a: + return 0; + } +} +'''); + } } test_function_nonNullable_blockBody_switchStatement_nullable_exhaustive_default() async { @@ -270,27 +305,39 @@ int f(Foo? foo) { } test_function_nonNullable_blockBody_switchStatement_nullable_notExhaustive_null() async { - await assertErrorsInCode( - r''' + if (_arePatternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' enum Foo { a, b } int f(Foo? foo) { switch (foo) { +//^^^^^^ +// [diag.nonExhaustiveSwitchStatement] The type 'Foo?' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'null'. case Foo.a: return 0; case Foo.b: return 1; } } -''', - [ - if (!_arePatternsEnabled) ...[ - error(diag.bodyMightCompleteNormally, 23, 1), - error(diag.missingEnumConstantInSwitch, 39, 12), - ] else - error(diag.nonExhaustiveSwitchStatement, 39, 6), - ], - ); +'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +enum Foo { a, b } + +int f(Foo? foo) { +// ^ +// [diag.bodyMightCompleteNormally] The body might complete normally, causing 'null' to be returned, but the return type, 'int', is a potentially non-nullable type. + switch (foo) { +//^^^^^^^^^^^^ +// [diag.missingEnumConstantInSwitch] Missing case clause for 'null'. + case Foo.a: + return 0; + case Foo.b: + return 1; + } +} +'''); + } } test_function_nullable_blockBody() async { diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart index f000b0834ee..898cb37b96e 100644 --- a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart +++ b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -29,20 +28,18 @@ class C { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_inClass_instanceMethod_staticMethodInAugmentation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' class A { void foo() {} } augment class A { static void foo() {} +// ^^^ +// [diag.conflictingStaticAndInstance] Class 'A' can't define static member 'foo' and have instance member 'A.foo' with the same name. } -''', - [error(diag.conflictingStaticAndInstance, 61, 3)], - ); +'''); } test_inClass_staticGetter_instanceGetter() async { @@ -100,20 +97,18 @@ class C { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_inClass_staticMethod_instanceMethodInAugmentation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' class A { static void foo() {} +// ^^^ +// [diag.conflictingStaticAndInstance] Class 'A' can't define static member 'foo' and have instance member 'A.foo' with the same name. } augment class A { void foo() {} } -''', - [error(diag.conflictingStaticAndInstance, 24, 3)], - ); +'''); } test_inClass_staticMethod_instanceSetter() async { @@ -290,20 +285,18 @@ class B extends Object with M { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_inMixin_instanceMethod_staticMethodInAugmentation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' mixin A { void foo() {} } augment mixin A { static void foo() {} +// ^^^ +// [diag.conflictingStaticAndInstance] Class 'A' can't define static member 'foo' and have instance member 'A.foo' with the same name. } -''', - [error(diag.conflictingStaticAndInstance, 61, 3)], - ); +'''); } test_inMixin_instanceMethod_staticSetter() async { @@ -358,20 +351,18 @@ class B extends Object with A { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_inMixin_staticMethod_instanceMethodInAugmentation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' mixin A { static void foo() {} +// ^^^ +// [diag.conflictingStaticAndInstance] Class 'A' can't define static member 'foo' and have instance member 'A.foo' with the same name. } augment mixin A { void foo() {} } -''', - [error(diag.conflictingStaticAndInstance, 24, 3)], - ); +'''); } test_inSuper_implicitObject_staticMethod_instanceGetter() async { diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_property_access_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_property_access_test.dart index d72ea179a51..f6bb8bb55e7 100644 --- a/pkg/analyzer/test/src/diagnostics/const_eval_property_access_test.dart +++ b/pkg/analyzer/test/src/diagnostics/const_eval_property_access_test.dart @@ -2,8 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -34,35 +32,27 @@ const C b = C(false || a.x); } test_constructorFieldInitializer_fromSeparateLibrary() async { - var lib = newFile('$testPackageLibPath/lib.dart', r''' + var lib = getFile('$testPackageLibPath/lib.dart'); + + await resolveFilesWithDiagnostics({ + lib: r''' class A { final int f; const A() : f = T.foo; +// ^^^^^ +// [context 1] The error is in the field initializer of 'A', and occurs here. +// [diag.invalidConstant] Invalid constant value. +// ^^^ +// [diag.undefinedGetter] The getter 'foo' isn't defined for the type 'Type'. } -'''); - await assertErrorsInCode( - r''' +''', + testFile: r''' import 'lib.dart'; const a = const A(); +// ^^^^^^^^^ +// [diag.constEvalPropertyAccess][context 1] The property 'foo' can't be accessed on the type 'Type' in a constant expression. ''', - [ - error( - diag.constEvalPropertyAccess, - 29, - 9, - contextMessages: [ - contextMessage( - lib, - 46, - 5, - textContains: [ - "The error is in the field initializer of 'A', and occurs here.", - ], - ), - ], - ), - ], - ); + }); } test_length_dynamic_notNull() async { diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart index 034bbce29aa..bd6cef3ba89 100644 --- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart +++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -945,29 +944,22 @@ class B implements A { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_method_returnType_interface_fromAugmentation() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' class A { int foo() => 0; +// ^^^ +// [context 1] The member being overridden. } class B { String foo() => ''; +// ^^^ +// [diag.invalidOverride][context 1] 'B.foo' ('String Function()') isn't a valid override of 'A.foo' ('int Function()'). } augment class B implements A {} -''', - [ - error( - diag.invalidOverride, - 50, - 3, - contextMessages: [message(testFile, 16, 3)], - ), - ], - ); +'''); } test_method_returnType_interface_grandparent() async { @@ -1017,29 +1009,22 @@ class B extends A { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_method_returnType_superclass_fromAugmentation() async { - await assertErrorsInCode( - ''' + await resolveTestCodeWithDiagnostics(''' class A { int foo() => 0; +// ^^^ +// [context 1] The member being overridden. } class B { String foo() => ''; +// ^^^ +// [diag.invalidOverride][context 1] 'B.foo' ('String Function()') isn't a valid override of 'A.foo' ('int Function()'). } augment class B extends A {} -''', - [ - error( - diag.invalidOverride, - 50, - 3, - contextMessages: [message(testFile, 16, 3)], - ), - ], - ); +'''); } test_method_returnType_superclass_grandparent() async { @@ -1143,29 +1128,22 @@ mixin M on A { '''); } - @SkippedTest() // TODO(scheglov): implement augmentation test_mixin_method_returnType_on_fromAugmentation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' class A { int foo() => 0; +// ^^^ +// [context 1] The member being overridden. } mixin M { String foo() => ''; +// ^^^ +// [diag.invalidOverride][context 1] 'M.foo' ('String Function()') isn't a valid override of 'A.foo' ('int Function()'). } augment mixin M on A {} -''', - [ - error( - diag.invalidOverride, - 50, - 3, - contextMessages: [message(testFile, 16, 3)], - ), - ], - ); +'''); } test_mixin_setter_type_on() async { diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart index c802ed3e939..c2d9db291c1 100644 --- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -18,20 +17,17 @@ main() { @reflectiveTest class NonConstantListElementFromDeferredLibraryTest extends PubPackageResolutionTest { - @failingTest test_const_ifElement_thenTrue_deferredElse() async { - // reports wrong error code (which is not crucial to fix) newFile('$testPackageLibPath/lib1.dart', r''' const int c = 1; '''); - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' import 'lib1.dart' deferred as a; const cond = true; var v = const [ if (cond) 'a' else a.c ]; -''', - [error(diag.nonConstantListElementFromDeferredLibrary, 0, 0)], - ); +// ^^^ +// [diag.nonConstantListElement] The values in a const list literal must be constants. +'''); } test_const_ifElement_thenTrue_deferredThen() async { diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart index 8e329bbb227..e08b7e776fb 100644 --- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -18,19 +17,16 @@ main() { @reflectiveTest class NonConstantMapKeyFromDeferredLibraryTest extends PubPackageResolutionTest { - @failingTest test_const_ifElement_thenTrue_deferredElse() async { - // reports wrong error code newFile('$testPackageLibPath/lib1.dart', r''' const int c = 1;'''); - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' import 'lib1.dart' deferred as a; const cond = true; var v = const { if (cond) 0: 1 else a.c : 0}; -''', - [error(diag.nonConstantMapKeyFromDeferredLibrary, 0, 0)], - ); +// ^^^ +// [diag.nonConstantMapKey] The keys in a const map literal must be constant. +'''); } test_const_ifElement_thenTrue_deferredThen() async { diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart index 0f02ed2a989..7e48b18d452 100644 --- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -18,19 +17,16 @@ main() { @reflectiveTest class NonConstantMapValueFromDeferredLibraryTest extends PubPackageResolutionTest { - @failingTest test_const_ifElement_thenTrue_elseDeferred() async { - // reports wrong error code newFile('$testPackageLibPath/lib1.dart', r''' const int c = 1;'''); - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' import 'lib1.dart' deferred as a; const cond = true; var v = const { if (cond) 'a': 'b' else 'c' : a.c}; -''', - [error(diag.nonConstantMapValueFromDeferredLibrary, 99, 3)], - ); +// ^^^ +// [diag.nonConstantMapValue] The values in a const map literal must be constant. +'''); } test_const_ifElement_thenTrue_thenDeferred() async { diff --git a/pkg/analyzer/test/src/diagnostics/prefix_collides_with_top_level_member_test.dart b/pkg/analyzer/test/src/diagnostics/prefix_collides_with_top_level_member_test.dart index fc989162149..3836031256d 100644 --- a/pkg/analyzer/test/src/diagnostics/prefix_collides_with_top_level_member_test.dart +++ b/pkg/analyzer/test/src/diagnostics/prefix_collides_with_top_level_member_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -105,26 +104,24 @@ class foo {} } test_part_topLevelFunction_inLibrary() async { - var a = newFile('$testPackageLibPath/a.dart', r''' + var a = getFile('$testPackageLibPath/a.dart'); + + await resolveFilesWithDiagnostics({ + a: r''' part 'test.dart'; void foo() {} -'''); - - await assertErrorsInCode( - r''' +// ^^^ +// [context 1] The first definition of this name. +''', + testFile: r''' part of 'a.dart'; import 'dart:math' as foo; +// ^^^^^^^^^^^ +// [diag.unusedImport] Unused import: 'dart:math'. +// ^^^ +// [diag.prefixCollidesWithTopLevelMember][context 1] The name 'foo' is already used as an import prefix and can't be used to name a top-level element. ''', - [ - error(diag.unusedImport, 25, 11), - error( - diag.prefixCollidesWithTopLevelMember, - 40, - 3, - contextMessages: [message(a, 23, 3)], - ), - ], - ); + }); } test_part_topLevelFunction_inPart() async { @@ -146,30 +143,28 @@ void foo() {} } test_part_topLevelFunction_inPart2() async { - newFile('$testPackageLibPath/a.dart', r''' + var a = getFile('$testPackageLibPath/a.dart'); + var b = getFile('$testPackageLibPath/b.dart'); + + await resolveFilesWithDiagnostics({ + a: r''' part 'test.dart'; part 'b.dart'; -'''); - - var b = newFile('$testPackageLibPath/b.dart', r''' +''', + b: r''' part of 'a.dart'; void foo() {} -'''); - - await assertErrorsInCode( - r''' +// ^^^ +// [context 1] The first definition of this name. +''', + testFile: r''' part of 'a.dart'; import 'dart:math' as foo; +// ^^^^^^^^^^^ +// [diag.unusedImport] Unused import: 'dart:math'. +// ^^^ +// [diag.prefixCollidesWithTopLevelMember][context 1] The name 'foo' is already used as an import prefix and can't be used to name a top-level element. ''', - [ - error(diag.unusedImport, 25, 11), - error( - diag.prefixCollidesWithTopLevelMember, - 40, - 3, - contextMessages: [message(b, 23, 3)], - ), - ], - ); + }); } } diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_base_is_not_base_final_or_sealed_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_base_is_not_base_final_or_sealed_test.dart index e4769412189..17aa9f5f820 100644 --- a/pkg/analyzer/test/src/diagnostics/subtype_of_base_is_not_base_final_or_sealed_test.dart +++ b/pkg/analyzer/test/src/diagnostics/subtype_of_base_is_not_base_final_or_sealed_test.dart @@ -2,8 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer_testing/analysis_rule/analysis_rule.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -160,36 +158,21 @@ class D extends C {} } test_class_sealed_extends_outside() async { - var a = newFile('$testPackageLibPath/a.dart', r''' + var a = getFile('$testPackageLibPath/a.dart'); + await resolveFilesWithDiagnostics({ + a: r''' base class A {} -'''); - - await assertErrorsInCode( - r''' +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B extends A {} class C extends B {} +// ^ +// [diag.subtypeOfBaseIsNotBaseFinalOrSealed][context 1] The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'. ''', - [ - this.error( - diag.subtypeOfBaseIsNotBaseFinalOrSealed, - 51, - 1, - text: - "The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.", - contextMessages: [ - contextMessage( - a, - 11, - 1, - textContains: [ - "The type 'B' is a subtype of 'A', and 'A' is defined here.", - ], - ), - ], - ), - ], - ); + }); } test_class_sealed_extends_unordered() async { @@ -275,36 +258,21 @@ class C extends B {} } test_mixinClass_sealed_outside() async { - var a = newFile('$testPackageLibPath/a.dart', r''' + var a = getFile('$testPackageLibPath/a.dart'); + await resolveFilesWithDiagnostics({ + a: r''' base mixin class A {} -'''); - - await assertErrorsInCode( - r''' +// ^ +// [context 1] The type 'B' is a subtype of 'A', and 'A' is defined here. +''', + testFile: r''' import 'a.dart'; sealed class B with A {} class C extends B {} +// ^ +// [diag.subtypeOfBaseIsNotBaseFinalOrSealed][context 1] The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'. ''', - [ - this.error( - diag.subtypeOfBaseIsNotBaseFinalOrSealed, - 48, - 1, - text: - "The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.", - contextMessages: [ - contextMessage( - a, - 17, - 1, - textContains: [ - "The type 'B' is a subtype of 'A', and 'A' is defined here.", - ], - ), - ], - ), - ], - ); + }); } test_mixinClass_with() async { diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_final_is_not_base_final_or_sealed_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_final_is_not_base_final_or_sealed_test.dart index 7d9cf1d7a5f..f3b5177405f 100644 --- a/pkg/analyzer/test/src/diagnostics/subtype_of_final_is_not_base_final_or_sealed_test.dart +++ b/pkg/analyzer/test/src/diagnostics/subtype_of_final_is_not_base_final_or_sealed_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -29,27 +28,13 @@ class B extends A {} @SkippedTest() // TODO(scheglov): implement augmentation test_class_extends_inAugmentation() async { - newFile('$testPackageLibPath/a.dart', r''' -part of 'test.dart'; -augment class B extend A {} -'''); - - await assertErrorsInCode( - r''' -part 'a.dart'; + await resolveTestCodeWithDiagnostics(r''' final class A {} class B {} -''', - [ - error( - diag.subtypeOfFinalIsNotBaseFinalOrSealed, - 38, - 1, - text: - "The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.", - ), - ], - ); +// ^ +// [diag.subtypeOfFinalIsNotBaseFinalOrSealed] The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'. +augment class B extends A {} +'''); } test_class_extends_outside() async { diff --git a/pkg/analyzer/test/src/diagnostics/switch_case_completes_normally_test.dart b/pkg/analyzer/test/src/diagnostics/switch_case_completes_normally_test.dart index 292bd6665c1..50e0b7a75a7 100644 --- a/pkg/analyzer/test/src/diagnostics/switch_case_completes_normally_test.dart +++ b/pkg/analyzer/test/src/diagnostics/switch_case_completes_normally_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -46,8 +45,8 @@ void f(int a) { } test_completes() async { - await assertErrorsInCode( - ''' + if (_patternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' void f(int a) { switch (a) { case 0: @@ -55,9 +54,20 @@ void f(int a) { default: return; } -}''', - [if (!_patternsEnabled) error(diag.switchCaseCompletesNormally, 35, 4)], - ); +}'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +void f(int a) { + switch (a) { + case 0: +// ^^^^ +// [diag.switchCaseCompletesNormally] The 'case' shouldn't complete normally. + print(0); + default: + return; + } +}'''); + } } test_continue_loop() async { @@ -119,8 +129,8 @@ Never neverCompletes() { } test_multiple_cases_sharing_a_body() async { - await assertErrorsInCode( - ''' + if (_patternsEnabled) { + await resolveTestCodeWithDiagnostics(r''' void f(int a) { switch (a) { case 0: @@ -129,9 +139,21 @@ void f(int a) { default: return; } -}''', - [if (!_patternsEnabled) error(diag.switchCaseCompletesNormally, 35, 4)], - ); +}'''); + } else { + await resolveTestCodeWithDiagnostics(r''' +void f(int a) { + switch (a) { + case 0: +// ^^^^ +// [diag.switchCaseCompletesNormally] The 'case' shouldn't complete normally. + case 1: + print(0); + default: + return; + } +}'''); + } } test_return() async { diff --git a/pkg/analyzer/test/src/diagnostics/todo_test.dart b/pkg/analyzer/test/src/diagnostics/todo_test.dart index 468aac75c77..1109fdfbe4f 100644 --- a/pkg/analyzer/test/src/diagnostics/todo_test.dart +++ b/pkg/analyzer/test/src/diagnostics/todo_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -73,76 +72,56 @@ TODO: Implement2 } test_todo_multiLineCommentWrapped() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { /* TODO(a): Implement something +// [diag.todo][column 6][length 64] TODO(a): Implement something that is too long for one line * that is too long for one line * This line is not part of the todo */ /* TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line * that is too long for one line * This line is not part of the todo */ /* TODO(a): Implement something +// [diag.todo][column 6][length 64] TODO(a): Implement something that is too long for one line * that is too long for one line * * This line is not part of the todo */ /* TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line * that is too long for one line * * This line is not part of the todo - */ + */ } -''', - [ - error( - diag.todo, - 14, - 64, - text: 'TODO(a): Implement something that is too long for one line', - ), - error( - diag.todo, - 129, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - error( - diag.todo, - 241, - 64, - text: 'TODO(a): Implement something that is too long for one line', - ), - error( - diag.todo, - 362, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - ], - ); +'''); } test_todo_multiLineCommentWrapped_windows_line_endings() async { - await assertErrorsInCode( + await resolveTestCodeWithDiagnostics( r''' main() { /* TODO(a): Implement something +// [diag.todo][column 6][length 65] TODO(a): Implement something that is too long for one line * that is too long for one line * This line is not part of the todo */ /* TODO: Implement something +// [diag.todo][column 6][length 62] TODO: Implement something that is too long for one line * that is too long for one line * This line is not part of the todo */ /* TODO(a): Implement something +// [diag.todo][column 6][length 65] TODO(a): Implement something that is too long for one line * that is too long for one line * * This line is not part of the todo */ /* TODO: Implement something +// [diag.todo][column 6][length 62] TODO: Implement something that is too long for one line * that is too long for one line * * This line is not part of the todo @@ -151,32 +130,6 @@ main() { ''' .split("\n") .join("\r\n"), - [ - error( - diag.todo, - 15, - 65, - text: 'TODO(a): Implement something that is too long for one line', - ), - error( - diag.todo, - 134, - 62, - text: 'TODO: Implement something that is too long for one line', - ), - error( - diag.todo, - 250, - 65, - text: 'TODO(a): Implement something that is too long for one line', - ), - error( - diag.todo, - 376, - 62, - text: 'TODO: Implement something that is too long for one line', - ), - ], ); } @@ -193,32 +146,25 @@ main() { test_todo_singleLineCommentDoubleCommented() async { // Continuations are ignored for code that looks like commented comments // although the original TODOs are still picked up. - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { // // TODO: Implement something +// [diag.todo][column 12][length 67] TODO: Implement something that is too long for one line // // that is too long for one line // main() { // // TODO: Implement something +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [diag.todo] TODO: Implement something // // this is not a todo // main() { // // TODO: Implement something +// ^^^^^^^^^^^^^^^^^^^^^^^^^ +// [diag.todo] TODO: Implement something // main() { } -''', - [ - error( - diag.todo, - 20, - 67, - text: 'TODO: Implement something that is too long for one line', - ), - error(diag.todo, 117, 25, text: 'TODO: Implement something'), - error(diag.todo, 202, 25, text: 'TODO: Implement something'), - ], - ); +'''); } test_todo_singleLineCommentFollowedByDartdoc() async { @@ -232,111 +178,61 @@ void f() {} } test_todo_singleLineCommentLessIndentedContinuation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // this is not part of the todo } -''', - [ - error( - diag.todo, - 14, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - ], - ); +'''); } test_todo_singleLineCommentMoreIndentedContinuation() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // this is not part of the todo } -''', - [ - error( - diag.todo, - 14, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - ], - ); +'''); } test_todo_singleLineCommentNested() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // TODO: This is a separate todo that is accidentally indented +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// [diag.todo] TODO: This is a separate todo that is accidentally indented } -''', - [ - error( - diag.todo, - 14, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - error( - diag.todo, - 82, - 59, - text: 'TODO: This is a separate todo that is accidentally indented', - ), - ], - ); +'''); } test_todo_singleLineCommentWrapped() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' main() { // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // this is not part of the todo // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // this is not part of the todo // TODO: Implement something +// [diag.todo][column 6][length 61] TODO: Implement something that is too long for one line // that is too long for one line // // this is not part of the todo } -''', - [ - error( - diag.todo, - 14, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - error( - diag.todo, - 116, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - error( - diag.todo, - 220, - 61, - text: 'TODO: Implement something that is too long for one line', - ), - ], - ); +'''); } test_undone() async { diff --git a/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart b/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart index fc51f278b7e..97aa22f3540 100644 --- a/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart +++ b/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart @@ -8,7 +8,6 @@ import 'package:analyzer/analysis_rule/rule_visitor_registry.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/error/error.dart'; -import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; import 'package:analyzer/src/test_utilities/lint_registration_mixin.dart'; import 'package:analyzer_testing/utilities/utilities.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -80,16 +79,13 @@ class UnignorableIgnoreTest extends PubPackageResolutionTest ); var avoidIntRule = _AvoidIntRule(); registerLintRule(avoidIntRule); - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' // ignore: avoid_int +// ^^^^^^^^^ +// [diag.unignorableIgnore] The diagnostic 'avoid_int' can't be ignored. int a = 0; -''', - [ - error(diag.unignorableIgnore, 11, 9), - error(avoidIntRule.diagnosticCode, 21, 3), - ], - ); +// [diag.avoidInt][column 1][length 3] Avoid int. +'''); } } @@ -98,7 +94,7 @@ class _AvoidIntRule extends AnalysisRule { 'avoid_int', 'Avoid int.', correctionMessage: 'Try avoiding int.', - uniqueName: 'LintCode.avoid_int', + uniqueName: 'avoid_int', ); _AvoidIntRule() : super(name: 'avoid_int', description: ''); diff --git a/pkg/analyzer/test/src/diagnostics/yield_in_non_generator_test.dart b/pkg/analyzer/test/src/diagnostics/yield_in_non_generator_test.dart index bddb218e97b..c37233899e6 100644 --- a/pkg/analyzer/test/src/diagnostics/yield_in_non_generator_test.dart +++ b/pkg/analyzer/test/src/diagnostics/yield_in_non_generator_test.dart @@ -2,7 +2,6 @@ // 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/diagnostic/diagnostic.dart' as diag; import 'package:test_reflective_loader/test_reflective_loader.dart'; import '../dart/resolution/context_collection_resolution.dart'; @@ -35,20 +34,15 @@ f() async* { '''); } - @FailingTest( - reason: - 'We are currently trying to parse the yield statement as a ' - 'binary expression.', - ) test_sync() async { - await assertErrorsInCode( - r''' + await resolveTestCodeWithDiagnostics(r''' f() { yield 0; +//^^^^^ +// [diag.expectedToken] Expected to find ';'. +// [diag.undefinedIdentifier] Undefined name 'yield'. } -''', - [error(diag.yieldInNonGenerator, 0, 0)], - ); +'''); } test_syncStar() async { diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart index 325ff1b92ce..1b1e7327526 100644 --- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart +++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart @@ -3,10 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/error/error.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag; -import 'package:analyzer/src/utilities/extensions/file_system.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -22,10 +18,6 @@ void main() { @reflectiveTest class InferredTypeTest extends PubPackageResolutionTest { - File get dartAsyncFile { - return getFile('${sdkRoot.posixPath}/lib/async/async.dart'); - } - test_asyncClosureReturnType_flatten() async { var result = await resolveTestCodeWithDiagnostics(r''' Future futureInt = null; @@ -440,14 +432,14 @@ var y = () => x; @SkippedTest(reason: 'Element model rewrite') test_circularReference_viaClosures_initializerTypes() async { - print('-' * 64); - var result = await assertErrorsInCode( - ''' + var result = await resolveTestCodeWithDiagnostics(''' var x = () => y; +// ^ +// [diag.topLevelCycle] The type of 'x' can't be inferred because it depends on itself through the cycle: x, y. var y = () => x; -''', - [error(diag.topLevelCycle, 4, 1), error(diag.topLevelCycle, 21, 1)], - ); +// ^ +// [diag.topLevelCycle] The type of 'y' can't be inferred because it depends on itself through the cycle: x, y. +'''); var x = result.libraryElement.topLevelVariables[0]; var y = result.libraryElement.topLevelVariables[1]; @@ -2092,371 +2084,611 @@ int get y => null; await resolveTestCodeWithDiagnostics(r''' void add(int x) {} add2(int y) {} -main() { - Future f; +void foo(Future f) { var a = f.then(add); -// ^ -// [diag.unusedLocalVariable] The value of the local variable 'a' isn't used. -// ^ -// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. + var b = f.then(add2); -// ^ -// [diag.unusedLocalVariable] The value of the local variable 'b' isn't used. -// ^ -// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. + + (a, b); } '''); } - test_futureThen() async { - String build({ - required String declared, - required String downwards, - required String upwards, - }) => - ''' + test_futureThen_conditional_declaredFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' import 'dart:async'; class MyFuture implements Future { MyFuture() {} MyFuture.value(T x) {} dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); - MyFuture then(FutureOr f(T x), {Function onError}) => null; + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } } -void main() { - $declared f; - $downwards t1 = f.then((_) async => await new $upwards.value(1)); - $downwards t2 = f.then((_) async { - return await new $upwards.value(2);}); - $downwards t3 = f.then((_) async => 3); - $downwards t4 = f.then((_) async { - return 4;}); - $downwards t5 = f.then((_) => new $upwards.value(5)); - $downwards t6 = f.then((_) {return new $upwards.value(6);}); - $downwards t7 = f.then((_) async => new $upwards.value(7)); - $downwards t8 = f.then((_) async { - return new $upwards.value(8);}); -} -'''; +void foo(Future f) { + Future t1 = f.then( + (x) async => x ? 2 : await new Future.value(3), + ); - List diagnostics = [ - error( - diag.invalidOverride, - 188, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 226, 7), - error(diag.returnOfInvalidTypeFromMethod, 239, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 295, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 367, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 452, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 495, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 550, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 610, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 677, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 743, 1), - ]; - await _assertErrors( - build(declared: "MyFuture", downwards: "Future", upwards: "Future"), - diagnostics, - ); - await _assertErrors( - build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"), - diagnostics, - ); - await _assertErrors( - build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"), - diagnostics, - ); - await _assertErrors( - build(declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"), - diagnostics, - ); - await _assertErrors( - build(declared: "Future", downwards: "Future", upwards: "MyFuture"), - diagnostics, - ); - await _assertErrors( - build(declared: "Future", downwards: "Future", upwards: "Future"), - diagnostics, - ); + // Note: Why the duplicate here? + Future t2 = f.then((x) async { + return await x ? 2 : new Future.value(3); + }); + + Future t5 = f.then((x) => x ? 2 : new Future.value(3)); + + Future t6 = f.then((x) { + return x ? 2 : new Future.value(3); + }); + + (t1, t2, t5, t6); +} +'''); } - test_futureThen_conditional() async { - String build({ - required String declared, - required String downwards, - required String upwards, - }) => - ''' + test_futureThen_conditional_declaredFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' import 'dart:async'; + class MyFuture implements Future { MyFuture() {} MyFuture.value(T x) {} dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); - MyFuture then(FutureOr f(T x), {Function onError}) => null; + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } } -void main() { - $declared f; - $downwards t1 = f.then( - (x) async => x ? 2 : await new $upwards.value(3)); - $downwards t2 = f.then((x) async { // TODO(leafp): Why the duplicate here? - return await x ? 2 : new $upwards.value(3);}); - $downwards t5 = f.then( - (x) => x ? 2 : new $upwards.value(3)); - $downwards t6 = f.then( - (x) {return x ? 2 : new $upwards.value(3);}); +void foo(Future f) { + Future t1 = f.then( + (x) async => x ? 2 : await new MyFuture.value(3), + ); + + // Note: Why the duplicate here? + Future t2 = f.then((x) async { + return await x ? 2 : new MyFuture.value(3); + }); + + Future t5 = f.then((x) => x ? 2 : new MyFuture.value(3)); + + Future t6 = f.then((x) { + return x ? 2 : new MyFuture.value(3); + }); + + (t1, t2, t5, t6); } -'''; - await _assertErrors( - build(declared: "MyFuture", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 300, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 387, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 519, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 594, 1), - ], - ); - await disposeAnalysisContextCollection(); +'''); + } - await _assertErrors( - build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 300, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 389, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 523, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 600, 1), - ], - ); - await disposeAnalysisContextCollection(); + test_futureThen_conditional_declaredMyFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; - await _assertErrors( - build(declared: "MyFuture", downwards: "MyFuture", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 302, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 391, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 525, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 602, 1), - ], - ); - await disposeAnalysisContextCollection(); +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} - await _assertErrors( - build(declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 302, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 393, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 529, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 608, 1), - ], - ); - await disposeAnalysisContextCollection(); +void foo(MyFuture f) { + Future t1 = f.then( + (x) async => x ? 2 : await new Future.value(3), + ); - await _assertErrors( - build(declared: "Future", downwards: "Future", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 298, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 387, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 521, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 598, 1), - ], - ); - await disposeAnalysisContextCollection(); + // Note: Why the duplicate here? + Future t2 = f.then((x) async { + return await x ? 2 : new Future.value(3); + }); - await _assertErrors( - build(declared: "Future", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 298, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 385, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 517, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 592, 1), - ], - ); - await disposeAnalysisContextCollection(); + Future t5 = f.then((x) => x ? 2 : new Future.value(3)); + + Future t6 = f.then((x) { + return x ? 2 : new Future.value(3); + }); + + (t1, t2, t5, t6); +} +'''); + } + + test_futureThen_conditional_declaredMyFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + Future t1 = f.then( + (x) async => x ? 2 : await new MyFuture.value(3), + ); + + // Note: Why the duplicate here? + Future t2 = f.then((x) async { + return await x ? 2 : new MyFuture.value(3); + }); + + Future t5 = f.then((x) => x ? 2 : new MyFuture.value(3)); + + Future t6 = f.then((x) { + return x ? 2 : new MyFuture.value(3); + }); + + (t1, t2, t5, t6); +} +'''); + } + + test_futureThen_conditional_declaredMyFuture_downwardsMyFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + MyFuture t1 = f.then( + (x) async => x ? 2 : await new Future.value(3), + ); + + // Note: Why the duplicate here? + MyFuture t2 = f.then((x) async { + return await x ? 2 : new Future.value(3); + }); + + MyFuture t5 = f.then((x) => x ? 2 : new Future.value(3)); + + MyFuture t6 = f.then((x) { + return x ? 2 : new Future.value(3); + }); + + (t1, t2, t5, t6); +} +'''); + } + + test_futureThen_conditional_declaredMyFuture_downwardsMyFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + MyFuture t1 = f.then( + (x) async => x ? 2 : await new MyFuture.value(3), + ); + + // Note: Why the duplicate here? + MyFuture t2 = f.then((x) async { + return await x ? 2 : new MyFuture.value(3); + }); + + MyFuture t5 = f.then((x) => x ? 2 : new MyFuture.value(3)); + + MyFuture t6 = f.then((x) { + return x ? 2 : new MyFuture.value(3); + }); + + (t1, t2, t5, t6); +} +'''); + } + + test_futureThen_declaredFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(Future f) { + Future t1 = f.then((_) async => await new Future.value(1)); + + Future t2 = f.then((_) async { + return await new Future.value(2); + }); + + Future t3 = f.then((_) async => 3); + + Future t4 = f.then((_) async { + return 4; + }); + + Future t5 = f.then((_) => new Future.value(5)); + + Future t6 = f.then((_) { + return new Future.value(6); + }); + + Future t7 = f.then((_) async => new Future.value(7)); + + Future t8 = f.then((_) async { + return new Future.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); + } + + test_futureThen_declaredFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(Future f) { + Future t1 = f.then((_) async => await new MyFuture.value(1)); + + Future t2 = f.then((_) async { + return await new MyFuture.value(2); + }); + + Future t3 = f.then((_) async => 3); + + Future t4 = f.then((_) async { + return 4; + }); + + Future t5 = f.then((_) => new MyFuture.value(5)); + + Future t6 = f.then((_) { + return new MyFuture.value(6); + }); + + Future t7 = f.then((_) async => new MyFuture.value(7)); + + Future t8 = f.then((_) async { + return new MyFuture.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); + } + + test_futureThen_declaredMyFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + Future t1 = f.then((_) async => await new Future.value(1)); + + Future t2 = f.then((_) async { + return await new Future.value(2); + }); + + Future t3 = f.then((_) async => 3); + + Future t4 = f.then((_) async { + return 4; + }); + + Future t5 = f.then((_) => new Future.value(5)); + + Future t6 = f.then((_) { + return new Future.value(6); + }); + + Future t7 = f.then((_) async => new Future.value(7)); + + Future t8 = f.then((_) async { + return new Future.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); + } + + test_futureThen_declaredMyFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + Future t1 = f.then((_) async => await new MyFuture.value(1)); + + Future t2 = f.then((_) async { + return await new MyFuture.value(2); + }); + + Future t3 = f.then((_) async => 3); + + Future t4 = f.then((_) async { + return 4; + }); + + Future t5 = f.then((_) => new MyFuture.value(5)); + + Future t6 = f.then((_) { + return new MyFuture.value(6); + }); + + Future t7 = f.then((_) async => new MyFuture.value(7)); + + Future t8 = f.then((_) async { + return new MyFuture.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); + } + + test_futureThen_declaredMyFuture_downwardsMyFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + MyFuture t1 = f.then((_) async => await new Future.value(1)); + + MyFuture t2 = f.then((_) async { + return await new Future.value(2); + }); + + MyFuture t3 = f.then((_) async => 3); + + MyFuture t4 = f.then((_) async { + return 4; + }); + + MyFuture t5 = f.then((_) => new Future.value(5)); + + MyFuture t6 = f.then((_) { + return new Future.value(6); + }); + + MyFuture t7 = f.then((_) async => new Future.value(7)); + + MyFuture t8 = f.then((_) async { + return new Future.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); + } + + test_futureThen_declaredMyFuture_downwardsMyFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void foo(MyFuture f) { + MyFuture t1 = f.then((_) async => await new MyFuture.value(1)); + + MyFuture t2 = f.then((_) async { + return await new MyFuture.value(2); + }); + + MyFuture t3 = f.then((_) async => 3); + + MyFuture t4 = f.then((_) async { + return 4; + }); + + MyFuture t5 = f.then((_) => new MyFuture.value(5)); + + MyFuture t6 = f.then((_) { + return new MyFuture.value(6); + }); + + MyFuture t7 = f.then((_) async => new MyFuture.value(7)); + + MyFuture t8 = f.then((_) async { + return new MyFuture.value(8); + }); + + (t1, t2, t3, t4, t5, t6, t7, t8); +} +'''); } test_futureThen_downwardsMethodTarget() async { // Not working yet, see: https://github.com/dart-lang/sdk/issues/27114 - await assertErrorsInCode( - r''' -main() { - Future f; + await resolveTestCodeWithDiagnostics(r''' +void foo(Future f) { Future> b = f +// [diag.invalidAssignment][column 25][length 51] A value of type 'Future>' can't be assigned to a variable of type 'Future>'. .then((x) => []) .whenComplete(() {}); b = f.then((x) => []); -} - ''', - [ - error(diag.unusedLocalVariable, 46, 1), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 50, 1), - error(diag.invalidAssignment, 50, 51), - error(diag.notAssignedPotentiallyNonNullableLocalVariable, 109, 1), - ], - ); - } - - test_futureThen_explicitFuture() async { - await resolveTestCodeWithDiagnostics(r''' -m1() { - Future f; - var x = f.then>>((x) => []); -// ^ -// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. -// ^^ -// [diag.returnOfInvalidTypeFromClosure] The returned type 'List' isn't returnable from a 'FutureOr>>' function, as required by the closure's context. - Future> y = x; -// ^ -// [diag.unusedLocalVariable] The value of the local variable 'y' isn't used. -// ^ -// [diag.invalidAssignment] A value of type 'Future>>' can't be assigned to a variable of type 'Future>'. -} -m2() { - Future f; - var x = f.then>((x) => []); -// ^ -// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. - Future> y = x; -// ^ -// [diag.unusedLocalVariable] The value of the local variable 'y' isn't used. + b; } '''); } - test_futureThen_upwards() async { + test_futureThen_explicitFuture() async { + await resolveTestCodeWithDiagnostics(r''' +void foo1(Future f) { + var x = f.then>>((x) => []); +// ^^ +// [diag.returnOfInvalidTypeFromClosure] The returned type 'List' isn't returnable from a 'FutureOr>>' function, as required by the closure's context. + Future> y = x; +// ^ +// [diag.invalidAssignment] A value of type 'Future>>' can't be assigned to a variable of type 'Future>'. + y; +} + +void foo2(Future f) { + var x = f.then>((x) => []); + Future> y = x; + y; +} +'''); + } + + test_futureThen_upwards_declaredFuture_downwardsFuture_upwardsFuture() async { // Regression test for https://github.com/dart-lang/sdk/issues/27088. - String build({ - required String declared, - required String downwards, - required String upwards, - }) => - ''' + await resolveTestCodeWithDiagnostics(r''' import 'dart:async'; + class MyFuture implements Future { MyFuture() {} MyFuture.value(T x) {} dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); - MyFuture then(FutureOr f(T x), {Function onError}) => null; + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } } void main() { var f = foo().then((_) => 2.3); - $downwards f2 = f; + Future f2 = f; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f2' isn't used. +// ^ +// [diag.invalidAssignment] A value of type 'Future' can't be assigned to a variable of type 'Future'. // The unnecessary cast is to illustrate that we inferred for // the generic type args, even though we had a return type context. - $downwards f3 = foo().then( - (_) => 2.3) as $upwards; + Future f3 = foo().then( +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f3' isn't used. +// [diag.unnecessaryCast][column 20][length 47] Unnecessary cast. + (_) => 2.3) as Future; } -$declared foo() => new $declared.value(1); - '''; +Future foo() => new Future.value(1); +'''); + } - await assertErrorsInCode( - build(declared: "MyFuture", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.unusedLocalVariable, 309, 2), - error(diag.invalidAssignment, 314, 1), - error(diag.unusedLocalVariable, 475, 2), - ], - ); - await disposeAnalysisContextCollection(); + test_futureThen_upwards_declaredMyFuture_downwardsFuture_upwardsFuture() async { + // Regression test for https://github.com/dart-lang/sdk/issues/27088. + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; - await assertErrorsInCode( - build(declared: "MyFuture", downwards: "MyFuture", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.unusedLocalVariable, 311, 2), - error(diag.invalidAssignment, 316, 1), - error(diag.unusedLocalVariable, 479, 2), - error(diag.unnecessaryCast, 484, 49), - ], - ); - await disposeAnalysisContextCollection(); +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} - await assertErrorsInCode( - build(declared: "Future", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.unusedLocalVariable, 309, 2), - error(diag.invalidAssignment, 314, 1), - error(diag.unusedLocalVariable, 475, 2), - error(diag.unnecessaryCast, 480, 47), - ], - ); - await disposeAnalysisContextCollection(); +void main() { + var f = foo().then((_) => 2.3); + Future f2 = f; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f2' isn't used. +// ^ +// [diag.invalidAssignment] A value of type 'MyFuture' can't be assigned to a variable of type 'Future'. + + // The unnecessary cast is to illustrate that we inferred for + // the generic type args, even though we had a return type context. + Future f3 = foo().then( +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f3' isn't used. + (_) => 2.3) as Future; +} +MyFuture foo() => new MyFuture.value(1); +'''); + } + + test_futureThen_upwards_declaredMyFuture_downwardsMyFuture_upwardsMyFuture() async { + // Regression test for https://github.com/dart-lang/sdk/issues/27088. + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; + +class MyFuture implements Future { + MyFuture() {} + MyFuture.value(T x) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +void main() { + var f = foo().then((_) => 2.3); + MyFuture f2 = f; +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f2' isn't used. +// ^ +// [diag.invalidAssignment] A value of type 'MyFuture' can't be assigned to a variable of type 'MyFuture'. + + // The unnecessary cast is to illustrate that we inferred for + // the generic type args, even though we had a return type context. + MyFuture f3 = foo().then( +// ^^ +// [diag.unusedLocalVariable] The value of the local variable 'f3' isn't used. +// [diag.unnecessaryCast][column 22][length 49] Unnecessary cast. + (_) => 2.3) as MyFuture; +} +MyFuture foo() => new MyFuture.value(1); +'''); } test_futureThen_upwardsFromBlock() async { @@ -2464,9 +2696,11 @@ $declared foo() => new $declared.value(1); await resolveTestCodeWithDiagnostics(r''' main() { Future base; - var f = base.then((x) { return x == 0; }); + var f = base.then((x) { // ^^^^ // [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'base' must be assigned before it can be used. + return x == 0; + }); var g = base.then((x) => x == 0); // ^^^^ // [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'base' must be assigned before it can be used. @@ -2478,153 +2712,174 @@ main() { '''); } - test_futureUnion_asyncConditional() async { - String build({ - required String downwards, - required String upwards, - String expectedInfo = '', - }) => - ''' + test_futureUnion_asyncConditional_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' import 'dart:async'; class MyFuture implements Future { MyFuture() {} - MyFuture.value(x) {} + MyFuture.value([T? x]) {} dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); - MyFuture then(FutureOr f(T x), {Function onError}) => null; + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } } -$downwards g1(bool x) async { - return x ? 42 : new $upwards.value(42); } -$downwards g2(bool x) async => - x ? 42 : new $upwards.value(42); -$downwards g3(bool x) async { - var y = x ? 42 : ${expectedInfo}new $upwards.value(42); +Future g1(bool x) async { + return x ? 42 : new Future.value(42); } +Future g2(bool x) async => + x ? 42 : new Future.value(42); +Future g3(bool x) async { + var y = x ? 42 : new Future.value(42); return y; +// ^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Object' can't be returned from the function 'g3' because it has a return type of 'Future'. } - '''; - - await assertErrorsInCode(build(downwards: "Future", upwards: "Future"), [ - error( - diag.invalidOverride, - 185, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 223, 7), - error(diag.returnOfInvalidTypeFromMethod, 236, 4), - error(diag.returnOfInvalidTypeFromFunction, 464, 1), - ]); - await disposeAnalysisContextCollection(); - - await assertErrorsInCode(build(downwards: "Future", upwards: "MyFuture"), [ - error( - diag.invalidOverride, - 185, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 223, 7), - error(diag.returnOfInvalidTypeFromMethod, 236, 4), - error(diag.returnOfInvalidTypeFromFunction, 470, 1), - ]); - await disposeAnalysisContextCollection(); +'''); } - test_futureUnion_downwards() async { - String build({ - required String declared, - required String downwards, - required String upwards, - String expectedError = '', - }) { - return ''' + test_futureUnion_asyncConditional_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' import 'dart:async'; class MyFuture implements Future { MyFuture() {} - MyFuture.value([x]) {} + MyFuture.value([T? x]) {} dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); - MyFuture then(FutureOr f(T x), {Function onError}) => null; + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } } -$declared f; +Future g1(bool x) async { + return x ? 42 : new MyFuture.value(42); } +Future g2(bool x) async => + x ? 42 : new MyFuture.value(42); +Future g3(bool x) async { + var y = x ? 42 : new MyFuture.value(42); + return y; +// ^ +// [diag.returnOfInvalidTypeFromFunction] A value of type 'Object' can't be returned from the function 'g3' because it has a return type of 'Future'. +} +'''); + } + + test_futureUnion_downwards_declaredFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; +class MyFuture implements Future { + MyFuture() {} + MyFuture.value([T? x]) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. // Instantiates Future -$downwards t1 = f.then((_) => - new $upwards.value($expectedError'hi')); +Future t1 = f.then((_) => + new Future.value('hi')); +// ^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'String' can't be assigned to the parameter type 'FutureOr?'. // Instantiates List -$downwards> t2 = f.then((_) => [3]); -$downwards> g2() async { return [3]; } -$downwards> g3() async { - return new $upwards.value( +Future> t2 = f.then((_) => [3]); +Future> g2() async { return [3]; } +Future> g3() async { + return new Future.value( [3]); } -'''; - } +'''); + } - await assertErrorsInCode( - build(declared: "MyFuture", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notInitializedNonNullableVariable, 256, 1), - error(diag.argumentTypeNotAssignable, 338, 4), - ], - ); - await disposeAnalysisContextCollection(); + test_futureUnion_downwards_declaredFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; +class MyFuture implements Future { + MyFuture() {} + MyFuture.value([T? x]) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} - await assertErrorsInCode( - build(declared: "MyFuture", downwards: "Future", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notInitializedNonNullableVariable, 256, 1), - ], - ); - await disposeAnalysisContextCollection(); +Future f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. +// Instantiates Future +Future t1 = f.then((_) => + new MyFuture.value('hi')); +// ^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'String' can't be assigned to the parameter type 'int?'. - await assertErrorsInCode( - build(declared: "Future", downwards: "Future", upwards: "Future"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notInitializedNonNullableVariable, 254, 1), - error(diag.argumentTypeNotAssignable, 336, 4), - ], - ); - await disposeAnalysisContextCollection(); +// Instantiates List +Future> t2 = f.then((_) => [3]); +Future> g2() async { return [3]; } +Future> g3() async { + return new MyFuture.value( + [3]); } +'''); + } - await assertErrorsInCode( - build(declared: "Future", downwards: "Future", upwards: "MyFuture"), - [ - error( - diag.invalidOverride, - 187, - 4, - contextMessages: [message(dartAsyncFile, 570, 4)], - ), - error(diag.missingDefaultValueForParameter, 225, 7), - error(diag.returnOfInvalidTypeFromMethod, 238, 4), - error(diag.notInitializedNonNullableVariable, 254, 1), - ], - ); - await disposeAnalysisContextCollection(); + test_futureUnion_downwards_declaredMyFuture_downwardsFuture_upwardsFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; +class MyFuture implements Future { + MyFuture() {} + MyFuture.value([T? x]) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +MyFuture f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. +// Instantiates Future +Future t1 = f.then((_) => + new Future.value('hi')); +// ^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'String' can't be assigned to the parameter type 'FutureOr?'. + +// Instantiates List +Future> t2 = f.then((_) => [3]); +Future> g2() async { return [3]; } +Future> g3() async { + return new Future.value( + [3]); } +'''); + } + + test_futureUnion_downwards_declaredMyFuture_downwardsFuture_upwardsMyFuture() async { + await resolveTestCodeWithDiagnostics(r''' +import 'dart:async'; +class MyFuture implements Future { + MyFuture() {} + MyFuture.value([T? x]) {} + dynamic noSuchMethod(invocation) => super.noSuchMethod(invocation); + MyFuture then(FutureOr Function(T) f, {Function? onError}) { + return MyFuture(); + } +} + +MyFuture f; +// ^ +// [diag.notInitializedNonNullableVariable] The non-nullable variable 'f' must be initialized. +// Instantiates Future +Future t1 = f.then((_) => + new MyFuture.value('hi')); +// ^^^^ +// [diag.argumentTypeNotAssignable] The argument type 'String' can't be assigned to the parameter type 'int?'. + +// Instantiates List +Future> t2 = f.then((_) => [3]); +Future> g2() async { return [3]; } +Future> g3() async { + return new MyFuture.value( + [3]); } +'''); } test_futureUnion_downwardsGenericMethodWithFutureReturn() async { @@ -2654,13 +2909,9 @@ class A {} await resolveTestCodeWithDiagnostics(r''' T id(T x) => x; -main() async { - Future f; +foo(Future f) async { String s = await id(f); -// ^ -// [diag.unusedLocalVariable] The value of the local variable 's' isn't used. -// ^ -// [diag.notAssignedPotentiallyNonNullableLocalVariable] The non-nullable local variable 'f' must be assigned before it can be used. + s; } '''); } @@ -5659,20 +5910,6 @@ main() { _assertTypeStr(y.type, 'void'); } - Future _assertErrors( - String code, - List expectedDiagnostics, - ) async { - var result = await resolveTestCode(code); - assertErrorsInList( - result.diagnostics.where((e) { - return e.diagnosticCode != diag.unusedLocalVariable && - e.diagnosticCode.type != DiagnosticType.TODO; - }).toList(), - expectedDiagnostics, - ); - } - void _assertTypeStr(DartType type, String expected) { var typeStr = type.getDisplayString(); expect(typeStr, expected); diff --git a/pkg/analyzer_testing/lib/src/expected_diagnostics.dart b/pkg/analyzer_testing/lib/src/expected_diagnostics.dart index 43ccf843753..b9d8afd6ac1 100644 --- a/pkg/analyzer_testing/lib/src/expected_diagnostics.dart +++ b/pkg/analyzer_testing/lib/src/expected_diagnostics.dart @@ -11,20 +11,19 @@ import 'package:analyzer_testing/utilities/extensions/diagnostic_code.dart'; /// Returns [content] with generated diagnostic expectation marker lines removed. String removeDiagnosticExpectations(String content) { - var lines = _Line.parse(content); + var allLines = _Line.parse(content); + var codeLines = allLines + .where((line) => !_LineMarker.isMarker(line)) + .toList(); var buffer = StringBuffer(); - var isFirstLine = true; - for (var line in lines) { - if (_LineMarker.isMarker(line)) { - continue; - } - - if (isFirstLine) { - isFirstLine = false; - } else { - buffer.writeln(); - } + for (var i = 0; i < codeLines.length; i++) { + var line = codeLines[i]; buffer.write(line.text); + // Write terminators as separators between retained lines; a terminator + // before a removed marker line should not become a trailing terminator. + if (i < codeLines.length - 1) { + buffer.write(line.lineTerminator); + } } return buffer.toString(); } @@ -293,32 +292,35 @@ final class _ExpectedDiagnosticsUpdater { String _writeContent() { var buffer = StringBuffer(); - var isFirstLine = true; for (var line in lines) { - if (isFirstLine) { - isFirstLine = false; - } else { - buffer.writeln(); - } buffer.write(line.text); var markers = markersByLine[line.number]; if (markers != null) { + var markerLineTerminator = line.lineTerminator; + + // Use a separator when adding markers after an unterminated final line. + if (markerLineTerminator.isEmpty) { + markerLineTerminator = '\n'; + } + markers.sort(_GeneratedMarker.compare); ({int column, int length})? currentCaret; for (var marker in markers) { if (marker.caretLength case var caretLength?) { var markerCaret = (column: marker.column, length: caretLength); if (markerCaret != currentCaret) { - buffer.writeln(); + buffer.write(markerLineTerminator); buffer.write(_caretLine(marker.column, caretLength)); currentCaret = markerCaret; } } - buffer.writeln(); + buffer.write(markerLineTerminator); buffer.write(marker.expectationText); } } + + buffer.write(line.lineTerminator); } return buffer.toString(); } @@ -456,7 +458,14 @@ final class _Line { /// The line text without the trailing newline characters. final String text; - _Line({required this.number, required this.text}); + /// The line terminator, if present. + final String lineTerminator; + + _Line({ + required this.number, + required this.text, + required this.lineTerminator, + }); /// Splits [content] into lines while preserving each line's offset. /// @@ -470,24 +479,34 @@ final class _Line { for (var index = 0; index < content.length; index++) { var codeUnit = content.codeUnitAt(index); if (codeUnit == 0x0D || codeUnit == 0x0A) { - result.add( - _Line( - number: lineNumber++, - text: content.substring(lineStart, index), - ), - ); + var lineText = content.substring(lineStart, index); - // Consume the `\n` in a `\r\n` line break. + var lineTerminator = content.substring(index, index + 1); if (codeUnit == 0x0D && index + 1 < content.length && content.codeUnitAt(index + 1) == 0x0A) { + lineTerminator = content.substring(index, index + 2); index++; } + + result.add( + _Line( + number: lineNumber++, + text: lineText, + lineTerminator: lineTerminator, + ), + ); lineStart = index + 1; } } - result.add(_Line(number: lineNumber, text: content.substring(lineStart))); + result.add( + _Line( + number: lineNumber, + text: content.substring(lineStart), + lineTerminator: '', + ), + ); return result; } }