in src/org/intellij/grammar/generator/ParserGenerator.java [1345:1512]
private void generateElementTypesHolder(String className, Map<String, BnfRule> sortedCompositeTypes) {
String tokenTypeClass = getRootAttribute(myFile, KnownAttribute.TOKEN_TYPE_CLASS);
String tokenTypeFactory = getRootAttribute(myFile, KnownAttribute.TOKEN_TYPE_FACTORY);
Set<String> imports = new LinkedHashSet<>();
imports.add(C.IElementTypeClass);
if (G.generatePsi) {
imports.add(C.PsiElementClass);
imports.add(C.AstNodeClass);
}
if (G.generateTokenSets && !myTokenSets.isEmpty()) {
imports.add(C.TokenSetClass);
}
boolean useExactElements = "all".equals(G.generateExactTypes) || G.generateExactTypes.contains("elements");
boolean useExactTokens = "all".equals(G.generateExactTypes) || G.generateExactTypes.contains("tokens");
Map<String, Trinity<String, String, RuleInfo>> compositeToClassAndFactoryMap = new HashMap<>();
for (String elementType : sortedCompositeTypes.keySet()) {
BnfRule rule = sortedCompositeTypes.get(elementType);
RuleInfo ruleInfo = ruleInfo(rule);
String elementTypeClass = getAttribute(rule, KnownAttribute.ELEMENT_TYPE_CLASS);
String elementTypeFactory = getAttribute(rule, KnownAttribute.ELEMENT_TYPE_FACTORY);
compositeToClassAndFactoryMap.put(elementType, Trinity.create(elementTypeClass, elementTypeFactory, ruleInfo));
if (useFactory(elementTypeFactory)) {
imports.add(StringUtil.getPackageName(elementTypeFactory));
}
else {
ContainerUtil.addIfNotNull(imports, elementTypeClass);
}
}
if (useFactory(tokenTypeFactory)) {
imports.add(StringUtil.getPackageName(tokenTypeFactory));
}
else {
ContainerUtil.addIfNotNull(imports, tokenTypeClass);
}
if (G.generatePsi) {
imports.addAll(ContainerUtil.sorted(
JBIterable.from(sortedCompositeTypes.values()).map(this::ruleInfo).map(o -> o.implPackage + ".*").toSet()));
if (G.generatePsiClassesMap) {
imports.add(CommonClassNames.JAVA_UTIL_COLLECTIONS);
imports.add(CommonClassNames.JAVA_UTIL_SET);
imports.add("java.util.LinkedHashMap");
}
if (G.generatePsiFactory) {
if (JBIterable.from(myRuleInfos.values()).find(o -> o.mixedAST) != null) {
imports.add(COMPOSITE_PSI_ELEMENT_CLASS);
}
}
}
generateClassHeader(className, imports, "", Java.INTERFACE);
if (G.generateElementTypes) {
for (String elementType : sortedCompositeTypes.keySet()) {
Trinity<String, String, RuleInfo> info = compositeToClassAndFactoryMap.get(elementType);
String elementCreateCall;
if (!useFactory(info.second)) {
elementCreateCall = "new " + shorten(info.first);
}
else {
elementCreateCall = shorten(StringUtil.getPackageName(info.second)) + "." + StringUtil.getShortName(info.second);
}
String fieldType = useExactElements && info.first != null ? info.first : C.IElementTypeClass;
String callFix = elementCreateCall.endsWith("IElementType") ? ", null" : "";
out("%s %s = %s(\"%s\"%s);", shorten(fieldType), elementType, elementCreateCall, elementType, callFix);
}
}
if (G.generateTokenTypes) {
newLine();
String exactType = null;
Map<String, String> sortedTokens = new TreeMap<>();
String tokenCreateCall;
if (!useFactory(tokenTypeFactory)) {
exactType = tokenTypeClass;
tokenCreateCall = "new " + shorten(exactType);
}
else {
tokenCreateCall = shorten(StringUtil.getPackageName(tokenTypeFactory)) + "." + StringUtil.getShortName(tokenTypeFactory);
}
String fieldType = ObjectUtils.notNull(useExactTokens ? exactType : null, C.IElementTypeClass);
for (String tokenText : mySimpleTokens.keySet()) {
String tokenName = ObjectUtils.chooseNotNull(mySimpleTokens.get(tokenText), tokenText);
if (isIgnoredWhitespaceToken(tokenName, tokenText)) continue;
sortedTokens.put(getElementType(tokenName), isRegexpToken(tokenText) ? tokenName : tokenText);
}
for (String tokenType : sortedTokens.keySet()) {
String callFix = tokenCreateCall.endsWith("IElementType") ? ", null" : "";
String tokenString = sortedTokens.get(tokenType);
out("%s %s = %s(\"%s\"%s);", shorten(fieldType), tokenType, tokenCreateCall, StringUtil.escapeStringCharacters(tokenString), callFix);
}
generateTokenSets();
}
if (G.generatePsi && G.generatePsiClassesMap) {
String shortJC = shorten(CommonClassNames.JAVA_LANG_CLASS);
String shortET = shorten(C.IElementTypeClass);
newLine();
out("class Classes {");
newLine();
out("public static %s<?> findClass(%s elementType) {", shortJC, shortET);
out("return ourMap.get(elementType);");
out("}");
newLine();
out("public static %s<%s> elementTypes() {", shorten(CommonClassNames.JAVA_UTIL_SET), shortET);
out("return %s.unmodifiableSet(ourMap.keySet());", shorten(CommonClassNames.JAVA_UTIL_COLLECTIONS));
out("}");
newLine();
String type = shorten("java.util.LinkedHashMap<" + C.IElementTypeClass + ", java.lang.Class<?>>");
out("private static final %s ourMap = new %1$s();", type);
newLine();
out("static {");
for (String elementType : sortedCompositeTypes.keySet()) {
BnfRule rule = sortedCompositeTypes.get(elementType);
RuleInfo info = ruleInfo(rule);
if (info.isAbstract) continue;
String psiClass = getRulePsiClassName(rule, myImplClassFormat);
out("ourMap.put(" + elementType + ", " + psiClass + ".class);");
}
out("}");
out("}");
}
if (G.generatePsi && G.generatePsiFactory) {
newLine();
boolean first1;
boolean first2;
out("class Factory {");
first1 = true;
for (String elementType : sortedCompositeTypes.keySet()) {
BnfRule rule = sortedCompositeTypes.get(elementType);
RuleInfo info = ruleInfo(rule);
if (info.isAbstract) continue;
if (info.mixedAST) continue;
if (first1) {
out("public static %s createElement(%s node) {", shorten(C.PsiElementClass), shorten(C.AstNodeClass));
out("%s type = node.getElementType();", shorten(C.IElementTypeClass));
}
String psiClass = getAttribute(rule, KnownAttribute.PSI_IMPL_PACKAGE) + "." + getRulePsiClassName(rule, myImplClassFormat);
out((!first1 ? "else " : "") + "if (type == " + elementType + ") {");
out("return new " + shorten(psiClass) + "(node);");
first1 = false;
out("}");
}
if (!first1) {
out("throw new AssertionError(\"Unknown element type: \" + type);");
out("}");
}
first2 = true;
for (String elementType : sortedCompositeTypes.keySet()) {
BnfRule rule = sortedCompositeTypes.get(elementType);
RuleInfo info = ruleInfo(rule);
if (info.isAbstract) continue;
if (!info.mixedAST) continue;
if (first2) {
if (!first1) newLine();
out("public static %s createElement(%s type) {", shorten(COMPOSITE_PSI_ELEMENT_CLASS),
shorten(C.IElementTypeClass));
}
String psiClass = getRulePsiClassName(rule, myImplClassFormat);
out((!first2 ? "else" : "") + " if (type == " + elementType + ") {");
out("return new " + psiClass + "(type);");
first2 = false;
out("}");
}
if (!first2) {
out("throw new AssertionError(\"Unknown element type: \" + type);");
out("}");
}
out("}");
}
out("}");
}