Reflective PsiElements creation in JqlParserDefinition

This commit is contained in:
Mikhail Golubev
2013-08-26 13:23:43 +04:00
parent 0f40312edc
commit 0e7e61ea6e
4 changed files with 53 additions and 79 deletions
@@ -15,22 +15,49 @@
*/
package com.intellij.tasks.jira.jql;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Constructor;
/**
* @author Mikhail Golubev
*/
public class JqlElementType extends IElementType {
private String myName;
private static final Class<?>[] PARAMETER_TYPES = {ASTNode.class};
private final Class<? extends PsiElement> myClass;
private Constructor<? extends PsiElement> myConstructor;
public JqlElementType(@NotNull @NonNls String debugName) {
this(debugName, ASTWrapperPsiElement.class);
}
public JqlElementType(@NotNull @NonNls String debugName, @NotNull Class<? extends PsiElement> cls) {
super(debugName, JqlLanguage.INSTANCE);
myName = debugName;
myClass = cls;
}
@Override
public String toString() {
return "JQL: " + super.toString();
}
@NotNull
public PsiElement createElement(@NotNull ASTNode node) {
try {
if (myConstructor == null) {
myConstructor = myClass.getConstructor(PARAMETER_TYPES);
}
return myConstructor.newInstance(node);
}
catch (Exception e) {
throw new AssertionError(
String.format("Class %s must have constructor accepting single ASTNode parameter", myClass.getName()));
}
}
}
@@ -3,6 +3,7 @@ package com.intellij.tasks.jira.jql;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.tasks.jira.jql.psi.impl.*;
/**
* @author Mikhail Golubev
@@ -47,11 +48,12 @@ import com.intellij.psi.tree.TokenSet;
* field ::= string
* | NUMBER
* | CUSTOM_FIELD
* operand ::= ("empty" | "null")
* operand ::= empty
* | string
* | NUMBER
* | func
* | list
* empty ::= "empty" | "null"
* list ::= "(" operand {"," operand} ")"
* func ::= fname "(" arg_list ")"
* # function name can be even number (!)
@@ -59,7 +61,7 @@ import com.intellij.psi.tree.TokenSet;
* arg_list ::= argument {"," argument}
* argument ::= string | NUMBER
* string ::= SQUOTED_STRING
* | QUOTED_STRIN
* | QUOTED_STRING
* | UNQOUTED_STRING
* order_by ::= "order" "by" sort_key {sort_key}
* sort_key ::= field ("asc" | "desc")
@@ -67,28 +69,28 @@ import com.intellij.psi.tree.TokenSet;
*/
public interface JqlElementTypes {
IFileElementType FILE = new IFileElementType(JqlLanguage.INSTANCE);
IElementType QUERY = new JqlElementType("QUERY");
IElementType OR_CLAUSE = new JqlElementType("OR_CLAUSE");
IElementType AND_CLAUSE = new JqlElementType("AND_CLAUSE");
IElementType NOT_CLAUSE = new JqlElementType("NOT_CLAUSE");
IElementType QUERY = new JqlElementType("QUERY", JqlQueryImpl.class);
IElementType OR_CLAUSE = new JqlElementType("OR_CLAUSE", JqlOrClauseImpl.class);
IElementType AND_CLAUSE = new JqlElementType("AND_CLAUSE", JqlAndClauseImpl.class);
IElementType NOT_CLAUSE = new JqlElementType("NOT_CLAUSE", JqlNotClauseImpl.class);
// actually parenthesized clause, named so to be consistent with official grammar
IElementType SUB_CLAUSE = new JqlElementType("SUB_CLAUSE");
IElementType SUB_CLAUSE = new JqlElementType("SUB_CLAUSE", JqlSubClauseImpl.class);
//IElementType TERMINAL_CLAUSE = new JqlElementType("TERMINAL_CLAUSE");
// field (= | != | ~ | !~ | < | > | <= | >= | is [not] | [not] in) value
IElementType SIMPLE_CLAUSE = new JqlElementType("SIMPLE_CLAUSE");
IElementType SIMPLE_CLAUSE = new JqlElementType("SIMPLE_CLAUSE", JqlSimpleClauseImpl.class);
// field was [not] [in] value {history_predicate}
IElementType WAS_CLAUSE = new JqlElementType("WAS_CLAUSE");
IElementType WAS_CLAUSE = new JqlElementType("WAS_CLAUSE", JqlWasClauseImpl.class);
// field changed {history_predicate}
IElementType CHANGED_CLAUSE = new JqlElementType("CHANGED_CLAUSE");
IElementType LIST = new JqlElementType("LIST");
IElementType ORDER_BY = new JqlElementType("ORDER_BY");
IElementType IDENTIFIER = new JqlElementType("IDENTIFIER");
IElementType LITERAL = new JqlElementType("LITERAL");
IElementType FUNCTION_CALL = new JqlElementType("FUNCTION_CALL");
IElementType ARGUMENT_LIST = new JqlElementType("ARGUMENT_LIST");
IElementType SORT_KEY = new JqlElementType("SORT_KEY");
IElementType EMPTY = new JqlElementType("EMPTY");
IElementType HISTORY_PREDICATE = new JqlElementType("HISTORY_PREDICATE");
IElementType CHANGED_CLAUSE = new JqlElementType("CHANGED_CLAUSE", JqlChangedClauseImpl.class);
IElementType LIST = new JqlElementType("LIST", JqlListImpl.class);
IElementType ORDER_BY = new JqlElementType("ORDER_BY", JqlOrderByImpl.class);
IElementType IDENTIFIER = new JqlElementType("IDENTIFIER", JqlIdentifierImpl.class);
IElementType LITERAL = new JqlElementType("LITERAL", JqlLiteralImpl.class);
IElementType FUNCTION_CALL = new JqlElementType("FUNCTION_CALL", JqlFunctionCallImpl.class);
IElementType ARGUMENT_LIST = new JqlElementType("ARGUMENT_LIST", JqlArgumentListImpl.class);
IElementType SORT_KEY = new JqlElementType("SORT_KEY", JqlSortKeyImpl.class);
IElementType EMPTY = new JqlElementType("EMPTY", JqlEmptyValueImpl.class);
IElementType HISTORY_PREDICATE = new JqlElementType("HISTORY_PREDICATE", JqlHistoryPredicateImpl.class);
TokenSet OPERAND_NODES = TokenSet.create(
JqlTokenTypes.NUMBER_LITERAL, JqlTokenTypes.STRING_LITERAL, LIST, FUNCTION_CALL
@@ -13,7 +13,6 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.tasks.jira.jql.psi.impl.*;
import org.jetbrains.annotations.NotNull;
/**
@@ -59,57 +58,9 @@ public class JqlParserDefinition implements ParserDefinition {
@NotNull
@Override
public PsiElement createElement(ASTNode node) {
IElementType type = node.getElementType();
if (type == JqlElementTypes.QUERY) {
return new JqlQueryImpl(node);
}
if (type == JqlElementTypes.AND_CLAUSE) {
return new JqlAndClauseImpl(node);
}
if (type == JqlElementTypes.OR_CLAUSE) {
return new JqlOrClauseImpl(node);
}
if (type == JqlElementTypes.NOT_CLAUSE) {
return new JqlNotClauseImpl(node);
}
if (type == JqlElementTypes.SUB_CLAUSE) {
return new JqlSubClauseImpl(node);
}
if (type == JqlElementTypes.SIMPLE_CLAUSE) {
return new JqlSimpleClauseImpl(node);
}
if (type == JqlElementTypes.WAS_CLAUSE) {
return new JqlWasClauseImpl(node);
}
if (type == JqlElementTypes.CHANGED_CLAUSE) {
return new JqlChangedClauseImpl(node);
}
if (type == JqlElementTypes.FUNCTION_CALL) {
return new JqlFunctionCallImpl(node);
}
if (type == JqlElementTypes.IDENTIFIER) {
return new JqlIdentifierImpl(node);
}
if (type == JqlElementTypes.HISTORY_PREDICATE) {
return new JqlHistoryPredicateImpl(node);
}
if (type == JqlElementTypes.ARGUMENT_LIST) {
return new JqlArgumentListImpl(node);
}
if (type == JqlElementTypes.LITERAL) {
return new JqlLiteralImpl(node);
}
if (type == JqlElementTypes.EMPTY) {
return new JqlEmptyValueImpl(node);
}
if (type == JqlElementTypes.LIST) {
return new JqlListImpl(node);
}
if (type == JqlElementTypes.SORT_KEY) {
return new JqlSortKeyImpl(node);
}
if (type == JqlElementTypes.ORDER_BY) {
return new JqlOrderByImpl(node);
final IElementType type = node.getElementType();
if (type instanceof JqlElementType) {
return ((JqlElementType)type).createElement(node);
}
return new ASTWrapperPsiElement(node);
}
@@ -104,12 +104,6 @@ public interface JqlTokenTypes {
TokenSet HISTORY_PREDICATES = TokenSet.create(
ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, FROM_KEYWORD, TO_KEYWORD, BY_KEYWORD
);
TokenSet WAS_CONSTRAINTS = TokenSet.create(
ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, BY_KEYWORD
);
TokenSet CHANGED_CONSTRAINTS = TokenSet.create(
ON_KEYWORD, BEFORE_KEYWORD, AFTER_KEYWORD, DURING_KEYWORD, FROM_KEYWORD, TO_KEYWORD, BY_KEYWORD
);
TokenSet SORT_ORDERS = TokenSet.create(ASC_KEYWORD, DESC_KEYWORD);
TokenSet EMPTY_VALUES = TokenSet.create(EMPTY_KEYWORD, NULL_KEYWORD);
TokenSet LITERALS = TokenSet.create(NUMBER_LITERAL, STRING_LITERAL);