diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java new file mode 100644 index 0000000000..6694ae1c0b --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java @@ -0,0 +1,85 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.antlr; + +import java.util.List; + +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; +import org.antlr.v4.runtime.tree.RuleNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.ast.AntlrBaseNode; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.AbstractRule; + +public abstract class AbstractAntlrVisitor extends AbstractRule implements ParseTreeVisitor { + + protected RuleContext data; + + @Override + public void start(RuleContext ctx) { + data = ctx; + } + + @Override + public T visit(ParseTree tree) { + return tree.accept(this); + } + + @Override + public T visitChildren(RuleNode node) { + T result = this.defaultResult(); + int n = node.getChildCount(); + + for (int i = 0; i < n && this.shouldVisitNextChild(node, result); ++i) { + ParseTree c = node.getChild(i); + T childResult = c.accept(this); + result = this.aggregateResult(result, childResult); + } + + return result; + } + + @Override + public T visitTerminal(TerminalNode node) { + return this.defaultResult(); + } + + @Override + public T visitErrorNode(ErrorNode node) { + return this.defaultResult(); + } + + protected T defaultResult() { + return null; + } + + protected T aggregateResult(T aggregate, T nextResult) { + return nextResult; + } + + protected boolean shouldVisitNextChild(RuleNode node, T currentResult) { + return true; + } + + @Override + public void apply(List nodes, RuleContext ctx) { + visitAll(nodes); + } + + protected void visitAll(List nodes) { + for (Node n : nodes) { + AntlrBaseNode node = (AntlrBaseNode) n; + visit(node); + } + } + + public Object visit(final AntlrBaseNode node) { + return node.accept(this); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java new file mode 100644 index 0000000000..ba24b30575 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java @@ -0,0 +1,42 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.antlr; + +import java.util.List; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.ast.AntlrBaseNode; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.AbstractRuleChainVisitor; +import net.sourceforge.pmd.lang.rule.XPathRule; + +public class AntlrRuleChainVisitor extends AbstractRuleChainVisitor { + @Override + protected void visit(Rule rule, Node node, RuleContext ctx) { + if (rule instanceof AbstractAntlrVisitor) { + ((AntlrBaseNode) node).accept((AbstractAntlrVisitor) rule); + } else { + ((XPathRule) rule).evaluate(node, ctx); + } + } + + @Override + protected void indexNodes(List nodes, RuleContext ctx) { + final AbstractAntlrVisitor antlrVisitor = new AbstractAntlrVisitor() { + // Perform a visitation of the AST to index nodes which need + // visiting by type + @Override + public Object visit(final AntlrBaseNode node) { + indexNode(node); + return super.visit(node); + } + }; + + for (int i = 0; i < nodes.size(); i++) { + antlrVisitor.visit((AntlrBaseNode) nodes.get(i)); + } + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java new file mode 100644 index 0000000000..8d2584643e --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java @@ -0,0 +1,36 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.antlr; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleViolation; +import net.sourceforge.pmd.lang.ast.AntlrBaseNode; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.rule.AbstractRuleViolationFactory; +import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; +import net.sourceforge.pmd.lang.rule.RuleViolationFactory; + +public final class AntlrRuleViolationFactory extends AbstractRuleViolationFactory { + public static final RuleViolationFactory INSTANCE = new AntlrRuleViolationFactory(); + + private AntlrRuleViolationFactory() { + } + + @Override + protected RuleViolation createRuleViolation(final Rule rule, final RuleContext ruleContext, final Node node, + final String message) { + return new ParametricRuleViolation<>(rule, ruleContext, (AntlrBaseNode) node, message); + } + + @Override + protected RuleViolation createRuleViolation(final Rule rule, final RuleContext ruleContext, final Node node, + final String message, final int beginLine, final int endLine) { + final ParametricRuleViolation violation = new ParametricRuleViolation<>(rule, ruleContext, + (AntlrBaseNode) node, message); + violation.setLines(beginLine, endLine); + return violation; + } +} diff --git a/pmd-swift/src/main/ant/antlr4.xml b/pmd-swift/src/main/ant/antlr4.xml index 60f6be9a3b..bd54620a73 100644 --- a/pmd-swift/src/main/ant/antlr4.xml +++ b/pmd-swift/src/main/ant/antlr4.xml @@ -1,10 +1,17 @@ - - + + + \ No newline at end of file diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java new file mode 100644 index 0000000000..62c94cc4a6 --- /dev/null +++ b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java @@ -0,0 +1,14 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.swift; + +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.swift.antlr4.SwiftBaseVisitor; + +public abstract class AbstractSwiftRule extends SwiftBaseVisitor { + public AbstractSwiftRule() { + super.setLanguage(LanguageRegistry.getLanguage(SwiftLanguageModule.NAME)); + } +}