1
2
3
4 package net.sourceforge.pmd.lang.vm.rule.basic;
5
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9
10 import net.sourceforge.pmd.lang.vm.ast.ASTBlock;
11 import net.sourceforge.pmd.lang.vm.ast.ASTDirective;
12 import net.sourceforge.pmd.lang.vm.ast.ASTReference;
13 import net.sourceforge.pmd.lang.vm.ast.ASTStringLiteral;
14 import net.sourceforge.pmd.lang.vm.rule.AbstractVmRule;
15
16 public class UnusedMacroParameterRule extends AbstractVmRule {
17
18 @Override
19 public Object visit(final ASTDirective node, final Object data) {
20 if ("macro".equals(node.getDirectiveName())) {
21 final Set<String> paramNames = new HashSet<String>();
22 final List<ASTReference> params = node.findChildrenOfType(ASTReference.class);
23 for (final ASTReference param : params) {
24 paramNames.add(param.literal());
25 }
26 final ASTBlock macroBlock = node.getFirstChildOfType(ASTBlock.class);
27 if (macroBlock != null) {
28 for (final ASTReference referenceInMacro : macroBlock.findDescendantsOfType(ASTReference.class)) {
29 checkForParameter(paramNames, referenceInMacro.literal());
30 }
31 for (final ASTStringLiteral literalInMacro : macroBlock.findDescendantsOfType(ASTStringLiteral.class)) {
32 final String text = literalInMacro.literal();
33 checkForParameter(paramNames, text);
34 }
35 }
36 if (!paramNames.isEmpty()) {
37 addViolation(data, node, paramNames.toString());
38 }
39 }
40 return super.visit(node, data);
41 }
42
43 private void checkForParameter(final Set<String> paramNames, final String nameToSearch) {
44 final Set<String> paramsContained = new HashSet<String>();
45 for (final String param : paramNames) {
46 if (containsAny(nameToSearch, formatNameVariations(param))) {
47 paramsContained.add(param);
48 }
49 }
50 paramNames.removeAll(paramsContained);
51 }
52
53 private boolean containsAny(final String text, final String[] formatNameVariations) {
54 for (final String formattedName : formatNameVariations) {
55 if (text.contains(formattedName)) {
56 return true;
57 }
58 }
59 return false;
60 }
61
62 private String[] formatNameVariations(final String param) {
63 final String actualName = param.substring(1);
64 return new String[] {param, "${" + actualName + "}", "${" + actualName + ".", "$!" + actualName,
65 "$!{" + actualName + ".", "$!{" + actualName + "}"};
66 }
67 }