From 42160153a14bf6e086884d2929ccf49c8956f640 Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Thu, 8 Aug 2019 14:41:18 -0700 Subject: [PATCH 1/3] Ignoring assignment statements before class and function declaration --- .../Analyzer/Handlers/AssignmentHandler.cs | 15 ++++++- src/Analysis/Ast/Test/AssignmentTests.cs | 42 +++++++++++++++++++ .../Ast/Test/LintInheritNonClassTests.cs | 11 +++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs index 5837a9d0c..f58a5f01b 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs @@ -71,12 +71,25 @@ public void HandleAssignment(AssignmentStatement node) { } var source = value.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; - Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, Eval.GetLocationOfName(ne)); + var location = Eval.GetLocationOfName(ne); + if (IsValidAssignment(ne.Name, location)) { + Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, location); + } } TryHandleClassVariable(node, value); } + private bool IsValidAssignment(string name, Location loc) { + if (Eval.GetInScope(name) is ILocatedMember m) { + // If assignment happens before class or function declaration then ignore + if(loc.IndexSpan.Start < m.Location.IndexSpan.Start) { + return false; + } + } + return true; + } + public void HandleAnnotatedExpression(ExpressionWithAnnotation expr, IMember value) { if (expr?.Annotation == null) { return; diff --git a/src/Analysis/Ast/Test/AssignmentTests.cs b/src/Analysis/Ast/Test/AssignmentTests.cs index 9c443b1e4..01fe3dac8 100644 --- a/src/Analysis/Ast/Test/AssignmentTests.cs +++ b/src/Analysis/Ast/Test/AssignmentTests.cs @@ -308,6 +308,48 @@ def func(self): .Which.Should().HaveMembers(listMemberNames); } + [TestMethod, Priority(0)] + public async Task AssignBeforeClassDef() { + const string code = @" +D = 5 +class D: ... +"; + var analysis = await GetAnalysisAsync(code); + analysis.Should().HaveVariable("D").OfType("D"); + } + + [TestMethod, Priority(0)] + public async Task AssignAfterClassDef() { + const string code = @" +class D: ... +D = 5 +"; + var analysis = await GetAnalysisAsync(code); + analysis.Should().HaveVariable("D").OfType(BuiltinTypeId.Int); + } + + [TestMethod, Priority(0)] + public async Task AssignBeforeFunctionDef() { + const string code = @" +D = 5 +def D(): + pass +"; + var analysis = await GetAnalysisAsync(code); + analysis.Should().HaveVariable("D").OfType("D"); + } + + [TestMethod, Priority(0)] + public async Task AssignAfterFunctionDef() { + const string code = @" +def D(): + pass +D = 5 +"; + var analysis = await GetAnalysisAsync(code); + analysis.Should().HaveVariable("D").OfType(BuiltinTypeId.Int); + } + [TestMethod, Priority(0)] public async Task StrIndex() { const string code = @" diff --git a/src/Analysis/Ast/Test/LintInheritNonClassTests.cs b/src/Analysis/Ast/Test/LintInheritNonClassTests.cs index a3d792d77..201638a20 100644 --- a/src/Analysis/Ast/Test/LintInheritNonClassTests.cs +++ b/src/Analysis/Ast/Test/LintInheritNonClassTests.cs @@ -455,6 +455,17 @@ class Test3(SupportsInt): class Test3(FrozenSet): mystr = 'test' +"; + var analysis = await GetAnalysisAsync(code); + analysis.Diagnostics.Should().BeEmpty(); + } + + [TestMethod, Priority(0)] + public async Task InheritFromEnum() { + const string code = @" +from enum import Enum, EnumMeta + +class C(Enum): ... "; var analysis = await GetAnalysisAsync(code); analysis.Diagnostics.Should().BeEmpty(); From 17f0599ba1be9d49105722f233c4cc5bdca6ec0e Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Thu, 8 Aug 2019 15:54:46 -0700 Subject: [PATCH 2/3] Update comment --- src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs index f58a5f01b..23867959b 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs @@ -82,7 +82,8 @@ public void HandleAssignment(AssignmentStatement node) { private bool IsValidAssignment(string name, Location loc) { if (Eval.GetInScope(name) is ILocatedMember m) { - // If assignment happens before class or function declaration then ignore + // Class and function definition are processed first, so only override + // if assignment happens after declaration if(loc.IndexSpan.Start < m.Location.IndexSpan.Start) { return false; } From b2249266aec79e0caff07bb53c7bd771d0e60d4a Mon Sep 17 00:00:00 2001 From: Cameron Trando Date: Mon, 12 Aug 2019 16:09:41 -0700 Subject: [PATCH 3/3] formatting --- src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs | 2 +- src/Analysis/Ast/Test/AssignmentTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs index 23867959b..5e09a7aa4 100644 --- a/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs +++ b/src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs @@ -84,7 +84,7 @@ private bool IsValidAssignment(string name, Location loc) { if (Eval.GetInScope(name) is ILocatedMember m) { // Class and function definition are processed first, so only override // if assignment happens after declaration - if(loc.IndexSpan.Start < m.Location.IndexSpan.Start) { + if (loc.IndexSpan.Start < m.Location.IndexSpan.Start) { return false; } } diff --git a/src/Analysis/Ast/Test/AssignmentTests.cs b/src/Analysis/Ast/Test/AssignmentTests.cs index 01fe3dac8..b586c1200 100644 --- a/src/Analysis/Ast/Test/AssignmentTests.cs +++ b/src/Analysis/Ast/Test/AssignmentTests.cs @@ -315,7 +315,7 @@ public async Task AssignBeforeClassDef() { class D: ... "; var analysis = await GetAnalysisAsync(code); - analysis.Should().HaveVariable("D").OfType("D"); + analysis.Should().HaveClass("D"); } [TestMethod, Priority(0)] @@ -336,7 +336,7 @@ def D(): pass "; var analysis = await GetAnalysisAsync(code); - analysis.Should().HaveVariable("D").OfType("D"); + analysis.Should().HaveFunction("D"); } [TestMethod, Priority(0)]