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

Commit 57eb7d6

Browse files
author
Mikhail Arkhipov
authored
Process class member definitions in order (#1108)
1 parent f3ffe2c commit 57eb7d6

4 files changed

Lines changed: 40 additions & 31 deletions

File tree

src/Analysis/Ast/Impl/Analyzer/Symbols/ClassEvaluator.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,26 @@ private void ProcessClassBody() {
8686
foreach (var s in GetStatements<FromImportStatement>(_classDef)) {
8787
ImportHandler.HandleFromImport(s);
8888
}
89-
9089
foreach (var s in GetStatements<ImportStatement>(_classDef)) {
9190
ImportHandler.HandleImport(s);
9291
}
93-
9492
UpdateClassMembers();
9593

9694
// Process assignments so we get class variables declared.
97-
foreach (var s in GetStatements<AssignmentStatement>(_classDef)) {
98-
AssignmentHandler.HandleAssignment(s);
99-
}
100-
foreach (var s in GetStatements<ExpressionStatement>(_classDef)) {
101-
AssignmentHandler.HandleAnnotatedExpression(s.Expression as ExpressionWithAnnotation, null);
95+
// Note that annotated definitions and assignments can be intermixed
96+
// and must be processed in order. Consider
97+
// class A:
98+
// x: int
99+
// x = 1
100+
foreach (var s in GetStatements<Statement>(_classDef)) {
101+
switch (s) {
102+
case AssignmentStatement assignment:
103+
AssignmentHandler.HandleAssignment(assignment);
104+
break;
105+
case ExpressionStatement e:
106+
AssignmentHandler.HandleAnnotatedExpression(e.Expression as ExpressionWithAnnotation, null);
107+
break;
108+
}
102109
}
103110
UpdateClassMembers();
104111

src/Analysis/Ast/Impl/Definitions/IReferenceCollection.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/Analysis/Ast/Test/LintUndefinedVarsTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,17 @@ public async Task GlobalScope() {
611611
d[0].SourceSpan.Should().Be(2, 7, 2, 16);
612612
}
613613

614+
[TestMethod, Priority(0)]
615+
public async Task ClassMemberDefinition() {
616+
const string code = @"
617+
class A:
618+
i: int
619+
i = 0
620+
";
621+
var d = await LintAsync(code);
622+
d.Should().BeEmpty();
623+
}
624+
614625
private async Task<IReadOnlyList<DiagnosticsEntry>> LintAsync(string code, InterpreterConfiguration configuration = null) {
615626
var analysis = await GetAnalysisAsync(code, configuration ?? PythonVersions.LatestAvailable3X);
616627
var a = Services.GetService<IPythonAnalyzer>();

src/Analysis/Ast/Test/ReferencesTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,21 @@ def func(a: A):
269269
x.References[1].Span.Should().Be(6, 14, 6, 15);
270270
}
271271

272+
[TestMethod, Priority(0)]
273+
public async Task ClassFieldAnnotation() {
274+
const string code = @"
275+
class A:
276+
x: int
277+
x = 0
278+
";
279+
var analysis = await GetAnalysisAsync(code);
280+
var x = analysis.GlobalScope.Children[0].Should().HaveVariable("x").Which;
281+
x.Should().NotBeNull();
282+
x.References.Should().HaveCount(2);
283+
x.References[0].Span.Should().Be(3, 5, 3, 6);
284+
x.References[1].Span.Should().Be(4, 5, 4, 6);
285+
}
286+
272287
[TestMethod, Priority(0)]
273288
public async Task Assignments() {
274289
const string code = @"

0 commit comments

Comments
 (0)