@Override
    protected void addCompletions(
        @NotNull CompletionParameters parameters,
        ProcessingContext processingContext,
        @NotNull CompletionResultSet completionResultSet) {

      PsiElement position = parameters.getPosition();
      if (!Symfony2ProjectComponent.isEnabled(position)) {
        return;
      }

      PsiElement prevSiblingOfType =
          PsiElementUtils.getPrevSiblingOfType(
              position, YamlElementPatternHelper.getPreviousCommaSibling());
      if (prevSiblingOfType == null) {
        return;
      }

      String service = PsiElementUtils.trimQuote(prevSiblingOfType.getText());
      if (StringUtils.isBlank(service)) {
        return;
      }

      PhpClass phpClass = ServiceUtil.getServiceClass(prevSiblingOfType.getProject(), service);
      if (phpClass == null) {
        return;
      }

      for (Method method : phpClass.getMethods()) {
        if (method.getAccess().isPublic() && !(method.getName().startsWith("__"))) {
          completionResultSet.addElement(new PhpLookupElement(method));
        }
      }
    }
  /**
   * Find a string return value of a method context "function() { return 'foo'}" First match wins
   */
  @Nullable
  public static String getMethodReturnAsString(
      @NotNull PhpClass phpClass, @NotNull String methodName) {

    Method method = phpClass.findMethodByName(methodName);
    if (method == null) {
      return null;
    }

    final Set<String> values = new HashSet<String>();
    method.acceptChildren(
        new PsiRecursiveElementWalkingVisitor() {
          @Override
          public void visitElement(PsiElement element) {

            if (PhpElementsUtil.getMethodReturnPattern().accepts(element)) {
              String value = PhpElementsUtil.getStringValue(element);
              if (value != null && StringUtils.isNotBlank(value)) {
                values.add(value);
              }
            }

            super.visitElement(element);
          }
        });

    if (values.size() == 0) {
      return null;
    }

    // we support only first item
    return values.iterator().next();
  }
  public ControllerAction(PhpClass phpClass, int startOffset) {
    this.currentControllerName = phpClass.getName();
    Pattern pattern = Pattern.compile(".*?this->render\\((.*?)\\).*?");

    for (Method method : phpClass.getOwnMethods()) {
      TextRange textRange = method.getTextRange();
      final String methodName = method.getName();
      Matcher matcher = pattern.matcher(method.getText());
      List<String> renderViews =
          new ArrayList<String>() {
            {
              add(methodName);
            }
          };

      while (matcher.find()) {
        renderViews.add(matcher.group(1).replace("'", ""));
      }

      if (textRange.getStartOffset() <= startOffset && startOffset <= textRange.getEndOffset()) {
        this.currentActionName = methodName;
      }

      // Method name will be unique. Because PHP doesn't have [overroad] like java.
      actions.put(methodName, new Function(method.getName(), textRange, renderViews));
    }
  }
  @Nullable
  public static String getControllerMethodShortcut(Method method) {

    // indexAction
    String methodName = method.getName();
    if (!methodName.endsWith("Action")) {
      return null;
    }

    PhpClass phpClass = method.getContainingClass();
    if (null == phpClass) {
      return null;
    }

    // defaultController
    // default/Folder/FolderController
    String className = phpClass.getName();
    if (!className.endsWith("Controller")) {
      return null;
    }

    SymfonyBundleUtil symfonyBundleUtil =
        new SymfonyBundleUtil(PhpIndex.getInstance(method.getProject()));
    SymfonyBundle symfonyBundle = symfonyBundleUtil.getContainingBundle(phpClass);
    if (symfonyBundle == null) {
      return null;
    }

    // find the bundle name of file
    PhpClass BundleClass = symfonyBundle.getPhpClass();
    if (null == BundleClass) {
      return null;
    }

    // check if files is in <Bundle>/Controller/*
    if (!phpClass.getNamespaceName().startsWith(BundleClass.getNamespaceName() + "Controller\\")) {
      return null;
    }

    // strip the controller folder name
    String templateFolderName =
        phpClass.getNamespaceName().substring(BundleClass.getNamespaceName().length() + 11);

    // HomeBundle:default:indexes
    // HomeBundle:default/Test:indexes
    templateFolderName = templateFolderName.replace("\\", "/");
    String shortcutName =
        symfonyBundle.getName()
            + ":"
            + templateFolderName
            + className.substring(0, className.lastIndexOf("Controller"))
            + ":"
            + methodName.substring(0, methodName.lastIndexOf("Action"));

    // we should support types later on
    // HomeBundle:default:indexes.html.twig
    return shortcutName + ".html.twig";
  }
 @Nullable
 public static Method getClassMethod(PhpClass phpClass, String methodName) {
   for (Method method : phpClass.getMethods()) {
     if (method.getName().equals(methodName)) {
       return method;
     }
   }
   return null;
 }
  public static ArrayList<Method> getClassPublicMethod(PhpClass phpClass) {
    ArrayList<Method> methods = new ArrayList<Method>();

    for (Method method : phpClass.getMethods()) {
      if (method.getAccess().isPublic() && !method.getName().startsWith("__")) {
        methods.add(method);
      }
    }

    return methods;
  }
  private static void collectMethodElementsWithParents(
      final @NotNull Method method,
      final int depth,
      @NotNull final Collection<PsiElement> elements,
      @NotNull final Processor<PsiElement> processor) {

    method.acceptChildren(
        new PsiRecursiveElementWalkingVisitor() {
          @Override
          public void visitElement(PsiElement psiElement) {

            if (processor.process(psiElement)) {
              elements.add(psiElement);
            }

            if (psiElement instanceof MethodReference
                && ((MethodReference) psiElement).getReferenceType() == PhpModifier.State.PARENT
                && method.getName().equals(((MethodReference) psiElement).getName())) {
              PsiElement resolve = ((MethodReference) psiElement).resolve();
              if (depth > 0 && resolve instanceof Method) {
                collectMethodElementsWithParents((Method) resolve, depth - 1, elements, processor);
              }
            }

            super.visitElement(psiElement);
          }
        });
  }
  public static List<Variable> getVariableReferencesInScope(
      final Variable variable, final boolean includeSelf) {

    final List<Variable> variables = new ArrayList<Variable>();

    Variable variableDecl = null;
    if (!variable.isDeclaration()) {
      PsiElement psiElement = variable.resolve();
      if (psiElement instanceof Variable) {
        variableDecl = (Variable) psiElement;
      }
    } else {
      variableDecl = variable;
    }

    if (variableDecl == null) {
      return variables;
    }

    Method method = PsiTreeUtil.getParentOfType(variable, Method.class);

    PhpPsiUtil.hasReferencesInSearchScope(
        method.getUseScope(),
        variableDecl,
        new CommonProcessors.FindProcessor<PsiReference>() {
          @Override
          protected boolean accept(PsiReference psiReference) {

            PsiElement variableRef = psiReference.getElement();
            if (variableRef instanceof Variable) {
              if (includeSelf) {
                variables.add((Variable) variableRef);
              } else {
                if (!variableRef.equals(variable)) {
                  variables.add((Variable) variableRef);
                }
              }
            }

            return false;
          }
        });

    return variables;
  }
  @Nullable
  public static PsiElement[] getMethodParameterReferences(Method method, int parameterIndex) {

    // we dont have a parameter on resolved method
    Parameter[] parameters = method.getParameters();
    if (parameters.length == 0 || parameterIndex >= parameters.length) {
      return null;
    }

    final String tempVariableName = parameters[parameterIndex].getName();
    return PsiTreeUtil.collectElements(
        method.getLastChild(),
        new PsiElementFilter() {
          @Override
          public boolean isAccepted(PsiElement element) {
            return element instanceof Variable
                && tempVariableName.equals(((Variable) element).getName());
          }
        });
  }
  private static ArrayList<Method> getImplementedMethods(
      @Nullable PhpClass phpClass, @NotNull Method method, ArrayList<Method> implementedMethods) {
    if (phpClass == null) {
      return implementedMethods;
    }

    Method[] methods = phpClass.getOwnMethods();
    for (Method ownMethod : methods) {
      if (PhpLangUtil.equalsMethodNames(ownMethod.getName(), method.getName())) {
        implementedMethods.add(ownMethod);
      }
    }

    for (PhpClass interfaceClass : phpClass.getImplementedInterfaces()) {
      getImplementedMethods(interfaceClass, method, implementedMethods);
    }

    getImplementedMethods(phpClass.getSuperClass(), method, implementedMethods);

    return implementedMethods;
  }
 public static Method[] getImplementedMethods(@NotNull Method method) {
   ArrayList<Method> items =
       getImplementedMethods(method.getContainingClass(), method, new ArrayList<Method>());
   return items.toArray(new Method[items.size()]);
 }