Improve the range selected for const_constructor_with_non_final_field

Change-Id: I168e92c32b581dffcad25804161b56f4d99c1dd1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/130300
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Brian Wilkerson 2020-01-05 23:50:22 +00:00 committed by commit-bot@chromium.org
parent b975366803
commit 877d6f745d
6 changed files with 41 additions and 18 deletions

View file

@ -5,7 +5,8 @@
import 'dart:collection';
import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message;
import 'package:analyzer/dart/ast/ast.dart' show AstNode;
import 'package:analyzer/dart/ast/ast.dart'
show AstNode, ConstructorDeclaration;
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@ -119,6 +120,21 @@ class ErrorReporter {
errorCode, element.nameOffset, element.nameLength, arguments);
}
/// Report a diagnostic with the given [code] and [arguments]. The
/// location of the diagnostic will be the name of the [constructor].
void reportErrorForName(ErrorCode code, ConstructorDeclaration constructor,
{List<Object> arguments}) {
// TODO(brianwilkerson) Consider extending this method to take any
// declaration and compute the correct range for the name of that
// declaration. This might make it easier to be consistent.
if (constructor.name != null) {
var offset = constructor.returnType.offset;
reportErrorForOffset(code, offset, constructor.name.end - offset);
} else {
reportErrorForNode(code, constructor.returnType);
}
}
/**
* Report an error with the given [errorCode] and [arguments].
* The [node] is used to compute the location of the error.

View file

@ -2164,8 +2164,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
* Verify that if the given [constructor] declaration is 'const' then there
* are no non-final instance variable. The [constructorElement] is the
* constructor element.
*
* See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD].
*/
void _checkForConstConstructorWithNonFinalField(
ConstructorDeclaration constructor,
@ -2178,8 +2176,11 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
if (!classElement.hasNonFinalField) {
return;
}
_errorReporter.reportErrorForNode(
// TODO(brianwilkerson) Stop generating
// CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD when either
// CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER or
// CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD is also generated.
_errorReporter.reportErrorForName(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
constructor);
}

View file

@ -398,8 +398,7 @@ class B extends Object with A {
const B();
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 55, 10),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 61, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 61, 1),
]);
@ -414,21 +413,30 @@ class B extends A {
const B();
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 43, 10),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 49, 1),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 49, 1),
]);
}
test_constConstructorWithNonFinalField_this() async {
test_constConstructorWithNonFinalField_this_named() async {
await assertErrorsInCode(r'''
class A {
int x;
const A.a();
}
''', [
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 27, 3),
]);
}
test_constConstructorWithNonFinalField_this_unnamed() async {
await assertErrorsInCode(r'''
class A {
int x;
const A();
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 21, 10),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 27, 1),
]);
}

View file

@ -25,8 +25,7 @@ class B extends Object with A {
const B();
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 56, 10),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
]);
@ -79,8 +78,7 @@ class X extends Object with M {
const X();
}
''', [
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 56, 10),
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
]);

View file

@ -14,7 +14,7 @@ class B extends A
with Mixin
{
const B(foo) : super(foo);
//^^^^^^^^^^^^^^^^^^^^^^^^^^
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD

View file

@ -34,7 +34,7 @@ class C0 implements I0 {
class C1 {
const C1();
//^^^^^^^^^^^
// ^^
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
// ^
// [cfe] Constructor is marked 'const' so all fields must be final.