Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 4035a01

Browse files
authored
Ignoring assignment statements that occur before class and function declarations (#1422)
1 parent 25b4846 commit 4035a01

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,26 @@ public void HandleAssignment(AssignmentStatement node) {
7171
}
7272

7373
var source = value.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration;
74-
Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, Eval.GetLocationOfName(ne));
74+
var location = Eval.GetLocationOfName(ne);
75+
if (IsValidAssignment(ne.Name, location)) {
76+
Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, location);
77+
}
7578
}
7679

7780
TryHandleClassVariable(node, value);
7881
}
7982

83+
private bool IsValidAssignment(string name, Location loc) {
84+
if (Eval.GetInScope(name) is ILocatedMember m) {
85+
// Class and function definition are processed first, so only override
86+
// if assignment happens after declaration
87+
if (loc.IndexSpan.Start < m.Location.IndexSpan.Start) {
88+
return false;
89+
}
90+
}
91+
return true;
92+
}
93+
8094
public void HandleAnnotatedExpression(ExpressionWithAnnotation expr, IMember value) {
8195
if (expr?.Annotation == null) {
8296
return;

src/Analysis/Ast/Test/AssignmentTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,48 @@ def func(self):
308308
.Which.Should().HaveMembers(listMemberNames);
309309
}
310310

311+
[TestMethod, Priority(0)]
312+
public async Task AssignBeforeClassDef() {
313+
const string code = @"
314+
D = 5
315+
class D: ...
316+
";
317+
var analysis = await GetAnalysisAsync(code);
318+
analysis.Should().HaveClass("D");
319+
}
320+
321+
[TestMethod, Priority(0)]
322+
public async Task AssignAfterClassDef() {
323+
const string code = @"
324+
class D: ...
325+
D = 5
326+
";
327+
var analysis = await GetAnalysisAsync(code);
328+
analysis.Should().HaveVariable("D").OfType(BuiltinTypeId.Int);
329+
}
330+
331+
[TestMethod, Priority(0)]
332+
public async Task AssignBeforeFunctionDef() {
333+
const string code = @"
334+
D = 5
335+
def D():
336+
pass
337+
";
338+
var analysis = await GetAnalysisAsync(code);
339+
analysis.Should().HaveFunction("D");
340+
}
341+
342+
[TestMethod, Priority(0)]
343+
public async Task AssignAfterFunctionDef() {
344+
const string code = @"
345+
def D():
346+
pass
347+
D = 5
348+
";
349+
var analysis = await GetAnalysisAsync(code);
350+
analysis.Should().HaveVariable("D").OfType(BuiltinTypeId.Int);
351+
}
352+
311353
[TestMethod, Priority(0)]
312354
public async Task StrIndex() {
313355
const string code = @"

src/Analysis/Ast/Test/LintInheritNonClassTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,17 @@ class Test3(SupportsInt):
474474
475475
class Test3(FrozenSet):
476476
mystr = 'test'
477+
";
478+
var analysis = await GetAnalysisAsync(code);
479+
analysis.Diagnostics.Should().BeEmpty();
480+
}
481+
482+
[TestMethod, Priority(0)]
483+
public async Task InheritFromEnum() {
484+
const string code = @"
485+
from enum import Enum, EnumMeta
486+
487+
class C(Enum): ...
477488
";
478489
var analysis = await GetAnalysisAsync(code);
479490
analysis.Diagnostics.Should().BeEmpty();

0 commit comments

Comments
 (0)