Improve message around re-assigning a local final.

Add a new ASSIGNMENT_TO_LOCAL_FINAL code for the new text.

Fixes https://github.com/dart-lang/sdk/issues/28721

Bug: https://github.com/dart-lang/sdk/issues/28721
Change-Id: I5492dd0d9ee09d5b73296b46fe10271661c3c64f
Reviewed-on: https://dart-review.googlesource.com/29621
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Sam Rawlins 2017-12-15 01:09:55 +00:00 committed by commit-bot@chromium.org
parent 3ebdf40490
commit ee07335392
5 changed files with 68 additions and 49 deletions

View file

@ -533,6 +533,7 @@ const List<ErrorCode> errorCodeValues = const [
StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
StaticWarningCode.ASSIGNMENT_TO_CONST,
StaticWarningCode.ASSIGNMENT_TO_FINAL,
StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL,
StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
StaticWarningCode.ASSIGNMENT_TO_FUNCTION,
StaticWarningCode.ASSIGNMENT_TO_METHOD,

View file

@ -3320,6 +3320,17 @@ class StaticWarningCode extends ErrorCode {
"'{0}' can't be used as a setter because it is final.",
"Try finding a different setter, or making '{0}' non-final.");
/**
* 5 Variables: Attempting to assign to a final variable elsewhere will cause
* a NoSuchMethodError to be thrown, because no setter is defined for it. The
* assignment will also give rise to a static warning for the same reason.
*/
static const StaticWarningCode ASSIGNMENT_TO_FINAL_LOCAL =
const StaticWarningCode(
'ASSIGNMENT_TO_FINAL_LOCAL',
"'{0}', a final variable, can only be set once.",
"Try making '{0}' non-final.");
/**
* 5 Variables: Attempting to assign to a final variable elsewhere will cause
* a NoSuchMethodError to be thrown, because no setter is defined for it. The

View file

@ -2574,17 +2574,24 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_CONST, expression);
} else if (element.isFinal) {
if (element is FieldElementImpl &&
element.setter == null &&
element.isSynthetic) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
highlightedNode,
[element.name, element.enclosingElement.displayName]);
if (element is FieldElementImpl) {
if (element.setter == null && element.isSynthetic) {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
highlightedNode,
[element.name, element.enclosingElement.displayName]);
} else {
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_FINAL,
highlightedNode,
[element.name]);
}
return;
}
_errorReporter.reportErrorForNode(StaticWarningCode.ASSIGNMENT_TO_FINAL,
highlightedNode, [element.name]);
_errorReporter.reportErrorForNode(
StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL,
highlightedNode,
[element.name]);
}
} else if (element is FunctionElement) {
_errorReporter.reportErrorForNode(

View file

@ -376,71 +376,71 @@ class StaticWarningCodeTest_Kernel extends StaticWarningCodeTest_Driver {
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_localVariable() async {
return super.test_assignmentToFinal_localVariable();
test_assignmentToFinalLocal_localVariable() async {
return super.test_assignmentToFinalLocal_localVariable();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_localVariable_plusEq() async {
return super.test_assignmentToFinal_localVariable_plusEq();
test_assignmentToFinalLocal_localVariable_plusEq() async {
return super.test_assignmentToFinalLocal_localVariable_plusEq();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_parameter() async {
return super.test_assignmentToFinal_parameter();
test_assignmentToFinalLocal_parameter() async {
return super.test_assignmentToFinalLocal_parameter();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_postfixMinusMinus() async {
return super.test_assignmentToFinal_postfixMinusMinus();
test_assignmentToFinalLocal_postfixMinusMinus() async {
return super.test_assignmentToFinalLocal_postfixMinusMinus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_postfixPlusPlus() async {
return super.test_assignmentToFinal_postfixPlusPlus();
test_assignmentToFinalLocal_postfixPlusPlus() async {
return super.test_assignmentToFinalLocal_postfixPlusPlus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_prefixMinusMinus() async {
return super.test_assignmentToFinal_prefixMinusMinus();
test_assignmentToFinalLocal_prefixMinusMinus() async {
return super.test_assignmentToFinalLocal_prefixMinusMinus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_prefixPlusPlus() async {
return super.test_assignmentToFinal_prefixPlusPlus();
test_assignmentToFinalLocal_prefixPlusPlus() async {
return super.test_assignmentToFinalLocal_prefixPlusPlus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_suffixMinusMinus() async {
return super.test_assignmentToFinal_suffixMinusMinus();
test_assignmentToFinalLocal_suffixMinusMinus() async {
return super.test_assignmentToFinalLocal_suffixMinusMinus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_suffixPlusPlus() async {
return super.test_assignmentToFinal_suffixPlusPlus();
test_assignmentToFinalLocal_suffixPlusPlus() async {
return super.test_assignmentToFinalLocal_suffixPlusPlus();
}
@override
@failingTest
@potentialAnalyzerProblem
test_assignmentToFinal_topLevelVariable() async {
return super.test_assignmentToFinal_topLevelVariable();
test_assignmentToFinalLocal_topLevelVariable() async {
return super.test_assignmentToFinalLocal_topLevelVariable();
}
@override

View file

@ -716,110 +716,110 @@ f() {
verify([source]);
}
test_assignmentToFinal_localVariable() async {
test_assignmentToFinalLocal_localVariable() async {
Source source = addSource(r'''
f() {
final x = 0;
x = 1;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_localVariable_plusEq() async {
test_assignmentToFinalLocal_localVariable_plusEq() async {
Source source = addSource(r'''
f() {
final x = 0;
x += 1;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_parameter() async {
test_assignmentToFinalLocal_parameter() async {
Source source = addSource(r'''
f(final x) {
x = 1;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_postfixMinusMinus() async {
test_assignmentToFinalLocal_postfixMinusMinus() async {
Source source = addSource(r'''
f() {
final x = 0;
x--;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_postfixPlusPlus() async {
test_assignmentToFinalLocal_postfixPlusPlus() async {
Source source = addSource(r'''
f() {
final x = 0;
x++;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_prefixMinusMinus() async {
test_assignmentToFinalLocal_prefixMinusMinus() async {
Source source = addSource(r'''
f() {
final x = 0;
--x;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_prefixPlusPlus() async {
test_assignmentToFinalLocal_prefixPlusPlus() async {
Source source = addSource(r'''
f() {
final x = 0;
++x;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_suffixMinusMinus() async {
test_assignmentToFinalLocal_suffixMinusMinus() async {
Source source = addSource(r'''
f() {
final x = 0;
x--;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_suffixPlusPlus() async {
test_assignmentToFinalLocal_suffixPlusPlus() async {
Source source = addSource(r'''
f() {
final x = 0;
x++;
}''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}
test_assignmentToFinal_topLevelVariable() async {
test_assignmentToFinalLocal_topLevelVariable() async {
Source source = addSource(r'''
final x = 0;
f() { x = 1; }''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL]);
assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_FINAL_LOCAL]);
verify([source]);
}