2020package org .sonar .python .index ;
2121
2222import java .util .Collections ;
23+ import java .util .HashSet ;
2324import java .util .List ;
2425import java .util .Map ;
2526import java .util .Objects ;
@@ -116,43 +117,52 @@ private static List<FunctionDescriptor.Parameter> parameters(List<FunctionSymbol
116117 )).collect (Collectors .toList ());
117118 }
118119
120+ // TODO SONARPY-958: Cleanup the symbol construction from descriptors by extracting this logic in a builder class
119121 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 ());
124127 }
128+ // The symbol generated from the descriptor will not have the descriptor name if an alias (localSymbolName) is defined
125129 String symbolName = localSymbolName != null ? localSymbolName : descriptor .name ();
126130 switch (descriptor .kind ()) {
127131 case CLASS :
128- return createClassSymbol (descriptor , projectLevelSymbolTable , createdSymbols , symbolName );
132+ return createClassSymbol (descriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn , symbolName );
129133 case FUNCTION :
130- return createFunctionSymbol ((FunctionDescriptor ) descriptor , projectLevelSymbolTable , createdSymbols , symbolName );
134+ return createFunctionSymbol ((FunctionDescriptor ) descriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn , symbolName );
131135 case VARIABLE :
132136 return new SymbolImpl (symbolName , descriptor .fullyQualifiedName ());
133137 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 ;
138145 default :
139146 throw new IllegalStateException (String .format ("Error while creating a Symbol from a Descriptor: Unexpected descriptor kind: %s" , descriptor .kind ()));
140147 }
141148 }
142149
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 ) {
144152 ClassDescriptor classDescriptor = (ClassDescriptor ) descriptor ;
145153 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 );
149158 return classSymbol ;
150159 }
151160
152161 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 ) {
154164 classSymbol .addMembers (classDescriptor .members ().stream ()
155- .map (memberFqn -> DescriptorUtils .symbolFromDescriptor (memberFqn , projectLevelSymbolTable , null , createdSymbols ))
165+ .map (memberFqn -> DescriptorUtils .symbolFromDescriptor (memberFqn , projectLevelSymbolTable , null , createdSymbolsByDescriptor , createdSymbolsByFqn ))
156166 .map (member -> {
157167 if (member instanceof FunctionSymbolImpl ) {
158168 ((FunctionSymbolImpl ) member ).setOwner (classSymbol );
@@ -163,47 +173,49 @@ private static void addMembers(ClassSymbolImpl classSymbol, ClassDescriptor clas
163173 }
164174
165175 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 ) {
167178 classDescriptor .superClasses ().stream ()
168179 .map (superClassFqn -> {
169- if (createdSymbols .containsKey (superClassFqn )) {
170- return createdSymbols .get (superClassFqn );
180+ if (createdSymbolsByFqn .containsKey (superClassFqn )) {
181+ return createdSymbolsByFqn .get (superClassFqn );
171182 }
172- Symbol symbol = projectLevelSymbolTable .getSymbol (superClassFqn , null , createdSymbols );
183+ Symbol symbol = projectLevelSymbolTable .getSymbol (superClassFqn , null , createdSymbolsByDescriptor , createdSymbolsByFqn );
173184 symbol = symbol != null ? symbol : typeshedSymbolWithFQN (superClassFqn );
174- createdSymbols .put (superClassFqn , symbol );
185+ createdSymbolsByFqn .put (superClassFqn , symbol );
175186 return symbol ;
176187 }
177188 )
178189 .forEach (classSymbol ::addSuperClass );
179190 }
180191
181192 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 ) {
183195 FunctionSymbolImpl functionSymbol = new FunctionSymbolImpl (functionDescriptor , symbolName );
184- addParameters (functionSymbol , functionDescriptor , projectLevelSymbolTable , createdSymbols );
196+ addParameters (functionSymbol , functionDescriptor , projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn );
185197 return functionSymbol ;
186198 }
187199
188200 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 ) {
190202 functionDescriptor .parameters ().stream ().map (parameterDescriptor -> {
191203 FunctionSymbolImpl .ParameterImpl parameter = new FunctionSymbolImpl .ParameterImpl (parameterDescriptor );
192- setParameterType (parameter , parameterDescriptor .annotatedType (), projectLevelSymbolTable , createdSymbols );
204+ setParameterType (parameter , parameterDescriptor .annotatedType (), projectLevelSymbolTable , createdSymbolsByDescriptor , createdSymbolsByFqn );
193205 return parameter ;
194206 }).forEach (functionSymbol ::addParameter );
195207 }
196208
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 ) {
199211 InferredType declaredType ;
200212 if (parameter .isKeywordVariadic ()) {
201213 declaredType = InferredTypes .DICT ;
202214 } else if (parameter .isPositionalVariadic ()) {
203215 declaredType = InferredTypes .TUPLE ;
204216 } 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 );
207219 String annotatedTypeName = parameter .annotatedTypeName ();
208220 if (typeSymbol == null && annotatedTypeName != null ) {
209221 typeSymbol = typeshedSymbolWithFQN (annotatedTypeName );
0 commit comments