public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
   registrar.registerReferenceProvider(
       PsiJavaPatterns.literalExpression()
           .annotationParam("org.unitils.dbunit.annotation.DataSet", "value"),
       new URIReferenceProvider(),
       PsiReferenceRegistrar.HIGHER_PRIORITY);
   registrar.registerReferenceProvider(
       PsiJavaPatterns.literalExpression()
           .annotationParam("org.unitils.dbunit.annotation.ExpectedDataSet", "value"),
       new URIReferenceProvider(),
       PsiReferenceRegistrar.HIGHER_PRIORITY);
   registrar.registerReferenceProvider(
       PsiJavaPatterns.literalExpression()
           .insideAnnotationParam(
               PlatformPatterns.string()
                   .with(
                       new PatternCondition<String>("DataSet") {
                         public boolean accepts(
                             @NotNull final String annotationFQN,
                             final ProcessingContext context) {
                           return annotationFQN.equals("org.unitils.dbunit.annotation.DataSet");
                         }
                       }),
               "value"),
       new URIReferenceProvider());
 }
  public static CompletionResultSet addJavaSorting(
      final CompletionParameters parameters, CompletionResultSet result) {
    final PsiElement position = parameters.getPosition();
    final ExpectedTypeInfo[] expectedTypes =
        PsiJavaPatterns.psiElement()
                .beforeLeaf(PsiJavaPatterns.psiElement().withText("."))
                .accepts(position)
            ? ExpectedTypeInfo.EMPTY_ARRAY
            : JavaSmartCompletionContributor.getExpectedTypes(parameters);
    final CompletionType type = parameters.getCompletionType();
    final boolean smart = type == CompletionType.SMART;
    final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position);

    List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>();
    afterProximity.add(new PreferContainingSameWords(expectedTypes));
    if (smart) {
      afterProximity.add(new PreferFieldsAndGetters());
    }
    afterProximity.add(new PreferShorter(expectedTypes));

    CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher());
    if (!smart && afterNew) {
      sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes));
    } else if (PsiTreeUtil.getParentOfType(position, PsiReferenceList.class) == null) {
      sorter =
          ((CompletionSorterImpl) sorter)
              .withClassifier("liftShorterClasses", true, new LiftShorterClasses(position));
    }
    if (smart) {
      sorter =
          sorter.weighAfter("priority", new PreferDefaultTypeWeigher(expectedTypes, parameters));
    }

    List<LookupElementWeigher> afterPrefix = ContainerUtil.newArrayList();
    if (!smart) {
      ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes));
    }
    ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes));
    if (!smart && !afterNew) {
      afterPrefix.add(new PreferExpected(false, expectedTypes));
    }
    Collections.addAll(
        afterPrefix,
        new PreferByKindWeigher(type, position),
        new PreferSimilarlyEnding(expectedTypes),
        new PreferNonGeneric(),
        new PreferAccessible(position),
        new PreferSimple(),
        new PreferEnumConstants(parameters));

    sorter =
        sorter.weighAfter(
            "prefix", afterPrefix.toArray(new LookupElementWeigher[afterPrefix.size()]));
    sorter =
        sorter.weighAfter(
            "proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()]));
    return result.withRelevanceSorter(sorter);
  }
            @Override
            @Nullable
            public ExpectedTypeInfo[] fun(final CompletionLocation location) {
              if (PsiJavaPatterns.psiElement()
                  .beforeLeaf(PsiJavaPatterns.psiElement().withText("."))
                  .accepts(location.getCompletionParameters().getPosition())) {
                return ExpectedTypeInfo.EMPTY_ARRAY;
              }

              return JavaSmartCompletionContributor.getExpectedTypes(
                  location.getCompletionParameters());
            }
  public static CompletionResultSet addJavaSorting(
      final CompletionParameters parameters, CompletionResultSet result) {
    String prefix = result.getPrefixMatcher().getPrefix();
    final PsiElement position = parameters.getPosition();
    final ExpectedTypeInfo[] expectedTypes =
        PsiJavaPatterns.psiElement()
                .beforeLeaf(PsiJavaPatterns.psiElement().withText("."))
                .accepts(position)
            ? ExpectedTypeInfo.EMPTY_ARRAY
            : JavaSmartCompletionContributor.getExpectedTypes(parameters);
    final CompletionType type = parameters.getCompletionType();
    final boolean smart = type == CompletionType.SMART;
    final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position);

    List<LookupElementWeigher> afterNegativeStats = new ArrayList<LookupElementWeigher>();
    if (!smart) {
      ContainerUtil.addIfNotNull(afterNegativeStats, preferStatics(position));
    }
    afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type, position));
    ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes));
    if (!smart && !afterNew) {
      afterNegativeStats.add(new PreferExpected(false, expectedTypes));
    }
    afterNegativeStats.add(new PreferSimilarlyEnding(expectedTypes, prefix));

    List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>();
    afterProximity.add(new PreferContainingSameWords(expectedTypes));
    if (smart) {
      afterProximity.add(new PreferFieldsAndGetters());
    }
    afterProximity.add(new PreferShorter(expectedTypes, prefix));

    CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher());
    if (!smart && afterNew) {
      sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes));
    } else {
      final ProjectFileIndex fileIndex =
          ProjectRootManager.getInstance(position.getProject()).getFileIndex();
      sorter =
          ((CompletionSorterImpl) sorter)
              .withClassifier(
                  "liftShorter",
                  true,
                  new ClassifierFactory<LookupElement>("liftShorterClasses") {
                    @Override
                    public Classifier<LookupElement> createClassifier(
                        Classifier<LookupElement> next) {
                      return new LiftShorterItemsClassifier(
                          next,
                          new LiftShorterItemsClassifier.LiftingCondition() {
                            @Override
                            public boolean shouldLift(
                                LookupElement shorterElement,
                                LookupElement longerElement,
                                ProcessingContext context) {
                              if (super.shouldLift(shorterElement, longerElement, context)) {
                                return true;
                              }
                              Object object = shorterElement.getObject();
                              if (object instanceof PsiClass) {
                                PsiFile file = ((PsiClass) object).getContainingFile();
                                if (file != null) {
                                  VirtualFile vFile = file.getOriginalFile().getVirtualFile();
                                  if (vFile != null && fileIndex.isInSource(vFile)) {
                                    return true;
                                  }
                                }
                              }
                              return false;
                            }
                          });
                    }
                  });
    }
    if (smart) {
      sorter =
          sorter.weighBefore(
              "negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters));
    }
    sorter =
        sorter.weighAfter(
            "negativeStats",
            afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()]));
    sorter =
        sorter.weighAfter(
            "prefix",
            new PreferNonGeneric(),
            new PreferAccessible(position),
            new PreferSimple(),
            new PreferEnumConstants(parameters));
    sorter =
        sorter.weighAfter(
            "proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()]));
    return result.withRelevanceSorter(sorter);
  }
public class TypeCompletionHandler extends AbstractCompletionHandler {
  private static final List<PsiPrimitiveType> PRIMITIVE_TYPES =
      ImmutableList.of(
          PsiType.BYTE,
          PsiType.CHAR,
          PsiType.DOUBLE,
          PsiType.FLOAT,
          PsiType.INT,
          PsiType.LONG,
          PsiType.SHORT,
          PsiType.BOOLEAN,
          PsiType.VOID);

  public static final PsiJavaElementPattern.Capture<PsiElement> IN_TYPE_PARAMETER =
      PsiJavaPatterns.psiElement()
          .afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.SUPER, "&")
          .withParent(
              PsiJavaPatterns.psiElement(PsiReferenceList.class)
                  .withParent(PsiTypeParameter.class));

  public static final PsiJavaElementPattern.Capture<PsiElement> INSIDE_METHOD_THROWS_CLAUSE =
      PsiJavaPatterns.psiElement()
          .afterLeaf(PsiKeyword.THROWS, ",")
          .inside(PsiMethod.class)
          .andNot(PsiJavaPatterns.psiElement().inside(PsiCodeBlock.class))
          .andNot(PsiJavaPatterns.psiElement().inside(PsiParameterList.class));

  public static final ElementPattern<PsiElement> AFTER_THROW_NEW =
      psiElement()
          .afterLeaf(
              psiElement()
                  .withText(PsiKeyword.NEW)
                  .afterLeaf(psiElement().withText(PsiKeyword.THROW)));

  private final ElementFilter _filter;
  private int _weight;
  @NotNull private final PrefixMatcher _prefixMatcher;
  private final boolean _javaCtx;

  public TypeCompletionHandler(
      @NotNull CompletionParameters parameters, @NotNull CompletionResultSet result, int weight) {
    super(parameters, result);
    _filter = getDefaultFilter(parameters.getPosition());
    _weight = weight;
    _prefixMatcher = result.getPrefixMatcher();
    _javaCtx = parameters.getPosition() instanceof PsiIdentifier;
  }

  public TypeCompletionHandler(
      @NotNull CompletionParameters parameters,
      @NotNull CompletionResultSet result,
      ElementFilter filter,
      int weight) {
    super(parameters, result);
    _filter = filter;
    _weight = weight;
    _prefixMatcher = result.getPrefixMatcher();
    _javaCtx = parameters.getPosition() instanceof PsiIdentifier;
  }

  @NotNull
  private ElementFilter getDefaultFilter(PsiElement insertedElement) {
    return AFTER_THROW_NEW.accepts(insertedElement)
        ? new AssignableFromFilter("java.lang.Throwable")
        : IN_TYPE_PARAMETER.accepts(insertedElement)
            ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class))
            : INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement)
                ? new AnyInnerFilter(new AssignableFromFilter("java.lang.Throwable"))
                : getLocalFilter(insertedElement);
  }

  @Override
  public void handleCompletePath() {
    final PsiElement position = getContext().getPosition();
    if (position instanceof GosuIdentifierImpl) {
      if (position.getParent() instanceof GosuTypeLiteralImpl) {
        if (position.getParent().getParent() instanceof GosuUsesStatementImpl) {
          return;
        }
      }
    }

    // primitives are always available
    addPrimitives();

    addScratchpadInnerClasses(position);

    // ## THIS IS DOGASS SLOW, the eventual call to CustomPsiClassCache.getByShortName() is f*****g
    // molasses, don't do this here.
    //    AllClassesGetter.processJavaClasses( _params, _prefixMatcher, _params.getInvocationCount()
    // <= 1, new Consumer<PsiClass>() {
    //  ...
    //    } );

    addTypeLoaderTypes();
    if (getTotalCompletions() == 0 && _params.getInvocationCount() < 2) {
      stopFilterByInvocationCount();
      addTypeLoaderTypes();
    }
  }

  private void addTypeLoaderTypes() {
    Set<String> fqnSet = new HashSet<String>();
    for (ITypeLoader loader : TypeSystem.getAllTypeLoaders()) {
      if (!loader.showTypeNamesInIDE()) {
        continue;
      }
      for (CharSequence typeName : loader.getAllTypeNames()) {
        String fqn = typeName.toString();
        int iAngle = fqn.indexOf('<');
        if (iAngle >= 0) {
          fqn = fqn.substring(0, iAngle);
        }
        if (fqnSet.contains(fqn)) {
          continue;
        }
        int iDot = fqn.lastIndexOf('.');
        String relativeName = iDot >= 0 ? fqn.substring(iDot + 1) : fqn;
        if (_prefixMatcher.prefixMatches(relativeName)) {
          if (_filter == null || _filter.isAcceptable(fqn, _params.getPosition())) {
            IType type = TypeSystem.getByFullNameIfValid(fqn, loader.getModule());
            if (type == null) {
              continue;
            }

            // Note this second cache lookup exists because there is a many-to-one mapping
            // between type names and ITypes e.g., several type names may map to an entity type.
            fqn = type.getName();
            if (fqnSet.contains(fqn)) {
              continue;
            }
            fqnSet.add(fqn);

            addCompletion(
                new GosuTypeCompletionProposal(type, getContext().getPosition(), _weight),
                _javaCtx);
          }
        }
      }
    }
  }

  private void addScratchpadInnerClasses(@Nullable PsiElement position) {
    if (position == null) {
      return;
    }

    PsiFile psiFile = position.getContainingFile();
    if (!(psiFile instanceof GosuScratchpadFileImpl)) {
      return;
    }

    GosuScratchpadFileImpl scratchpadFile = (GosuScratchpadFileImpl) psiFile;
    for (PsiClass cls : scratchpadFile.getPsiClass().getInnerClasses()) {
      if (cls.getName().startsWith(_prefixMatcher.getPrefix())) {
        addCompletion(new PsiClassCompletionProposal(cls, _weight), _javaCtx);
      }
    }
  }

  private void addPrimitives() {
    for (PsiType type : PRIMITIVE_TYPES) {
      if (type.getCanonicalText().startsWith(_prefixMatcher.getPrefix())) {
        addCompletion(new PrimitiveCompletionProposal(type), _javaCtx);
      }
    }

    if ("block".startsWith(_prefixMatcher.getPrefix())) {
      addCompletion(new RawCompletionProposal("block"));
    }
  }
}
  @Override
  public Result acceptChar(char c, final int prefixLength, final Lookup lookup) {
    if (!lookup.getPsiFile().getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
      return null;
    }

    LookupElement item = lookup.getCurrentItem();
    if (item == null) return null;

    final Object o = item.getObject();
    if (c == '!') {
      if (o instanceof PsiVariable) {
        if (PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) o).getType()))
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      if (o instanceof PsiMethod) {
        final PsiType type = ((PsiMethod) o).getReturnType();
        if (type != null && PsiType.BOOLEAN.isAssignableFrom(type))
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      if (o instanceof PsiKeyword && ((PsiKeyword) o).textMatches(PsiKeyword.INSTANCEOF)) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }

      return null;
    }
    if (c == '.' && isWithinLiteral(lookup)) return Result.ADD_TO_PREFIX;

    if (c == ':') {
      PsiFile file = lookup.getPsiFile();
      PsiDocumentManager.getInstance(file.getProject())
          .commitDocument(lookup.getEditor().getDocument());
      PsiElement leaf = file.findElementAt(lookup.getEditor().getCaretModel().getOffset() - 1);
      if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_8)) {
        PsiStatement statement = PsiTreeUtil.getParentOfType(leaf, PsiStatement.class);
        if (statement == null
            || statement.getTextRange().getStartOffset()
                != leaf.getTextRange().getStartOffset()) { // not typing a statement label
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
        }
      }
      if (PsiTreeUtil.getParentOfType(leaf, PsiSwitchLabelStatement.class) != null
          || PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class) != null) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      return Result.HIDE_LOOKUP;
    }

    if (c == '[' || c == ']' || c == ')' || c == '>')
      return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP;
    if (c == '<' && o instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
    if (c == '(') {
      if (o instanceof PsiClass) {
        if (PsiJavaPatterns.psiElement()
            .afterLeaf(PsiKeyword.NEW)
            .accepts(lookup.getPsiElement())) {
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
        }
        return Result.HIDE_LOOKUP;
      }
      if (o instanceof PsiType) {
        return Result.HIDE_LOOKUP;
      }
    }
    if ((c == ',' || c == '=') && o instanceof PsiVariable) {
      int lookupStart = lookup.getLookupStart();
      String name = ((PsiVariable) o).getName();
      if (lookupStart >= 0 && name != null && name.equals(lookup.itemPattern(item))) {
        return Result.HIDE_LOOKUP;
      }
    }

    if (c == '#'
        && PsiTreeUtil.getParentOfType(lookup.getPsiElement(), PsiDocComment.class) != null) {
      if (o instanceof PsiClass) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
    }
    if (c == '(' && PsiKeyword.RETURN.equals(item.getLookupString())) {
      return Result.HIDE_LOOKUP;
    }
    return null;
  }
  public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
    // errors tag add Reference Provider for Setters Method on parameter field
    registerXmlAttributeReferenceProvider(
        registrar, new SetterMethodsReferenceProvider(FORM_TAG), FIELD_ATTR, ERRORS_TAG);

    // all stripes tags for input form add Reference Provider for Setters Method
    registerXmlAttributeReferenceProvider(
        registrar, new SetterMethodsReferenceProvider(FORM_TAG), NAME_ATTR, INPUT_TAGS);

    // param tag add Reference Provider for Setter Methods
    registerXmlAttributeReferenceProvider(
        registrar, new SetterMethodsReferenceProvider(LINK_TAG), NAME_ATTR, PARAM_TAG);
    registerXmlAttributeReferenceProvider(
        registrar, new SetterMethodsReferenceProvider(URL_TAG), NAME_ATTR, PARAM_TAG);

    registerXmlAttributeReferenceProvider(
        registrar,
        new PsiReferenceProvider() {
          @NotNull
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement element, @NotNull ProcessingContext context) {
            if (PsiTreeUtil.getChildOfType(element, ELExpressionHolder.class) != null) {
              return PsiReference.EMPTY_ARRAY;
            }

            final PsiClass actionBeanPsiClass =
                StripesReferenceUtil.getBeanClassFromParentTag(
                    (XmlTag) element.getParent().getParent(), FORM_TAG);

            if (null != actionBeanPsiClass) {
              List<String> arr = StringUtil.split(ElementManipulators.getValueText(element), ",");

              List<PsiReference> retval = new LinkedList<PsiReference>();
              int offset = 1;
              for (String anArr : arr) {
                Collections.addAll(
                    retval,
                    new SetterReferenceExSet(anArr, element, offset, '.', actionBeanPsiClass, false)
                        .getPsiReferences());
                offset += (anArr.length() + 1);
              }

              return retval.toArray(new PsiReference[retval.size()]);
            }

            return PsiReference.EMPTY_ARRAY;
          }
        },
        FIELDS_ATTR,
        FIELD_METADATA_TAG);

    registrar.registerReferenceProvider(
        PsiJavaPatterns.literalExpression()
            .and(
                new FilterPattern(
                    new AndFilter(
                        new SuperParentFilter(
                            new QualifiedNameElementFilter(VALIDATE_NESTED_PROPERTIES_ANNOTATION)),
                        new AnnotationParameterFilter(
                            PsiLiteralExpression.class, VALIDATE_ANNOTATION, FIELD_ATTR)))),
        new PsiReferenceProvider() {
          @NotNull
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement element, @NotNull ProcessingContext context) {
            PsiMember parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
            if (parent == null) parent = PsiTreeUtil.getParentOfType(element, PsiField.class);

            PsiClass cls =
                StripesReferenceUtil.resolveClassInType(
                    PropertyUtil.getPropertyType(parent), element.getProject());
            return null == cls
                ? PsiReference.EMPTY_ARRAY
                : new SetterReferenceExSet(element, 1, '.', cls, false).getPsiReferences();
          }
        });

    registrar.registerReferenceProvider(
        PsiJavaPatterns.literalExpression()
            .and(
                new FilterPattern(
                    new OrFilter(
                        new StringArrayAnnotationParameterFilter(
                            STRICT_BINDING_ANNOTATION, ALLOW_ATTR),
                        new StringArrayAnnotationParameterFilter(
                            STRICT_BINDING_ANNOTATION, DENY_ATTR)))),
        new PsiReferenceProvider() {
          @NotNull
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement element, @NotNull ProcessingContext context) {
            PsiClass cls = PsiTreeUtil.getParentOfType(element, PsiClass.class);
            return null == cls
                ? PsiReference.EMPTY_ARRAY
                : new SetterReferenceExSet(element, 1, '.', cls, false) {
                  @NotNull
                  @Override
                  protected SetterReferenceEx<PsiElement> createReferenceWithBraces(
                      TextRange range, int index, boolean hasBraces) {
                    return new StrictBindingReference(range, this.isSupportBraces(), this, index);
                  }
                }.getPsiReferences();
          }
        });

    registrar.registerReferenceProvider(
        PsiJavaPatterns.literalExpression()
            .and(
                new FilterPattern(
                    new AnnotationParameterFilter(
                        PsiLiteralExpression.class, URL_BINDING_ANNOTATION, VALUE_ATTR))),
        new PsiReferenceProvider() {
          @NotNull
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement element, @NotNull ProcessingContext context) {
            PsiClass actionBeanPsiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
            String str = ElementManipulators.getValueText(element);

            if (null != actionBeanPsiClass && str.startsWith("/")) {
              final List<PsiReference> retval = new LinkedList<PsiReference>();
              for (int i = 0, eqInd = -1, lBraceInd = -1, braceStack = 0; i < str.length(); i++) {
                if (str.charAt(i) == '{') {
                  braceStack++;
                  lBraceInd = i;
                  eqInd = -1;
                } else if (str.charAt(i)
                    == '}') { // we found closing brace and need to retrieve references if possible
                  braceStack--;
                  if (braceStack != 0)
                    continue; // braces are unbalanced - we should not try to parse

                  int endInd =
                      eqInd != -1
                          ? eqInd // there's '=' sign within curly braces bounded part of string.
                                  // processign only part of text located within curl braces
                          : i; // no '=' sign found. process whole text from curly braces;

                  String txt = str.substring(1 + lBraceInd, endInd);
                  if ($EVENT.equals(txt) && eqInd == -1) {
                    retval.add(
                        new UrlBindingReference(
                            element,
                            new TextRange(1 + lBraceInd + 1, 1 + endInd),
                            actionBeanPsiClass));
                  } else {
                    //                                final PsiReference[] psiReferences = new
                    // SetterReferenceExSet(str, element, 1 + lBraceInd + 1, '.',
                    // actionBeanPsiClass, true).getPsiReferences();
                    Collections.addAll(
                        retval,
                        new UrlSetterReferenceExSet(
                                txt, element, 1 + lBraceInd + 1, '.', actionBeanPsiClass, true)
                            .getPsiReferences()
                        //                                        new UrlSetterReferenceExSet(txt,
                        // element, 1, '.', actionBeanPsiClass, true).getPsiReferences()
                        );
                  }

                  // retval.add(new UrlBindingReference(element, new TextRange(1 + lBraceInd + 1, 1
                  // + lBraceInd + 1), actionBeanPsiClass));
                } else if (str.charAt(i) == '=') {
                  eqInd = i;
                }
              }

              return retval.toArray(new PsiReference[retval.size()]);
            }

            return PsiReference.EMPTY_ARRAY;
          }
        });

    registrar.registerReferenceProvider(
        PsiJavaPatterns.literalExpression()
            .methodCallParameter(
                0,
                PsiJavaPatterns.psiMethod()
                    .definedInClass(VALIDATION_ERRORS)
                    .withName(
                        StandardPatterns.string()
                            .oneOf(ADD_METHOD, ADD_ALL_METHOD, PUT_METHOD, PUT_ALL_METHOD))),
        new PsiReferenceProvider() {
          @NotNull
          @Override
          public PsiReference[] getReferencesByElement(
              @NotNull PsiElement element, @NotNull ProcessingContext context) {
            PsiClass cls = PsiTreeUtil.getParentOfType(element, PsiClass.class);
            return null == cls
                ? PsiReference.EMPTY_ARRAY
                : new SetterReferenceExSet(element, 1, '.', cls, true).getPsiReferences();
          }
        });
  }