Skip to content

Commit fcdfc8a

Browse files
committed
refactor: rename 'isNewStatement' to 'isStatementBeginning'
1 parent 0d7de53 commit fcdfc8a

File tree

9 files changed

+429
-409
lines changed

9 files changed

+429
-409
lines changed

src/parser/common/semanticContextCollector.ts

+26-20
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ abstract class SemanticContextCollector {
3434
* Link to @case4 and @case5
3535
* Find the previous unhidden token.
3636
* If can't find tokenIndex or current token is whiteSpace at caretPosition,
37-
* prevTokenIndex is useful to help us determine if it is new statement.
37+
* prevTokenIndex is useful to help us determine if it is beginning of statement.
3838
*/
3939
while (i >= 0) {
4040
if (
@@ -50,7 +50,7 @@ abstract class SemanticContextCollector {
5050
}
5151

5252
/**
53-
* We can directly conclude newStatement semantics when current token is
53+
* We can directly conclude beginning of statement semantics when current token is
5454
* the first token of tokenStream or the previous token is semicolon
5555
*/
5656
if (
@@ -59,7 +59,7 @@ abstract class SemanticContextCollector {
5959
(this._prevTokenIndex &&
6060
this._allTokens[this._prevTokenIndex].text === SQL_SPLIT_SYMBOL_TEXT)
6161
) {
62-
this._isNewStatement = true;
62+
this._isStatementBeginning = true;
6363
}
6464
}
6565
}
@@ -72,7 +72,7 @@ abstract class SemanticContextCollector {
7272
private _allTokens: Token[] = [];
7373

7474
/**
75-
* If current caret position is in a newStatement semantics, it needs to follow some cases:
75+
* If current caret position is in a beginning of statement semantics, it needs to follow some cases:
7676
* @case1 there is no statement node with an error before the current statement in the parse tree;
7777
*
7878
* @case2 if it is an uncomplete keyword, it will be parsed as an `ErrorNode`
@@ -85,9 +85,9 @@ abstract class SemanticContextCollector {
8585
* so we find the first unhidden token before the whiteSpace token, and the unhidden token
8686
* should be the last leaf node of statement its belongs to;
8787
*
88-
* @case5 if the previous token is split symbol like `;`, ignore case1 and forcefully judged as newStatement.
88+
* @case5 if the previous token is split symbol like `;`, ignore case1 and forcefully judged as beginning of statement.
8989
*/
90-
private _isNewStatement: boolean = false;
90+
private _isStatementBeginning: boolean = false;
9191

9292
/**
9393
* Prev tokenIndex that not white space before current tokenIndex or caret position
@@ -96,7 +96,7 @@ abstract class SemanticContextCollector {
9696

9797
public get semanticContext(): SemanticContext {
9898
return {
99-
isNewStatement: this._isNewStatement,
99+
isStatementBeginning: this._isStatementBeginning,
100100
};
101101
}
102102

@@ -147,7 +147,9 @@ abstract class SemanticContextCollector {
147147
this._prevTokenIndex && ctx.stop?.tokenIndex === this._prevTokenIndex;
148148

149149
if (isWhiteSpaceToken && isPrevTokenEndOfStatement && ctx.exception === null) {
150-
this._isNewStatement = !this.prevStatementHasError(ctx) ? true : this._isNewStatement;
150+
this._isStatementBeginning = !this.prevStatementHasError(ctx)
151+
? true
152+
: this._isStatementBeginning;
151153
}
152154
}
153155

@@ -157,7 +159,7 @@ abstract class SemanticContextCollector {
157159
visitErrorNode(node: ErrorNode): void {
158160
if (
159161
node.symbol.tokenIndex !== this._tokenIndex ||
160-
this._isNewStatement ||
162+
this._isStatementBeginning ||
161163
this.options.sqlSplitStrategy === SqlSplitStrategy.STRICT
162164
)
163165
return;
@@ -170,7 +172,7 @@ abstract class SemanticContextCollector {
170172
* The error node is a direct child node of the program node
171173
*/
172174
if (this.isRootRule(parent)) {
173-
this._isNewStatement = !this.prevStatementHasError(currentNode);
175+
this._isStatementBeginning = !this.prevStatementHasError(currentNode);
174176
return;
175177
}
176178

@@ -180,15 +182,15 @@ abstract class SemanticContextCollector {
180182
**/
181183
while (parent !== null && parent.ruleIndex !== this.getStatementRuleType()) {
182184
if (parent.children?.[0] !== currentNode) {
183-
this._isNewStatement = false;
185+
this._isStatementBeginning = false;
184186
return;
185187
}
186188

187189
currentNode = parent;
188190
parent = currentNode.parent;
189191
}
190192

191-
let isNewStatement = true;
193+
let isStatementBeginning = true;
192194

193195
/**
194196
* Link to @case1
@@ -204,18 +206,20 @@ abstract class SemanticContextCollector {
204206
* For example, just typed 'CREATE', 'INSERT'.
205207
*/
206208
const isStatementEOF = parent.exception?.offendingToken?.text === '<EOF>';
207-
isNewStatement =
208-
this.prevStatementHasError(parent) && !isStatementEOF ? false : isNewStatement;
209+
isStatementBeginning =
210+
this.prevStatementHasError(parent) && !isStatementEOF
211+
? false
212+
: isStatementBeginning;
209213
}
210214
}
211215

212-
this._isNewStatement = isNewStatement;
216+
this._isStatementBeginning = isStatementBeginning;
213217
}
214218

215219
visitTerminal(node: TerminalNode): void {
216220
if (
217221
node.symbol.tokenIndex !== this._tokenIndex ||
218-
this._isNewStatement ||
222+
this._isStatementBeginning ||
219223
this.options.sqlSplitStrategy === SqlSplitStrategy.STRICT
220224
)
221225
return;
@@ -229,15 +233,15 @@ abstract class SemanticContextCollector {
229233
**/
230234
while (parent !== null && parent.ruleIndex !== this.getStatementRuleType()) {
231235
if (parent.children?.[0] !== currentNode) {
232-
this._isNewStatement = false;
236+
this._isStatementBeginning = false;
233237
return;
234238
}
235239

236240
currentNode = parent;
237241
parent = currentNode.parent!;
238242
}
239243

240-
let isNewStatement = true;
244+
let isStatementBeginning = true;
241245

242246
/**
243247
* Link to @case1
@@ -248,11 +252,13 @@ abstract class SemanticContextCollector {
248252
const currentStatementRuleIndex =
249253
programRule?.children?.findIndex((node) => node === parent) || -1;
250254
if (currentStatementRuleIndex > 0) {
251-
isNewStatement = this.prevStatementHasError(parent) ? false : isNewStatement;
255+
isStatementBeginning = this.prevStatementHasError(parent)
256+
? false
257+
: isStatementBeginning;
252258
}
253259
}
254260

255-
this._isNewStatement = isNewStatement;
261+
this._isStatementBeginning = isStatementBeginning;
256262
}
257263

258264
enterEveryRule(_node: ParserRuleContext): void {}

src/parser/common/types.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export interface Suggestions<T = WordRange> {
7171
export type LOCALE_TYPE = 'zh_CN' | 'en_US';
7272

7373
export interface SemanticContext {
74-
isNewStatement: boolean;
74+
isStatementBeginning: boolean;
7575
}
7676

7777
export enum SqlSplitStrategy {
@@ -83,15 +83,15 @@ export enum SqlSplitStrategy {
8383

8484
export interface SemanticCollectOptions {
8585
/**
86-
* `sqlSplitStrategy` will affects the result of `isNewStatement`;
86+
* `sqlSplitStrategy` will affects the result of `isStatementBeginning`;
8787
*
8888
* For example:
8989
*
9090
* The sql is "select id from t1 create\<cart_position\>"
9191
*
92-
* - `SqlSplitStrategy.STRICT`: split symbol `;` is missing after select statement so that it considerd as one statement, and `isNewStatement` is false
92+
* - `SqlSplitStrategy.STRICT`: split symbol `;` is missing after select statement so that it considerd as one statement, and `isStatementBeginning` is false
9393
*
94-
* - `SqlSplitStrategy.LOOSE`: in parse tree, it will parse to "select id from t1" and "create" two single statement, so `isNewStatement` is true
94+
* - `SqlSplitStrategy.LOOSE`: in parse tree, it will parse to "select id from t1" and "create" two single statement, so `isStatementBeginning` is true
9595
*
9696
* @default SqlSplitStrategy.STRICT
9797
*/

test/parser/flink/contextCollect/semanticContextCollector.test.ts

+57-55
Original file line numberDiff line numberDiff line change
@@ -8,137 +8,139 @@ describe('Flink semantic context collector tests', () => {
88
const flinkSql = new FlinkSQL();
99
const text = fs.readFileSync(path.join(__dirname, 'fixtures', 'semantic.sql'), 'utf-8');
1010

11-
test('new statement with uncomplete keyword', () => {
11+
test('beginning of statement with uncomplete keyword', () => {
1212
const sql = readSQLByRange({ sql: text }, { startLine: 1, endLine: 1 });
13-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
13+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
1414
lineNumber: 1,
1515
column: 5,
1616
});
17-
expect(isNewStatement).toBeTruthy();
17+
expect(isStatementBeginning).toBeTruthy();
1818
});
1919

20-
test('new statement with complete keyword', () => {
20+
test('beginning of statement with complete keyword', () => {
2121
const sql = readSQLByRange({ sql: text }, { startLine: 3, endLine: 3 });
22-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
22+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
2323
lineNumber: 1,
2424
column: 7,
2525
});
26-
expect(isNewStatement).toBeTruthy();
26+
expect(isStatementBeginning).toBeTruthy();
2727
});
2828

29-
test('not new statement with uncomplete keyword', () => {
29+
test('not beginning of statement with uncomplete keyword', () => {
3030
const sql = readSQLByRange({ sql: text }, { startLine: 5, endLine: 5 });
31-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
31+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
3232
lineNumber: 1,
3333
column: 22,
3434
});
35-
expect(isNewStatement).toBeFalsy();
35+
expect(isStatementBeginning).toBeFalsy();
3636
});
3737

38-
test('not new statement with complete keyword', () => {
38+
test('not beginning of statement with complete keyword', () => {
3939
const sql = readSQLByRange({ sql: text }, { startLine: 7, endLine: 7 });
40-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
40+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
4141
lineNumber: 1,
4242
column: 22,
4343
});
44-
expect(isNewStatement).toBeFalsy();
44+
expect(isStatementBeginning).toBeFalsy();
4545
});
4646

47-
test('not new statement if type white space after keyword', () => {
47+
test('not beginning of statement if type white space after keyword', () => {
4848
const sql = readSQLByRange({ sql: text }, { startLine: 9, endLine: 9 });
49-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
49+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
5050
lineNumber: 1,
5151
column: 8,
5252
});
53-
expect(isNewStatement).toBeFalsy();
53+
expect(isStatementBeginning).toBeFalsy();
5454
});
5555

56-
test('new statement after an exists statement', () => {
56+
test('beginning of statement after an exists statement', () => {
5757
const sql = readSQLByRange({ sql: text }, { startLine: 11, endLine: 12 });
58-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
58+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
5959
lineNumber: 2,
6060
column: 4,
6161
});
62-
expect(isNewStatement).toBeTruthy();
62+
expect(isStatementBeginning).toBeTruthy();
6363
});
6464

65-
test('new statement after an exists statement and typed white space', () => {
65+
test('beginning of statement after an exists statement and typed white space', () => {
6666
const sql = readSQLByRange({ sql: text }, { startLine: 14, endLine: 15 });
67-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
67+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
6868
lineNumber: 2,
6969
column: 2,
7070
});
71-
expect(isNewStatement).toBeTruthy();
71+
expect(isStatementBeginning).toBeTruthy();
7272
});
7373

74-
test('not new statement if previous statement exists error', () => {
74+
test('not beginning of statement if previous statement exists error', () => {
7575
const sql = readSQLByRange({ sql: text }, { startLine: 17, endLine: 22 });
76-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
76+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
7777
lineNumber: 6,
7878
column: 4,
7979
});
80-
expect(isNewStatement).toBeFalsy();
80+
expect(isStatementBeginning).toBeFalsy();
8181
});
8282

83-
test('new statement if previous token text is semicolon even if has error', () => {
83+
test('beginning of statement if previous token text is semicolon even if has error', () => {
8484
const sql = readSQLByRange({ sql: text }, { startLine: 24, endLine: 24 });
8585
// typed keyword
8686
const ctx1 = flinkSql.getSemanticContextAtCaretPosition(sql, {
8787
lineNumber: 1,
8888
column: 13,
8989
});
90-
expect(ctx1.isNewStatement).toBeTruthy();
90+
expect(ctx1.isStatementBeginning).toBeTruthy();
9191

9292
// typed white space
9393
const ctx2 = flinkSql.getSemanticContextAtCaretPosition(sql, {
9494
lineNumber: 1,
9595
column: 9,
9696
});
97-
expect(ctx2.isNewStatement).toBeTruthy();
97+
expect(ctx2.isStatementBeginning).toBeTruthy();
9898
});
9999

100-
test('new statement between two statement', () => {
100+
test('beginning of statement between two statement', () => {
101101
const sql = readSQLByRange({ sql: text }, { startLine: 26, endLine: 28 });
102-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
102+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
103103
lineNumber: 2,
104104
column: 4,
105105
});
106-
expect(isNewStatement).toBeTruthy();
106+
expect(isStatementBeginning).toBeTruthy();
107107
});
108108

109-
test('not new statement between two statement', () => {
109+
test('not beginning of statement between two statement', () => {
110110
const sql = readSQLByRange({ sql: text }, { startLine: 30, endLine: 32 });
111-
const { isNewStatement } = flinkSql.getSemanticContextAtCaretPosition(sql, {
111+
const { isStatementBeginning } = flinkSql.getSemanticContextAtCaretPosition(sql, {
112112
lineNumber: 2,
113113
column: 13,
114114
});
115-
expect(isNewStatement).toBeFalsy();
115+
expect(isStatementBeginning).toBeFalsy();
116116
});
117117

118118
test('test sqlSplitStrategy', () => {
119119
const sql = readSQLByRange({ sql: text }, { startLine: 34, endLine: 35 });
120-
const { isNewStatement: isNewStatement1 } = flinkSql.getSemanticContextAtCaretPosition(
121-
sql,
122-
{
123-
lineNumber: 2,
124-
column: 7,
125-
},
126-
{
127-
sqlSplitStrategy: SqlSplitStrategy.LOOSE,
128-
}
129-
);
130-
expect(isNewStatement1).toBeTruthy();
120+
const { isStatementBeginning: isStatementBeginning1 } =
121+
flinkSql.getSemanticContextAtCaretPosition(
122+
sql,
123+
{
124+
lineNumber: 2,
125+
column: 7,
126+
},
127+
{
128+
sqlSplitStrategy: SqlSplitStrategy.LOOSE,
129+
}
130+
);
131+
expect(isStatementBeginning1).toBeTruthy();
131132

132-
const { isNewStatement: isNewStatement2 } = flinkSql.getSemanticContextAtCaretPosition(
133-
sql,
134-
{
135-
lineNumber: 2,
136-
column: 7,
137-
},
138-
{
139-
sqlSplitStrategy: SqlSplitStrategy.STRICT,
140-
}
141-
);
142-
expect(isNewStatement2).toBeFalsy();
133+
const { isStatementBeginning: isStatementBeginning2 } =
134+
flinkSql.getSemanticContextAtCaretPosition(
135+
sql,
136+
{
137+
lineNumber: 2,
138+
column: 7,
139+
},
140+
{
141+
sqlSplitStrategy: SqlSplitStrategy.STRICT,
142+
}
143+
);
144+
expect(isStatementBeginning2).toBeFalsy();
143145
});
144146
});

0 commit comments

Comments
 (0)