Skip to content

Commit c2053d3

Browse files
committed
HBX-3184: Improve the implementation of AntlrSimpleHQLLexer, HQLAnalyzer and SubQuery
Signed-off-by: Koen Aers <koen.aers@gmail.com>
1 parent 7565262 commit c2053d3

File tree

3 files changed

+146
-168
lines changed

3 files changed

+146
-168
lines changed

orm/src/main/java/org/hibernate/tool/ide/completion/AntlrSimpleHQLLexer.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,11 @@
1313
*/
1414
public class AntlrSimpleHQLLexer implements SimpleHQLLexer {
1515

16-
private HqlLexer lexer;
16+
private final HqlLexer lexer;
1717
private Token token;
1818

19-
public AntlrSimpleHQLLexer(char[] cs, int length) {
19+
public AntlrSimpleHQLLexer(char[] cs) {
2020
lexer = new HqlLexer(CharStreams.fromString(new String(cs)));
21-
// Commenting out, not sure if this is still relevant and/or needed
22-
// {
23-
// public void newline() {
24-
// //super.newline();
25-
// }
26-
//
27-
// public int getColumn() {
28-
// return super.getCharPositionInLine();
29-
// }
30-
// };
31-
// lexer.setTabSize(1);
3221
}
3322

3423
public int getTokenLength() {
@@ -44,9 +33,6 @@ public int getTokenOffset() {
4433

4534
public int nextTokenId() {
4635
token = lexer.nextToken();
47-
if(token==null) {
48-
System.out.println(token);
49-
}
5036
return token.getType();
5137
}
5238

Lines changed: 96 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,97 @@
11
package org.hibernate.tool.ide.completion;
22

3-
import java.util.ArrayList;
4-
import java.util.Arrays;
5-
import java.util.Collections;
6-
import java.util.HashMap;
7-
import java.util.Iterator;
8-
import java.util.List;
9-
import java.util.Map;
10-
113
import org.hibernate.grammars.hql.HqlLexer;
124

13-
/**
14-
* The HQLAnalyzer can answer certain questions about a HQL String.
15-
*
16-
* @author leon, max.andersen@jboss.com
17-
*/
5+
import java.util.*;
6+
187
public class HQLAnalyzer {
198

20-
/** Defines the HQL keywords. Based on hql.g antlr grammer in 2005 ;) */
21-
private static String[] hqlKeywords = { "between", "class", "delete",
22-
"desc", "distinct", "elements", "escape", "exists", "false",
23-
"fetch", "from", "full", "group", "having", "in", "indices",
24-
"inner", "insert", "into", "is", "join", "left", "like", "new",
25-
"not", "null", "or", "order", "outer", "properties", "right",
26-
"select", "set", "some", "true", "union", "update", "versioned",
27-
"where", "and", "or", "as","on", "with",
28-
29-
// -- SQL tokens --
30-
// These aren't part of HQL, but recognized by the lexer. Could be
31-
// usefull for having SQL in the editor..but for now we keep them out
32-
// "case", "end", "else", "then", "when",
33-
34-
35-
// -- EJBQL tokens --
36-
"both", "empty", "leading", "member", "object", "of", "trailing",
9+
/** Defines the HQL keywords. Based on hql.g antlr grammer in 2005 ;) */
10+
private static final String[] hqlKeywords = { "between", "class", "delete",
11+
"desc", "distinct", "elements", "escape", "exists", "false",
12+
"fetch", "from", "full", "group", "having", "in", "indices",
13+
"inner", "insert", "into", "is", "join", "left", "like", "new",
14+
"not", "null", "or", "order", "outer", "properties", "right",
15+
"select", "set", "some", "true", "union", "update", "versioned",
16+
"where", "and", "or", "as","on", "with",
17+
18+
// -- SQL tokens --
19+
// These aren't part of HQL, but recognized by the lexer. Could be
20+
// usefull for having SQL in the editor..but for now we keep them out
21+
// "case", "end", "else", "then", "when",
22+
23+
24+
// -- EJBQL tokens --
25+
"both", "empty", "leading", "member", "object", "of", "trailing",
3726
};
38-
27+
3928

4029
/**
41-
* built-in function names. Various normal builtin functions in SQL/HQL.
42-
* Maybe sShould try and do this dynamically based on dialect or
43-
* sqlfunctionregistry
44-
*/
45-
private static String[] builtInFunctions = {
46-
// standard sql92 functions
47-
"substring", "locate", "trim", "length", "bit_length", "coalesce",
48-
"nullif", "abs", "mod", "sqrt",
49-
"upper",
50-
"lower",
51-
"cast",
52-
"extract",
30+
* built-in function names. Various normal builtin functions in SQL/HQL.
31+
* Maybe sShould try and do this dynamically based on dialect or
32+
* sqlfunctionregistry
33+
*/
34+
private static final String[] builtInFunctions = {
35+
// standard sql92 functions
36+
"substring", "locate", "trim", "length", "bit_length", "coalesce",
37+
"nullif", "abs", "mod", "sqrt",
38+
"upper",
39+
"lower",
40+
"cast",
41+
"extract",
42+
43+
// time functions mapped to ansi extract
44+
"second", "minute", "hour", "day",
45+
"month",
46+
"year",
5347

54-
// time functions mapped to ansi extract
55-
"second", "minute", "hour", "day",
56-
"month",
57-
"year",
48+
"str",
5849

59-
"str",
50+
// misc functions - based on oracle dialect
51+
"sign", "acos", "asin", "atan", "cos", "cosh", "exp", "ln", "sin",
52+
"sinh", "stddev", "sqrt", "tan", "tanh", "variance",
6053

61-
// misc functions - based on oracle dialect
62-
"sign", "acos", "asin", "atan", "cos", "cosh", "exp", "ln", "sin",
63-
"sinh", "stddev", "sqrt", "tan", "tanh", "variance",
54+
"round", "trunc", "ceil", "floor",
6455

65-
"round", "trunc", "ceil", "floor",
56+
"chr", "initcap", "lower", "ltrim", "rtrim", "soundex", "upper",
57+
"ascii", "length", "to_char", "to_date",
6658

67-
"chr", "initcap", "lower", "ltrim", "rtrim", "soundex", "upper",
68-
"ascii", "length", "to_char", "to_date",
59+
"current_date", "current_time", "current_timestamp", "lastday",
60+
"sysday", "systimestamp", "uid", "user",
6961

70-
"current_date", "current_time", "current_timestamp", "lastday",
71-
"sysday", "systimestamp", "uid", "user",
62+
"rowid", "rownum",
7263

73-
"rowid", "rownum",
64+
"concat", "instr", "instrb", "lpad", "replace", "rpad", "substr",
65+
"substrb", "translate",
7466

75-
"concat", "instr", "instrb", "lpad", "replace", "rpad", "substr",
76-
"substrb", "translate",
67+
"substring", "locate", "bit_length", "coalesce",
7768

78-
"substring", "locate", "bit_length", "coalesce",
69+
"atan2", "log", "mod", "nvl", "nvl2", "power",
7970

80-
"atan2", "log", "mod", "nvl", "nvl2", "power",
71+
"add_months", "months_between", "next_day",
8172

82-
"add_months", "months_between", "next_day",
73+
"max", "min", };
8374

84-
"max", "min", };
85-
8675
static {
87-
// to allow binary search
88-
Arrays.sort(builtInFunctions);
89-
Arrays.sort(hqlKeywords);
76+
// to allow binary search
77+
Arrays.sort(builtInFunctions);
78+
Arrays.sort(hqlKeywords);
9079
}
9180

92-
protected SimpleHQLLexer getLexer(char chars[], int end) {
93-
return new AntlrSimpleHQLLexer(chars,end);
81+
protected SimpleHQLLexer getLexer(char[] chars) {
82+
return new AntlrSimpleHQLLexer(chars);
9483
}
95-
96-
protected SimpleHQLLexer getLexer(char chars[]) {
97-
return new AntlrSimpleHQLLexer(chars,chars.length);
98-
}
99-
84+
10085
/**
10186
* Returns true if the position is at a location where an entityname makes sense.
102-
* e.g. "from Pr| where x"
103-
* @param query
104-
* @param cursorPosition
105-
* @return
87+
* e.g. "from Pr| where x"
10688
*/
10789
public boolean shouldShowEntityNames(String query, int cursorPosition) {
108-
return shouldShowEntityNames( query.toCharArray(), cursorPosition );
90+
return shouldShowEntityNames( query.toCharArray(), cursorPosition );
10991
}
110-
111-
public boolean shouldShowEntityNames(char chars[], int cursorPosition) {
112-
SimpleHQLLexer lexer = getLexer( chars, cursorPosition );
92+
93+
public boolean shouldShowEntityNames(char[] chars, int cursorPosition) {
94+
SimpleHQLLexer lexer = getLexer( chars);
11395
int tokenId = -1;
11496
boolean show = false;
11597
while ((tokenId = lexer.nextTokenId()) != HqlLexer.EOF) {
@@ -119,18 +101,17 @@ public boolean shouldShowEntityNames(char chars[], int cursorPosition) {
119101
(lexer.getTokenOffset() + lexer.getTokenLength()) < cursorPosition) {
120102
show = true;
121103
} else if (tokenId != HqlLexer.DOT && tokenId != HqlLexer.AS && tokenId != HqlLexer.COMMA && tokenId != HqlLexer.IDENTIFIER && tokenId != HqlLexer.WS) {
122-
show = false;
123-
}
104+
show = false;
105+
}
124106
}
125-
return show;
107+
return show;
126108
}
127-
109+
128110
public List<SubQuery> getVisibleSubQueries(char[] chars, int position) {
129-
SubQueryList sqList = getSubQueries(chars, position);
111+
SubQueryList sqList = getSubQueries(chars, position);
130112
List<SubQuery> visible = new ArrayList<SubQuery>();
131-
for (Iterator<SubQuery> iter = sqList.subQueries.iterator(); iter.hasNext();) {
132-
SubQuery sq = iter.next();
133-
if (sqList.caretDepth >= sq.depth && (sq.startOffset <= position || sq.endOffset >= position)) {
113+
for (SubQuery sq : sqList.subQueries) {
114+
if (sqList.caretDepth >= sq.depth && (sq.startOffset <= position || sq.endOffset >= position)) {
134115
visible.add(sq);
135116
}
136117
}
@@ -140,16 +121,15 @@ public List<SubQuery> getVisibleSubQueries(char[] chars, int position) {
140121
public List<EntityNameReference> getVisibleEntityNames(char[] chars, int position) {
141122
List<SubQuery> sqs = getVisibleSubQueries(chars, position);
142123
List<EntityNameReference> entityReferences = new ArrayList<EntityNameReference>();
143-
for (Iterator<SubQuery> iter = sqs.iterator(); iter.hasNext();) {
144-
SubQuery sq = iter.next();
145-
entityReferences.addAll(sq.getEntityNames());
146-
}
124+
for (SubQuery sq : sqs) {
125+
entityReferences.addAll(sq.getEntityNames());
126+
}
147127
return entityReferences;
148128
}
149129

150130
public SubQueryList getSubQueries(char[] query, int position) {
151-
SimpleHQLLexer syntax = getLexer( query );
152-
int numericId = -1;
131+
SimpleHQLLexer syntax = getLexer( query );
132+
int numericId = -1;
153133
List<SubQuery> subQueries = new ArrayList<SubQuery>();
154134
int depth = 0;
155135
int caretDepth = 0;
@@ -163,15 +143,15 @@ public SubQueryList getSubQueries(char[] query, int position) {
163143
caretDepth = depth;
164144
}
165145
} else if (numericId == HqlLexer.RIGHT_PAREN) {
166-
SubQuery currentDepthQuery = level2SubQuery.get(Integer.valueOf(depth));
146+
SubQuery currentDepthQuery = level2SubQuery.get(depth);
167147
// We check if we have a query on the current depth.
168148
// If yes, we'll have to close it
169149
if (currentDepthQuery != null && currentDepthQuery.depth == depth) {
170150
currentDepthQuery.endOffset = syntax.getTokenOffset();
171-
currentDepthQuery.tokenIds.add(Integer.valueOf(numericId));
151+
currentDepthQuery.tokenIds.add(numericId);
172152
currentDepthQuery.tokenText.add(String.valueOf(query, syntax.getTokenOffset(), syntax.getTokenLength()));
173153
subQueries.add(currentDepthQuery);
174-
level2SubQuery.remove(Integer.valueOf(depth));
154+
level2SubQuery.remove(depth);
175155
tokenAdded = true;
176156
}
177157
depth--;
@@ -184,32 +164,33 @@ public SubQueryList getSubQueries(char[] query, int position) {
184164
case HqlLexer.UPDATE:
185165
case HqlLexer.DELETE:
186166
case HqlLexer.SELECT:
187-
if (!level2SubQuery.containsKey(Integer.valueOf(depth))) {
167+
if (!level2SubQuery.containsKey(depth)) {
188168
current = new SubQuery();
189169
current.depth = depth;
190170
current.startOffset = syntax.getTokenOffset();
191-
level2SubQuery.put(Integer.valueOf(depth), current);
171+
level2SubQuery.put(depth, current);
172+
}
173+
if (current != null) {
174+
current.tokenIds.add(numericId);
175+
current.tokenText.add(String.valueOf(query, syntax.getTokenOffset(), syntax.getTokenLength()));
176+
break;
192177
}
193-
current.tokenIds.add(Integer.valueOf(numericId));
194-
current.tokenText.add(String.valueOf(query, syntax.getTokenOffset(), syntax.getTokenLength()));
195-
break;
196178
default:
197179
if (!tokenAdded) {
198-
SubQuery sq = level2SubQuery.get(Integer.valueOf(depth));
180+
SubQuery sq = level2SubQuery.get(depth);
199181
int i = depth;
200182
while (sq == null && i >= 0) {
201-
sq = level2SubQuery.get(Integer.valueOf(i--));
183+
sq = level2SubQuery.get(i--);
202184
}
203185
if (sq != null) {
204-
sq.tokenIds.add(Integer.valueOf(numericId));
186+
sq.tokenIds.add(numericId);
205187
sq.tokenText.add(String.valueOf(query, syntax.getTokenOffset(), syntax.getTokenLength()));
206188
}
207189
}
208190
}
209191
}
210-
for (Iterator<SubQuery> iter = level2SubQuery.values().iterator(); iter.hasNext();) {
211-
SubQuery sq = iter.next();
212-
sq.endOffset = syntax.getTokenOffset() + syntax.getTokenLength();
192+
for (SubQuery sq : level2SubQuery.values()) {
193+
sq.endOffset = syntax.getTokenOffset() + syntax.getTokenLength();
213194
subQueries.add(sq);
214195
}
215196
Collections.sort(subQueries);
@@ -219,11 +200,11 @@ public SubQueryList getSubQueries(char[] query, int position) {
219200
return sql;
220201
}
221202

222-
203+
223204
/** Returns reference name found from position and backwards in the array.
224205
**/
225206
public static String getEntityNamePrefix(char[] chars, int position) {
226-
StringBuffer buff = new StringBuffer();
207+
StringBuilder buff = new StringBuilder();
227208
for (int i = position - 1; i >= 0; i--) {
228209
char c = chars[i];
229210
if (c == '.' || Character.isJavaIdentifierPart(c)) {
@@ -242,13 +223,13 @@ public static class SubQueryList {
242223
public List<SubQuery> subQueries;
243224
}
244225

245-
226+
246227
static String[] getHQLKeywords() {
247228
return hqlKeywords;
248229
}
249-
230+
250231
static String[] getHQLFunctionNames() {
251232
return builtInFunctions;
252233
}
253-
234+
254235
}

0 commit comments

Comments
 (0)