Skip to content

Commit ab90a7d

Browse files
Make sure ambiguous symbols are always flattened (#951)
1 parent abbcb92 commit ab90a7d

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,20 @@ public static AmbiguousSymbol create(Set<Symbol> symbols) {
5555
if (!symbols.stream().map(Symbol::fullyQualifiedName).allMatch(fqn -> Objects.equals(firstSymbol.fullyQualifiedName(), fqn))) {
5656
return new AmbiguousSymbolImpl(resultingSymbolName, null, symbols);
5757
}
58-
return new AmbiguousSymbolImpl(resultingSymbolName, firstSymbol.fullyQualifiedName(), symbols);
58+
return new AmbiguousSymbolImpl(resultingSymbolName, firstSymbol.fullyQualifiedName(), flattenAmbiguousSymbols(symbols));
59+
}
60+
61+
private static Set<Symbol> flattenAmbiguousSymbols(Set<Symbol> symbols) {
62+
Set<Symbol> alternatives = new HashSet<>();
63+
for (Symbol symbol : symbols) {
64+
if (symbol.is(Kind.AMBIGUOUS)) {
65+
Set<Symbol> flattenedAlternatives = flattenAmbiguousSymbols(((AmbiguousSymbol) symbol).alternatives());
66+
alternatives.addAll(flattenedAlternatives);
67+
} else {
68+
alternatives.add(symbol);
69+
}
70+
}
71+
return alternatives;
5972
}
6073

6174
public static AmbiguousSymbol create(Symbol... symbols) {

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,17 @@ private Map<String, Symbol> symbols(String... code) {
188188
FileInput fileInput = parse(new SymbolTableBuilder("", PythonTestUtils.pythonFile("foo")), code);
189189
return fileInput.globalVariables().stream().collect(Collectors.toMap(Symbol::name, Function.identity()));
190190
}
191+
192+
@Test
193+
public void nested_ambiguous_symbols_should_be_flattened() {
194+
SymbolImpl foo1 = new SymbolImpl("foo", "mod.foo");
195+
ClassSymbolImpl classSymbol1 = new ClassSymbolImpl("foo", "mod.foo");
196+
AmbiguousSymbol ambiguousSymbol1 = AmbiguousSymbolImpl.create(foo1, classSymbol1);
197+
SymbolImpl foo2 = new SymbolImpl("foo", "mod.foo");
198+
ClassSymbolImpl classSymbol2 = new ClassSymbolImpl("foo", "mod.foo");
199+
AmbiguousSymbol ambiguousSymbol2 = AmbiguousSymbolImpl.create(foo2, classSymbol2);
200+
AmbiguousSymbol ambiguousSymbol = AmbiguousSymbolImpl.create(ambiguousSymbol1, ambiguousSymbol2);
201+
assertThat(ambiguousSymbol.alternatives()).noneMatch(s -> s.is(Symbol.Kind.AMBIGUOUS));
202+
assertThat(ambiguousSymbol.alternatives()).containsExactlyInAnyOrder(foo1, foo2, classSymbol1, classSymbol2);
203+
}
191204
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,10 +404,9 @@ public void overloaded_functions() {
404404
assertThat(map.is(Kind.AMBIGUOUS)).isTrue();
405405
assertThat(((SymbolImpl) map).validForPythonVersions()).containsExactlyInAnyOrder("27", "35", "36", "37", "38", "39");
406406
ClassSymbol python3Symbol = (ClassSymbol) ((AmbiguousSymbol) map).alternatives().stream().filter(s -> s.is(Kind.CLASS)).findFirst().get();
407-
AmbiguousSymbol python2Symbol = (AmbiguousSymbol) ((AmbiguousSymbol) map).alternatives().stream().filter(s -> s.is(Kind.AMBIGUOUS)).findFirst().get();
408407
assertThat(((ClassSymbolImpl) python3Symbol).validForPythonVersions()).containsExactlyInAnyOrder("35", "36", "37", "38", "39");
409-
assertThat(((AmbiguousSymbolImpl) python2Symbol).validForPythonVersions()).containsExactly("27");
410-
for (Symbol alternative : python2Symbol.alternatives()) {
408+
Set<Symbol> python2Symbols = ((AmbiguousSymbol) map).alternatives().stream().filter(s -> s.is(Kind.FUNCTION)).collect(Collectors.toSet());
409+
for (Symbol alternative : python2Symbols) {
411410
assertThat(alternative.is(Kind.FUNCTION)).isTrue();
412411
assertThat(((FunctionSymbolImpl) alternative).validForPythonVersions()).containsExactly("27");
413412
}

0 commit comments

Comments
 (0)