void checkExpression(PsiExpression expression, ProblemsHolder holder, Pair<String, ? extends Set<String>> annotationName) {
    final PsiType type = expression.getType();
    if (type == null || !PsiUtilEx.isInjectionTargetType(type)) {
      return;
    }

    final PsiModifierListOwner contextOwner = AnnotationUtilEx.getAnnotatedElementFor(expression, AnnotationUtilEx.LookupType.CONTEXT_ONLY);
    if (contextOwner != null && PsiUtilEx.isLanguageAnnotationTarget(contextOwner)) {
      final PsiAnnotation[] annotations = AnnotationUtilEx.getAnnotationFrom(contextOwner, annotationName, true);
      if (annotations.length > 0) {
        final String expected = AnnotationUtilEx.calcAnnotationValue(annotations, "value");
        if (expected != null) {
          final PsiModifierListOwner declOwner =
              AnnotationUtilEx.getAnnotatedElementFor(expression, AnnotationUtilEx.LookupType.PREFER_DECLARATION);
          if (declOwner != null && PsiUtilEx.isLanguageAnnotationTarget(declOwner)) {
            final PsiAnnotation[] as = AnnotationUtilEx.getAnnotationFrom(declOwner, annotationName, true);
            if (as.length > 0) {
              final String actual = AnnotationUtilEx.calcAnnotationValue(as, "value");
              if (!expected.equals(actual)) {
                // language annotation values from context and declaration don't match
                holder.registerProblem(expression, IntelliLangBundle.message("inspection.language.mismatch.description", expected, actual));
              }
            }
            else if (CHECK_NON_ANNOTATED_REFERENCES) {
              final PsiElement decl =
                  PsiTreeUtil.getParentOfType(expression, PsiVariable.class, PsiExpressionList.class, PsiAssignmentExpression.class);
              // only nag about direct assignment or passing the reference as parameter
              if (decl instanceof PsiVariable variable) {
                if (variable.getInitializer() != expression) {
                  return;
                }
                if (JavaPsiStringTemplateUtil.isStrTemplate(expression)) {
                  // Allow reassigning STR processor to apply language for standard concatenation
                  return;
                }
              }
              else if (decl instanceof PsiExpressionList list) {
                if (!ArrayUtil.contains(expression, list.getExpressions())) {
                  return;
                }
              }
              else if (decl instanceof PsiAssignmentExpression a) {
                if (a.getRExpression() != expression) {
                  return;
                }
              }
              if (declOwner instanceof PsiField && CollectionUtils.isConstantEmptyArray((PsiField)declOwner)) {
                // don't warn about unannotated empty array constants.
                return;
              }
              // context implies language, but declaration isn't annotated
              final PsiAnnotation annotation = annotations[annotations.length - 1];
              String fqn = Objects.requireNonNull(annotation.getQualifiedName());
              List<LocalQuickFix> fixes = new SmartList<>();
              PsiModifierListOwner owner = AnnotationUtilEx.getAnnotatedElementFor(expression, AnnotationUtilEx.LookupType.PREFER_DECLARATION);
              if (owner != null && AddAnnotationPsiFix.isAvailable(owner, fqn)) {
                fixes.add(new AddAnnotationFix(fqn, owner, annotation.getParameterList().getAttributes()));
              }
              holder.registerProblem(expression, IntelliLangBundle.message("inspection.language.problem.description", expected),
                                     fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
            }
          }
        }
      }
    }
  }
void checkExpression(PsiExpression expression, ProblemsHolder holder, Pair<String, ? extends Set<String>> annotationName)