Skip to content

Commit 73f9603

Browse files
committed
SONARPY-2332 implement ast based propagation of unary expressions
add stuff to trivial type propagation visistor
1 parent ba1efec commit 73f9603

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ private void applyPropagations(Set<Propagation> propagations, Set<SymbolV2> init
9595
}
9696
}
9797

98+
9899
private record Propagator(TypeTable typeTable) {
100+
99101
/**
100102
* @return true if the propagation effectively changed the inferred type of assignment LHS
101103
*/
@@ -125,6 +127,13 @@ private void propagateTypeToUsages(Propagation propagation, PythonType newType)
125127
// Avoid propagation to usages in nested scopes, as this may lead to FPs
126128
.filter(n -> isInSameScope(propagation, n, scopeTree))
127129
.forEach(n -> n.typeV2(newType));
130+
131+
updateTree(propagation);
132+
}
133+
134+
private void updateTree(Propagation propagation) {
135+
Tree scopeTree = propagation.scopeTree(propagation.lhsName());
136+
scopeTree.accept(new TrivialTypePropagationVisitor(typeTable));
128137
}
129138

130139
@CheckForNull

python-frontend/src/main/java/org/sonar/python/tree/UnaryExpressionImpl.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@
2727
import org.sonar.plugins.python.api.tree.TreeVisitor;
2828
import org.sonar.plugins.python.api.tree.UnaryExpression;
2929
import org.sonar.plugins.python.api.types.InferredType;
30+
import org.sonar.python.types.HasTypeDependencies;
3031
import org.sonar.python.types.InferredTypes;
3132
import org.sonar.python.types.v2.PythonType;
3233

33-
public class UnaryExpressionImpl extends PyTree implements UnaryExpression {
34+
public class UnaryExpressionImpl extends PyTree implements UnaryExpression, HasTypeDependencies {
3435

3536
private static final Map<String, Kind> KINDS_BY_OPERATOR = kindsByOperator();
3637

@@ -99,4 +100,9 @@ public UnaryExpression typeV2(PythonType type) {
99100
public PythonType typeV2() {
100101
return type;
101102
}
103+
104+
@Override
105+
public List<Expression> typeDependencies() {
106+
return List.of(expression);
107+
}
102108
}

python-frontend/src/test/java/org/sonar/python/semantic/v2/TypeInferenceV2Test.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2610,6 +2610,18 @@ static Stream<Arguments> unary_expression_of_variables() {
26102610
Arguments.of("x = True; ~x", INT_TYPE),
26112611
Arguments.of("x = True; not x", BOOL_TYPE),
26122612
Arguments.of("x = 1; not x", BOOL_TYPE),
2613+
Arguments.of("x = 1; y = -x; -y", INT_TYPE),
2614+
Arguments.of("x = 1; x = 1; y = -x; -y", INT_TYPE),
2615+
Arguments.of("x = 1; y = 1; y = -x; -y", INT_TYPE),
2616+
2617+
Arguments.of("""
2618+
if someCond:
2619+
x = 1
2620+
else:
2621+
x = True
2622+
y = x
2623+
-y
2624+
""", INT_TYPE),
26132625

26142626
Arguments.of("x = 1; -(x + 1)", INT_TYPE)
26152627
);
@@ -2618,10 +2630,20 @@ static Stream<Arguments> unary_expression_of_variables() {
26182630
@ParameterizedTest
26192631
@MethodSource("unary_expression_of_variables")
26202632
void unary_expression_of_variables(String code, PythonType expectedType) {
2621-
assertThat(lastExpression(code)).extracting(expr -> expr.typeV2().unwrappedType()).isEqualTo(expectedType);
2633+
assertThat(lastExpression(code).typeV2()).isInstanceOf(ObjectType.class).extracting(PythonType::unwrappedType).isEqualTo(expectedType);
26222634
}
26232635

26242636

2637+
@ParameterizedTest
2638+
@MethodSource("unary_expression_of_variables")
2639+
void unary_expression_of_variables_with_try_except(String code, PythonType expectedType) {
2640+
var codeWithTryCatch = """
2641+
try: pass
2642+
except: pass
2643+
""" + code;
2644+
assertThat(lastExpression(codeWithTryCatch)).extracting(expr -> expr.typeV2().unwrappedType()).isEqualTo(expectedType);
2645+
}
2646+
26252647
@Test
26262648
void imported_ambiguous_symbol() {
26272649
FileInput fileInput = inferTypes("""

0 commit comments

Comments
 (0)