package com.cedricziel.idea.typo3.icons;

import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.PhpIndex;
import com.jetbrains.php.lang.psi.elements.*;
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Set;

public class IconReferenceContributor extends PsiReferenceContributor {

    private static final String ICON_FACTORY = "\\TYPO3\\CMS\\Core\\Imaging\\IconFactory";

    @Override
    public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
        // known method calls
        registrar.registerReferenceProvider(
                PlatformPatterns.psiElement(StringLiteralExpression.class),
                new PsiReferenceProvider() {
                    @NotNull
                    @Override
                    public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
                        StringLiteralExpression stringLiteralExpression = (StringLiteralExpression) element;

                        PsiElement parent = stringLiteralExpression.getParent();
                        while (!(parent instanceof MethodReference)) {

                            if (parent != null) {
                                parent = parent.getParent();
                            }
                        }

                        if (!(parent instanceof MethodReference)) {
                            return new PsiReference[0];
                        }

                        MethodReference methodReference = (MethodReference) parent;
                        String methodName = methodReference.getName();

                        if (methodReference.getFirstPsiChild() instanceof Variable) {
                            Variable variable = (Variable) methodReference.getFirstPsiChild();
                            PhpType inferredType = variable.getInferredType();
                            Set<String> types = inferredType.getTypes();
                            for (String type : types) {
                                Collection<? extends PhpNamedElement> bySignature = PhpIndex.getInstance(element.getProject()).getBySignature(type);
                                for (PhpNamedElement el : bySignature) {
                                    if (el.getFQN().equals(ICON_FACTORY) && methodName.equals("getIcon")) {
                                        return new PsiReference[]{new IconReference(stringLiteralExpression)};
                                    }
                                }
                            }
                        }

                        PhpExpression classReference = methodReference.getClassReference();
                        if (classReference == null || !(classReference instanceof ClassReference)) {
                            return new PsiReference[0];
                        }

                        String fqn = ((ClassReference) classReference).getFQN();
                        if (methodName != null && methodName.equals("getIcon") && fqn.equals(ICON_FACTORY)) {
                            return new PsiReference[]{new IconReference(stringLiteralExpression)};
                        }

                        return new PsiReference[0];
                    }
                }
        );
    }
}

@@ -35,16 +35,67 @@
 icons;%0A%0A
+import com.cedricziel.idea.typo3.util.PhpLangUtil;%0A
 import c
@@ -282,17 +282,212 @@
 lements.
-*
+MethodReference;%0Aimport com.jetbrains.php.lang.psi.elements.PhpNamedElement;%0Aimport com.jetbrains.php.lang.psi.elements.StringLiteralExpression;%0Aimport com.jetbrains.php.lang.psi.elements.Variable
 ;%0Aimport
@@ -1720,159 +1720,8 @@
  %7D%0A%0A
-                        if (!(parent instanceof MethodReference)) %7B%0A                            return new PsiReference%5B0%5D;%0A                        %7D%0A%0A
     
@@ -2257,24 +2257,66 @@
  : types) %7B%0A
+                                try %7B%0A    
             
@@ -2480,24 +2480,28 @@
             
+    
 for (PhpName
@@ -2561,24 +2561,28 @@
             
+  
+  
 if (el.getFQ
@@ -2637,24 +2637,28 @@
 etIcon%22)) %7B%0A
+    
             
@@ -2784,32 +2784,36 @@
                 
+    
 %7D%0A              
@@ -2822,34 +2822,42 @@
                 
-%7D%0A
+    %7D%0A    
                 
@@ -2873,228 +2873,140 @@
    %7D
-%0A                        %7D%0A%0A                        PhpExpression classReference = methodReference.getClassReference();%0A                        if (classReference == null %7C%7C !(classReference instanceof ClassReference)) %7B
+ catch (RuntimeException e) %7B%0A                                    // invalid index signature, skip%0A                                %7D
 %0A   
@@ -3034,35 +3034,9 @@
     
-return new PsiReference%5B0%5D;
+%7D
 %0A   
@@ -3094,55 +3094,68 @@
 ing 
-fqn = ((ClassReference) classReference).getFQN(
+className = PhpLangUtil.getClassName(stringLiteralExpression
 );%0A 
@@ -3202,16 +3202,37 @@
  null &&
+ className != null &&
  methodN
@@ -3260,11 +3260,17 @@
  && 
-fqn
+className
 .equ

Resolve IconFactory by class correctly