Skip to content

Commit 8a7caa9

Browse files
SONARPY-2467 Fix performance bottleneck of GlobalSymbolComputation due to DjangoViewsVisitor (#2246)
1 parent 9a9623b commit 8a7caa9

File tree

3 files changed

+15
-5
lines changed

3 files changed

+15
-5
lines changed

python-frontend/src/main/java/org/sonar/python/semantic/ProjectLevelSymbolTable.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.sonar.python.types.v2.FunctionType;
4747
import org.sonar.python.types.v2.PythonType;
4848
import org.sonar.python.types.v2.TriBool;
49+
import org.sonar.python.types.v2.TypeCheckBuilder;
4950
import org.sonar.python.types.v2.TypeChecker;
5051
import org.sonar.python.types.v2.UnknownType;
5152

@@ -223,11 +224,21 @@ public Collection<Symbol> stubFilesSymbols() {
223224
private class DjangoViewsVisitor extends BaseTreeVisitor {
224225

225226
String fullyQualifiedModuleName;
227+
private TypeCheckBuilder confPathCall = null;
228+
private TypeCheckBuilder pathCall = null;
226229

227230
public DjangoViewsVisitor(String fullyQualifiedModuleName) {
228231
this.fullyQualifiedModuleName = fullyQualifiedModuleName;
229232
}
230233

234+
@Override
235+
public void visitFileInput(FileInput fileInput) {
236+
TypeChecker typeChecker = new TypeChecker(new BasicTypeTable(new ProjectLevelTypeTable(ProjectLevelSymbolTable.this)));
237+
confPathCall = typeChecker.typeCheckBuilder().isTypeWithName("django.urls.conf.path");
238+
pathCall = typeChecker.typeCheckBuilder().isTypeWithName("django.urls.path");
239+
super.visitFileInput(fileInput);
240+
}
241+
231242
@Override
232243
public void visitCallExpression(CallExpression callExpression) {
233244
super.visitCallExpression(callExpression);
@@ -246,9 +257,8 @@ public void visitCallExpression(CallExpression callExpression) {
246257
}
247258

248259
private boolean isCallRegisteringDjangoView(CallExpression callExpression) {
249-
TypeChecker typeChecker = new TypeChecker(new BasicTypeTable(new ProjectLevelTypeTable(ProjectLevelSymbolTable.this)));
250-
TriBool isConfPathCall = typeChecker.typeCheckBuilder().isTypeWithName("django.urls.conf.path").check(callExpression.callee().typeV2());
251-
TriBool isPathCall = typeChecker.typeCheckBuilder().isTypeWithName("django.urls.path").check(callExpression.callee().typeV2());
260+
TriBool isConfPathCall = confPathCall.check(callExpression.callee().typeV2());
261+
TriBool isPathCall = pathCall.check(callExpression.callee().typeV2());
252262
return isConfPathCall.equals(TriBool.TRUE) || isPathCall.equals(TriBool.TRUE);
253263
}
254264
}

python-frontend/src/test/java/org/sonar/python/semantic/ProjectLevelSymbolTableTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ void importedStubModules() {
521521
""");
522522
ProjectLevelSymbolTable projectLevelSymbolTable = ProjectLevelSymbolTable.empty();
523523
projectLevelSymbolTable.addModule(tree, "my_package", pythonFile("mod.py"));
524-
assertThat(projectLevelSymbolTable.typeShedDescriptorsProvider().stubModules()).containsExactlyInAnyOrder("math", "os");
524+
assertThat(projectLevelSymbolTable.typeShedDescriptorsProvider().stubModules()).containsExactlyInAnyOrder("math", "os", "django", "django.urls.conf", "django.urls");
525525
}
526526

527527
@Test

sonar-python-plugin/src/test/java/org/sonar/plugins/python/PythonSensorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ void write_cpd_tokens_to_cache() throws IOException {
11131113

11141114
assertThat(writeCache.getData().keySet()).containsExactlyInAnyOrder(
11151115
"python:cache_version", "python:files", "python:descriptors:moduleKey:pass.py", "python:imports:moduleKey:pass.py",
1116-
"python:cpd:data:moduleKey:pass.py", "python:cpd:stringTable:moduleKey:pass.py", "python:content_hashes:moduleKey:pass.py");
1116+
"python:cpd:data:moduleKey:pass.py", "python:cpd:stringTable:moduleKey:pass.py", "python:content_hashes:moduleKey:pass.py", "python:typeshed_modules");
11171117

11181118
byte[] tokenData = writeCache.getData().get("python:cpd:data:moduleKey:pass.py");
11191119
byte[] stringTable = writeCache.getData().get("python:cpd:stringTable:moduleKey:pass.py");

0 commit comments

Comments
 (0)