Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a generate option to use faster stub getters getStubOrPsiChild #317

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions resources/messages/attributeDescriptions/generate.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@
<td>positive number, <b>2</b></td>
<td>Parser: generate FIRST-based look-ahead optimization</td>
</tr>
<tr>
<td>fast-stub-child-accessors</td>
<td>yes, <b>no</b></td>
<td>PSI: generate more performant stubbed PSI accessors. Requires exact-types="elements" or exact-types="all"</td>
</tr>
<tr>
<td>java</td>
<td>6, 8, <b>11</b>, etc.</td>
Expand Down
9 changes: 7 additions & 2 deletions src/org/intellij/grammar/generator/GenOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ public class GenOptions {
public final boolean generateTokenTypes;
public final boolean generateTokenSets;
public final boolean generateElementTypes;
public final String generateExactTypes;
public final boolean generateExactElements;
public final boolean generateExactTokens;
public final boolean generateExtendedPin;
public final boolean generatePsi;
public final boolean generatePsiFactory;
public final boolean generatePsiClassesMap;
public final boolean generateVisitor;
public final String visitorValue;
public final boolean generateFQN;
public final boolean generateFastStubChildAccessors;
public final Case generateTokenCase;
public final Case generateElementCase;
public final boolean generateTokenAccessors;
Expand All @@ -45,14 +47,17 @@ public GenOptions(BnfFile myFile) {
generateTokenTypes = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKENS, genOptions, "tokens");
generateTokenSets = generateTokenTypes && "yes".equals(genOptions.get("token-sets"));
generateElementTypes = !"no".equals(genOptions.get("elements"));
generateExactTypes = StringUtil.notNullize(genOptions.get("exact-types"));
String generateExactTypes = StringUtil.notNullize(genOptions.get("exact-types"));
generateExactElements = "all".equals(generateExactTypes) || generateExactTypes.contains("elements");
generateExactTokens = "all".equals(generateExactTypes) || generateExactTypes.contains("tokens");
generateFirstCheck = getGenerateOption(myFile, KnownAttribute.GENERATE_FIRST_CHECK, genOptions, "first-check", "firstCheck");
generateExtendedPin = getGenerateOption(myFile, KnownAttribute.EXTENDED_PIN, genOptions, "extended-pin", "extendedPin");
generateTokenAccessors = getGenerateOption(myFile, KnownAttribute.GENERATE_TOKEN_ACCESSORS, genOptions, "token-accessors", "tokenAccessors");
generateTokenAccessorsSet = genOptions.containsKey("token-accessors") || genOptions.containsKey("tokenAccessors");
generateVisitor = !"no".equals(genOptions.get("visitor"));
visitorValue = "void".equals(genOptions.get("visitor-value")) ? null : StringUtil.nullize(genOptions.get("visitor-value"));
generateFQN = "yes".equals(genOptions.get("fqn"));
generateFastStubChildAccessors = generateExactElements && "yes".equals(genOptions.get("fast-stub-child-accessors"));

generateTokenCase = ParserGeneratorUtil.enumFromString(genOptions.get("token-case"), Case.UPPER);
generateElementCase = ParserGeneratorUtil.enumFromString(genOptions.get("element-case"), Case.UPPER);
Expand Down
20 changes: 11 additions & 9 deletions src/org/intellij/grammar/generator/ParserGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1503,8 +1503,6 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
if (G.generateTokenSets && !myTokenSets.isEmpty()) {
imports.add(TOKEN_SET_CLASS);
}
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()) {
Expand Down Expand Up @@ -1551,7 +1549,7 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
else {
elementCreateCall = shorten(StringUtil.getPackageName(info.second)) + "." + StringUtil.getShortName(info.second);
}
String fieldType = useExactElements && info.first != null ? info.first : IELEMENTTYPE_CLASS;
String fieldType = G.generateExactElements && info.first != null ? info.first : IELEMENTTYPE_CLASS;
String callFix = elementCreateCall.endsWith("IElementType") ? ", null" : "";
out("%s %s = %s(\"%s\"%s);", shorten(fieldType), elementType, elementCreateCall, elementType, callFix);
}
Expand All @@ -1568,7 +1566,7 @@ private void generateElementTypesHolder(String className, Map<String, BnfRule> s
else {
tokenCreateCall = shorten(StringUtil.getPackageName(tokenTypeFactory)) + "." + StringUtil.getShortName(tokenTypeFactory);
}
String fieldType = ObjectUtils.notNull(useExactTokens ? exactType : null, IELEMENTTYPE_CLASS);
String fieldType = ObjectUtils.notNull(G.generateExactTokens ? exactType : null, IELEMENTTYPE_CLASS);
for (String tokenText : mySimpleTokens.keySet()) {
String tokenName = ObjectUtils.chooseNotNull(mySimpleTokens.get(tokenText), tokenText);
if (isIgnoredWhitespaceToken(tokenName, tokenText)) continue;
Expand Down Expand Up @@ -1998,11 +1996,15 @@ private String generatePsiAccessorImplCall(@NotNull BnfRule rule, @NotNull RuleM
result = getterName + "(" + getElementType(methodInfo.path) + ")";
}
else {
String className = shorten(getAccessorType(methodInfo.rule));
String getterName = stubbed && many ? "getStubChildrenOfTypeAsList" :
stubbed ? "getStubChildOfType" :
many ? "getChildrenOfTypeAsList" : "getChildOfType";
result = format("%s.%s(this, %s.class)", shorten(myPsiTreeUtilClass), getterName, className);
if (stubbed && !many && G.generateFastStubChildAccessors && myGraphHelper.getExtendsRules(methodInfo.rule).size() < 2) {
result = format("getStubOrPsiChild(%s)", getElementType(methodInfo.rule));
} else {
String className = shorten(getAccessorType(methodInfo.rule));
String getterName = stubbed && many ? "getStubChildrenOfTypeAsList" :
stubbed ? "getStubChildOfType" :
many ? "getChildrenOfTypeAsList" : "getChildOfType";
result = format("%s.%s(this, %s.class)", shorten(myPsiTreeUtilClass), getterName, className);
}
}
return required && !mixedAST ? "notNullChild(" + result + ")" : result;
}
Expand Down
63 changes: 61 additions & 2 deletions testData/generator/Stub.PSI.expected.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface FooTypes {
IElementType ELEMENT_3 = FooParserDefinition.createType("ELEMENT_3");
IElementType ELEMENT_4 = FooParserDefinition.createType("ELEMENT_4");
IElementType ELEMENT_5 = FooParserDefinition.createType("ELEMENT_5");
IElementType ELEMENT_6 = FooParserDefinition.createType("ELEMENT_6");
IElementType INTERFACE_TYPE = FooParserDefinition.createType("INTERFACE_TYPE");
IElementType STRUCT_TYPE = FooParserDefinition.createType("STRUCT_TYPE");
IElementType TYPE = FooParserDefinition.createType("TYPE");
Expand All @@ -38,6 +39,9 @@ else if (type == ELEMENT_4) {
else if (type == ELEMENT_5) {
return new Element5Impl(node);
}
else if (type == ELEMENT_6) {
return new Element6Impl(node);
}
else if (type == INTERFACE_TYPE) {
return new InterfaceTypeImpl(node);
}
Expand Down Expand Up @@ -122,6 +126,20 @@ public interface Element4 extends PsiElement, StubBasedPsiElement<Element4Stub>

public interface Element5 extends PsiElement {

}
// ---- Element6.java -----------------
//header.txt
package test.psi;

import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;

public interface Element6 extends PsiElement {

@NotNull
Type getType();

}
// ---- InterfaceType.java -----------------
//header.txt
Expand Down Expand Up @@ -324,7 +342,7 @@ public void accept(@NotNull PsiElementVisitor visitor) {
@Override
@NotNull
public Element4 getElement4() {
return notNullChild(MyPsiTreeUtil.getStubChildOfType(this, Element4.class));
return notNullChild(getStubOrPsiChild(ELEMENT_4));
}

}
Expand Down Expand Up @@ -372,7 +390,7 @@ public void accept(@NotNull PsiElementVisitor visitor) {
@Override
@Nullable
public Element2 getElement2() {
return MyPsiTreeUtil.getStubChildOfType(this, Element2.class);
return getStubOrPsiChild(ELEMENT_2);
}

}
Expand Down Expand Up @@ -406,6 +424,43 @@ public void accept(@NotNull PsiElementVisitor visitor) {
else super.accept(visitor);
}

}
// ---- Element6Impl.java -----------------
//header.txt
package test.psi.impl;

import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import test.psi.MyPsiTreeUtil;
import static test.FooTypes.*;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import test.psi.*;

public class Element6Impl extends ASTWrapperPsiElement implements Element6 {

public Element6Impl(@NotNull ASTNode node) {
super(node);
}

public void accept(@NotNull Visitor visitor) {
visitor.visitElement6(this);
}

@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof Visitor) accept((Visitor)visitor);
else super.accept(visitor);
}

@Override
@NotNull
public Type getType() {
return notNullChild(MyPsiTreeUtil.getChildOfType(this, Type.class));
}

}
// ---- InterfaceTypeImpl.java -----------------
//header.txt
Expand Down Expand Up @@ -637,6 +692,10 @@ public void visitElement5(@NotNull Element5 o) {
visitPsiElement(o);
}

public void visitElement6(@NotNull Element6 o) {
visitPsiElement(o);
}

public void visitInterfaceType(@NotNull InterfaceType o) {
visitType(o);
}
Expand Down
8 changes: 7 additions & 1 deletion testData/generator/Stub.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,24 @@
parserUtilClass="org.intellij.grammar.parser.GeneratedParserUtilBase"
expressionUtilClass="test.FooUtil"

generate = [
exact-types = "elements"
fast-stub-child-accessors = "yes"
]

extends("element1|type")="org.intellij.grammar.test.StubTest.GenericBase<?>"
extends("simple")="org.intellij.grammar.test.StubTest.SimpleBase"
extends("missing")="test.stub.MissingBase"

extends(".*type")=type
}
root ::= element1 | element2 | element3 | element4 | element5 | type
root ::= element1 | element2 | element3 | element4 | element5 | element6
element1 ::= 'aa' element5 { stubClass="test.stub.Element1Stub" }
element2 ::= 'bb' element4* { stubClass="test.stub.Element2Stub" }
element3 ::= 'bb' element4 { stubClass="test.stub.Element3Stub" }
element4 ::= 'bb' | element2 { stubClass="test.stub.Element4Stub" }
element5 ::= 'cc'
element6 ::= 'dd' type

type ::= interface_type | struct_type {stubClass="test.stub.TypeStub"}
struct_type ::= 'struct'
Expand Down
16 changes: 14 additions & 2 deletions testData/generator/Stub.expected.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ public static boolean element5(PsiBuilder builder_, int level_) {
return result_;
}

/* ********************************************************** */
// 'dd' type
public static boolean element6(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "element6")) return false;
boolean result_;
Marker marker_ = enter_section_(builder_, level_, _NONE_, ELEMENT_6, "<element 6>");
result_ = consumeToken(builder_, "dd");
result_ = result_ && type(builder_, level_ + 1);
exit_section_(builder_, level_, marker_, result_, false, null);
return result_;
}

/* ********************************************************** */
// 'interface'
public static boolean interface_type(PsiBuilder builder_, int level_) {
Expand All @@ -122,7 +134,7 @@ public static boolean interface_type(PsiBuilder builder_, int level_) {
}

/* ********************************************************** */
// element1 | element2 | element3 | element4 | element5 | type
// element1 | element2 | element3 | element4 | element5 | element6
static boolean root(PsiBuilder builder_, int level_) {
if (!recursion_guard_(builder_, level_, "root")) return false;
boolean result_;
Expand All @@ -131,7 +143,7 @@ static boolean root(PsiBuilder builder_, int level_) {
if (!result_) result_ = element3(builder_, level_ + 1);
if (!result_) result_ = element4(builder_, level_ + 1);
if (!result_) result_ = element5(builder_, level_ + 1);
if (!result_) result_ = type(builder_, level_ + 1);
if (!result_) result_ = element6(builder_, level_ + 1);
return result_;
}

Expand Down