private static boolean processField(
      @NotNull GrTypeDefinition grType,
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @NotNull PsiElement place,
      boolean processInstanceMethods,
      @NotNull PsiSubstitutor substitutor,
      @NotNull PsiElementFactory factory,
      @NotNull LanguageLevel level,
      CandidateInfo fieldInfo) {
    final PsiField field = (PsiField) fieldInfo.getElement();
    if (!processInstanceMember(processInstanceMethods, field) || isSameDeclaration(place, field)) {
      return true;
    }
    LOG.assertTrue(field.getContainingClass() != null);
    final PsiSubstitutor finalSubstitutor =
        PsiClassImplUtil.obtainFinalSubstitutor(
            field.getContainingClass(),
            fieldInfo.getSubstitutor(),
            grType,
            substitutor,
            factory,
            level);

    return processor.execute(field, state.put(PsiSubstitutor.KEY, finalSubstitutor));
  }
  @Nullable
  public static PsiField findFieldByName(
      GrTypeDefinition grType, String name, boolean checkBases, boolean includeSynthetic) {
    if (!checkBases) {
      for (PsiField field : CollectClassMembersUtil.getFields(grType, includeSynthetic)) {
        if (name.equals(field.getName())) return field;
      }

      return null;
    }

    Map<String, CandidateInfo> fieldsMap =
        CollectClassMembersUtil.getAllFields(grType, includeSynthetic);
    final CandidateInfo info = fieldsMap.get(name);
    return info == null ? null : (PsiField) info.getElement();
  }
  public static boolean processDeclarations(
      @NotNull GrTypeDefinition grType,
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @Nullable PsiElement lastParent,
      @NotNull PsiElement place) {
    if (place instanceof GrCodeReferenceElement && lastParent instanceof GrModifierList) {
      final PsiElement possibleAnnotation =
          PsiTreeUtil.skipParentsOfType(place, GrCodeReferenceElement.class);
      if (possibleAnnotation instanceof GrAnnotation
          && possibleAnnotation.getParent() == lastParent) {
        return true; // don't process class members while resolving annotation which annotates
                     // current class
      }
    }

    for (final PsiTypeParameter typeParameter : grType.getTypeParameters()) {
      if (!processElement(processor, typeParameter, state)) return false;
    }

    NameHint nameHint = processor.getHint(NameHint.KEY);
    String name = nameHint == null ? null : nameHint.getName(state);
    ClassHint classHint = processor.getHint(ClassHint.KEY);
    final PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());

    boolean processInstanceMethods =
        (shouldProcessMethods(classHint) || shouldProcessProperties(classHint))
            && shouldProcessInstanceMembers(grType, lastParent);

    LanguageLevel level = PsiUtil.getLanguageLevel(place);
    if (shouldProcessProperties(classHint)) {
      Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
      if (name != null) {
        CandidateInfo fieldInfo = fieldsMap.get(name);
        if (fieldInfo != null) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              fieldInfo)) {
            return false;
          }
        } else if (grType.isTrait() && lastParent != null) {
          PsiField field = findFieldByName(grType, name, false, true);
          if (field != null && field.hasModifierProperty(PsiModifier.PUBLIC)) {
            if (!processField(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
              return false;
            }
          }
        }
      } else {
        for (CandidateInfo info : fieldsMap.values()) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              info)) {
            return false;
          }
        }
        if (grType.isTrait() && lastParent != null) {
          for (PsiField field : CollectClassMembersUtil.getFields(grType, true)) {
            if (field.hasModifierProperty(PsiModifier.PUBLIC)) {
              if (!processField(
                  grType,
                  processor,
                  state,
                  place,
                  processInstanceMethods,
                  substitutor,
                  factory,
                  level,
                  new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
                return false;
              }
            }
          }
        }
      }
    }

    if (shouldProcessMethods(classHint)) {
      Map<String, List<CandidateInfo>> methodsMap =
          CollectClassMembersUtil.getAllMethods(grType, true);
      boolean isPlaceGroovy = place.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
      if (name == null) {
        for (List<CandidateInfo> list : methodsMap.values()) {
          for (CandidateInfo info : list) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      } else {
        List<CandidateInfo> byName = methodsMap.get(name);
        if (byName != null) {
          for (CandidateInfo info : byName) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      }
    }

    final GrTypeDefinitionBody body = grType.getBody();
    if (body != null) {
      if (shouldProcessClasses(classHint)) {
        for (PsiClass innerClass : getInnerClassesForResolve(grType, lastParent, place)) {
          final String innerClassName = innerClass.getName();
          if (nameHint != null && !innerClassName.equals(nameHint.getName(state))) {
            continue;
          }

          if (!processor.execute(innerClass, state)) {
            return false;
          }
        }
      }
    }

    return true;
  }