20
20
package org .sonar .python .index ;
21
21
22
22
import java .util .Collections ;
23
+ import java .util .HashSet ;
23
24
import java .util .List ;
24
25
import java .util .Map ;
25
26
import java .util .Objects ;
@@ -116,43 +117,52 @@ private static List<FunctionDescriptor.Parameter> parameters(List<FunctionSymbol
116
117
)).collect (Collectors .toList ());
117
118
}
118
119
120
+ // TODO SONARPY-958: Cleanup the symbol construction from descriptors by extracting this logic in a builder class
119
121
public static Symbol symbolFromDescriptor (Descriptor descriptor , ProjectLevelSymbolTable projectLevelSymbolTable ,
120
- @ Nullable String localSymbolName , Map <String , Symbol > createdSymbols ) {
121
- // The symbol generated from the descriptor will not have the descriptor name if an alias (localSymbolName) is defined
122
- if (createdSymbols .containsKey (descriptor .fullyQualifiedName ())) {
123
- return createdSymbols .get (descriptor .fullyQualifiedName ());
122
+ @ Nullable String localSymbolName , Map <Descriptor , Symbol > createdSymbolsByDescriptor , Map <String , Symbol > createdSymbolsByFqn ) {
123
+ if (createdSymbolsByDescriptor .containsKey (descriptor )) {
124
+ return createdSymbolsByDescriptor .get (descriptor );
125
+ } else if (descriptor .fullyQualifiedName () != null && createdSymbolsByFqn .containsKey (descriptor .fullyQualifiedName ())) {
126
+ return createdSymbolsByFqn .get (descriptor .fullyQualifiedName ());
124
127
}
128
+ // The symbol generated from the descriptor will not have the descriptor name if an alias (localSymbolName) is defined
125
129
String symbolName = localSymbolName != null ? localSymbolName : descriptor .name ();
126
130
switch (descriptor .kind ()) {
127
131
case CLASS :
128
- return createClassSymbol (descriptor , projectLevelSymbolTable , createdSymbols , symbolName );
132
+ return createClassSymbol (descriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn , symbolName );
129
133
case FUNCTION :
130
- return createFunctionSymbol ((FunctionDescriptor ) descriptor , projectLevelSymbolTable , createdSymbols , symbolName );
134
+ return createFunctionSymbol ((FunctionDescriptor ) descriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn , symbolName );
131
135
case VARIABLE :
132
136
return new SymbolImpl (symbolName , descriptor .fullyQualifiedName ());
133
137
case AMBIGUOUS :
134
- Set <Symbol > alternatives = ((AmbiguousDescriptor ) descriptor ).alternatives ().stream ()
135
- .map (a -> DescriptorUtils .symbolFromDescriptor (a , projectLevelSymbolTable , symbolName , createdSymbols ))
136
- .collect (Collectors .toSet ());
137
- return new AmbiguousSymbolImpl (symbolName , descriptor .fullyQualifiedName (), alternatives );
138
+ Set <Symbol > alternatives = new HashSet <>();
139
+ AmbiguousSymbolImpl ambiguousSymbol = new AmbiguousSymbolImpl (symbolName , descriptor .fullyQualifiedName (), alternatives );
140
+ createdSymbolsByDescriptor .put (descriptor , ambiguousSymbol );
141
+ alternatives .addAll (((AmbiguousDescriptor ) descriptor ).alternatives ().stream ()
142
+ .map (a -> DescriptorUtils .symbolFromDescriptor (a , projectLevelSymbolTable , symbolName , createdSymbolsByDescriptor , createdSymbolsByFqn ))
143
+ .collect (Collectors .toSet ()));
144
+ return ambiguousSymbol ;
138
145
default :
139
146
throw new IllegalStateException (String .format ("Error while creating a Symbol from a Descriptor: Unexpected descriptor kind: %s" , descriptor .kind ()));
140
147
}
141
148
}
142
149
143
- private static ClassSymbolImpl createClassSymbol (Descriptor descriptor , ProjectLevelSymbolTable projectLevelSymbolTable , Map <String , Symbol > createdSymbols , String symbolName ) {
150
+ private static ClassSymbolImpl createClassSymbol (Descriptor descriptor , ProjectLevelSymbolTable projectLevelSymbolTable , Map <Descriptor , Symbol > createdSymbolsByDescriptor ,
151
+ Map <String , Symbol > createdSymbolByFqn , String symbolName ) {
144
152
ClassDescriptor classDescriptor = (ClassDescriptor ) descriptor ;
145
153
ClassSymbolImpl classSymbol = new ClassSymbolImpl ((ClassDescriptor ) descriptor , symbolName );
146
- createdSymbols .put (descriptor .fullyQualifiedName (), classSymbol );
147
- addSuperClasses (classSymbol , classDescriptor , projectLevelSymbolTable , createdSymbols );
148
- addMembers (classSymbol , classDescriptor , projectLevelSymbolTable , createdSymbols );
154
+ createdSymbolsByDescriptor .put (descriptor , classSymbol );
155
+ createdSymbolByFqn .put (descriptor .fullyQualifiedName (), classSymbol );
156
+ addSuperClasses (classSymbol , classDescriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolByFqn );
157
+ addMembers (classSymbol , classDescriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolByFqn );
149
158
return classSymbol ;
150
159
}
151
160
152
161
private static void addMembers (ClassSymbolImpl classSymbol , ClassDescriptor classDescriptor ,
153
- ProjectLevelSymbolTable projectLevelSymbolTable , Map <String , Symbol > createdSymbols ) {
162
+ ProjectLevelSymbolTable projectLevelSymbolTable , Map <Descriptor , Symbol > createdSymbolsByDescriptor ,
163
+ Map <String , Symbol > createdSymbolsByFqn ) {
154
164
classSymbol .addMembers (classDescriptor .members ().stream ()
155
- .map (memberFqn -> DescriptorUtils .symbolFromDescriptor (memberFqn , projectLevelSymbolTable , null , createdSymbols ))
165
+ .map (memberFqn -> DescriptorUtils .symbolFromDescriptor (memberFqn , projectLevelSymbolTable , null , createdSymbolsByDescriptor , createdSymbolsByFqn ))
156
166
.map (member -> {
157
167
if (member instanceof FunctionSymbolImpl ) {
158
168
((FunctionSymbolImpl ) member ).setOwner (classSymbol );
@@ -163,47 +173,49 @@ private static void addMembers(ClassSymbolImpl classSymbol, ClassDescriptor clas
163
173
}
164
174
165
175
private static void addSuperClasses (ClassSymbolImpl classSymbol , ClassDescriptor classDescriptor ,
166
- ProjectLevelSymbolTable projectLevelSymbolTable , Map <String , Symbol > createdSymbols ) {
176
+ ProjectLevelSymbolTable projectLevelSymbolTable , Map <Descriptor , Symbol > createdSymbolsByDescriptor ,
177
+ Map <String , Symbol > createdSymbolsByFqn ) {
167
178
classDescriptor .superClasses ().stream ()
168
179
.map (superClassFqn -> {
169
- if (createdSymbols .containsKey (superClassFqn )) {
170
- return createdSymbols .get (superClassFqn );
180
+ if (createdSymbolsByFqn .containsKey (superClassFqn )) {
181
+ return createdSymbolsByFqn .get (superClassFqn );
171
182
}
172
- Symbol symbol = projectLevelSymbolTable .getSymbol (superClassFqn , null , createdSymbols );
183
+ Symbol symbol = projectLevelSymbolTable .getSymbol (superClassFqn , null , createdSymbolsByDescriptor , createdSymbolsByFqn );
173
184
symbol = symbol != null ? symbol : typeshedSymbolWithFQN (superClassFqn );
174
- createdSymbols .put (superClassFqn , symbol );
185
+ createdSymbolsByFqn .put (superClassFqn , symbol );
175
186
return symbol ;
176
187
}
177
188
)
178
189
.forEach (classSymbol ::addSuperClass );
179
190
}
180
191
181
192
private static FunctionSymbolImpl createFunctionSymbol (FunctionDescriptor functionDescriptor , ProjectLevelSymbolTable projectLevelSymbolTable ,
182
- Map <String , Symbol > createdSymbols , String symbolName ) {
193
+ Map <Descriptor , Symbol > createdSymbolsByDescriptor , Map <String , Symbol > createdSymbolsByFqn ,
194
+ String symbolName ) {
183
195
FunctionSymbolImpl functionSymbol = new FunctionSymbolImpl (functionDescriptor , symbolName );
184
- addParameters (functionSymbol , functionDescriptor , projectLevelSymbolTable , createdSymbols );
196
+ addParameters (functionSymbol , functionDescriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn );
185
197
return functionSymbol ;
186
198
}
187
199
188
200
private static void addParameters (FunctionSymbolImpl functionSymbol , FunctionDescriptor functionDescriptor ,
189
- ProjectLevelSymbolTable projectLevelSymbolTable , Map <String , Symbol > createdSymbols ) {
201
+ ProjectLevelSymbolTable projectLevelSymbolTable , Map <Descriptor , Symbol > createdSymbolsByDescriptor , Map < String , Symbol > createdSymbolsByFqn ) {
190
202
functionDescriptor .parameters ().stream ().map (parameterDescriptor -> {
191
203
FunctionSymbolImpl .ParameterImpl parameter = new FunctionSymbolImpl .ParameterImpl (parameterDescriptor );
192
- setParameterType (parameter , parameterDescriptor .annotatedType (), projectLevelSymbolTable , createdSymbols );
204
+ setParameterType (parameter , parameterDescriptor .annotatedType (), projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn );
193
205
return parameter ;
194
206
}).forEach (functionSymbol ::addParameter );
195
207
}
196
208
197
- private static void setParameterType (FunctionSymbolImpl .ParameterImpl parameter , String annotatedType ,
198
- ProjectLevelSymbolTable projectLevelSymbolTable , Map <String , Symbol > createdSymbols ) {
209
+ private static void setParameterType (FunctionSymbolImpl .ParameterImpl parameter , String annotatedType , ProjectLevelSymbolTable projectLevelSymbolTable ,
210
+ Map < Descriptor , Symbol > createdSymbolsByDescriptor , Map <String , Symbol > createdSymbolsByFqn ) {
199
211
InferredType declaredType ;
200
212
if (parameter .isKeywordVariadic ()) {
201
213
declaredType = InferredTypes .DICT ;
202
214
} else if (parameter .isPositionalVariadic ()) {
203
215
declaredType = InferredTypes .TUPLE ;
204
216
} else {
205
- Symbol existingSymbol = createdSymbols .get (annotatedType );
206
- Symbol typeSymbol = existingSymbol != null ? existingSymbol : projectLevelSymbolTable .getSymbol (annotatedType , null , createdSymbols );
217
+ Symbol existingSymbol = createdSymbolsByFqn .get (annotatedType );
218
+ Symbol typeSymbol = existingSymbol != null ? existingSymbol : projectLevelSymbolTable .getSymbol (annotatedType , null , createdSymbolsByDescriptor , createdSymbolsByFqn );
207
219
String annotatedTypeName = parameter .annotatedTypeName ();
208
220
if (typeSymbol == null && annotatedTypeName != null ) {
209
221
typeSymbol = typeshedSymbolWithFQN (annotatedTypeName );
0 commit comments