Skip to content

Commit de3be9c

Browse files
guillaume-dequennesonartech
authored andcommitted
SONARPY-4806 Preserve unknown decorators in serialized metadata
GitOrigin-RevId: f2c7fb1b5c2d0ee946ac9ae95f889b24e52e04cc
1 parent 4a95332 commit de3be9c

70 files changed

Lines changed: 137 additions & 29 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎python-frontend/src/main/java/org/sonar/python/semantic/FunctionSymbolImpl.java‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public FunctionSymbolImpl(SymbolsProtos.FunctionSymbol functionSymbolProto, @Nul
104104
isInstanceMethod = containerClassFqn != null && !functionSymbolProto.getIsStatic() && !functionSymbolProto.getIsClassMethod();
105105
isAsynchronous = functionSymbolProto.getIsAsynchronous();
106106
hasDecorators = functionSymbolProto.getHasDecorators();
107-
decorators = functionSymbolProto.getResolvedDecoratorNamesList();
107+
decorators = resolvedDecoratorNames(functionSymbolProto.getResolvedDecoratorNamesList());
108108
SymbolsProtos.Type returnAnnotation = typeTable.resolve(
109109
functionSymbolProto.getReturnAnnotationId(), functionSymbolProto.hasReturnAnnotation(), functionSymbolProto.getReturnAnnotation());
110110
String returnTypeName = returnAnnotation == null ? "" : returnAnnotation.getFullyQualifiedName();
@@ -145,13 +145,18 @@ public FunctionSymbolImpl(FunctionDescriptor functionDescriptor, String symbolNa
145145
isInstanceMethod = functionDescriptor.isInstanceMethod();
146146
isAsynchronous = functionDescriptor.isAsynchronous();
147147
hasDecorators = functionDescriptor.hasDecorators();
148-
decorators = functionDescriptor.decorators();
148+
decorators = resolvedDecoratorNames(functionDescriptor.decorators());
149149
annotatedReturnTypeName = functionDescriptor.annotatedReturnTypeName();
150150
functionDefinitionLocation = functionDescriptor.definitionLocation();
151151
// TODO: Will no longer be true once SONARPY-647 is fixed
152152
isStub = false;
153153
}
154154

155+
private static List<String> resolvedDecoratorNames(List<String> names) {
156+
// V1 exposes resolved names only. Keep unknown placeholders in descriptors for V2 consumers.
157+
return names.stream().filter(name -> name != null && !name.isEmpty()).toList();
158+
}
159+
155160
public void setParametersWithType(ParameterList parametersList) {
156161
this.parameters.clear();
157162
createParameterNames(parametersList.all(), functionDefinitionLocation == null ? null : functionDefinitionLocation.fileId());

‎python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/FunctionDescriptorToPythonTypeConverter.java‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.sonar.python.semantic.v2.converter;
1818

1919
import java.util.List;
20-
import java.util.Objects;
2120
import java.util.Optional;
2221
import org.sonar.plugins.python.api.types.v2.ParameterV2;
2322
import org.sonar.plugins.python.api.types.v2.PythonType;
@@ -48,9 +47,9 @@ public PythonType convert(ConversionContext ctx, FunctionDescriptor from) {
4847

4948
var decorators = from.decorators()
5049
.stream()
51-
.filter(Objects::nonNull) // SONARPY-2813 needs to be done to fix the null decorators
52-
.map(ctx.lazyTypesContext()::getOrCreateLazyType)
53-
.map(TypeWrapper::of)
50+
.map(decorator -> decorator == null || decorator.isEmpty()
51+
? TypeWrapper.UNKNOWN_TYPE_WRAPPER
52+
: TypeWrapper.of(ctx.lazyTypesContext().getOrCreateLazyType(decorator)))
5453
.toList();
5554

5655
var typeOrigin = ctx.typeOrigin();

‎python-frontend/src/main/java/org/sonar/python/semantic/v2/converter/PythonTypeToDescriptorConverter.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ private static Descriptor convert(FunctionType type) {
134134
var decorators = type.decorators()
135135
.stream()
136136
.map(TypeWrapper::type)
137-
.map(decorator -> FullyQualifiedNameHelper.getFullyQualifiedName(decorator).orElse(null))
138-
.filter(Objects::nonNull)
137+
.map(decorator -> FullyQualifiedNameHelper.getFullyQualifiedName(decorator).orElse(""))
139138
.toList();
140139

141140
var returnType = type.returnType();

‎python-frontend/src/main/java/org/sonar/python/semantic/v2/typeshed/FunctionSymbolToDescriptorConverter.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public FunctionDescriptor convert(SymbolsProtos.FunctionSymbol functionSymbol, b
6262
.map(SymbolsProtos.FunctionSymbol::getResolvedDecoratorNamesList)
6363
.stream()
6464
.flatMap(Collection::stream)
65-
.map(TypeShedUtils::normalizedFqn)
65+
// Empty entries represent unknown decorators and must remain serializable in descriptor caches.
66+
.map(name -> name.isEmpty() ? "" : TypeShedUtils.normalizedFqn(name))
6667
.toList();
6768
var parameters = functionSymbol.getParametersList().stream()
6869
.map(parameterConverter::convert)

0 commit comments

Comments
 (0)