added Antlr visitor infrastructure and swift implementation

This commit is contained in:
lsoncini
2019-02-25 18:34:51 -03:00
parent 47bc813caf
commit 8255af258f
5 changed files with 186 additions and 2 deletions

View File

@ -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<T> extends AbstractRule implements ParseTreeVisitor<T> {
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<? extends Node> nodes, RuleContext ctx) {
visitAll(nodes);
}
protected void visitAll(List<? extends Node> nodes) {
for (Node n : nodes) {
AntlrBaseNode node = (AntlrBaseNode) n;
visit(node);
}
}
public Object visit(final AntlrBaseNode node) {
return node.accept(this);
}
}

View File

@ -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<Node> nodes, RuleContext ctx) {
final AbstractAntlrVisitor antlrVisitor = new AbstractAntlrVisitor<Object>() {
// 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));
}
}
}

View File

@ -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<AntlrBaseNode> violation = new ParametricRuleViolation<>(rule, ruleContext,
(AntlrBaseNode) node, message);
violation.setLines(beginLine, endLine);
return violation;
}
}

View File

@ -1,10 +1,17 @@
<project name="pmd" default="antlr4" basedir="../../../../">
<property name="target-package-dir" value="${target}/net/sourceforge/pmd/lang/swift/antlr4" />
<target name="antlr4" description="Generates all Antlr4 aspects within PMD">
<replace file="${target-package-dir}/SwiftParser.java"
token="extends ParserRuleContext"
value="extends net.sourceforge.pmd.lang.ast.AntlrBaseNode" />
<replace file="${target-package-dir}/SwiftBaseVisitor.java"
token="extends AbstractParseTreeVisitor"
value="extends AbstractAntlrVisitor" />
<replace file="${target-package-dir}/SwiftBaseVisitor.java"
token="public class SwiftBaseVisitor"
value="public abstract class SwiftBaseVisitor" />
<replace file="${target-package-dir}/SwiftBaseVisitor.java"
token="import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;"
value="import net.sourceforge.pmd.lang.antlr.AbstractAntlrVisitor;" />
</target>
</project>

View File

@ -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<T> extends SwiftBaseVisitor<T> {
public AbstractSwiftRule() {
super.setLanguage(LanguageRegistry.getLanguage(SwiftLanguageModule.NAME));
}
}