@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly,
                                                 @NotNull LocalInspectionToolSession session) {
    return new JavaElementVisitor() {
      @Override
      public void visitExpression(@NotNull PsiExpression expression) {
        super.visitExpression(expression);

        if (expression instanceof PsiParenthesizedExpression) {
          return;
        }
        visitExpressionImpl(expression);
      }

      @Override
      public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
        super.visitReferenceExpression(expression);

        if (expression.getParent() instanceof PsiCallExpression) {
          return;
        }
        visitExpressionImpl(expression);
      }

      public void visitExpressionImpl(PsiExpression expression) {
        if (ComplexityCalculator.isDefinitelySimple(expression) ||
            SideEffectCalculator.isDefinitelyWithSideEffect(expression) ||
            expression instanceof PsiLambdaExpression ||
            ExpressionUtils.isVoidContext(expression)) {
          return;
        }
        DuplicateExpressionsContext context = DuplicateExpressionsContext.getOrCreateContext(expression, session);
        if (context == null || context.mayHaveSideEffect(expression)) {
          return;
        }
        if (context.getComplexity(expression) > complexityThreshold) {
          context.addOccurrence(expression);
        }
      }

      @Override
      public void visitMethod(@NotNull PsiMethod method) {
        super.visitMethod(method);

        PsiCodeBlock body = method.getBody();
        if (body != null) {
          registerProblemsForExpressions(body, session);
        }
      }

      @Override
      public void visitClassInitializer(@NotNull PsiClassInitializer initializer) {
        super.visitClassInitializer(initializer);

        registerProblemsForExpressions(initializer.getBody(), session);
      }

      @Override
      public void visitLambdaExpression(@NotNull PsiLambdaExpression expression) {
        super.visitLambdaExpression(expression);

        PsiElement body = expression.getBody();
        if (body instanceof PsiCodeBlock) {
          registerProblemsForExpressions((PsiCodeBlock)body, session);
        }
      }

      public void registerProblemsForExpressions(@NotNull PsiCodeBlock body, @NotNull UserDataHolder session) {
        DuplicateExpressionsContext context = DuplicateExpressionsContext.getContext(body, session);
        if (context == null) return;

        Set<PsiExpression> processed = new HashSet<>();
        context.forEach((pattern, occurrences) -> {
          if (!processed.contains(pattern)) {
            processed.addAll(occurrences);
            registerProblems(occurrences, body);
          }
        });
      }

      public void registerProblems(@NotNull List<? extends PsiExpression> occurrences, @NotNull PsiCodeBlock body) {
        if (occurrences.size() > 1 && areSafeToExtract(occurrences, body)) {
          Map<PsiExpression, List<PsiVariable>> reusableVariables = collectReusableVariables(occurrences);
          for (PsiExpression occurrence : occurrences) {
            List<LocalQuickFix> fixes = new ArrayList<>();
            List<PsiVariable> variables = reusableVariables.get(occurrence);
            if (variables != null) {
              for (PsiVariable variable : variables) {
                fixes.add(new ReuseVariableFix(occurrence, variable));
              }
            }
            PsiVariable variable = findVariableByInitializer(occurrence);
            if (variable != null && canReplaceOtherOccurrences(occurrence, occurrences, variable)) {
              fixes.add(new ReplaceOtherOccurrencesFix(occurrence, variable));
            }
            else if (isOnTheFly) {
              fixes.add(new IntroduceVariableFix(occurrence));
            }
            holder.registerProblem(occurrence, JavaBundle.message("inspection.duplicate.expressions.message"),
                                   fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
          }
        }
      }
    };
  }
@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
                                                 boolean isOnTheFly,
                                                 @NotNull LocalInspectionToolSession session)