Skip to content

Commit c33934a

Browse files
ghislainpiotguillaume-dequenne
authored andcommitted
SONARPY-2161 Replace v2 TypeShed with TypeShedDescriptorsProvider
1 parent 9e2dfed commit c33934a

File tree

15 files changed

+55
-50
lines changed

15 files changed

+55
-50
lines changed

its/ruling/src/test/resources/expected/python-S3699.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,5 @@
1515
],
1616
"project:tensorflow/tools/pip_package/setup.py": [
1717
141
18-
],
19-
"project:twisted-12.1.0/twisted/trial/test/test_script.py": [
20-
407,
21-
417
2218
]
2319
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"project:mypy-0.782/mypy/suggestions.py": [
3+
65
4+
]
5+
}

its/ruling/src/test/resources/expected_extended/salt/python-S3699.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
"salt:salt/cloud/clouds/linode.py": [
33
1814
44
],
5-
"salt:salt/ext/tornado/test/util.py": [
6-
113
7-
],
85
"salt:salt/utils/http.py": [
96
453
107
]

python-checks/src/test/java/org/sonar/python/checks/quickfix/PythonQuickFixVerifier.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import org.sonar.python.caching.CacheContextImpl;
4040
import org.sonar.python.parser.PythonParser;
4141
import org.sonar.python.semantic.ProjectLevelSymbolTable;
42-
import org.sonar.python.semantic.v2.TypeShed;
4342
import org.sonar.python.tree.IPythonTreeMaker;
4443
import org.sonar.python.tree.PythonTreeMaker;
4544

@@ -161,7 +160,7 @@ private static PythonVisitorContext createVisitorContext(PythonParser parser, Py
161160

162161
return new PythonVisitorContext(fileInput,
163162
pythonFile, null, "",
164-
ProjectLevelSymbolTable.empty(), new TypeShed(ProjectLevelSymbolTable.empty()), CacheContextImpl.dummyCache(), SonarProduct.SONARLINT);
163+
ProjectLevelSymbolTable.empty(), CacheContextImpl.dummyCache(), SonarProduct.SONARLINT);
165164
}
166165

167166
private static String applyQuickFix(String codeWithIssue, PythonQuickFix quickFix) {

python-checks/src/test/resources/checks/nonCallableCalled.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,10 @@ def no_fp_on_decorated_classes():
381381
unknown_decorated_class() # OK
382382
employee = Employee("John Doe", 30, "Software Engineer")
383383
employee() # FN
384+
385+
386+
def fp_typed_dict():
387+
from typing_extensions import TypedDict
388+
# TypedDict is defined as "TypedDict: object" in typing_extensions.pyi
389+
# Despite actually being a function
390+
x = TypedDict('x', {'a': int, 'b': str}) # Noncompliant

python-frontend/src/main/java/org/sonar/plugins/python/api/PythonVisitorContext.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import org.sonar.python.semantic.v2.ProjectLevelTypeTable;
3636
import org.sonar.python.semantic.v2.SymbolTableBuilderV2;
3737
import org.sonar.python.semantic.v2.TypeInferenceV2;
38-
import org.sonar.python.semantic.v2.TypeShed;
3938

4039
public class PythonVisitorContext extends PythonInputFileContext {
4140

@@ -51,7 +50,7 @@ public PythonVisitorContext(FileInput rootTree, PythonFile pythonFile, @Nullable
5150
SymbolTableBuilder symbolTableBuilder = packageName != null ? new SymbolTableBuilder(packageName, pythonFile) : new SymbolTableBuilder(pythonFile);
5251
symbolTableBuilder.visitFileInput(rootTree);
5352
var symbolTable = new SymbolTableBuilderV2(rootTree).build();
54-
var projectLevelTypeTable = new ProjectLevelTypeTable(ProjectLevelSymbolTable.empty(), new TypeShed(ProjectLevelSymbolTable.empty()));
53+
var projectLevelTypeTable = new ProjectLevelTypeTable(ProjectLevelSymbolTable.empty());
5554
new TypeInferenceV2(projectLevelTypeTable, pythonFile, symbolTable).inferTypes(rootTree);
5655
this.typeChecker = new TypeChecker(projectLevelTypeTable);
5756
}
@@ -65,20 +64,20 @@ public PythonVisitorContext(FileInput rootTree, PythonFile pythonFile, @Nullable
6564

6665
var symbolTable = new SymbolTableBuilderV2(rootTree)
6766
.build();
68-
var projectLevelTypeTable = new ProjectLevelTypeTable(projectLevelSymbolTable, new TypeShed(projectLevelSymbolTable));
67+
var projectLevelTypeTable = new ProjectLevelTypeTable(projectLevelSymbolTable);
6968
new TypeInferenceV2(projectLevelTypeTable, pythonFile, symbolTable).inferTypes(rootTree);
7069
this.typeChecker = new TypeChecker(projectLevelTypeTable);
7170
}
7271

7372
public PythonVisitorContext(FileInput rootTree, PythonFile pythonFile, @Nullable File workingDirectory, String packageName,
74-
ProjectLevelSymbolTable projectLevelSymbolTable, TypeShed typeShed, CacheContext cacheContext, SonarProduct sonarProduct) {
73+
ProjectLevelSymbolTable projectLevelSymbolTable, CacheContext cacheContext, SonarProduct sonarProduct) {
7574
super(pythonFile, workingDirectory, cacheContext, sonarProduct);
7675
this.rootTree = rootTree;
7776
this.parsingException = null;
7877
new SymbolTableBuilder(packageName, pythonFile, projectLevelSymbolTable).visitFileInput(rootTree);
7978
var symbolTable = new SymbolTableBuilderV2(rootTree)
8079
.build();
81-
var projectLevelTypeTable = new ProjectLevelTypeTable(projectLevelSymbolTable, typeShed);
80+
var projectLevelTypeTable = new ProjectLevelTypeTable(projectLevelSymbolTable);
8281
new TypeInferenceV2(projectLevelTypeTable, pythonFile, symbolTable).inferTypes(rootTree);
8382
this.typeChecker = new TypeChecker(projectLevelTypeTable);
8483
}

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,9 @@ public class ProjectLevelTypeTable {
4343
))
4444
);
4545

46-
4746
public ProjectLevelTypeTable(ProjectLevelSymbolTable projectLevelSymbolTable) {
48-
this(projectLevelSymbolTable, new TypeShed(projectLevelSymbolTable));
49-
}
50-
51-
public ProjectLevelTypeTable(ProjectLevelSymbolTable projectLevelSymbolTable, TypeShed typeShed) {
5247
this.lazyTypesContext = new LazyTypesContext(this);
53-
this.symbolsModuleTypeProvider = new SymbolsModuleTypeProvider(projectLevelSymbolTable, typeShed, lazyTypesContext);
48+
this.symbolsModuleTypeProvider = new SymbolsModuleTypeProvider(projectLevelSymbolTable, lazyTypesContext);
5449
this.rootModule = this.symbolsModuleTypeProvider.createBuiltinModule();
5550
}
5651

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.util.Optional;
2929
import java.util.Set;
3030
import java.util.function.Function;
31-
import java.util.function.Predicate;
3231
import java.util.stream.Collectors;
3332
import javax.annotation.Nullable;
3433
import org.sonar.plugins.python.api.symbols.AmbiguousSymbol;
@@ -38,6 +37,8 @@
3837
import org.sonar.python.semantic.ClassSymbolImpl;
3938
import org.sonar.python.semantic.FunctionSymbolImpl;
4039
import org.sonar.python.semantic.ProjectLevelSymbolTable;
40+
import org.sonar.python.semantic.v2.converter.AnyDescriptorToPythonTypeConverter;
41+
import org.sonar.python.semantic.v2.typeshed.TypeShedDescriptorsProvider;
4142
import org.sonar.python.types.InferredTypes;
4243
import org.sonar.python.types.protobuf.SymbolsProtos;
4344
import org.sonar.python.types.v2.ClassType;
@@ -56,15 +57,22 @@
5657
public class SymbolsModuleTypeProvider {
5758
public static final String OBJECT_TYPE_FQN = "object";
5859
private final ProjectLevelSymbolTable projectLevelSymbolTable;
59-
private final TypeShed typeShed;
60-
private ModuleType rootModule;
61-
private LazyTypesContext lazyTypesContext;
60+
private final ModuleType rootModule;
61+
private final LazyTypesContext lazyTypesContext;
62+
private final TypeShedDescriptorsProvider typeShedDescriptorsProvider;
63+
private final AnyDescriptorToPythonTypeConverter anyDescriptorToPythonTypeConverter;
6264

63-
public SymbolsModuleTypeProvider(ProjectLevelSymbolTable projectLevelSymbolTable, TypeShed typeShed, LazyTypesContext lazyTypeContext) {
65+
public SymbolsModuleTypeProvider(ProjectLevelSymbolTable projectLevelSymbolTable, LazyTypesContext lazyTypeContext) {
6466
this.projectLevelSymbolTable = projectLevelSymbolTable;
65-
this.typeShed = typeShed;
6667
this.lazyTypesContext = lazyTypeContext;
67-
this.rootModule = createModuleFromSymbols(null, null, typeShed.builtinSymbols().values());
68+
this.typeShedDescriptorsProvider = new TypeShedDescriptorsProvider(projectLevelSymbolTable.projectBasePackages());
69+
this.anyDescriptorToPythonTypeConverter = new AnyDescriptorToPythonTypeConverter(lazyTypesContext);
70+
71+
var rootModuleMembers = typeShedDescriptorsProvider.builtinDescriptors()
72+
.entrySet()
73+
.stream()
74+
.collect(Collectors.toMap(Map.Entry::getKey, e -> anyDescriptorToPythonTypeConverter.convert(e.getValue())));
75+
this.rootModule = new ModuleType(null, null, rootModuleMembers);
6876
}
6977

7078
public ModuleType createBuiltinModule() {
@@ -92,9 +100,11 @@ private Optional<ModuleType> createModuleTypeFromProjectLevelSymbolTable(String
92100
}
93101

94102
private Optional<ModuleType> createModuleTypeFromTypeShed(String moduleName, String moduleFqn, ModuleType parent) {
95-
return Optional.ofNullable(typeShed.symbolsForModule(moduleFqn))
96-
.filter(Predicate.not(Map::isEmpty))
97-
.map(typeShedModuleSymbols -> createModuleFromSymbols(moduleName, parent, typeShedModuleSymbols.values()));
103+
var moduleMembers = typeShedDescriptorsProvider.descriptorsForModule(moduleFqn)
104+
.entrySet().stream()
105+
.collect(Collectors.toMap(Map.Entry::getKey, e -> anyDescriptorToPythonTypeConverter.convert(e.getValue())));
106+
return Optional.of(moduleMembers).filter(m -> !m.isEmpty())
107+
.map(m -> new ModuleType(moduleName, parent, m));
98108
}
99109

100110
private ModuleType createModuleFromSymbols(@Nullable String name, @Nullable ModuleType parent, Collection<Symbol> symbols) {

python-frontend/src/test/java/org/sonar/plugins/python/api/PythonVisitorContextTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ void sonar_product() {
102102
PythonFile pythonFile = pythonFile("my_module.py");
103103
FileInput fileInput = mock(FileInputImpl.class);
104104

105-
PythonVisitorContext pythonVisitorContext = new PythonVisitorContext(fileInput, pythonFile, workingDirectory, myPackage, projectLevelSymbolTable, typeShed, cacheContext, SonarProduct.SONARLINT);
105+
PythonVisitorContext pythonVisitorContext = new PythonVisitorContext(fileInput, pythonFile, workingDirectory, myPackage, projectLevelSymbolTable, cacheContext, SonarProduct.SONARLINT);
106106
assertThat(pythonVisitorContext.sonarProduct()).isEqualTo(SonarProduct.SONARLINT);
107107

108-
pythonVisitorContext = new PythonVisitorContext(fileInput, pythonFile, workingDirectory, myPackage, projectLevelSymbolTable, typeShed, cacheContext, SonarProduct.SONARQUBE);
108+
pythonVisitorContext = new PythonVisitorContext(fileInput, pythonFile, workingDirectory, myPackage, projectLevelSymbolTable, cacheContext, SonarProduct.SONARQUBE);
109109
assertThat(pythonVisitorContext.sonarProduct()).isEqualTo(SonarProduct.SONARQUBE);
110110

111111
pythonVisitorContext = new PythonVisitorContext(fileInput, pythonFile, workingDirectory, myPackage, projectLevelSymbolTable, cacheContext);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class ProjectLevelTypeTableTest {
3232
@Test
3333
void getBuiltinTypeTest() {
3434
var symbolTable = ProjectLevelSymbolTable.empty();
35-
var table = new ProjectLevelTypeTable(symbolTable, new TypeShed(symbolTable));
35+
var table = new ProjectLevelTypeTable(symbolTable);
3636

3737
var listClassType = table.getType("list");
3838
Assertions.assertThat(listClassType).isNotNull().isInstanceOf(ClassType.class);
@@ -47,7 +47,7 @@ void getBuiltinTypeTest() {
4747
@Test
4848
void getTypeshedTypeTest() {
4949
var symbolTable = ProjectLevelSymbolTable.empty();
50-
var table = new ProjectLevelTypeTable(symbolTable, new TypeShed(symbolTable));
50+
var table = new ProjectLevelTypeTable(symbolTable);
5151

5252
var generatorClassType = table.getType("typing.Generator");
5353
Assertions.assertThat(generatorClassType).isNotNull().isInstanceOf(ClassType.class);
@@ -60,7 +60,7 @@ void getTypeshedTypeTest() {
6060
@Test
6161
void updateTypeTableDuringGetTypeTest() {
6262
var symbolTable = ProjectLevelSymbolTable.empty();
63-
var table = new ProjectLevelTypeTable(symbolTable, new TypeShed(symbolTable));
63+
var table = new ProjectLevelTypeTable(symbolTable);
6464

6565
var rootModuleType = table.getType();
6666
Assertions.assertThat(rootModuleType.hasMember("typing")).isNotEqualTo(TriBool.TRUE);

0 commit comments

Comments
 (0)