From f779688cab29279b30e26b2e9d0f0ee3f63ebc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 24 Apr 2020 01:24:02 +0200 Subject: [PATCH] Make getText @NoAttribute --- .../ast/impl/antlr4/AntlrBaseInnerNode.java | 6 +- .../ast/impl/antlr4/AntlrNameDictionary.java | 84 ++++++++++++++----- .../pmd/lang/ast/impl/antlr4/AntlrNode.java | 14 +--- .../ast/impl/antlr4/PmdAntlrTerminalNode.java | 6 ++ .../ProhibitedInterfaceBuilderRule.java | 62 -------------- .../category/swift/bestpractices.xml | 4 +- .../bestpractices/xml/UnavailableFunction.xml | 12 +-- 7 files changed, 83 insertions(+), 105 deletions(-) delete mode 100644 pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseInnerNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseInnerNode.java index 3deadf5cc3..39860ff648 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseInnerNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseInnerNode.java @@ -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(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNameDictionary.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNameDictionary.java index 41c225b745..473a2f5008 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNameDictionary.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNameDictionary.java @@ -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. + * + *

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); - } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java index 96a23c80a3..b450666e76 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java @@ -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. *

* 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 children() { - return (NodeStream) Node.super.children(); - } - - } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/PmdAntlrTerminalNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/PmdAntlrTerminalNode.java index c0ea6e1d74..21eb88da78 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/PmdAntlrTerminalNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/PmdAntlrTerminalNode.java @@ -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; diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java deleted file mode 100644 index f3e3e9ac00..0000000000 --- a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java +++ /dev/null @@ -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 buildVisitor(RuleContext ruleCtx) { - return new SwiftBaseVisitor() { - - @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 attributes, - final String match) { - - final boolean violate = attributes.stream().anyMatch(atr -> match.equals(atr.getText())); - if (violate) { - addViolation(ruleCtx, node); - } - - return null; - } - }; - } -} diff --git a/pmd-swift/src/main/resources/category/swift/bestpractices.xml b/pmd-swift/src/main/resources/category/swift/bestpractices.xml index 9adf59fee4..fded26b5ed 100644 --- a/pmd-swift/src/main/resources/category/swift/bestpractices.xml +++ b/pmd-swift/src/main/resources/category/swift/bestpractices.xml @@ -26,9 +26,9 @@ Rules which enforce generally accepted best practices. - //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"] diff --git a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/rule/bestpractices/xml/UnavailableFunction.xml b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/rule/bestpractices/xml/UnavailableFunction.xml index 8c9210ec87..01c07c973f 100644 --- a/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/rule/bestpractices/xml/UnavailableFunction.xml +++ b/pmd-swift/src/test/resources/net/sourceforge/pmd/lang/swift/rule/bestpractices/xml/UnavailableFunction.xml @@ -16,8 +16,7 @@ class ViewController: UIViewController { } } ]]> - swift - + NSObject { fatalError() } ]]> - swift - + - swift - + - swift - + \ No newline at end of file