in src/org/intellij/grammar/generator/ParserGenerator.java [351:428]
private void generateVisitor(String psiClass, Map<String, BnfRule> sortedRules) {
String superIntf = ObjectUtils.notNull(ContainerUtil.getFirstItem(getRootAttribute(myFile, KnownAttribute.IMPLEMENTS)),
KnownAttribute.IMPLEMENTS.getDefaultValue().get(0)).second;
Set<String> imports = new LinkedHashSet<>(Arrays.asList("org.jetbrains.annotations.*", PSI_ELEMENT_VISITOR_CLASS, superIntf));
MultiMap<String, String> supers = new MultiMap<>();
for (BnfRule rule : sortedRules.values()) {
supers.putValues(rule.getName(), getSuperInterfaceNames(myFile, rule, myIntfClassFormat));
}
{
// ensure only public supers are exposed, replace non-public with default super-intf for simplicity
Map<String, String> replacements = new HashMap<>();
Set<String> visited = new HashSet<>();
for (String s : supers.values()) {
if (!visited.add(s)) continue;
NavigatablePsiElement aClass = myJavaHelper.findClass(s);
if (aClass != null && !myJavaHelper.isPublic(aClass)) {
replacements.put(s, superIntf);
}
}
for (String key : supers.keySet()) {
for (ListIterator<String> it = ((List<String>)supers.get(key)).listIterator(); it.hasNext(); ) {
String s = replacements.get(it.next());
if (s != null) {
if (s.isEmpty()) it.remove();
else it.set(s);
}
}
}
}
imports.addAll(ContainerUtil.sorted(
JBIterable.from(sortedRules.values()).map(this::ruleInfo).map(o -> o.intfPackage + ".*").toSet()));
imports.addAll(supers.values());
String r = G.visitorValue != null ? "<" + G.visitorValue + ">" : "";
String t = G.visitorValue != null ? G.visitorValue : "void";
String ret = G.visitorValue != null ? "return " : "";
generateClassHeader(psiClass + r, imports, "", Java.CLASS, PSI_ELEMENT_VISITOR_CLASS);
Set<String> visited = new HashSet<>();
Set<String> all = new TreeSet<>();
for (BnfRule rule : sortedRules.values()) {
String methodName = getRulePsiClassName(rule, null);
visited.add(methodName);
out("public %s visit%s(%s %s o) {", t, methodName, shorten(NOTNULL_ANNO), getRulePsiClassName(rule, myIntfClassFormat));
boolean first = true;
for (String top : supers.get(rule.getName())) {
if (!first && top.equals(superIntf)) continue;
top = getRawClassName(top);
if (first) all.add(top);
String text = "visit" + myIntfClassFormat.strip(StringUtil.getShortName(top)) + "(o);";
if (first) {
out(ret + text);
}
else {
out("// " + text);
}
if (first) first = false;
}
out("}");
newLine();
}
all.remove(superIntf);
for (String top : JBIterable.from(all).append(superIntf)) {
String methodName = myIntfClassFormat.strip(StringUtil.getShortName(top));
if (visited.contains(methodName)) continue;
out("public %s visit%s(%s %s o) {", t, methodName, shorten(NOTNULL_ANNO), shorten(top));
if (!methodName.equals(StringUtil.getShortName(top)) && !top.equals(superIntf)) {
out(ret + "visit" + myIntfClassFormat.strip(StringUtil.getShortName(superIntf)) + "(o);");
}
else {
String superPrefix = methodName.equals("Element") ? "super." : "";
out(superPrefix + "visitElement(o);");
if (G.visitorValue != null) out(ret + "null;");
}
out("}");
newLine();
}
out("}");
}