From a48d415bcf7d61f7b634a5d661140bf4952982bc Mon Sep 17 00:00:00 2001 From: Maksim Grebeniuk <122789225+maksim-grebeniuk-sonarsource@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:03:43 +0200 Subject: [PATCH] SONARPY-2256 Resolve fully qualified names for class members descriptors (#2104) --- .../PythonTypeToDescriptorConverter.java | 41 +++++++++++-------- .../PythonTypeToDescriptorConverterTest.java | 3 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverter.java b/python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverter.java index c760747771..d14bb8c2f4 100644 --- a/python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverter.java +++ b/python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverter.java @@ -42,7 +42,7 @@ public class PythonTypeToDescriptorConverter { public Descriptor convert(String moduleFqn, SymbolV2 symbol, Set types) { var candidates = types.stream() - .map(type -> convert(moduleFqn, symbol.name(), type)) + .map(type -> convert(moduleFqn, moduleFqn, symbol.name(), type)) .flatMap(candidate -> { if (candidate instanceof AmbiguousDescriptor ambiguousDescriptor) { return ambiguousDescriptor.alternatives().stream(); @@ -59,30 +59,30 @@ public Descriptor convert(String moduleFqn, SymbolV2 symbol, Set typ return new AmbiguousDescriptor(symbol.name(), symbolFqn(moduleFqn, symbol.name()), candidates); } - private Descriptor convert(String moduleFqn, String symbolName, PythonType type) { + private Descriptor convert(String moduleFqn, String parentFqn, String symbolName, PythonType type) { if (type instanceof FunctionType functionType) { - return convert(moduleFqn, symbolName, functionType); + return convert(moduleFqn, parentFqn, symbolName, functionType); } if (type instanceof ClassType classType) { - return convert(moduleFqn, symbolName, classType); + return convert(moduleFqn, parentFqn, symbolName, classType); } if (type instanceof UnionType unionType) { - return convert(moduleFqn, symbolName, unionType); + return convert(moduleFqn, parentFqn, symbolName, unionType); } if (type instanceof UnknownType.UnresolvedImportType unresolvedImportType) { - return convert(moduleFqn, symbolName, unresolvedImportType); + return convert(parentFqn, symbolName, unresolvedImportType); } - return new VariableDescriptor(symbolName, symbolFqn(moduleFqn, symbolName), null); + return new VariableDescriptor(symbolName, symbolFqn(parentFqn, symbolName), null); } - private Descriptor convert(String moduleFqn, String symbolName, FunctionType type) { + private Descriptor convert(String moduleFqn, String parentFqn, String symbolName, FunctionType type) { var parameters = type.parameters() .stream() .map(parameter -> convert(moduleFqn, parameter)) .toList(); - return new FunctionDescriptor(symbolName, symbolFqn(moduleFqn, symbolName), + return new FunctionDescriptor(symbolName, symbolFqn(parentFqn, symbolName), parameters, type.isAsynchronous(), type.isInstanceMethod(), @@ -91,13 +91,18 @@ private Descriptor convert(String moduleFqn, String symbolName, FunctionType typ type.definitionLocation().orElse(null), null, null - ); + ); } - private Descriptor convert(String moduleFqn, String symbolName, ClassType type) { - Set memberDescriptors = type.members().stream().map(m -> convert(moduleFqn, m.name(), m.type())).collect(Collectors.toSet()); + private Descriptor convert(String moduleFqn, String parentFqn, String symbolName, ClassType type) { + var symbolFqn = symbolFqn(parentFqn, symbolName); + var memberDescriptors = type.members() + .stream() + .map(m -> convert(moduleFqn, symbolFqn, m.name(), m.type())) + .collect(Collectors.toSet()); List superClasses = type.superClasses().stream().map(TypeWrapper::type).map(t -> typeFqn(moduleFqn, t)).toList(); - return new ClassDescriptor(symbolName, symbolFqn(moduleFqn, symbolName), + + return new ClassDescriptor(symbolName, symbolFqn, superClasses, memberDescriptors, type.hasDecorators(), @@ -109,9 +114,9 @@ private Descriptor convert(String moduleFqn, String symbolName, ClassType type) ); } - private Descriptor convert(String moduleFqn, String symbolName, UnionType type) { + private Descriptor convert(String moduleFqn, String parentFqn, String symbolName, UnionType type) { var candidates = type.candidates().stream() - .map(candidateType -> convert(moduleFqn, symbolName, candidateType)) + .map(candidateType -> convert(moduleFqn, parentFqn, symbolName, candidateType)) .collect(Collectors.toSet()); return new AmbiguousDescriptor(symbolName, symbolFqn(moduleFqn, symbolName), @@ -119,9 +124,9 @@ private Descriptor convert(String moduleFqn, String symbolName, UnionType type) ); } - private static Descriptor convert(String moduleFqn, String symbolName, UnknownType.UnresolvedImportType type) { + private static Descriptor convert(String parentFqn, String symbolName, UnknownType.UnresolvedImportType type) { return new VariableDescriptor(symbolName, - symbolFqn(moduleFqn, symbolName), + symbolFqn(parentFqn, symbolName), type.importPath() ); } @@ -135,8 +140,8 @@ private FunctionDescriptor.Parameter convert(String moduleFqn, ParameterV2 param parameter.hasDefaultValue(), parameter.isKeywordOnly(), parameter.isPositionalOnly(), - parameter.isKeywordVariadic(), parameter.isPositionalVariadic(), + parameter.isKeywordVariadic(), parameter.location()); } diff --git a/python-frontend/src/test/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverterTest.java b/python-frontend/src/test/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverterTest.java index ee0e6ba5c4..c6c03818a4 100644 --- a/python-frontend/src/test/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverterTest.java +++ b/python-frontend/src/test/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverterTest.java @@ -109,8 +109,7 @@ void testConvertClassType() { VariableDescriptor memberVariableDescriptor = (VariableDescriptor) memberDescriptor; assertThat(memberVariableDescriptor.name()).isEqualTo("aMember"); assertThat(memberVariableDescriptor.annotatedType()).isEqualTo("int"); - // TODO SONARPY-2222 expected fullyqualified name of the member is "foo.myClass.aMember" - assertThat(memberVariableDescriptor.fullyQualifiedName()).isEqualTo("foo.aMember"); + assertThat(memberVariableDescriptor.fullyQualifiedName()).isEqualTo("foo.myClass.aMember"); assertThat(classDescriptor.hasDecorators()).isTrue(); assertThat(classDescriptor.definitionLocation()).isEqualTo(location);