public static boolean hasTest(PsiModifierListOwner element) {
   return CachedValuesManager.getCachedValue(
       element,
       () ->
           CachedValueProvider.Result.create(
               hasTest(element, true), PsiModificationTracker.MODIFICATION_COUNT));
 }
 @NotNull
 @Override
 public GrReflectedMethod[] getReflectedMethods() {
   return CachedValuesManager.getCachedValue(
       this,
       new CachedValueProvider<GrReflectedMethod[]>() {
         @Override
         public Result<GrReflectedMethod[]> compute() {
           return Result.create(
               GrReflectedMethodImpl.createReflectedMethods(GrMethodBaseImpl.this),
               PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
         }
       });
 }
 @NotNull
 public static PsiMethod[] getAllMethods(final GrTypeDefinition grType) {
   return CachedValuesManager.getCachedValue(
       grType,
       new CachedValueProvider<PsiMethod[]>() {
         @Nullable
         @Override
         public Result<PsiMethod[]> compute() {
           List<PsiMethod> list = ContainerUtil.newArrayList();
           getAllMethodsInner(grType, list, new HashSet<PsiClass>());
           return Result.create(
               list.toArray(new PsiMethod[list.size()]),
               PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT,
               grType);
         }
       });
 }
 /**
  * Returns all annotations for <code>listOwner</code>, possibly walking up the method hierarchy.
  *
  * @see com.intellij.codeInsight.AnnotationUtil#isAnnotated(com.intellij.psi.PsiModifierListOwner,
  *     java.lang.String, boolean)
  */
 private static PsiAnnotation[] getAnnotations(
     @NotNull final PsiModifierListOwner listOwner, final boolean inHierarchy) {
   final PsiModifierList modifierList = listOwner.getModifierList();
   if (modifierList == null) {
     return PsiAnnotation.EMPTY_ARRAY;
   }
   if (!inHierarchy) {
     return modifierList.getAnnotations();
   }
   return CachedValuesManager.getCachedValue(
       listOwner,
       new CachedValueProvider<PsiAnnotation[]>() {
         @Nullable
         @Override
         public Result<PsiAnnotation[]> compute() {
           return Result.create(
               getHierarchyAnnotations(listOwner, modifierList),
               PsiModificationTracker.MODIFICATION_COUNT);
         }
       });
 }
 @NotNull
 public static HierarchicalMethodSignature getHierarchicalMethodSignature(final PsiMethod method) {
   return CachedValuesManager.getCachedValue(
       method,
       new CachedValueProvider<HierarchicalMethodSignature>() {
         @Nullable
         @Override
         public Result<HierarchicalMethodSignature> compute() {
           PsiClass aClass = method.getContainingClass();
           HierarchicalMethodSignature result = null;
           if (aClass != null) {
             result = getSignaturesMap(aClass).get(method.getSignature(PsiSubstitutor.EMPTY));
           }
           if (result == null) {
             result =
                 new HierarchicalMethodSignatureImpl(
                     (MethodSignatureBackedByPsiMethod) method.getSignature(PsiSubstitutor.EMPTY));
           }
           return Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
         }
       });
 }
  static PsiSubstitutor infer(
      @NotNull PsiTypeParameter[] typeParameters,
      @NotNull PsiParameter[] parameters,
      @NotNull PsiExpression[] arguments,
      @NotNull PsiSubstitutor partialSubstitutor,
      @NotNull final PsiElement parent,
      @NotNull final ParameterTypeInferencePolicy policy) {
    if (parent instanceof PsiCall) {
      final PsiExpressionList argumentList = ((PsiCall) parent).getArgumentList();
      final MethodCandidateInfo.CurrentCandidateProperties properties =
          MethodCandidateInfo.getCurrentMethod(argumentList);
      // overload resolution can't depend on outer call => should not traverse to top
      if (properties != null
          && !properties.isApplicabilityCheck()
          &&
          // in order to to avoid caching of candidates's errors on parent (!) , so check for
          // overload resolution is left here
          // But overload resolution can depend on type of lambda parameter. As it can't depend on
          // lambda body,
          // traversing down would stop at lambda level and won't take into account overloaded
          // method
          !MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argumentList)) {
        final PsiCall topLevelCall =
            PsiResolveHelper.ourGraphGuard.doPreventingRecursion(
                parent,
                false,
                new Computable<PsiCall>() {
                  @Override
                  public PsiCall compute() {
                    if (parent instanceof PsiExpression
                        && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression) parent)) {
                      return null;
                    }
                    return LambdaUtil.treeWalkUp(parent);
                  }
                });
        if (topLevelCall != null) {

          InferenceSession session;
          if (MethodCandidateInfo.isOverloadCheck()
              || !PsiDiamondType.ourDiamondGuard.currentStack().isEmpty()
              || LambdaUtil.isLambdaParameterCheck()) {
            session = startTopLevelInference(topLevelCall, policy);
          } else {
            session =
                CachedValuesManager.getCachedValue(
                    topLevelCall,
                    new CachedValueProvider<InferenceSession>() {
                      @Nullable
                      @Override
                      public Result<InferenceSession> compute() {
                        return new Result<InferenceSession>(
                            startTopLevelInference(topLevelCall, policy),
                            PsiModificationTracker.MODIFICATION_COUNT);
                      }
                    });

            if (session != null) {
              // reject cached top level session if it was based on wrong candidate: check nested
              // session if candidate (it's type parameters) are the same
              // such situations are avoided when overload resolution is performed
              // (MethodCandidateInfo.isOverloadCheck above)
              // but situations when client code iterates through
              // PsiResolveHelper.getReferencedMethodCandidates or similar are impossible to guess
              final Map<PsiElement, InferenceSession> sessions =
                  session.getInferenceSessionContainer().myNestedSessions;
              final InferenceSession childSession = sessions.get(parent);
              if (childSession != null) {
                for (PsiTypeParameter parameter : typeParameters) {
                  if (!childSession
                      .getInferenceSubstitution()
                      .getSubstitutionMap()
                      .containsKey(parameter)) {
                    session = startTopLevelInference(topLevelCall, policy);
                    break;
                  }
                }
              }
            }
          }

          if (session != null) {
            final PsiSubstitutor childSubstitutor =
                inferNested(
                    typeParameters,
                    parameters,
                    arguments,
                    partialSubstitutor,
                    (PsiCall) parent,
                    policy,
                    properties,
                    session);
            if (childSubstitutor != null) return childSubstitutor;
          } else if (topLevelCall instanceof PsiMethodCallExpression) {
            return new InferenceSession(
                    typeParameters, partialSubstitutor, parent.getManager(), parent, policy)
                .prepareSubstitution();
          }
        }
      }
    }

    final InferenceSession inferenceSession =
        new InferenceSession(
            typeParameters, partialSubstitutor, parent.getManager(), parent, policy);
    inferenceSession.initExpressionConstraints(parameters, arguments, parent);
    return inferenceSession.infer(parameters, arguments, parent);
  }