⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unusedprivatemethodrule.java

📁 检查Java程序漏洞
💻 JAVA
字号:
/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html*/package net.sourceforge.pmd.rules;import net.sourceforge.pmd.AbstractRule;import net.sourceforge.pmd.RuleContext;import net.sourceforge.pmd.ast.ASTArguments;import net.sourceforge.pmd.ast.ASTClassBody;import net.sourceforge.pmd.ast.ASTCompilationUnit;import net.sourceforge.pmd.ast.ASTInterfaceDeclaration;import net.sourceforge.pmd.ast.ASTMethodDeclarator;import net.sourceforge.pmd.ast.ASTName;import net.sourceforge.pmd.ast.ASTPrimaryExpression;import net.sourceforge.pmd.ast.ASTPrimaryPrefix;import net.sourceforge.pmd.ast.ASTPrimarySuffix;import net.sourceforge.pmd.ast.AccessNode;import net.sourceforge.pmd.ast.SimpleNode;import java.text.MessageFormat;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class UnusedPrivateMethodRule extends AbstractRule {    private Set privateMethodNodes = new HashSet();    // TODO - What I need is a Visitor that does a breadth first search    private boolean trollingForDeclarations;    private int depth;    // Skip interfaces because they have no implementation    public Object visit(ASTInterfaceDeclaration node, Object data) {        return data;    }    // Reset state when we leave an ASTCompilationUnit    public Object visit(ASTCompilationUnit node, Object data) {        depth = 0;        super.visit(node, data);        privateMethodNodes.clear();        depth = 0;        trollingForDeclarations = false;        return data;    }    public Object visit(ASTClassBody node, Object data) {        depth++;        // first troll for declarations, but only in the top level class        if (depth == 1) {            trollingForDeclarations = true;            super.visit(node, null);            trollingForDeclarations = false;        } else {            trollingForDeclarations = false;        }        // troll for usages, regardless of depth        super.visit(node, null);        // if we're back at the top level class, harvest        if (depth == 1) {            RuleContext ctx = (RuleContext) data;            harvestUnused(ctx);        }        depth--;        return data;    }    //ASTMethodDeclarator    // FormalParameters    //  FormalParameter    //  FormalParameter    public Object visit(ASTMethodDeclarator node, Object data) {        if (!trollingForDeclarations) {            return super.visit(node, data);        }        AccessNode parent = (AccessNode) node.jjtGetParent();        if (!parent.isPrivate()) {            return super.visit(node, data);        }        // exclude these serializable things        if (node.getImage().equals("readObject") || node.getImage().equals("writeObject") || node.getImage().equals("readResolve") || node.getImage().equals("writeReplace")) {            return super.visit(node, data);        }        privateMethodNodes.add(node);        return super.visit(node, data);    }    //PrimarySuffix    // Arguments    //  ArgumentList    //   Expression    //   Expression    public Object visit(ASTPrimarySuffix node, Object data) {        if (!trollingForDeclarations && (node.jjtGetParent() instanceof ASTPrimaryExpression) && (node.getImage() != null)) {            if (node.jjtGetNumChildren() > 0) {                ASTArguments args = (ASTArguments) node.jjtGetChild(0);                removeIfUsed(node.getImage(), args.getArgumentCount());                return super.visit(node, data);            }            // to handle this.foo()            //PrimaryExpression            // PrimaryPrefix            // PrimarySuffix <-- this node has "foo"            // PrimarySuffix <-- this node has null            //  Arguments            ASTPrimaryExpression parent = (ASTPrimaryExpression) node.jjtGetParent();            int pointer = 0;            while (true) {                if (parent.jjtGetChild(pointer).equals(node)) {                    break;                }                pointer++;            }            // now move to the next PrimarySuffix and get the number of arguments            pointer++;            // this.foo = foo;            // yields this:            // PrimaryExpression            //  PrimaryPrefix            //  PrimarySuffix            // so we check for that            if (parent.jjtGetNumChildren() <= pointer) {                return super.visit(node, data);            }            if (!(parent.jjtGetChild(pointer) instanceof ASTPrimarySuffix)) {                return super.visit(node, data);            }            ASTPrimarySuffix actualMethodNode = (ASTPrimarySuffix) parent.jjtGetChild(pointer);            // when does this happen?            if (actualMethodNode.jjtGetNumChildren() == 0 || !(actualMethodNode.jjtGetChild(0) instanceof ASTArguments)) {                return super.visit(node, data);            }            ASTArguments args = (ASTArguments) actualMethodNode.jjtGetChild(0);            removeIfUsed(node.getImage(), args.getArgumentCount());            // what about Outer.this.foo()?        }        return super.visit(node, data);    }    //PrimaryExpression    // PrimaryPrefix    //  Name    // PrimarySuffix    //  Arguments    public Object visit(ASTName node, Object data) {        if (!trollingForDeclarations && (node.jjtGetParent() instanceof ASTPrimaryPrefix)) {            ASTPrimaryExpression primaryExpression = (ASTPrimaryExpression) node.jjtGetParent().jjtGetParent();            if (primaryExpression.jjtGetNumChildren() > 1) {                ASTPrimarySuffix primarySuffix = (ASTPrimarySuffix) primaryExpression.jjtGetChild(1);                if (primarySuffix.jjtGetNumChildren() > 0 && (primarySuffix.jjtGetChild(0) instanceof ASTArguments)) {                    ASTArguments arguments = (ASTArguments) primarySuffix.jjtGetChild(0);                    removeIfUsed(node.getImage(), arguments.getArgumentCount());                }            }        }        return super.visit(node, data);    }    private void removeIfUsed(String nodeImage, int args) {        String img = (nodeImage.indexOf('.') == -1) ? nodeImage : nodeImage.substring(nodeImage.indexOf('.') + 1, nodeImage.length());        for (Iterator i = privateMethodNodes.iterator(); i.hasNext();) {            ASTMethodDeclarator methodNode = (ASTMethodDeclarator) i.next();            // are name and number of parameters the same?            if (methodNode.getImage().equals(img) && methodNode.getParameterCount() == args) {                // should check parameter types here, this misses some unused methods                i.remove();            }        }    }    private void harvestUnused(RuleContext ctx) {        for (Iterator i = privateMethodNodes.iterator(); i.hasNext();) {            SimpleNode node = (SimpleNode) i.next();            ctx.getReport().addRuleViolation(createRuleViolation(ctx, node.getBeginLine(), MessageFormat.format(getMessage(), new Object[]{node.getImage()})));        }    }    /*    TODO this uses the symbol table        public Object visit(ASTUnmodifiedClassDeclaration node, Object data) {            for (Iterator i = node.getScope().getUnusedMethodDeclarations();i.hasNext();) {                VariableNameDeclaration decl = (VariableNameDeclaration)i.next();                // exclude non-private methods and serializable methods                if (!decl.getAccessNodeParent().isPrivate() || decl.getImage().equals("readObject") || decl.getImage().equals("writeObject")|| decl.getImage().equals("readResolve")) {                    continue;                }                RuleContext ctx = (RuleContext)data;                ctx.getReport().addRuleViolation(createRuleViolation(ctx, decl.getNode().getBeginLine(), MessageFormat.format(getMessage(), new Object[] {decl.getNode().getImage()})));            }            return super.visit(node, data);        }    */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -