Skip to content

Commit 5f3b936

Browse files
SONARPY-963 Custom stubs should have priority over protobuf generated symbols. Ambigous Symbols of all classes should be disambiguated (#1044)
1 parent e1aa0ec commit 5f3b936

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

python-frontend/src/main/java/org/sonar/python/types/TypeShed.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,16 +198,16 @@ private static Set<Symbol> searchTypeShedForModule(String moduleName) {
198198
return new HashSet<>();
199199
}
200200
modulesInProgress.add(moduleName);
201-
Collection<Symbol> symbolsFromProtobuf = getSymbolsFromProtobufModule(moduleName).values();
202-
if (!symbolsFromProtobuf.isEmpty()) {
203-
modulesInProgress.remove(moduleName);
204-
return new HashSet<>(symbolsFromProtobuf);
205-
}
206201
Set<Symbol> customSymbols = new HashSet<>(getModuleSymbols(moduleName, CUSTOM_THIRD_PARTY, builtinGlobalSymbols).values());
207202
if (!customSymbols.isEmpty()) {
208203
modulesInProgress.remove(moduleName);
209204
return customSymbols;
210205
}
206+
Collection<Symbol> symbolsFromProtobuf = getSymbolsFromProtobufModule(moduleName).values();
207+
if (!symbolsFromProtobuf.isEmpty()) {
208+
modulesInProgress.remove(moduleName);
209+
return new HashSet<>(symbolsFromProtobuf);
210+
}
211211
Set<Symbol> thirdPartySymbols = new HashSet<>(getModuleSymbols(moduleName, THIRD_PARTY_2AND3, builtinGlobalSymbols).values());
212212
if (thirdPartySymbols.isEmpty()) {
213213
thirdPartySymbols = commonSymbols(getModuleSymbols(moduleName, THIRD_PARTY_2, builtinGlobalSymbols),
@@ -283,12 +283,28 @@ private static Symbol disambiguateWithLatestPythonSymbol(Set<Symbol> alternative
283283
return latestPythonSymbol;
284284
}
285285

286+
287+
/**
288+
* Returns stub symbols to be used by SonarSecurity.
289+
* Ambiguous symbols that only contain class symbols are disambiguated with latest Python version.
290+
*/
286291
public static Collection<Symbol> stubFilesSymbols() {
287292
Set<Symbol> symbols = new HashSet<>(TypeShed.builtinSymbols().values());
288-
typeShedSymbols.values().forEach(symbolsByFqn -> symbols.addAll(symbolsByFqn.values()));
293+
for (Map<String, Symbol> symbolsByFqn : typeShedSymbols.values()) {
294+
for (Symbol symbol : symbolsByFqn.values()) {
295+
symbols.add(isAmbiguousSymbolOfClasses(symbol) ? disambiguateWithLatestPythonSymbol(((AmbiguousSymbol) symbol).alternatives()) : symbol);
296+
}
297+
}
289298
return symbols;
290299
}
291300

301+
private static boolean isAmbiguousSymbolOfClasses(Symbol symbol) {
302+
if (symbol.is(Symbol.Kind.AMBIGUOUS)) {
303+
return ((AmbiguousSymbol) symbol).alternatives().stream().allMatch(s -> s.is(Symbol.Kind.CLASS));
304+
}
305+
return false;
306+
}
307+
292308
static class ReturnTypeVisitor extends BaseTreeVisitor {
293309

294310
@Override

python-frontend/src/test/java/org/sonar/python/types/TypeShedTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,4 +488,12 @@ public void variables_from_protobuf() throws TextFormat.ParseException {
488488
assertThat(symbols.values()).extracting(Symbol::kind, Symbol::fullyQualifiedName, Symbol::annotatedTypeName)
489489
.containsExactlyInAnyOrder(tuple(Kind.OTHER, "mod.foo", "str"), tuple(Kind.OTHER, "mod.bar", null));
490490
}
491+
492+
@Test
493+
public void stubFilesSymbols_should_not_contain_ambiguous_symbols_of_classes() {
494+
// populate typeshed symbols cache by importing socket module
495+
symbolsForModule("socket");
496+
Collection<Symbol> symbols = TypeShed.stubFilesSymbols();
497+
assertThat(symbols).noneMatch(s -> s.is(Kind.AMBIGUOUS) && ((AmbiguousSymbol) s).alternatives().stream().allMatch(a -> a.is(Kind.CLASS)));
498+
}
491499
}

0 commit comments

Comments
 (0)