analyzer: Do not allow errors to be ignored inline. Fixes #27218

Change-Id: If37dabba3ec18a9f79f44c4ea38d6920a4013019
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140142
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Sam Rawlins 2020-04-10 17:16:24 +00:00 committed by commit-bot@chromium.org
parent 830bfd8886
commit 2c420267b7
6 changed files with 149 additions and 53 deletions

View file

@ -2,10 +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.
// ignore_for_file: const_initialized_with_non_constant_value
// TODO(paulberry): Support testing errors in analyzer id testing.
String method() => 'foo';
const String string0 =

View file

@ -7,6 +7,7 @@ import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
@ -411,12 +412,39 @@ class LibraryAnalyzer {
LineInfo lineInfo = _fileToLineInfo[file];
bool isIgnored(AnalysisError error) {
var code = error.errorCode;
// Don't allow error severity issues to be ignored.
if (error.severity == Severity.error) {
bool privileged = false;
if (code == StaticTypeWarningCode.UNDEFINED_FUNCTION ||
code == StaticTypeWarningCode.UNDEFINED_PREFIXED_NAME) {
// Special case a small number of errors in Flutter code which are
// ignored. The erroneous code is found in a conditionally imported
// library, which uses a special version of the "dart:ui" library
// which the Analyzer does not use during analysis. See
// https://github.com/flutter/flutter/issues/52899.
if (file.path.contains('flutter')) {
privileged = true;
}
}
if (code == CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY &&
file.path.contains('tests/compiler/dart2js')) {
// Special case the dart2js language tests. Some of these import
// various internal libraries.
privileged = true;
}
if (!privileged) return false;
}
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
String name = error.errorCode.name.toLowerCase();
String name = code.name.toLowerCase();
if (ignoreInfo.ignoredAt(name, errorLine)) {
return true;
}
String uniqueName = error.errorCode.uniqueName;
String uniqueName = code.uniqueName;
int period = uniqueName.indexOf('.');
if (period >= 0) {
uniqueName = uniqueName.substring(period + 1);

View file

@ -16,86 +16,102 @@ main() {
@reflectiveTest
class ErrorSuppressionTest extends DriverResolutionTest with PackageMixin {
String get ignoredCode => 'const_initialized_with_non_constant_value';
String get ignoredCode => 'unused_element';
test_does_not_ignore_errors() async {
await assertErrorsInCode('''
int x = ''; // ignore: invalid_assignment
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
]);
}
test_error_cannot_be_ignored() async {
await assertErrorsInCode('''
// ignore: unused_import, undefined_function
f() => g();
''', [
error(StaticTypeWarningCode.UNDEFINED_FUNCTION, 52, 1),
]);
}
test_error_code_mismatch() async {
await assertErrorsInCode('''
// ignore: $ignoredCode
int x = '';
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
int _y = 0; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 61, 2),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 75,
1),
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 34, 2),
error(HintCode.UNUSED_ELEMENT, 42, 2),
]);
}
test_ignore_first() async {
await assertErrorsInCode('''
// ignore: invalid_assignment
int x = '';
// ignore: unnecessary_cast
int x = (0 as int);
// ... but no ignore here ...
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 82,
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 88,
1),
]);
}
test_ignore_first_trailing() async {
await assertErrorsInCode('''
int x = ''; // ignore: invalid_assignment
int x = (0 as int); // ignore: unnecessary_cast
// ... but no ignore here ...
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 82,
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 88,
1),
]);
}
test_ignore_for_file() async {
await assertErrorsInCode('''
int x = ''; //INVALID_ASSIGNMENT
int x = (0 as int); //UNNECESSARY_CAST
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// ignore_for_file: invalid_assignment
// ignore_for_file: unnecessary_cast
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 44,
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 49,
1),
]);
}
test_ignore_for_file_whitespace_variant() async {
await assertNoErrorsInCode('''
//ignore_for_file: $ignoredCode , invalid_assignment
int x = ''; //INVALID_ASSIGNMENT
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
//ignore_for_file: $ignoredCode , unnecessary_cast
int x = (0 as int); //UNNECESSARY_CAST
String _foo; //UNUSED_ELEMENT
''');
}
test_ignore_only_trailing() async {
await assertNoErrorsInCode('''
int x = ''; // ignore: invalid_assignment
int x = (0 as int); // ignore: unnecessary_cast
''');
}
test_ignore_second() async {
await assertErrorsInCode('''
//INVALID_ASSIGNMENT
int x = '';
//UNNECESSARY_CAST
int x = (0 as int);
// ignore: $ignoredCode
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
String _foo; //UNUSED_ELEMENT
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 29, 2),
error(HintCode.UNNECESSARY_CAST, 28, 8),
]);
}
test_ignore_second_trailing() async {
await assertErrorsInCode('''
//INVALID_ASSIGNMENT
int x = '';
const y = x; // ignore: $ignoredCode
//UNNECESSARY_CAST
int x = (0 as int);
String _foo; // ignore: $ignoredCode
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 29, 2),
error(HintCode.UNNECESSARY_CAST, 28, 8),
]);
}
@ -113,7 +129,7 @@ int x = f();
test_ignore_upper_case() async {
await assertNoErrorsInCode('''
int x = ''; // ignore: INVALID_ASSIGNMENT
int x = (0 as int); // ignore: UNNECESSARY_CAST
''');
}
@ -152,78 +168,111 @@ String y = 3; //INVALID_ASSIGNMENT
test_multiple_comments() async {
await assertErrorsInCode('''
int x = ''; //This is the first comment...
int x = (0 as int); //This is the first comment...
// ignore: $ignoredCode
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
String _foo; //UNUSED_ELEMENT
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
error(HintCode.UNNECESSARY_CAST, 9, 8),
]);
}
test_multiple_ignore_for_files() async {
await assertNoErrorsInCode('''
int x = ''; //INVALID_ASSIGNMENT
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// ignore_for_file: invalid_assignment,$ignoredCode
int x = (0 as int); //UNNECESSARY_CAST
String _foo; //UNUSED_ELEMENT
// ignore_for_file: unnecessary_cast,$ignoredCode
''');
}
test_multiple_ignores() async {
await assertNoErrorsInCode('''
int x = 3;
// ignore: invalid_assignment, $ignoredCode
const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// ignore: unnecessary_cast, $ignoredCode
int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
''');
}
test_multiple_ignores_trailing() async {
await assertNoErrorsInCode('''
int x = 3;
const String y = x; // ignore: invalid_assignment, $ignoredCode
int _y = x as int; // ignore: unnecessary_cast, $ignoredCode
''');
}
test_multiple_ignores_whitespace_variant_1() async {
await assertNoErrorsInCode('''
int x = 3;
//ignore:invalid_assignment,$ignoredCode
const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
//ignore:unnecessary_cast,$ignoredCode
int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
''');
}
test_multiple_ignores_whitespace_variant_2() async {
await assertNoErrorsInCode('''
int x = 3;
//ignore: invalid_assignment,$ignoredCode
const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
//ignore: unnecessary_cast,$ignoredCode
int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
''');
}
test_multiple_ignores_whitespace_variant_3() async {
await assertNoErrorsInCode('''
int x = 3;
// ignore: invalid_assignment,$ignoredCode
const String y = x; //INVALID_ASSIGNMENT, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// ignore: unnecessary_cast,$ignoredCode
int _y = x as int; //UNNECESSARY_CAST, UNUSED_ELEMENT
''');
}
test_no_ignores() async {
await assertErrorsInCode('''
int x = ''; //INVALID_ASSIGNMENT
int x = ''; //INVALID_ASSIGNMENT
const y = x; //CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 8, 2),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 44,
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 43,
1),
]);
}
test_trailing_not_above() async {
await assertErrorsInCode('''
int x = ''; // ignore: invalid_assignment
int y = '';
int x = (0 as int); // ignore: unnecessary_cast
int y = (0 as int);
''', [
error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 50, 2),
error(HintCode.UNNECESSARY_CAST, 57, 8),
]);
}
test_undefined_function_within_flutter_can_be_ignored() async {
await assertErrorsInFile(
'/workspace/flutterlib/flutter.dart',
'''
// ignore: undefined_function
f() => g();
''',
[],
);
}
test_undefined_function_within_flutter_without_ignore() async {
await assertErrorsInFile(
'/workspace/flutterlib/flutter.dart',
'''
f() => g();
''',
[error(StaticTypeWarningCode.UNDEFINED_FUNCTION, 7, 1)],
);
}
test_undefined_prefixed_name_within_flutter_can_be_ignored() async {
await assertErrorsInFile(
'/workspace/flutterlib/flutter.dart',
'''
import 'dart:collection' as c;
// ignore: undefined_prefixed_name
f() => c.g;
''',
[],
);
}
}

View file

@ -11,7 +11,9 @@ import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/analysis/testing_data.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
import '../util/id_testing_helper.dart';
@ -35,6 +37,18 @@ class ConstantsDataComputer extends DataComputer<String> {
@override
DataInterpreter<String> get dataValidator => const StringDataInterpreter();
@override
bool get supportsErrors => true;
@override
String computeErrorData(TestConfig config, TestingData testingData, Id id,
List<AnalysisError> errors) {
var errorCodes = errors.map((e) => e.errorCode).where((errorCode) =>
errorCode !=
CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE);
return errorCodes.isNotEmpty ? errorCodes.join(',') : null;
}
@override
void computeUnitData(TestingData testingData, CompilationUnit unit,
Map<Id, ActualData<String>> actualMap) {

View file

@ -1,3 +1,5 @@
analyzer:
errors:
import_internal_library: ignore
strong-mode:
implicit-casts: false

View file

@ -1 +1,8 @@
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|3716|5|94|Const constructors can't throw exceptions.
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7902|5|97|Const constructors can't throw exceptions.
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|940|5|95|Const constructors can't throw exceptions.
ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|973|5|94|Const constructors can't throw exceptions.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3714|3|5|Only redirecting factory constructors can be declared to be 'const'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7900|3|5|Only redirecting factory constructors can be declared to be 'const'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|938|3|5|Only redirecting factory constructors can be declared to be 'const'.
ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|971|3|5|Only redirecting factory constructors can be declared to be 'const'.