mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-06 12:57:14 +03:00
Added missing check for Final
variable assigned in a loop. (#8561)
This commit is contained in:
parent
ac8076818c
commit
c385edf274
@ -3058,6 +3058,8 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
this._reportMultipleFinalDeclarations(name, symbol, scope.type);
|
||||
|
||||
this._reportFinalInLoop(symbol);
|
||||
|
||||
this._reportMultipleTypeAliasDeclarations(name, symbol);
|
||||
|
||||
this._reportInvalidOverload(name, symbol);
|
||||
@ -3208,6 +3210,25 @@ export class Checker extends ParseTreeWalker {
|
||||
});
|
||||
}
|
||||
|
||||
private _reportFinalInLoop(symbol: Symbol) {
|
||||
if (!this._evaluator.isFinalVariable(symbol)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const decls = symbol.getDeclarations();
|
||||
if (decls.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ParseTreeUtils.isWithinLoop(decls[0].node)) {
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportGeneralTypeIssues,
|
||||
LocMessage.finalInLoop(),
|
||||
decls[0].node
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _reportMultipleFinalDeclarations(name: string, symbol: Symbol, scopeType: ScopeType) {
|
||||
if (!this._evaluator.isFinalVariable(symbol)) {
|
||||
return;
|
||||
|
@ -497,6 +497,7 @@ export namespace Localizer {
|
||||
export const finalClassIsAbstract = () =>
|
||||
new ParameterizedString<{ type: string }>(getRawString('Diagnostic.finalClassIsAbstract'));
|
||||
export const finalContext = () => getRawString('Diagnostic.finalContext');
|
||||
export const finalInLoop = () => getRawString('Diagnostic.finalInLoop');
|
||||
export const finalMethodOverride = () =>
|
||||
new ParameterizedString<{ name: string; className: string }>(
|
||||
getRawString('Diagnostic.finalMethodOverride')
|
||||
|
@ -197,6 +197,7 @@
|
||||
"expectedYieldExpr": "Expected expression in yield statement",
|
||||
"finalClassIsAbstract": "Class \"{type}\" is marked final and must implement all abstract symbols",
|
||||
"finalContext": "\"Final\" is not allowed in this context",
|
||||
"finalInLoop": "A \"Final\" variable cannot be assigned within a loop",
|
||||
"finalMethodOverride": "Method \"{name}\" cannot override final method defined in class \"{className}\"",
|
||||
"finalNonMethod": "Function \"{name}\" cannot be marked @final because it is not a method",
|
||||
"finalReassigned": "\"{name}\" is declared as Final and cannot be reassigned",
|
||||
|
@ -246,3 +246,25 @@ reveal_type(v11, expected_text='Literal[b""]')
|
||||
|
||||
v12: Final = b"2" and True
|
||||
reveal_type(v12, expected_text="Literal[True]")
|
||||
|
||||
|
||||
def func4():
|
||||
while 1 < 1:
|
||||
# This should generate an error because it's in a loop.
|
||||
x1: Final = 1
|
||||
|
||||
for i in range(10):
|
||||
if i < 3:
|
||||
# This should generate an error because it's in a loop.
|
||||
x2: Final[int] = 1
|
||||
|
||||
|
||||
class ClassF:
|
||||
while 1 < 2:
|
||||
# This should generate an error because it's in a loop.
|
||||
x1: Final = 1
|
||||
|
||||
for i in range(10):
|
||||
if i < 3:
|
||||
# This should generate an error because it's in a loop.
|
||||
x2: Final[int] = 1
|
||||
|
@ -33,7 +33,7 @@ test('Final2', () => {
|
||||
|
||||
test('Final3', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['final3.py']);
|
||||
TestUtils.validateResults(analysisResults, 38);
|
||||
TestUtils.validateResults(analysisResults, 42);
|
||||
});
|
||||
|
||||
test('Final4', () => {
|
||||
|
Loading…
Reference in New Issue
Block a user