public static PsiElement findArrayKeyValueInsideReference(
      PsiElement psiElement, String methodReferenceName, String keyName) {

    if (psiElement == null) {
      return null;
    }

    Collection<MethodReference> tests =
        PsiTreeUtil.findChildrenOfType(psiElement, MethodReference.class);
    for (MethodReference methodReference : tests) {

      // instance check
      // methodReference.getSignature().equals("#M#C\\Symfony\\Component\\OptionsResolver\\OptionsResolverInterface.setDefaults")
      if (PhpElementsUtil.isEqualMethodReferenceName(methodReference, methodReferenceName)) {
        PsiElement[] parameters = methodReference.getParameters();
        if (parameters.length > 0 && parameters[0] instanceof ArrayCreationExpression) {
          PsiElement keyValue =
              PhpElementsUtil.getArrayValue((ArrayCreationExpression) parameters[0], keyName);
          if (keyValue != null) {
            return keyValue;
          }
        }
      }
    }

    return null;
  }
  /**
   * Get array string values mapped with their PsiElements
   *
   * <p>["value", "value2"]
   */
  @NotNull
  public static Map<String, PsiElement> getArrayValuesAsMap(
      @NotNull ArrayCreationExpression arrayCreationExpression) {

    List<PsiElement> arrayValues =
        PhpPsiUtil.getChildren(
            arrayCreationExpression,
            new Condition<PsiElement>() {
              @Override
              public boolean value(PsiElement psiElement) {
                return psiElement.getNode().getElementType() == PhpElementTypes.ARRAY_VALUE;
              }
            });

    if (arrayValues == null) {
      return Collections.emptyMap();
    }

    Map<String, PsiElement> keys = new HashMap<String, PsiElement>();
    for (PsiElement child : arrayValues) {
      String stringValue = PhpElementsUtil.getStringValue(child.getFirstChild());
      if (stringValue != null && StringUtils.isNotBlank(stringValue)) {
        keys.put(stringValue, child);
      }
    }

    return keys;
  }
  public static Collection<PhpClass> getClassFromPhpTypeSetArrayClean(
      Project project, Set<String> types) {

    PhpType phpType = new PhpType();
    phpType.add(types);

    ArrayList<PhpClass> phpClasses = new ArrayList<PhpClass>();

    for (String typeName :
        PhpIndex.getInstance(project)
            .completeType(project, phpType, new HashSet<String>())
            .getTypes()) {
      if (typeName.startsWith("\\")) {

        // we clean array types \Foo[]
        if (typeName.endsWith("[]")) {
          typeName = typeName.substring(0, typeName.length() - 2);
        }

        PhpClass phpClass = PhpElementsUtil.getClassInterface(project, typeName);
        if (phpClass != null) {
          phpClasses.add(phpClass);
        }
      }
    }

    return phpClasses;
  }
  @Nullable
  public static PsiElement getArrayKeyValueInsideSignaturePsi(
      PsiElement psiElementInsideClass, String callTo[], String methodName, String keyName) {
    PhpClass phpClass = PsiTreeUtil.getParentOfType(psiElementInsideClass, PhpClass.class);
    if (phpClass == null) {
      return null;
    }

    String className = phpClass.getPresentableFQN();
    if (className == null) {
      return null;
    }

    for (String s : callTo) {
      // @TODO: replace signature
      PsiElement arrayKeyValueInsideSignature =
          PhpElementsUtil.getArrayKeyValueInsideSignaturePsi(
              psiElementInsideClass.getProject(),
              "#M#C\\" + className + "." + s,
              methodName,
              keyName);
      if (arrayKeyValueInsideSignature != null) {
        return arrayKeyValueInsideSignature;
      }
    }

    return null;
  }
  /** new FooClass() */
  @Nullable
  private static PhpClass getNewExpressionPhpClass(@NotNull NewExpression newExpression) {
    ClassReference classReference = newExpression.getClassReference();
    if (classReference != null) {
      String fqn = classReference.getFQN();
      if (fqn != null) {
        return PhpElementsUtil.getClass(newExpression.getProject(), fqn);
      }
    }

    return null;
  }
  @Nullable
  public static PsiElement getArrayKeyValueInsideSignaturePsi(
      Project project, String signature, String methodName, String keyName) {

    PsiElement psiElement = PhpElementsUtil.getPsiElementsBySignatureSingle(project, signature);
    if (psiElement == null) {
      return null;
    }

    for (MethodReference methodReference :
        PsiTreeUtil.findChildrenOfType(psiElement, MethodReference.class)) {

      if (PhpElementsUtil.isEqualMethodReferenceName(methodReference, methodName)) {
        PsiElement[] parameters = methodReference.getParameters();
        if (parameters.length > 0 && parameters[0] instanceof ArrayCreationExpression) {
          return PhpElementsUtil.getArrayValue((ArrayCreationExpression) parameters[0], keyName);
        }
      }
    }

    return null;
  }
  /**
   * Get class by shortcut namespace, on a scoped namespace
   *
   * @param project current project
   * @param classNameScope Namespace fo search "\Foo\Foo", "Foo\Foo", "Foo\Foo\", last "\*" is
   *     stripped
   * @param className Class name inside namespace also fqn is supported
   * @return PhpClass matched
   */
  public static PhpClass getClassInsideNamespaceScope(
      @NotNull Project project, @NotNull String classNameScope, @NotNull String className) {

    if (className.startsWith("\\")) {
      return PhpElementsUtil.getClassInterface(project, className);
    }

    // strip class name we namespace
    String strip = StringUtils.strip(classNameScope, "\\");
    int i = strip.lastIndexOf("\\");
    if (i <= 0) {
      return PhpElementsUtil.getClassInterface(project, className);
    }

    PhpClass phpClass =
        PhpElementsUtil.getClassInterface(
            project, strip.substring(0, i) + "\\" + StringUtils.strip(className, "\\"));
    if (phpClass != null) {
      return phpClass;
    }

    return PhpElementsUtil.getClassInterface(project, className);
  }
  public static Collection<PhpClass> getClassFromPhpTypeSet(Project project, Set<String> types) {

    PhpType phpType = new PhpType();
    phpType.add(types);

    List<PhpClass> phpClasses = new ArrayList<PhpClass>();

    for (String typeName :
        PhpIndex.getInstance(project)
            .completeType(project, phpType, new HashSet<String>())
            .getTypes()) {
      if (typeName.startsWith("\\")) {
        PhpClass phpClass = PhpElementsUtil.getClassInterface(project, typeName);
        if (phpClass != null) {
          phpClasses.add(phpClass);
        }
      }
    }

    return phpClasses;
  }