Make getText @NoAttribute

This commit is contained in:
Clément Fournier
2020-04-24 01:24:02 +02:00
parent 13b7fa6152
commit f779688cab
7 changed files with 83 additions and 105 deletions

View File

@@ -9,6 +9,8 @@ import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
import net.sourceforge.pmd.lang.ast.TextAvailableNode;
import net.sourceforge.pmd.lang.ast.xpath.NoAttribute;
import net.sourceforge.pmd.util.DataMap;
import net.sourceforge.pmd.util.DataMap.DataKey;
@@ -44,10 +46,10 @@ public abstract class AntlrBaseInnerNode<
}
/**
* TODO @NoAttribute (port swift rules)
* @see TextAvailableNode
*/
@Override
@SuppressWarnings("PMD.UselessOverridingMethod")
@NoAttribute
public String getText() {
return super.getText();
}

View File

@@ -13,7 +13,15 @@ import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public class AntlrNameDictionary implements Vocabulary {
/**
* Stores the XPath name of antlr terminals. I found no simple way to
* give names to punctuation (we could add a lexer rule, but it may
* conflict with other tokens). So their names are hardcoded here.
*
* <p>Terminal names start with {@code "T-"} in XPath to avoid conflicts
* with other stuff.
*/
public class AntlrNameDictionary {
private final String[] xpathNames;
private final Vocabulary vocabulary;
@@ -47,23 +55,77 @@ public class AntlrNameDictionary implements Vocabulary {
assert Stream.of(xpathNames).distinct().count() == xpathNames.length
: "Duplicate names in "+ Arrays.toString(xpathNames);
: "Duplicate names in " + Arrays.toString(xpathNames);
}
private static @Nullable String maybePunctName(String s) {
public Vocabulary getVocabulary() {
return vocabulary;
}
protected @Nullable String maybePunctName(String s) {
// these are hardcoded, but it's overridable
// here we try to avoid semantic overtones, because
// a-priori the same terminal may mean several things
// in different contexts.
switch (s) {
case "!": return "bang";
case "!!": return "double-bang";
case "?": return "question";
case "??": return "double-question";
case "?:": return "elvis";
case "?.": return "question-dot";
case ":": return "colon";
case ";": return "semi";
case ",": return "comma";
case "(": return "lparen";
case ")": return "rparen";
case "[": return "lbracket";
case "]": return "rbracket";
case "{": return "lbrace";
case "}": return "rbrace";
case "_": return "underscore";
case ".": return "dot";
case "..": return "double-dot";
case "...": return "ellipsis";
case "@": return "at-symbol";
case "$": return "dollar";
case "\\": return "backslash";
case "/": return "slash";
case "//": return "double-slash";
case "`": return "backtick";
case "'": return "squote";
case "\"": return "dquote";
case ">": return "gt";
case ">=": return "ge";
case "<": return "lt";
case "<=": return "le";
case "=": return "eq";
case "==": return "double-eq";
case "===": return "triple-eq";
case "!=": return "not-eq";
case ">>": return "double-gt";
case "<<": return "double-lt";
case ">>>": return "triple-gt";
case "<<<": return "triple-lt";
case "*": return "star";
case "**": return "double-star";
case "+": return "plus";
case "-": return "minus";
case "->": return "rarrow";
case "<-": return "larrow";
}
return null;
}
@@ -80,23 +142,7 @@ public class AntlrNameDictionary implements Vocabulary {
throw new IllegalArgumentException("I don't know token type " + tokenType);
}
@Override
public int getMaxTokenType() {
return vocabulary.getMaxTokenType();
}
@Override
public String getLiteralName(int tokenType) {
return vocabulary.getLiteralName(tokenType);
}
@Override
public String getSymbolicName(int tokenType) {
return vocabulary.getSymbolicName(tokenType);
}
@Override
public String getDisplayName(int tokenType) {
return vocabulary.getDisplayName(tokenType);
}
}

View File

@@ -6,15 +6,14 @@ package net.sourceforge.pmd.lang.ast.impl.antlr4;
import org.antlr.v4.runtime.tree.ParseTree;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.NodeStream;
import net.sourceforge.pmd.lang.ast.TextAvailableNode;
/**
* Base interface for all Antlr-based implementation of Node interface.
* <p>
* Initially all the methods implemented here will be no-op due to scope limitations
*/
public interface AntlrNode extends Node, ParseTree {
public interface AntlrNode extends ParseTree, TextAvailableNode {
@Override
@@ -23,13 +22,4 @@ public interface AntlrNode extends Node, ParseTree {
@Override
AntlrNode getParent();
@Override
@SuppressWarnings("unchecked")
default NodeStream<? extends AntlrNode> children() {
return (NodeStream<? extends AntlrNode>) Node.super.children();
}
}

View File

@@ -25,6 +25,12 @@ public abstract class PmdAntlrTerminalNode extends TerminalNodeImpl implements A
this.dico = dico;
}
// not @NoAttribute
@Override
public String getText() {
return super.getText();
}
@Override
public AntlrNode getChild(int i) {
return null;

View File

@@ -1,62 +0,0 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.swift.rule.bestpractices;
import java.util.List;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.swift.AbstractSwiftRule;
import net.sourceforge.pmd.lang.swift.ast.SwiftBaseVisitor;
import net.sourceforge.pmd.lang.swift.ast.SwiftParser.AttributeContext;
import net.sourceforge.pmd.lang.swift.ast.SwiftParser.FunctionHeadContext;
import net.sourceforge.pmd.lang.swift.ast.SwiftParser.VariableDeclarationHeadContext;
public class ProhibitedInterfaceBuilderRule extends AbstractSwiftRule {
private static final String IBACTION = "@IBAction";
private static final String IBOUTLET = "@IBOutlet";
public ProhibitedInterfaceBuilderRule() {
super();
addRuleChainVisit(FunctionHeadContext.class);
addRuleChainVisit(VariableDeclarationHeadContext.class);
}
@Override
public SwiftBaseVisitor<Void> buildVisitor(RuleContext ruleCtx) {
return new SwiftBaseVisitor<Void>() {
@Override
public Void visitFunctionHead(FunctionHeadContext ctx) {
if (ctx == null || ctx.attributes() == null) {
return null;
}
return visitDeclarationHead(ctx, ctx.attributes().attribute(), IBACTION);
}
@Override
public Void visitVariableDeclarationHead(final VariableDeclarationHeadContext ctx) {
if (ctx == null || ctx.attributes() == null) {
return null;
}
return visitDeclarationHead(ctx, ctx.attributes().attribute(), IBOUTLET);
}
private Void visitDeclarationHead(final Node node, final List<AttributeContext> attributes,
final String match) {
final boolean violate = attributes.stream().anyMatch(atr -> match.equals(atr.getText()));
if (violate) {
addViolation(ruleCtx, node);
}
return null;
}
};
}
}

View File

@@ -26,9 +26,9 @@ Rules which enforce generally accepted best practices.
<property name="version" value="2.0" />
<property name="xpath">
<value>
//VariableDeclarationHead/Attributes/Attribute[T-at-symbol and AttributeName/@Text = "IBOutlet"]
//VariableDeclarationHead/Attributes/Attribute[T-at-symbol and AttributeName/*/T-Identifier/@Text = "IBOutlet"]
|
//FunctionHead/Attributes/Attribute[T-at-symbol and AttributeName/@Text = "IBAction"]
//FunctionHead/Attributes/Attribute[T-at-symbol and AttributeName/*/T-Identifier/@Text = "IBAction"]
</value>
</property>
</properties>

View File

@@ -16,8 +16,7 @@ class ViewController: UIViewController {
}
}
]]></code>
<source-type>swift</source-type>
</test-code>
</test-code>
<test-code>
<description><![CDATA[
Good example #2
@@ -35,8 +34,7 @@ func jsonValue(_ jsonString: String) -> NSObject {
fatalError()
}
]]></code>
<source-type>swift</source-type>
</test-code>
</test-code>
<test-code>
<description><![CDATA[
Bad example #1
@@ -49,8 +47,7 @@ class ViewController: UIViewController {
}
}
]]></code>
<source-type>swift</source-type>
</test-code>
</test-code>
<test-code>
<description><![CDATA[
Bad example #2
@@ -61,6 +58,5 @@ func doSomething() {
fatalError("doSomething() has not been implemented")
}
]]></code>
<source-type>swift</source-type>
</test-code>
</test-code>
</test-data>