Skip to content

Commit 696732f

Browse files
SONARPY-2185 Avoid converting return types from ProjectLevelSymbolTable to PythonType (#2042)
1 parent fec96ed commit 696732f

File tree

6 files changed

+28
-140
lines changed

6 files changed

+28
-140
lines changed

python-checks/src/test/java/org/sonar/python/checks/GenericExceptionRaisedCheckTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@
1919
*/
2020
package org.sonar.python.checks;
2121

22+
import java.util.List;
2223
import org.junit.jupiter.api.Test;
2324
import org.sonar.python.checks.utils.PythonCheckVerifier;
2425

2526
class GenericExceptionRaisedCheckTest {
2627

2728
@Test
2829
void test() {
29-
PythonCheckVerifier.verify("src/test/resources/checks/genericExceptionRaised.py", new GenericExceptionRaisedCheck());
30+
PythonCheckVerifier.verify("src/test/resources/checks/genericException/genericExceptionRaised.py", new GenericExceptionRaisedCheck());
31+
}
32+
33+
@Test
34+
void test_multiple_files() {
35+
PythonCheckVerifier.verify(
36+
List.of(
37+
"src/test/resources/checks/genericException/genericExceptionImported.py",
38+
"src/test/resources/checks/genericException/genericExceptionImporter.py"
39+
),
40+
new GenericExceptionRaisedCheck()
41+
);
3042
}
3143

3244
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class CustomException(Exception):
2+
...
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from genericExceptionImported import CustomException
2+
3+
def no_issue_on_method_annotated_with_Self_return_type():
4+
raise CustomException().with_traceback("foo")
5+
6+
7+
def issue():
8+
raise BaseException() # Noncompliant

python-checks/src/test/resources/checks/genericExceptionRaised.py renamed to python-checks/src/test/resources/checks/genericException/genericExceptionRaised.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,7 @@ def python2_multiple_expressions(cond):
4444
raise 42, BaseException
4545
else:
4646
raise BaseException, 42 # Noncompliant
47+
48+
49+
def no_issue_with_self_return_type():
50+
raise MyException().with_traceback("foo")

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

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,13 @@
3838
import org.sonar.python.semantic.FunctionSymbolImpl;
3939
import org.sonar.python.semantic.ProjectLevelSymbolTable;
4040
import org.sonar.python.semantic.v2.converter.AnyDescriptorToPythonTypeConverter;
41-
import org.sonar.python.types.InferredTypes;
42-
import org.sonar.python.types.protobuf.SymbolsProtos;
4341
import org.sonar.python.types.v2.ClassType;
4442
import org.sonar.python.types.v2.FunctionType;
4543
import org.sonar.python.types.v2.LazyTypeWrapper;
4644
import org.sonar.python.types.v2.Member;
4745
import org.sonar.python.types.v2.ModuleType;
48-
import org.sonar.python.types.v2.ObjectType;
4946
import org.sonar.python.types.v2.ParameterV2;
5047
import org.sonar.python.types.v2.PythonType;
51-
import org.sonar.python.types.v2.SimpleTypeWrapper;
5248
import org.sonar.python.types.v2.TypeOrigin;
5349
import org.sonar.python.types.v2.TypeWrapper;
5450
import org.sonar.python.types.v2.UnionType;
@@ -131,7 +127,7 @@ private PythonType convertToFunctionType(FunctionSymbol symbol, Map<Symbol, Pyth
131127
.map(this::convertParameter)
132128
.toList();
133129

134-
var returnType = getReturnTypeFromSymbol(symbol);
130+
var returnType = PythonType.UNKNOWN;
135131

136132
TypeOrigin typeOrigin = symbol.isStub() ? TypeOrigin.STUB : TypeOrigin.LOCAL;
137133

@@ -151,14 +147,6 @@ private PythonType convertToFunctionType(FunctionSymbol symbol, Map<Symbol, Pyth
151147
return functionType;
152148
}
153149

154-
private TypeWrapper getReturnTypeFromSymbol(FunctionSymbol symbol) {
155-
var returnTypeFqns = getReturnTypeFqn(symbol);
156-
var returnTypeList = returnTypeFqns.stream().map(lazyTypesContext::getOrCreateLazyTypeWrapper).map(ObjectType::new).toList();
157-
//TODO Support type unions (SONARPY-2132)
158-
var type = returnTypeList.size() == 1 ? returnTypeList.get(0) : PythonType.UNKNOWN;
159-
return new SimpleTypeWrapper(type);
160-
}
161-
162150
PythonType resolvePossibleLazyType(String fullyQualifiedName) {
163151
if (rootModule == null) {
164152
// If root module has not been created yet, return lazy type
@@ -243,59 +231,4 @@ private PythonType convertToType(Symbol symbol, Map<Symbol, PythonType> createdT
243231
case OTHER -> PythonType.UNKNOWN;
244232
};
245233
}
246-
247-
private List<String> getReturnTypeFqn(FunctionSymbol symbol) {
248-
List<String> fqnList = List.of();
249-
if (symbol.annotatedReturnTypeName() != null && !OBJECT_TYPE_FQN.equals(symbol.annotatedReturnTypeName())) {
250-
fqnList = List.of(symbol.annotatedReturnTypeName());
251-
} else if (symbol instanceof FunctionSymbolImpl functionSymbol && functionSymbol.protobufReturnType() != null) {
252-
var protoReturnType = functionSymbol.protobufReturnType();
253-
fqnList = getSymbolTypeFqn(protoReturnType);
254-
}
255-
return fqnList;
256-
}
257-
258-
List<String> getSymbolTypeFqn(SymbolsProtos.Type type) {
259-
if (OBJECT_TYPE_FQN.equals(type.getFullyQualifiedName())) {
260-
return List.of();
261-
}
262-
switch (type.getKind()) {
263-
case INSTANCE:
264-
String typeName = type.getFullyQualifiedName();
265-
// _SpecialForm is the type used for some special types, like Callable, Union, TypeVar, ...
266-
// It comes from CPython impl: https://github.com/python/cpython/blob/e39ae6bef2c357a88e232dcab2e4b4c0f367544b/Lib/typing.py#L439
267-
// This doesn't seem to be very precisely specified in typeshed, because it has special semantic.
268-
// To avoid FPs, we treat it as ANY
269-
if ("typing._SpecialForm".equals(typeName)) {
270-
return List.of();
271-
}
272-
typeName = typeName.replaceFirst("^builtins\\.", "");
273-
return typeName.isEmpty() ? List.of() : List.of(typeName);
274-
case TYPE:
275-
return List.of("type");
276-
case TYPE_ALIAS:
277-
return getSymbolTypeFqn(type.getArgs(0));
278-
case CALLABLE:
279-
// this should be handled as a function type - see SONARPY-953
280-
// Creates FPs with `sys.gettrace`
281-
return List.of();
282-
case UNION:
283-
return type.getArgsList().stream().map(this::getSymbolTypeFqn).flatMap(Collection::stream).toList();
284-
case TUPLE:
285-
return List.of("tuple");
286-
case NONE:
287-
return List.of("NoneType");
288-
case TYPED_DICT:
289-
return List.of("dict");
290-
case TYPE_VAR:
291-
return Optional.of(type)
292-
.filter(InferredTypes::filterTypeVar)
293-
.map(SymbolsProtos.Type::getFullyQualifiedName)
294-
.map(List::of)
295-
.orElseGet(List::of);
296-
default:
297-
return List.of();
298-
}
299-
}
300-
301234
}

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

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

0 commit comments

Comments
 (0)