From 0e7e61ea6eeccd6a598b5ae2e37cb55efef6c511 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 23 Aug 2013 18:14:42 +0400 Subject: [PATCH] Reflective PsiElements creation in JqlParserDefinition --- .../tasks/jira/jql/JqlElementType.java | 31 ++++++++++- .../tasks/jira/jql/JqlElementTypes.java | 40 +++++++------- .../tasks/jira/jql/JqlParserDefinition.java | 55 +------------------ .../tasks/jira/jql/JqlTokenTypes.java | 6 -- 4 files changed, 53 insertions(+), 79 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java index fde826e4a62c..9d9dc9118997 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementType.java @@ -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 myClass; + private Constructor myConstructor; + public JqlElementType(@NotNull @NonNls String debugName) { + this(debugName, ASTWrapperPsiElement.class); + } + + public JqlElementType(@NotNull @NonNls String debugName, @NotNull Class 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())); + } + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java index 22a2f96e00ae..9919eb6d1d85 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlElementTypes.java @@ -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 diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java index 258db6992dbc..a8269625fcfd 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlParserDefinition.java @@ -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); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java index 1d0c6f1c6a0e..ddb8bdf577a6 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/jql/JqlTokenTypes.java @@ -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);