Fix name dictionary (all tokens need a name)
This commit is contained in:
@ -5,6 +5,9 @@
|
|||||||
package net.sourceforge.pmd.lang.ast.impl.antlr4;
|
package net.sourceforge.pmd.lang.ast.impl.antlr4;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
import org.antlr.v4.runtime.ParserRuleContext;
|
||||||
@ -35,10 +38,13 @@ public class AntlrNameDictionary {
|
|||||||
for (int i = 0; i < nonTermXpathNames.length; i++) {
|
for (int i = 0; i < nonTermXpathNames.length; i++) {
|
||||||
nonTermXpathNames[i] = StringUtils.capitalize(ruleNames[i]);
|
nonTermXpathNames[i] = StringUtils.capitalize(ruleNames[i]);
|
||||||
}
|
}
|
||||||
|
Set<String> seen = new HashSet<>();
|
||||||
|
Collections.addAll(seen, ruleNames);
|
||||||
|
|
||||||
// terminal names
|
// terminal names
|
||||||
terminalXPathNames = new String[vocab.getMaxTokenType()];
|
terminalXPathNames = new String[vocab.getMaxTokenType()];
|
||||||
for (int i = 0; i < terminalXPathNames.length; i++) {
|
terminalXPathNames[0] = "Invalid"; // See Token.INVALID_TYPE
|
||||||
|
for (int i = Token.MIN_USER_TOKEN_TYPE; i < terminalXPathNames.length; i++) {
|
||||||
String name = vocab.getSymbolicName(i);
|
String name = vocab.getSymbolicName(i);
|
||||||
|
|
||||||
|
|
||||||
@ -49,8 +55,8 @@ public class AntlrNameDictionary {
|
|||||||
// cleanup literal name, Antlr surrounds the image with single quotes
|
// cleanup literal name, Antlr surrounds the image with single quotes
|
||||||
name = name.substring(1, name.length() - 1);
|
name = name.substring(1, name.length() - 1);
|
||||||
|
|
||||||
if (!StringUtils.isAlphanumeric(name)) {
|
if (!name.matches("[a-zA-Z][\\w_-]+")) { // not alphanum
|
||||||
name = maybePunctName(name);
|
name = nonAlphaNumName(name);
|
||||||
} // otherwise something like "final"
|
} // otherwise something like "final"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +66,8 @@ public class AntlrNameDictionary {
|
|||||||
|
|
||||||
String finalName = "T-" + name;
|
String finalName = "T-" + name;
|
||||||
|
|
||||||
assert finalName.matches("[a-zA-Z][\\w_-]+"); // must be a valid xpath name
|
assert finalName.matches("[a-zA-Z][\\w_-]+") : "Not a valid XPath name " + finalName;
|
||||||
|
assert seen.add(finalName) : "Duplicate XPath name " + finalName;
|
||||||
|
|
||||||
terminalXPathNames[i] = finalName;
|
terminalXPathNames[i] = finalName;
|
||||||
}
|
}
|
||||||
@ -74,7 +81,7 @@ public class AntlrNameDictionary {
|
|||||||
return vocabulary;
|
return vocabulary;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @Nullable String maybePunctName(String s) {
|
protected @Nullable String nonAlphaNumName(String s) {
|
||||||
// these are hardcoded, but it's overridable
|
// these are hardcoded, but it's overridable
|
||||||
// here we try to avoid semantic overtones, because
|
// here we try to avoid semantic overtones, because
|
||||||
// a-priori the same terminal may mean several things
|
// a-priori the same terminal may mean several things
|
||||||
@ -107,7 +114,6 @@ public class AntlrNameDictionary {
|
|||||||
|
|
||||||
case "@": return "at-symbol";
|
case "@": return "at-symbol";
|
||||||
case "$": return "dollar";
|
case "$": return "dollar";
|
||||||
case "&": return "amp";
|
|
||||||
|
|
||||||
case "\\": return "backslash";
|
case "\\": return "backslash";
|
||||||
case "/": return "slash";
|
case "/": return "slash";
|
||||||
@ -115,6 +121,7 @@ public class AntlrNameDictionary {
|
|||||||
case "`": return "backtick";
|
case "`": return "backtick";
|
||||||
case "'": return "squote";
|
case "'": return "squote";
|
||||||
case "\"": return "dquote";
|
case "\"": return "dquote";
|
||||||
|
case "\"\"\"": return "triple-quote";
|
||||||
|
|
||||||
case ">": return "gt";
|
case ">": return "gt";
|
||||||
case ">=": return "ge";
|
case ">=": return "ge";
|
||||||
@ -131,6 +138,11 @@ public class AntlrNameDictionary {
|
|||||||
case "===": return "triple-eq";
|
case "===": return "triple-eq";
|
||||||
case "!=": return "not-eq";
|
case "!=": return "not-eq";
|
||||||
|
|
||||||
|
case "&": return "amp";
|
||||||
|
case "&&": return "double-amp";
|
||||||
|
case "|": return "pipe";
|
||||||
|
case "||": return "double-pipe";
|
||||||
|
|
||||||
case "*": return "star";
|
case "*": return "star";
|
||||||
case "**": return "double-star";
|
case "**": return "double-star";
|
||||||
|
|
||||||
|
@ -41,7 +41,9 @@ public abstract class BaseAntlrInnerNode<N extends GenericNode<N>> extends BaseA
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public N getChild(int index) {
|
public N getChild(int index) {
|
||||||
if (0 <= index && index < getNumChildren()) {
|
if (0 <= index && index < getNumChildren()) {
|
||||||
return (N) antlrNode.getChild(index).getPmdNode();
|
N pmdNode = (N) antlrNode.getChild(index).getPmdNode();
|
||||||
|
assert pmdNode.getIndexInParent() == index;
|
||||||
|
return pmdNode;
|
||||||
}
|
}
|
||||||
throw new IndexOutOfBoundsException("Index " + index + ", numChildren " + getNumChildren());
|
throw new IndexOutOfBoundsException("Index " + index + ", numChildren " + getNumChildren());
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ import net.sourceforge.pmd.lang.ast.impl.antlr4.*;
|
|||||||
|
|
||||||
@parser::members {
|
@parser::members {
|
||||||
|
|
||||||
static final AntlrNameDictionary DICO = new AntlrNameDictionary(VOCABULARY, ruleNames);
|
static final AntlrNameDictionary DICO = new SwiftNameDictionary(VOCABULARY, ruleNames);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SwiftTerminalNode createPmdTerminal(ParserRuleContext parent, Token t) {
|
public SwiftTerminalNode createPmdTerminal(ParserRuleContext parent, Token t) {
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.lang.swift.ast;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.Vocabulary;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.lang.ast.impl.antlr4.AntlrNameDictionary;
|
||||||
|
|
||||||
|
|
||||||
|
final class SwiftNameDictionary extends AntlrNameDictionary {
|
||||||
|
|
||||||
|
public SwiftNameDictionary(Vocabulary vocab, String[] ruleNames) {
|
||||||
|
super(vocab, ruleNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable String nonAlphaNumName(String name) {
|
||||||
|
{
|
||||||
|
String sup = super.nonAlphaNumName(name);
|
||||||
|
if (sup != null) {
|
||||||
|
return sup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.charAt(0) == '#' && StringUtils.isAlphanumeric(name.substring(1))) {
|
||||||
|
return "directive-" + name.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case "unowned(safe)": return "unowned-safe";
|
||||||
|
case "unowned(unsafe)": return "unowned-unsafe";
|
||||||
|
case "getter:": return "getter";
|
||||||
|
case "setter:": return "setter";
|
||||||
|
case "OSXApplicationExtension\u00AD": return "OSXApplicationExtension-";
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user