in src/org/intellij/grammar/generator/ParserGenerator.java [1562:1695]
private void generatePsiImpl(BnfRule rule, RuleInfo info) {
String psiClass = info.implClass;
String superInterface = info.intfClass;
String stubName = info.realStubClass;
String implSuper = info.realSuperClass;
Set<String> imports = new LinkedHashSet<>();
if (!G.generateFQN) {
imports.addAll(Arrays.asList(CommonClassNames.JAVA_UTIL_LIST,
"org.jetbrains.annotations.*",
C.AstNodeClass,
C.PsiElementClass));
if (myVisitorClassName != null) imports.add(PSI_ELEMENT_VISITOR_CLASS);
imports.add(myPsiTreeUtilClass);
}
else {
imports.add("#forced");
}
imports.add(staticStarImport(myTypeHolderClass));
if (!G.generateFQN) {
if (StringUtil.isNotEmpty(implSuper)) imports.add(implSuper);
imports.add(StringUtil.getPackageName(superInterface) + ".*");
imports.add(StringUtil.notNullize(myVisitorClassName));
imports.add(StringUtil.notNullize(myPsiImplUtilClass));
imports.addAll(getRuleMethodTypesToImport(rule));
}
Function<String, String> substitutor = stubName == null ? ParserGeneratorUtil::unwrapTypeArgumentForParamList : o -> {
String oo = unwrapTypeArgumentForParamList(o);
if (oo.equals(o)) return o;
int idx = oo.lastIndexOf(" ");
return idx == -1 ? stubName : oo.substring(0, idx) + " " + stubName;
};
Set<BnfRule> visited = new HashSet<>();
List<NavigatablePsiElement> constructors = Collections.emptyList();
BnfRule topSuperRule = null;
String topSuperClass = null;
for (BnfRule next = rule; next != null && next != topSuperRule; ) {
if (!visited.add(next)) {
addWarning(rule.getName() + " employs cyclic inheritance");
break;
}
topSuperRule = next;
String superClass = ruleInfo(next).realSuperClass;
if (superClass == null) continue;
next = getEffectiveSuperRule(myFile, next);
if (next != null && next != topSuperRule && getAttribute(topSuperRule, KnownAttribute.MIXIN) == null) continue;
topSuperClass = getRawClassName(superClass);
constructors = myJavaHelper.findClassMethods(topSuperClass, JavaHelper.MethodType.CONSTRUCTOR, "*", -1);
if (!constructors.isEmpty()) break;
}
if (!G.generateFQN) {
for (NavigatablePsiElement m : constructors) {
collectMethodTypesToImport(Collections.singletonList(m), false, imports);
}
if (stubName != null && constructors.isEmpty()) imports.add(G.fallbackStubElementType);
if (stubName != null) imports.add(stubName);
}
if (!G.generateTokenTypes) {
// add parser static imports hoping external token constants are there
for (RuleMethodsHelper.MethodInfo methodInfo : myRulesMethodsHelper.getFor(rule)) {
if (methodInfo.rule == null && !StringUtil.isEmpty(methodInfo.name)) {
for (String s : getRootAttribute(myFile, KnownAttribute.PARSER_IMPORTS).asStrings()) {
if (s.startsWith("static ")) imports.add(s);
}
break;
}
}
}
Java javaType = info.isAbstract ? Java.ABSTRACT_CLASS : Java.CLASS;
generateClassHeader(psiClass, imports, "", javaType, implSuper, superInterface);
String shortName = StringUtil.getShortName(psiClass);
if (constructors.isEmpty()) {
out("public " + shortName + "(" + shorten(C.AstNodeClass) + " node) {");
out("super(node);");
out("}");
newLine();
if (stubName != null) {
out("public " + shortName + "(" +
shorten(stubName) + " stub, " +
shorten(G.fallbackStubElementType) + " stubType) {");
out("super(stub, stubType);");
out("}");
newLine();
}
}
else {
for (NavigatablePsiElement m : constructors) {
List<String> types = myJavaHelper.getMethodTypes(m);
Function<Integer, List<String>> annoProvider = i -> myJavaHelper.getParameterAnnotations(m, (i - 1) / 2);
out("public " + shortName + "(" + getParametersString(types, 1, 3, substitutor, annoProvider, getShortener()) + ") {");
out("super(" + getParametersString(types, 1, 2, substitutor, annoProvider, getShortener()) + ");");
out("}");
newLine();
}
}
if (myVisitorClassName != null) {
String shortened = shorten(myVisitorClassName);
String r = G.visitorValue != null ? "<" + G.visitorValue + ">" : "";
String t = G.visitorValue != null ? " " + G.visitorValue : "void";
String ret = G.visitorValue != null ? "return " : "";
boolean addOverride = topSuperRule != rule && info.mixin == null;
if (!addOverride && topSuperClass != null) {
main: for (String curClass = topSuperClass; curClass != null; curClass = myJavaHelper.getSuperClassName(curClass)) {
for (NavigatablePsiElement m : myJavaHelper.findClassMethods(
curClass, JavaHelper.MethodType.INSTANCE, "accept", 1, myVisitorClassName)) {
String paramType = myJavaHelper.getMethodTypes(m).get(1);
if (getRawClassName(paramType).endsWith(StringUtil.getShortName(myVisitorClassName))) {
addOverride = true;
break main;
}
}
}
}
if (addOverride) {
out(shorten(OVERRIDE_ANNO));
}
out("public " + r + t + " accept(" + shorten(NOTNULL_ANNO) + " " + shortened + r + " visitor) {");
out(ret + "visitor.visit" + getRulePsiClassName(rule, null) + "(this);");
out("}");
newLine();
out(shorten(OVERRIDE_ANNO));
out("public void accept(" + shorten(NOTNULL_ANNO) + " " + shorten(PSI_ELEMENT_VISITOR_CLASS) + " visitor) {");
out("if (visitor instanceof " + shortened + ") accept((" + shortened + ")visitor);");
out("else super.accept(visitor);");
out("}");
newLine();
}
generatePsiClassMethods(rule, info, false);
out("}");
}