PsiElementVisitor (@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)); } } } }; }