View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.pmd.rules;
6   
7   import java.util.List;
8   import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
9   import net.sourceforge.pmd.lang.java.ast.ASTBlock;
10  import net.sourceforge.pmd.lang.java.ast.ASTExpression;
11  import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement;
12  import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
13  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
14  
15  /**
16   * Rule to check unnecessary local variables.
17   *
18   * @since 0.4
19   */
20  public final class UnnecessaryLocalRule extends AbstractJavaRulechainRule {
21      public UnnecessaryLocalRule() {
22          super(ASTVariableDeclarator.class);
23      }
24  
25      @Override
26      public Object visit(
27          final ASTVariableDeclarator variable,
28          final Object data
29      ) {
30          if (variable.getInitializer() != null) {
31              final String name = variableName(variable);
32              if (!name.isEmpty()) {
33                  asCtx(data).addViolation(variable, name);
34              }
35          }
36          return data;
37      }
38  
39      private static boolean hasReturnOrArguments(
40          final List<ASTExpression> exprs
41      ) {
42          boolean result = false;
43          if (exprs.size() == 1) {
44              final ASTExpression use = exprs.get(0);
45              if (use.ancestors(ASTReturnStatement.class).toStream()
46                  .findAny().isPresent()
47                  || use.ancestors(ASTArgumentList.class).toStream()
48                  .findAny().isPresent()
49              ) {
50                  result = true;
51              }
52          }
53          return result;
54      }
55  
56      private static String variableName(final ASTVariableDeclarator variable) {
57          String result = "";
58          final ASTBlock block = variable.ancestors(ASTBlock.class).first();
59          if (block != null) {
60              final String name = variable.getName();
61              final List<ASTExpression> uses = block
62                  .descendants(ASTExpression.class)
63                  .filter(expr -> name.equals(expr.getImage()))
64                  .toList();
65              if (hasReturnOrArguments(uses)) {
66                  result = name;
67              }
68          }
69          return result;
70      }
71  }