/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.vm.rule.basic;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.sourceforge.pmd.lang.vm.ast.ASTBlock;
import net.sourceforge.pmd.lang.vm.ast.ASTDirective;
import net.sourceforge.pmd.lang.vm.ast.ASTReference;
import net.sourceforge.pmd.lang.vm.ast.ASTStringLiteral;
import net.sourceforge.pmd.lang.vm.rule.AbstractVmRule;
public class UnusedMacroParameterRule extends AbstractVmRule {
@Override
public Object visit(final ASTDirective node, final Object data) {
if ("macro".equals(node.getDirectiveName())) {
final Set<String> paramNames = new HashSet<>();
final List<ASTReference> params = node.findChildrenOfType(ASTReference.class);
for (final ASTReference param : params) {
paramNames.add(param.literal());
}
final ASTBlock macroBlock = node.getFirstChildOfType(ASTBlock.class);
if (macroBlock != null) {
for (final ASTReference referenceInMacro : macroBlock.findDescendantsOfType(ASTReference.class)) {
checkForParameter(paramNames, referenceInMacro.literal());
}
for (final ASTStringLiteral literalInMacro : macroBlock.findDescendantsOfType(ASTStringLiteral.class)) {
final String text = literalInMacro.literal();
checkForParameter(paramNames, text);
}
}
if (!paramNames.isEmpty()) {
addViolation(data, node, paramNames.toString());
}
}
return super.visit(node, data);
}
private void checkForParameter(final Set<String> paramNames, final String nameToSearch) {
final Set<String> paramsContained = new HashSet<>();
for (final String param : paramNames) {
if (containsAny(nameToSearch, formatNameVariations(param))) {
paramsContained.add(param);
}
}
paramNames.removeAll(paramsContained);
}
private boolean containsAny(final String text, final String[] formatNameVariations) {
for (final String formattedName : formatNameVariations) {
if (text.contains(formattedName)) {
return true;
}
}
return false;
}
private String[] formatNameVariations(final String param) {
final String actualName = param.substring(1);
return new String[] { param, "${" + actualName + "}", "${" + actualName + ".", "$!" + actualName,
"$!{" + actualName + ".", "$!{" + actualName + "}", };
}
}