@Nullable
  public static String getArrayHashValue(
      ArrayCreationExpression arrayCreationExpression, String keyName) {
    ArrayHashElement translationArrayHashElement =
        PsiElementUtils.getChildrenOfType(
            arrayCreationExpression,
            PlatformPatterns.psiElement(ArrayHashElement.class)
                .withFirstChild(
                    PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY)
                        .withText(
                            PlatformPatterns.string()
                                .oneOf("'" + keyName + "'", "\"" + keyName + "\""))));

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

    if (!(translationArrayHashElement.getValue() instanceof StringLiteralExpression)) {
      return null;
    }

    StringLiteralExpression valueString =
        (StringLiteralExpression) translationArrayHashElement.getValue();
    if (valueString == null) {
      return null;
    }

    return valueString.getContents();
  }
  public void testDocumentAndOdmFallback() {
    for (String s : new String[] {"document", "odm"}) {
      assertCompletionContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"<caret>\" /></document></doctrine-mapping>",
          "string",
          "couchdb_foo_bar");

      assertNavigationMatch(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"couchdb_foo_bar<caret>\" /></document></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertCompletionContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"<caret>\" /></document></doctrine-mapping>",
          "string",
          "mongodb_foo_bar");

      assertNavigationMatch(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"mongodb_foo_bar<caret>\" /></document></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));
    }
  }
 public static PsiElementPattern.Capture<StringLiteralExpression> methodWithFirstStringPattern() {
   return PlatformPatterns.psiElement(StringLiteralExpression.class)
       .withParent(
           PlatformPatterns.psiElement(PhpElementTypes.PARAMETER_LIST)
               .withFirstChild(PlatformPatterns.psiElement(PhpElementTypes.STRING))
               .withParent(PlatformPatterns.psiElement(PhpElementTypes.METHOD_REFERENCE)))
       .withLanguage(PhpLanguage.INSTANCE);
 }
 /** matches "@Callback(<property>=)" */
 public static ElementPattern<PsiElement> getPropertyIdentifier(String propertyName) {
   return PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_IDENTIFIER)
       .withText(propertyName)
       .beforeLeafSkipping(
           PlatformPatterns.psiElement(PsiWhiteSpace.class),
           PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_TEXT).withText("="))
       .withParent(PlatformPatterns.psiElement(PhpDocElementTypes.phpDocAttributeList));
 }
 /** class "Foo" extends */
 public static PsiElementPattern.Capture<PsiElement> getClassNamePattern() {
   return PlatformPatterns.psiElement(PhpTokenTypes.IDENTIFIER)
       .afterLeafSkipping(
           PlatformPatterns.psiElement(PsiWhiteSpace.class),
           PlatformPatterns.psiElement(PhpTokenTypes.kwCLASS))
       .withParent(PhpClass.class)
       .withLanguage(PhpLanguage.INSTANCE);
 }
  /** only usable up to phpstorm 7 */
  public static ElementPattern<StringLiteralExpression> getPropertyValueString() {

    return PlatformPatterns.psiElement(StringLiteralExpression.class)
        .afterLeaf(PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_TEXT).withText("="))
        .withParent(
            PlatformPatterns.psiElement(PhpDocElementTypes.phpDocAttributeList)
                .withParent(PlatformPatterns.psiElement(PhpDocElementTypes.phpDocTag)))
        .withLanguage(PhpLanguage.INSTANCE);
  }
 /** foo: b<caret>ar foo: [ b<caret>ar ] foo: { b<caret>ar } foo: - b<caret>ar */
 private PsiElementPattern.Capture<PsiElement> getGlobalServiceStringPattern() {
   return PlatformPatterns.psiElement()
       .withParent(
           PlatformPatterns.or(
               PlatformPatterns.psiElement(YAMLKeyValue.class),
               PlatformPatterns.psiElement(YAMLSequence.class),
               PlatformPatterns.psiElement(YAMLArray.class),
               PlatformPatterns.psiElement(YAMLHash.class)));
 }
 /** return 'value' inside class method */
 public static ElementPattern<PhpExpression> getMethodReturnPattern() {
   return PlatformPatterns.or(
       PlatformPatterns.psiElement(StringLiteralExpression.class)
           .withParent(PlatformPatterns.psiElement(PhpReturn.class).inside(Method.class))
           .withLanguage(PhpLanguage.INSTANCE),
       PlatformPatterns.psiElement(ClassConstantReference.class)
           .withParent(PlatformPatterns.psiElement(PhpReturn.class).inside(Method.class))
           .withLanguage(PhpLanguage.INSTANCE));
 }
 /** $foo->bar('<caret>') */
 public static PsiElementPattern.Capture<PsiElement> getParameterInsideMethodReferencePattern() {
   return PlatformPatterns.psiElement()
       .withParent(
           PlatformPatterns.psiElement(StringLiteralExpression.class)
               .withParent(
                   PlatformPatterns.psiElement(ParameterList.class)
                       .withParent(PlatformPatterns.psiElement(MethodReference.class))))
       .withLanguage(PhpLanguage.INSTANCE);
 }
 /** public function indexAction() */
 public static PsiElementPattern.Capture<PsiElement> getActionMethodPattern() {
   return PlatformPatterns.psiElement(PhpTokenTypes.IDENTIFIER)
       .withText(PlatformPatterns.string().endsWith("Action"))
       .afterLeafSkipping(
           PlatformPatterns.psiElement(PsiWhiteSpace.class),
           PlatformPatterns.psiElement(PhpTokenTypes.kwFUNCTION))
       .inside(Method.class)
       .withLanguage(PhpLanguage.INSTANCE);
 }
 /** matches "@Callback(propertyName="<value>")" */
 public static PsiElementPattern.Capture<StringLiteralExpression> getPropertyIdentifierValue(
     String propertyName) {
   return PlatformPatterns.psiElement(StringLiteralExpression.class)
       .afterLeafSkipping(
           PlatformPatterns.or(
               PlatformPatterns.psiElement(PsiWhiteSpace.class),
               PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_TEXT).withText("=")),
           PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_IDENTIFIER).withText(propertyName))
       .withParent(PlatformPatterns.psiElement(PhpDocElementTypes.phpDocAttributeList));
 }
  public void testDocumentRepositoryClassNavigation() {
    assertNavigationMatch(
        XmlFileType.INSTANCE,
        "<doctrine-mongo-mapping><document repository-class=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></doctrine-mongo-mapping>",
        PlatformPatterns.psiElement(PhpClass.class));

    assertNavigationMatch(
        XmlFileType.INSTANCE,
        "<doctrine-foo-mapping><document repository-class=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></doctrine-foo-mapping>",
        PlatformPatterns.psiElement(PhpClass.class));
  }
  /**
   * matches "@Callback("<value>", foo...)" TODO: is this also valid "@Callback(key="", "<value>")"?
   */
  public static ElementPattern<PsiElement> getDefaultPropertyValue() {

    return PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_IDENTIFIER)
        .afterLeaf(
            PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_TEXT)
                .withText(PlatformPatterns.string().equalTo("\""))
                .afterLeaf(PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_LPAREN)))
        .withParent(
            PlatformPatterns.psiElement(PhpDocElementTypes.phpDocTagValue)
                .withParent(PlatformPatterns.psiElement(PhpDocElementTypes.phpDocTag)))
        .withLanguage(PhpLanguage.INSTANCE);
  }
  @Nullable
  @Override
  public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Editor editor) {

    if (!Symfony2ProjectComponent.isEnabled(psiElement)) {
      return null;
    }

    // only string values like "foo", foo
    if (!PlatformPatterns.psiElement(YAMLTokenTypes.TEXT)
            .withLanguage(YAMLLanguage.INSTANCE)
            .accepts(psiElement)
        && !PlatformPatterns.psiElement(YAMLTokenTypes.SCALAR_DSTRING)
            .withLanguage(YAMLLanguage.INSTANCE)
            .accepts(psiElement)
        && !PlatformPatterns.psiElement(YAMLTokenTypes.SCALAR_STRING)
            .withLanguage(YAMLLanguage.INSTANCE)
            .accepts(psiElement)) {

      return new PsiElement[] {};
    }

    String psiText = PsiElementUtils.getText(psiElement);
    if (null == psiText || psiText.length() == 0) {
      return new PsiElement[] {};
    }

    List<PsiElement> psiElements = new ArrayList<PsiElement>();

    if (psiText.startsWith("@") && psiText.length() > 1) {
      psiElements.addAll(Arrays.asList((serviceGoToDeclaration(psiElement, psiText.substring(1)))));
    }

    // match: %annotations.reader.class%
    if (psiText.length() > 3 && psiText.startsWith("%") && psiText.endsWith("%")) {
      psiElements.addAll(Arrays.asList((parameterGoToDeclaration(psiElement, psiText))));
    }

    if (psiText.contains("\\")) {
      psiElements.addAll(classGoToDeclaration(psiElement, psiText));
    }

    if (psiText.endsWith(".twig") || psiText.endsWith(".php")) {
      psiElements.addAll(templateGoto(psiElement, psiText));
    }

    if (psiText.matches("^[\\w_.]+") && getGlobalServiceStringPattern().accepts(psiElement)) {
      psiElements.addAll(Arrays.asList((serviceGoToDeclaration(psiElement, psiText))));
    }

    return psiElements.toArray(new PsiElement[psiElements.size()]);
  }
  private void collectSelects(
      QueryBuilderScopeContext qb, MethodReference methodReference, String name) {

    if (!Arrays.asList("select", "addSelect").contains(name)) {
      return;
    }

    // $qb->select('foo')
    PsiElement psiElement = PsiElementUtils.getMethodParameterPsiElementAt(methodReference, 0);
    String literalValue = PhpElementsUtil.getStringValue(psiElement);
    if (literalValue != null) {
      qb.addSelect(literalValue);
      return;
    }

    // $qb->select(array('foo', 'bar', 'accessoryDetail'))
    if (psiElement instanceof ArrayCreationExpression) {
      for (PsiElement arrayValue :
          PsiElementUtils.getChildrenOfTypeAsList(
              psiElement, PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE))) {
        if (arrayValue.getChildren().length == 1) {
          String arrayValueString = PhpElementsUtil.getStringValue(arrayValue.getChildren()[0]);
          if (arrayValueString != null) {
            qb.addSelect(arrayValueString);
          }
        }
      }
    }
  }
 private void addCompleteHandler(
     IElementType elementType, CompletionProvider<CompletionParameters> handler) {
   extend(
       CompletionType.BASIC,
       PlatformPatterns.psiElement(elementType).withLanguage(PerlLanguage.INSTANCE),
       handler);
 }
  @Override
  public void registerReferenceProviders(PsiReferenceRegistrar psiReferenceRegistrar) {

    psiReferenceRegistrar.registerReferenceProvider(
        PlatformPatterns.psiElement(StringLiteralExpression.class),
        new PsiReferenceProvider() {
          @NotNull
          @Override
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
            if (!Symfony2ProjectComponent.isEnabled(psiElement)
                || !(psiElement.getContext() instanceof ParameterList)) {
              return new PsiReference[0];
            }

            ParameterList parameterList = (ParameterList) psiElement.getContext();

            if (parameterList == null || !(parameterList.getContext() instanceof MethodReference)) {
              return new PsiReference[0];
            }

            MethodReference method = (MethodReference) parameterList.getContext();
            Symfony2InterfacesUtil interfacesUtil = new Symfony2InterfacesUtil();
            if (!interfacesUtil.isTranslatorCall(method)) {
              return new PsiReference[0];
            }

            int domainParameter = 2;
            if (method.getName().equals("transChoice")) {
              domainParameter = 3;
            }

            ParameterBag currentIndex = PsiElementUtils.getCurrentParameterIndex(psiElement);
            if (currentIndex == null) {
              return new PsiReference[0];
            }

            if (currentIndex.getIndex() == domainParameter) {
              return new PsiReference[] {
                new TranslationDomainReference((StringLiteralExpression) psiElement)
              };
            }

            if (currentIndex.getIndex() == 0) {
              String domain = PsiElementUtils.getMethodParameterAt(parameterList, domainParameter);

              if (domain == null) {
                domain = "messages";
              }

              return new PsiReference[] {
                new TranslationReference((StringLiteralExpression) psiElement, domain)
              };
            }

            return new PsiReference[0];
          }
        });
  }
 public PimpleCompletionContributor() {
   // $app['<caret>']
   extend(
       CompletionType.BASIC,
       PlatformPatterns.psiElement().withLanguage(PhpLanguage.INSTANCE),
       new ArrayAccessCompletionProvider());
   // $app[''] = $app->extend('<caret>', ...
   extend(
       CompletionType.BASIC,
       PlatformPatterns.psiElement().withLanguage(PhpLanguage.INSTANCE),
       new ExtendsMethodParameterListCompletionProvider());
   // $app->register(, ['<caret>' =>])
   extend(
       CompletionType.BASIC,
       PlatformPatterns.psiElement().withLanguage(PhpLanguage.INSTANCE),
       new RegisterFunctionValuesCompletionProvider());
 }
 public void testClassMethods() {
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('DateTime::format<caret>')",
       PlatformPatterns.psiElement(Method.class).withName("format"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('DateTime:::format<caret>')",
       PlatformPatterns.psiElement(Method.class).withName("format"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('DateTime:format<caret>')",
       PlatformPatterns.psiElement(Method.class).withName("format"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('\\DateTime:format<caret>')",
       PlatformPatterns.psiElement(Method.class).withName("format"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('\\DateTime:setTimezone<caret>')",
       PlatformPatterns.psiElement(Method.class).withName("setTimezone"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php '\\DateTime:setTimezone<caret>'",
       PlatformPatterns.psiElement(Method.class).withName("setTimezone"));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php \"\\DateTime:setTimezone<caret>\"",
       PlatformPatterns.psiElement(Method.class).withName("setTimezone"));
 }
 public void testClassNames() {
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('DateTime<caret>')",
       PlatformPatterns.psiElement(PhpClass.class));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php k('\\DateTime<caret>')",
       PlatformPatterns.psiElement(PhpClass.class));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php '\\DateTime<caret>'",
       PlatformPatterns.psiElement(PhpClass.class));
   assertNavigationMatch(
       PhpFileType.INSTANCE,
       "<?php \"\\DateTime<caret>\"",
       PlatformPatterns.psiElement(PhpClass.class));
 }
 public static ElementPattern<PsiElement> getDocBlockTag() {
   return PlatformPatterns.or(
       PlatformPatterns.psiElement()
           .withSuperParent(1, PhpDocPsiElement.class)
           .withParent(PhpDocComment.class)
           .withLanguage(PhpLanguage.INSTANCE),
       // eap:
       // * @<completion>
       //
       // "@" char is not detected on lexer, so provider additional asterisk check for more secured
       // pattern filter
       PlatformPatterns.psiElement()
           .afterLeafSkipping(
               PlatformPatterns.or(PlatformPatterns.psiElement(PsiWhiteSpace.class)),
               PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_LEADING_ASTERISK))
           .withSuperParent(1, PhpDocPsiElement.class)
           .withLanguage(PhpLanguage.INSTANCE));
 }
  public static boolean isMethodWithFirstString(PsiElement psiElement, String... methodName) {

    // filter out method calls without parameter
    // $this->methodName('service_name')
    // withName is not working, so simulate it in a hack
    if (!PlatformPatterns.psiElement(PhpElementTypes.METHOD_REFERENCE)
        .withChild(
            PlatformPatterns.psiElement(PhpElementTypes.PARAMETER_LIST)
                .withFirstChild(PlatformPatterns.psiElement(PhpElementTypes.STRING)))
        .accepts(psiElement)) {

      return false;
    }

    // cant we move it up to PlatformPatterns? withName condition dont looks working
    String methodRefName = ((MethodReference) psiElement).getName();

    return null != methodRefName && Arrays.asList(methodName).contains(methodRefName);
  }
  private static boolean isKeyword(ASTNode node) {
    if (node == null) return false;

    return TokenSets.KEYWORDS.contains(node.getElementType())
        || TokenSets.BRACES.contains(node.getElementType())
            && !PlatformPatterns.psiElement()
                .withText(")")
                .withParent(GrArgumentList.class)
                .afterLeaf(",")
                .accepts(node.getPsi());
  }
  public void testXmlTypes() {
    for (String s : new String[] {"couchdb", "orm", "mongodb"}) {
      assertCompletionContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"<caret>\" /></document></doctrine-mapping>",
          "string",
          s + "_foo_bar");

      assertCompletionContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><embedded-document><field type=\"<caret>\" /></embedded-document></doctrine-mapping>",
          "string",
          s + "_foo_bar");

      assertCompletionContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><embedded><field type=\"<caret>\" /></embedded></doctrine-mapping>",
          "string",
          s + "_foo_bar");

      assertNavigationMatch(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"string<caret>\" /></document></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          "foo." + s + ".xml",
          "<doctrine-mapping><embedded-document><field type=\"string<caret>\" /></embedded-document></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          "foo." + s + ".xml",
          "<doctrine-mapping><embedded><field type=\"string<caret>\" /></embedded></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertCompletionNotContains(
          "foo." + s + ".xml",
          "<doctrine-mapping><document><field type=\"<caret>\" /></document></doctrine-mapping>",
          "foo");
    }
  }
  /**
   * $this->methodName('service_name') $this->methodName(SERVICE::NAME)
   * $this->methodName($this->name)
   */
  public static boolean isMethodWithFirstStringOrFieldReference(
      PsiElement psiElement, String... methodName) {

    if (!PlatformPatterns.psiElement(PhpElementTypes.METHOD_REFERENCE)
        .withChild(
            PlatformPatterns.psiElement(PhpElementTypes.PARAMETER_LIST)
                .withFirstChild(
                    PlatformPatterns.or(
                        PlatformPatterns.psiElement(PhpElementTypes.STRING),
                        PlatformPatterns.psiElement(PhpElementTypes.FIELD_REFERENCE),
                        PlatformPatterns.psiElement(PhpElementTypes.CLASS_CONSTANT_REFERENCE))))
        .accepts(psiElement)) {

      return false;
    }

    // cant we move it up to PlatformPatterns? withName condition dont looks working
    String methodRefName = ((MethodReference) psiElement).getName();

    return null != methodRefName && Arrays.asList(methodName).contains(methodRefName);
  }
 private static void getMethodVars(Set<String> stringSet, Method method) {
   Collection<FieldReference> fieldReferences =
       PsiTreeUtil.collectElementsOfType(method, FieldReference.class);
   for (FieldReference fieldReference : fieldReferences) {
     PsiElement psiVar =
         PsiElementUtils.getChildrenOfType(
             fieldReference, PlatformPatterns.psiElement().withText("vars"));
     if (psiVar != null) {
       getFormViewVarsAttachKeys(stringSet, fieldReference);
     }
   }
 }
  /** @see DoctrineMetadataPattern#getXmlTargetDocumentClass() */
  public void testTargetDocumentNavigation() {
    for (String s : new String[] {"reference-one", "reference-many", "embed-many", "embed-one"}) {
      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-mapping><document><"
              + s
              + " target-document=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></document></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-foo-mapping><document><"
              + s
              + " target-document=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></document></doctrine-foo-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-foo-mapping><document name=\"Foo\\Bar\\Ns\\Foo\"><"
              + s
              + " target-document=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></document></doctrine-foo-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));
    }
  }
  /** @see DoctrineMetadataPattern#getXmlTargetEntityClass() */
  public void testTargetEntityNavigation() {
    for (String s : new String[] {"one-to-one", "one-to-many", "many-to-one", "many-to-many"}) {
      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-mapping><entity><"
              + s
              + " target-entity=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></entity></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-foo-mapping><entity><"
              + s
              + " target-entity=\"Foo\\Bar\\Ns<caret>\\BarRepo\"/></entity></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));

      assertNavigationMatch(
          XmlFileType.INSTANCE,
          "<doctrine-foo-mapping><entity name=\"Foo\\Bar\\Ns\\Foo\"><"
              + s
              + " target-entity=\"Bar<caret>Repo\"/></entity></doctrine-mapping>",
          PlatformPatterns.psiElement(PhpClass.class));
    }
  }
  public LiveTemplateCompletionContributor() {
    extend(
        CompletionType.BASIC,
        PlatformPatterns.psiElement(),
        new CompletionProvider<CompletionParameters>() {
          @Override
          protected void addCompletions(
              @NotNull CompletionParameters parameters,
              ProcessingContext context,
              @NotNull CompletionResultSet result) {
            final PsiFile file = parameters.getPosition().getContainingFile();
            final int offset = parameters.getOffset();
            final List<TemplateImpl> templates = listApplicableTemplates(file, offset);
            if (showAllTemplates()) {
              final Ref<Boolean> templatesShown = Ref.create(false);

              final CompletionResultSet finalResult = result;
              result.runRemainingContributors(
                  parameters,
                  new Consumer<CompletionResult>() {
                    @Override
                    public void consume(CompletionResult completionResult) {
                      finalResult.passResult(completionResult);
                      ensureTemplatesShown(templatesShown, templates, finalResult);
                    }
                  });

              ensureTemplatesShown(templatesShown, templates, result);
              return;
            }

            if (parameters.getInvocationCount() > 0) return; // only in autopopups for now

            String templatePrefix =
                findLiveTemplatePrefix(
                    file, parameters.getEditor(), result.getPrefixMatcher().getPrefix());
            final TemplateImpl template = findApplicableTemplate(file, offset, templatePrefix);
            if (template != null) {
              result = result.withPrefixMatcher(template.getKey());
              result.addElement(new LiveTemplateLookupElement(template, true));
            }
            for (final TemplateImpl possible : templates) {
              result.restartCompletionOnPrefixChange(possible.getKey());
            }
          }
        });
  }
 /**
  * fire on: @Callback(<completion>), @Callback("", <completion>) * @ORM\Column( <completion>, )
  */
 public static ElementPattern<PsiElement> getDocAttribute() {
   return PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_IDENTIFIER)
       .afterLeafSkipping(
           PlatformPatterns.psiElement(PsiWhiteSpace.class),
           PlatformPatterns.or(
               PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_COMMA),
               PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_LPAREN),
               PlatformPatterns.psiElement(PhpDocTokenTypes.DOC_LEADING_ASTERISK)))
       .inside(PlatformPatterns.psiElement(PhpDocElementTypes.phpDocTag))
       .withLanguage(PhpLanguage.INSTANCE);
 }