@@ -224,61 +224,66 @@ private static Map<String, String> getInlineCommentDocsVars(@NotNull PsiElement
224224 return variables ;
225225 }
226226
227- private static Map <String , Set <String >> convertHashMapToTypeSet (Map <String , String > hashMap ) {
228- Map <String , Set <String >> globalVars = new HashMap <>();
229-
230- for (final Map .Entry <String , String > entry : hashMap .entrySet ()) {
231- globalVars .put (entry .getKey (), new HashSet <>(Collections .singletonList (entry .getValue ())));
232- }
233-
234- return globalVars ;
235- }
236-
237227 @ NotNull
238228 public static Map <String , PsiVariable > collectScopeVariables (@ NotNull PsiElement psiElement ) {
239229 return collectScopeVariables (psiElement , new HashSet <>());
240230 }
241231
242232 @ NotNull
243233 public static Map <String , PsiVariable > collectScopeVariables (@ NotNull PsiElement psiElement , @ NotNull Set <VirtualFile > visitedFiles ) {
244- Map <String , Set <String >> globalVars = new HashMap <>();
245- Map <String , PsiVariable > controllerVars = new HashMap <>();
246-
247234 VirtualFile virtualFile = psiElement .getContainingFile ().getVirtualFile ();
248235 if (visitedFiles .contains (virtualFile )) {
249- return controllerVars ;
236+ return Collections . emptyMap () ;
250237 }
251238
252239 visitedFiles .add (virtualFile );
253240
241+ Map <String , PsiVariable > controllerVars = new HashMap <>();
242+
254243 TwigFileVariableCollectorParameter collectorParameter = new TwigFileVariableCollectorParameter (psiElement , visitedFiles );
255244 for (TwigFileVariableCollector collector : TWIG_FILE_VARIABLE_COLLECTORS .getExtensions ()) {
256245 Map <String , Set <String >> globalVarsScope = new HashMap <>();
257246 collector .collect (collectorParameter , globalVarsScope );
258247
259248 // @TODO: resolve this in change extension point, so that its only possible to provide data and dont give full scope to break / overwrite other variables
260249 globalVarsScope .forEach ((s , strings ) -> {
261- globalVars .putIfAbsent (s , new HashSet <> ());
262- globalVars .get (s ).addAll (strings );
250+ controllerVars .putIfAbsent (s , new PsiVariable ());
251+ controllerVars .get (s ).addTypes (strings );
263252 });
264253
265- // @TODO: provide merge for multiple matches
266- collector .collectPsiVariables (collectorParameter , controllerVars );
254+ // merging elements
255+ Map <String , PsiVariable > controllerVars1 = new HashMap <>();
256+ collector .collectPsiVariables (collectorParameter , controllerVars1 );
257+
258+ controllerVars1 .forEach ((s , psiVariable ) -> {
259+ controllerVars .putIfAbsent (s , new PsiVariable ());
260+ controllerVars .get (s ).addTypes (psiVariable .getTypes ());
261+
262+ PsiElement context = psiVariable .getElement ();
263+ if (context != null ) {
264+ controllerVars .get (s ).addElements (context );
265+ }
266+ });
267267 }
268268
269269 // globals first
270- globalVars .putAll (convertHashMapToTypeSet (findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .BLOCK_STATEMENT , true )));
271- globalVars .putAll (convertHashMapToTypeSet (findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .MACRO_STATEMENT , false )));
272- globalVars .putAll (convertHashMapToTypeSet (findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .FOR_STATEMENT , false )));
273-
274- for (Map .Entry <String , Set <String >> entry : globalVars .entrySet ()) {
275- Set <String > types = entry .getValue ();
270+ Collection <Map <String , String >> vars = Arrays .asList (
271+ findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .BLOCK_STATEMENT , true ),
272+ findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .MACRO_STATEMENT , false ),
273+ findInlineStatementVariableDocBlock (psiElement , TwigElementTypes .FOR_STATEMENT , false )
274+ );
276275
277- // collect iterator
278- types .addAll (collectIteratorReturns (psiElement , entry .getValue ()));
276+ for (Map <String , String > entry : vars ) {
277+ entry .forEach ((s , s2 ) -> {
278+ controllerVars .putIfAbsent (s , new PsiVariable ());
279+ controllerVars .get (s ).addType (s2 );
280+ });
281+ }
279282
280- // convert to variable model
281- controllerVars .put (entry .getKey (), new PsiVariable (types , null ));
283+ // collect iterator
284+ for (Map .Entry <String , PsiVariable > entry : controllerVars .entrySet ()) {
285+ PsiVariable psiVariable = entry .getValue ();
286+ psiVariable .addTypes (collectIteratorReturns (psiElement , psiVariable .getTypes ()));
282287 }
283288
284289 // check if we are in "for" scope and resolve types ending with []
@@ -347,7 +352,7 @@ private static Collection<String> collectForArrayScopeVariablesFoo(@NotNull Proj
347352 return previousElements ;
348353 }
349354
350- private static void collectForArrayScopeVariables (PsiElement psiElement , Map <String , PsiVariable > globalVars ) {
355+ private static void collectForArrayScopeVariables (@ NotNull PsiElement psiElement , @ NotNull Map <String , PsiVariable > globalVars ) {
351356 PsiElement twigCompositeElement = PsiTreeUtil .findFirstParent (psiElement , psiElement1 -> {
352357 if (psiElement1 instanceof TwigCompositeElement ) {
353358 if (PlatformPatterns .psiElement (TwigElementTypes .FOR_STATEMENT ).accepts (psiElement1 )) {
@@ -412,12 +417,12 @@ private static void collectForArrayScopeVariables(PsiElement psiElement, Map<Str
412417 }
413418
414419 // we already have same variable in scope, so merge types
415- if (globalVars .containsKey (scopeVariable )) {
416- globalVars .get (scopeVariable ).getTypes ().addAll (types );
420+ PsiVariable psiVariable = globalVars .get (scopeVariable );
421+ if (psiVariable != null ) {
422+ psiVariable .addTypes (types );
417423 } else {
418424 globalVars .put (scopeVariable , new PsiVariable (types ));
419425 }
420-
421426 }
422427
423428 @ NotNull
0 commit comments