Skip to content

Commit b4a5c1f

Browse files
committed
Generator: introduce "exact-types" option
1 parent a2b344f commit b4a5c1f

File tree

4 files changed

+44
-19
lines changed

4 files changed

+44
-19
lines changed

resources/messages/attributeDescriptions/generate.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@
5555
<td>Types: token type constants case option</td>
5656
</tr>
5757
<tr>
58-
<td>tokenAccessors</td>
58+
<td>exact-types</td>
59+
<td>all | <b>no</b> | tokens, elements, stubs</td>
60+
<td>Token and element types constants exact type</td>
61+
</tr>
62+
<tr>
63+
<td>token-accessors</td>
5964
<td>yes, <b>no</b></td>
6065
<td>PSI: generate token getters</td>
6166
</tr>
@@ -65,7 +70,7 @@
6570
<td>Parser: local variables style</td>
6671
</tr>
6772
<tr>
68-
<td>firstCheck</td>
73+
<td>first-check</td>
6974
<td>positive number, <b>2</b></td>
7075
<td>Parser: generate FIRST-based look-ahead optimization</td>
7176
</tr>

src/org/intellij/grammar/generator/GenOptions.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class GenOptions {
3636
public final Pattern generateRootRules;
3737
public final boolean generateTokenTypes;
3838
public final boolean generateElementTypes;
39+
public final String generateExactTypes;
3940
public final boolean generateExtendedPin;
4041
public final boolean generatePsi;
4142
public final boolean generatePsiFactory;
@@ -50,15 +51,16 @@ public class GenOptions {
5051
public GenOptions(BnfFile myFile) {
5152
Map<String, String> genOptions = getRootAttribute(myFile, KnownAttribute.GENERATE).asMap();
5253
names = Names.forName(genOptions.get("names"));
53-
generatePsi = getGenerateOption(myFile, KnownAttribute.GENERATE_PSI, genOptions.get("psi"));
54+
generatePsi = getGenerateOption(myFile, KnownAttribute.GENERATE_PSI, genOptions, "psi");
5455
generatePsiFactory = !"no".equals(genOptions.get("psi-factory"));
5556
generatePsiClassesMap = "yes".equals(genOptions.get("psi-classes-map"));
56-
generateTokenTypes = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKENS, genOptions.get("tokens"));
57+
generateTokenTypes = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKENS, genOptions, "tokens");
5758
generateElementTypes = !"no".equals(genOptions.get("elements"));
58-
generateFirstCheck = getGenerateOption(myFile, KnownAttribute.GENERATE_FIRST_CHECK, genOptions.get("firstCheck"));
59-
generateExtendedPin = getGenerateOption(myFile, KnownAttribute.EXTENDED_PIN, genOptions.get("extendedPin"));
60-
generateTokenAccessors = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKEN_ACCESSORS, genOptions.get("tokenAccessors"));
61-
generateTokenAccessorsSet = genOptions.containsKey("tokenAccessors");
59+
generateExactTypes = StringUtil.notNullize(genOptions.get("exact-types"));
60+
generateFirstCheck = getGenerateOption(myFile, KnownAttribute.GENERATE_FIRST_CHECK, genOptions, "first-check", "firstCheck");
61+
generateExtendedPin = getGenerateOption(myFile, KnownAttribute.EXTENDED_PIN, genOptions, "extended-pin", "extendedPin");
62+
generateTokenAccessors = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKEN_ACCESSORS, genOptions, "token-accessors", "tokenAccessors");
63+
generateTokenAccessorsSet = genOptions.containsKey("token-accessors") || genOptions.containsKey("tokenAccessors");
6264
generateRootRules = PatternUtil.compileSafe(genOptions.get("root-rules"), null);
6365
generateVisitor = !"no".equals(genOptions.get("visitor"));
6466
visitorValue = "void".equals(genOptions.get("visitor-value")) ? null : StringUtil.nullize(genOptions.get("visitor-value"));

src/org/intellij/grammar/generator/ParserGenerator.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package org.intellij.grammar.generator;
1818

1919
import com.intellij.openapi.diagnostic.Logger;
20-
import com.intellij.openapi.util.Couple;
2120
import com.intellij.openapi.util.Pair;
21+
import com.intellij.openapi.util.Trinity;
2222
import com.intellij.openapi.util.io.FileUtil;
2323
import com.intellij.openapi.util.text.StringUtil;
2424
import com.intellij.psi.CommonClassNames;
@@ -1348,17 +1348,26 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
13481348
imports.add(PSI_ELEMENT_CLASS);
13491349
imports.add(AST_NODE_CLASS);
13501350
}
1351-
Map<String, Couple<String>> compositeToClassAndFactoryMap = new THashMap<>();
1351+
boolean useExactElements = "all".equals(G.generateExactTypes) || G.generateExactTypes.contains("elements");
1352+
boolean useExactStubs = G.generateExactTypes.contains("stubs");
1353+
boolean useExactTokens = "all".equals(G.generateExactTypes) || G.generateExactTypes.contains("tokens");
1354+
1355+
Map<String, Trinity<String, String, RuleInfo>> compositeToClassAndFactoryMap = new THashMap<>();
13521356
for (String elementType : sortedCompositeTypes.keySet()) {
13531357
BnfRule rule = sortedCompositeTypes.get(elementType);
1358+
RuleInfo ruleInfo = ruleInfo(rule);
13541359
String elementTypeClass = getAttribute(rule, KnownAttribute.ELEMENT_TYPE_CLASS);
13551360
String elementTypeFactory = getAttribute(rule, KnownAttribute.ELEMENT_TYPE_FACTORY);
1356-
compositeToClassAndFactoryMap.put(elementType, Couple.of(elementTypeClass, elementTypeFactory));
1361+
compositeToClassAndFactoryMap.put(elementType, Trinity.create(elementTypeClass, elementTypeFactory, ruleInfo));
13571362
if (elementTypeFactory != null) {
13581363
imports.add(StringUtil.getPackageName(elementTypeFactory));
13591364
}
13601365
else {
13611366
ContainerUtil.addIfNotNull(imports, elementTypeClass);
1367+
if (useExactStubs && ruleInfo.stub != null) {
1368+
imports.add(ISTUBELEMENTTYPE_CLASS);
1369+
imports.add(ruleInfo.intfClass);
1370+
}
13621371
}
13631372
}
13641373
if (tokenTypeFactory != null) {
@@ -1384,28 +1393,35 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
13841393
generateClassHeader(className, imports, "", Java.INTERFACE);
13851394
if (G.generateElementTypes) {
13861395
for (String elementType : sortedCompositeTypes.keySet()) {
1387-
Couple<String> pair = compositeToClassAndFactoryMap.get(elementType);
1396+
String exactType = null;
1397+
Trinity<String, String, RuleInfo> info = compositeToClassAndFactoryMap.get(elementType);
13881398
String elementCreateCall;
1389-
if (pair.second == null) {
1390-
elementCreateCall = "new " + StringUtil.getShortName(pair.first);
1399+
if (info.second == null) {
1400+
elementCreateCall = "new " + (exactType = myShortener.fun(info.first));
13911401
}
13921402
else {
1393-
elementCreateCall = myShortener.fun(StringUtil.getPackageName(pair.second)) + "." + StringUtil.getShortName(pair.second);
1403+
elementCreateCall = myShortener.fun(StringUtil.getPackageName(info.second)) + "." + StringUtil.getShortName(info.second);
13941404
}
1405+
String fieldType = ObjectUtils.notNull(
1406+
useExactElements ? exactType :
1407+
useExactStubs && info.third.stub != null ? "IStubElementType<?, " + myShortener.fun(info.third.intfClass) + ">" :
1408+
"IElementType");
13951409
String callFix = elementCreateCall.equals("new IElementType") ? ", null" : "";
1396-
out("IElementType " + elementType + " = " + elementCreateCall + "(\"" + elementType + "\"" + callFix + ");");
1410+
out(fieldType + " " + elementType + " = " + elementCreateCall + "(\"" + elementType + "\"" + callFix + ");");
13971411
}
13981412
}
13991413
if (G.generateTokenTypes) {
14001414
newLine();
1415+
String exactType = null;
14011416
Map<String, String> sortedTokens = ContainerUtil.newTreeMap();
14021417
String tokenCreateCall;
14031418
if (tokenTypeFactory == null) {
1404-
tokenCreateCall = "new " + StringUtil.getShortName(tokenTypeClass);
1419+
tokenCreateCall = "new " + (exactType = myShortener.fun(tokenTypeClass));
14051420
}
14061421
else {
14071422
tokenCreateCall = myShortener.fun(StringUtil.getPackageName(tokenTypeFactory)) + "." + StringUtil.getShortName(tokenTypeFactory);
14081423
}
1424+
String fieldType = ObjectUtils.notNull(useExactTokens ? exactType : null, "IElementType");
14091425
for (String tokenText : mySimpleTokens.keySet()) {
14101426
String tokenName = ObjectUtils.chooseNotNull(mySimpleTokens.get(tokenText), tokenText);
14111427
if (isIgnoredWhitespaceToken(tokenName, tokenText)) continue;
@@ -1414,7 +1430,7 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
14141430
for (String tokenType : sortedTokens.keySet()) {
14151431
String callFix = tokenCreateCall.equals("new IElementType") ? ", null" : "";
14161432
String tokenString = sortedTokens.get(tokenType);
1417-
out("IElementType " + tokenType + " = " + tokenCreateCall + "(\"" + StringUtil.escapeStringCharacters(tokenString) + "\""+callFix+");");
1433+
out(fieldType + " " + tokenType + " = " + tokenCreateCall + "(\"" + StringUtil.escapeStringCharacters(tokenString) + "\""+callFix+");");
14181434
}
14191435
}
14201436
if (G.generatePsi && G.generatePsiClassesMap) {

src/org/intellij/grammar/generator/ParserGeneratorUtil.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ public static <T extends Enum<T>> T enumFromString(@Nullable String value, @NotN
115115
}
116116
}
117117

118-
public static <T> T getGenerateOption(@NotNull PsiElement node, @NotNull KnownAttribute<T> attribute, @Nullable String currentValue) {
118+
public static <T> T getGenerateOption(@NotNull PsiElement node, @NotNull KnownAttribute<T> attribute,
119+
@NotNull Map<String, String> genOptions, String... genOptionKeys) {
120+
String currentValue = JBIterable.of(genOptionKeys).map(genOptions::get).filter(Objects::nonNull).first();
119121
if (attribute.getDefaultValue() instanceof Boolean) {
120122
if ("yes".equals(currentValue)) return (T)Boolean.TRUE;
121123
if ("no".equals(currentValue)) return (T)Boolean.FALSE;

0 commit comments

Comments
 (0)