Skip to content

Commit 14db014

Browse files
committed
move ast propagation to its own class
1 parent 037a304 commit 14db014

File tree

3 files changed

+76
-36
lines changed

3 files changed

+76
-36
lines changed

python-frontend/src/main/java/org/sonar/python/semantic/v2/TypeInferenceV2.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.sonar.plugins.python.api.tree.StatementList;
3535
import org.sonar.plugins.python.api.tree.Tree;
3636
import org.sonar.python.semantic.SymbolUtils;
37+
import org.sonar.python.semantic.v2.types.AstBasedPropagation;
3738
import org.sonar.python.semantic.v2.types.FlowSensitiveTypeInference;
3839
import org.sonar.python.semantic.v2.types.Propagation;
3940
import org.sonar.python.semantic.v2.types.PropagationVisitor;
@@ -122,7 +123,8 @@ private Map<SymbolV2, Set<PythonType>> inferTypesAndMemberAccessSymbols(Tree sco
122123
statements.accept(tryStatementVisitor);
123124
if (tryStatementVisitor.hasTryStatement()) {
124125
// CFG doesn't model precisely try-except statements. Hence we fallback to AST based type inference
125-
return propagationVisitor.processPropagations(getTrackedVars(declaredVariables, assignedNames));
126+
return new AstBasedPropagation(propagationVisitor.propagationsByLhs(), projectLevelTypeTable)
127+
.processPropagations(getTrackedVars(declaredVariables, assignedNames));
126128
}
127129

128130
ControlFlowGraph cfg = controlFlowGraphSupplier.get();
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* SonarQube Python Plugin
3+
* Copyright (C) 2011-2024 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.python.semantic.v2.types;
21+
22+
import java.util.HashSet;
23+
import java.util.Iterator;
24+
import java.util.Map;
25+
import java.util.Set;
26+
import java.util.stream.Collectors;
27+
import org.sonar.python.semantic.v2.SymbolV2;
28+
import org.sonar.python.semantic.v2.TypeTable;
29+
import org.sonar.python.types.v2.PythonType;
30+
31+
public class AstBasedPropagation {
32+
private final Map<SymbolV2, Set<Propagation>> propagationsByLhs;
33+
private final TypeTable typeTable;
34+
35+
public AstBasedPropagation(Map<SymbolV2, Set<Propagation>> propagationsByLhs, TypeTable typeTable) {
36+
this.propagationsByLhs = propagationsByLhs;
37+
this.typeTable = typeTable;
38+
}
39+
40+
public Map<SymbolV2, Set<PythonType>> processPropagations(Set<SymbolV2> trackedVars) {
41+
Set<Propagation> propagations = new HashSet<>();
42+
Set<SymbolV2> initializedVars = new HashSet<>();
43+
44+
propagationsByLhs.forEach((lhs, props) -> {
45+
if (trackedVars.contains(lhs)) {
46+
props.stream()
47+
.filter(Assignment.class::isInstance)
48+
.map(Assignment.class::cast)
49+
.forEach(a -> a.computeDependencies(trackedVars));
50+
propagations.addAll(props);
51+
}
52+
});
53+
54+
applyPropagations(propagations, initializedVars, true);
55+
applyPropagations(propagations, initializedVars, false);
56+
return propagations.stream().collect(Collectors.groupingBy(Propagation::lhsSymbol, Collectors.mapping(Propagation::rhsType, Collectors.toSet())));
57+
}
58+
59+
private static void applyPropagations(Set<Propagation> propagations, Set<SymbolV2> initializedVars, boolean checkDependenciesReadiness) {
60+
Set<Propagation> workSet = new HashSet<>(propagations);
61+
while (!workSet.isEmpty()) {
62+
Iterator<Propagation> iterator = workSet.iterator();
63+
Propagation propagation = iterator.next();
64+
iterator.remove();
65+
if (!checkDependenciesReadiness || propagation.areDependenciesReady(initializedVars)) {
66+
boolean learnt = propagation.propagate(initializedVars);
67+
if (learnt) {
68+
workSet.addAll(propagation.dependents());
69+
}
70+
}
71+
}
72+
}
73+
}

python-frontend/src/main/java/org/sonar/python/semantic/v2/types/PropagationVisitor.java

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@
1818

1919
import java.util.HashMap;
2020
import java.util.HashSet;
21-
import java.util.Iterator;
2221
import java.util.List;
2322
import java.util.Map;
2423
import java.util.Optional;
2524
import java.util.Set;
26-
import java.util.stream.Collectors;
2725
import org.sonar.plugins.python.api.tree.AliasedName;
2826
import org.sonar.plugins.python.api.tree.AnnotatedAssignment;
2927
import org.sonar.plugins.python.api.tree.AssignmentStatement;
@@ -40,7 +38,6 @@
4038
import org.sonar.plugins.python.api.tree.Statement;
4139
import org.sonar.python.semantic.v2.SymbolV2;
4240
import org.sonar.python.tree.NameImpl;
43-
import org.sonar.python.types.v2.PythonType;
4441

4542
public class PropagationVisitor extends BaseTreeVisitor {
4643
private final Map<SymbolV2, Set<Propagation>> propagationsByLhs;
@@ -200,37 +197,5 @@ private void processAssignment(Statement assignmentStatement, Expression lhsExpr
200197
}
201198
}
202199

203-
public Map<SymbolV2, Set<PythonType>> processPropagations(Set<SymbolV2> trackedVars) {
204-
Set<Propagation> propagations = new HashSet<>();
205-
Set<SymbolV2> initializedVars = new HashSet<>();
206200

207-
propagationsByLhs.forEach((lhs, props) -> {
208-
if (trackedVars.contains(lhs)) {
209-
props.stream()
210-
.filter(Assignment.class::isInstance)
211-
.map(Assignment.class::cast)
212-
.forEach(a -> a.computeDependencies(trackedVars));
213-
propagations.addAll(props);
214-
}
215-
});
216-
217-
applyPropagations(propagations, initializedVars, true);
218-
applyPropagations(propagations, initializedVars, false);
219-
return propagations.stream().collect(Collectors.groupingBy(Propagation::lhsSymbol, Collectors.mapping(Propagation::rhsType, Collectors.toSet())));
220-
}
221-
222-
private static void applyPropagations(Set<Propagation> propagations, Set<SymbolV2> initializedVars, boolean checkDependenciesReadiness) {
223-
Set<Propagation> workSet = new HashSet<>(propagations);
224-
while (!workSet.isEmpty()) {
225-
Iterator<Propagation> iterator = workSet.iterator();
226-
Propagation propagation = iterator.next();
227-
iterator.remove();
228-
if (!checkDependenciesReadiness || propagation.areDependenciesReady(initializedVars)) {
229-
boolean learnt = propagation.propagate(initializedVars);
230-
if (learnt) {
231-
workSet.addAll(propagation.dependents());
232-
}
233-
}
234-
}
235-
}
236201
}

0 commit comments

Comments
 (0)