Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit 08b5971

Browse files
author
MikhailArkhipov
committed
Fix walk of multi-level if statement
1 parent 8fdf769 commit 08b5971

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

src/Analysis/Ast/Impl/Extensions/PythonWalkerExtensions.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,42 @@ namespace Microsoft.Python.Analysis {
2020
public static class PythonWalkerExtensions {
2121
public static bool WalkIfWithSystemConditions(this IfStatement node, PythonWalker walker, PythonLanguageVersion languageVersion, bool isWindows) {
2222
// System version, platform and os.path specializations
23-
var someRecognized = false;
23+
var executeElse = false;
2424
foreach (var test in node.Tests) {
25+
2526
var result = test.TryHandleSysVersionInfo(languageVersion);
26-
if (result != ConditionTestResult.Unrecognized) {
27-
if (result == ConditionTestResult.WalkBody) {
28-
test.Walk(walker);
29-
} else {
30-
node.ElseStatement?.Walk(walker);
27+
if (result == ConditionTestResult.Unrecognized) {
28+
result = test.TryHandleSysPlatform(isWindows);
29+
if (result == ConditionTestResult.Unrecognized) {
30+
result = test.TryHandleOsPath(isWindows);
3131
}
32-
someRecognized = true;
33-
continue;
3432
}
3533

36-
result = test.TryHandleSysPlatform(isWindows);
37-
if (result != ConditionTestResult.Unrecognized) {
38-
if (result == ConditionTestResult.WalkBody) {
34+
// If condition is satisfied, walk the corresponding block and
35+
// return false indicating that statement should not be walked again.
36+
// If condition is false or was not recognized, continue but remember
37+
// if we need to execute final else clause.
38+
switch (result) {
39+
case ConditionTestResult.WalkBody:
3940
test.Walk(walker);
40-
} else {
41-
node.ElseStatement?.Walk(walker);
42-
}
43-
someRecognized = true;
44-
continue;
41+
return false; // We only need to execute one of the clauses.
42+
case ConditionTestResult.DontWalkBody:
43+
// If condition is false, continue but remember
44+
// if we may need to execute the final else clause.
45+
executeElse = true;
46+
break;
47+
case ConditionTestResult.Unrecognized:
48+
continue; // See if other conditions may work.
4549
}
50+
}
4651

47-
result = test.TryHandleOsPath(isWindows);
48-
if (result != ConditionTestResult.Unrecognized) {
49-
if (result == ConditionTestResult.WalkBody) {
50-
test.Walk(walker);
51-
} else {
52-
node.ElseStatement?.Walk(walker);
53-
}
54-
return false; // Execute only one condition.
55-
}
52+
if (executeElse) {
53+
node.ElseStatement?.Walk(walker);
54+
return false;
5655
}
57-
return !someRecognized;
56+
57+
// We didn't walk anything, so me caller do their own thing.
58+
return true;
5859
}
5960
}
6061
}

src/Analysis/Ast/Test/ConditionalsTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@ def func(a, b): ...
152152
.Which.Should().HaveParameters(is3x ? new[] { "a" } : new[] { "a", "b" });
153153
}
154154

155+
[DataRow(false)]
156+
[DataRow(true)]
157+
[DataTestMethod, Priority(0)]
158+
public async Task FunctionByVersionElif(bool is3x) {
159+
const string code = @"
160+
if sys.version_info >= (3, 0):
161+
def func(a): ...
162+
elif sys.version_info < (3, 0):
163+
def func(a, b): ...
164+
";
165+
var analysis = await GetAnalysisAsync(code, is3x ? PythonVersions.LatestAvailable3X : PythonVersions.LatestAvailable2X);
166+
analysis.Should().HaveFunction("func")
167+
.Which.Should().HaveSingleOverload()
168+
.Which.Should().HaveParameters(is3x ? new[] { "a" } : new[] { "a", "b" });
169+
}
170+
155171
private IOSPlatform SubstitutePlatform(out IServiceManager sm) {
156172
sm = new ServiceManager();
157173
var platform = Substitute.For<IOSPlatform>();

0 commit comments

Comments
 (0)