Skip to content

Commit 663e19e

Browse files
authored
Merge PR #273: NodeType enum and other code review fixes
2 parents 4b72d62 + 201792e commit 663e19e

File tree

7 files changed

+91
-52
lines changed

7 files changed

+91
-52
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"@typescript-eslint/indent": "off",
3737
"@typescript-eslint/lines-between-class-members": "off",
3838
"@typescript-eslint/naming-convention": "error",
39-
"@typescript-eslint/no-unused-vars": "error",
39+
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
4040
"@typescript-eslint/quotes": [
4141
"error",
4242
"single",

src/core/ExpressionFormatter.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Clause,
1414
FunctionCall,
1515
LimitClause,
16+
NodeType,
1617
Parenthesis,
1718
} from './ast';
1819
import { isTabularStyle } from './config';
@@ -51,31 +52,31 @@ export default class ExpressionFormatter {
5152
for (this.index = 0; this.index < this.nodes.length; this.index++) {
5253
const node = this.nodes[this.index];
5354
switch (node.type) {
54-
case 'function_call':
55+
case NodeType.function_call:
5556
this.formatFunctionCall(node);
5657
break;
57-
case 'array_subscript':
58+
case NodeType.array_subscript:
5859
this.formatArraySubscript(node);
5960
break;
60-
case 'parenthesis':
61+
case NodeType.parenthesis:
6162
this.formatParenthesis(node);
6263
break;
63-
case 'between_predicate':
64+
case NodeType.between_predicate:
6465
this.formatBetweenPredicate(node);
6566
break;
66-
case 'clause':
67+
case NodeType.clause:
6768
this.formatClause(node);
6869
break;
69-
case 'binary_clause':
70+
case NodeType.binary_clause:
7071
this.formatBinaryClause(node);
7172
break;
72-
case 'limit_clause':
73+
case NodeType.limit_clause:
7374
this.formatLimitClause(node);
7475
break;
75-
case 'all_columns_asterisk':
76+
case NodeType.all_columns_asterisk:
7677
this.formatAllColumnsAsterisk(node);
7778
break;
78-
case 'token':
79+
case NodeType.token:
7980
this.formatToken(node.token);
8081
break;
8182
}
@@ -174,8 +175,7 @@ export default class ExpressionFormatter {
174175
this.layout.indentation.decreaseTopLevel();
175176
}
176177

177-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
178-
private formatAllColumnsAsterisk(node: AllColumnsAsterisk) {
178+
private formatAllColumnsAsterisk(_node: AllColumnsAsterisk) {
179179
this.layout.add('*', WS.SPACE);
180180
}
181181

@@ -242,6 +242,21 @@ export default class ExpressionFormatter {
242242
this.layout.add(WS.NEWLINE, WS.INDENT);
243243
}
244244

245+
// Breaks up block comment to multiple lines.
246+
// For example this comment (dots representing leading whitespace):
247+
//
248+
// ..../**
249+
// .....* Some description here
250+
// .....* and here too
251+
// .....*/
252+
//
253+
// gets broken to this array (note the leading single spaces):
254+
//
255+
// [ '/**',
256+
// '.* Some description here',
257+
// '.* and here too',
258+
// '.*/' ]
259+
//
245260
private splitBlockComment(comment: string): string[] {
246261
return comment.split(/\n/).map(line => {
247262
if (/^\s*\*/.test(line)) {

src/core/InlineBlock.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { BetweenPredicate, Parenthesis } from './ast';
1+
import { sum } from 'src/utils';
2+
import { BetweenPredicate, NodeType, Parenthesis } from './ast';
23
import { isToken, type Token, TokenType } from './token';
34

45
/**
@@ -24,26 +25,26 @@ export default class InlineBlock {
2425

2526
for (const node of parenthesis.children) {
2627
switch (node.type) {
27-
case 'function_call':
28+
case NodeType.function_call:
2829
length += node.nameToken.value.length + this.inlineWidth(node.parenthesis);
2930
break;
30-
case 'array_subscript':
31+
case NodeType.array_subscript:
3132
length += node.arrayToken.value.length + this.inlineWidth(node.parenthesis);
3233
break;
33-
case 'parenthesis':
34+
case NodeType.parenthesis:
3435
length += this.inlineWidth(node);
3536
break;
36-
case 'between_predicate':
37+
case NodeType.between_predicate:
3738
length += this.betweenWidth(node);
3839
break;
39-
case 'clause':
40-
case 'limit_clause':
41-
case 'binary_clause':
40+
case NodeType.clause:
41+
case NodeType.limit_clause:
42+
case NodeType.binary_clause:
4243
return Infinity;
43-
case 'all_columns_asterisk':
44+
case NodeType.all_columns_asterisk:
4445
length += 1;
4546
break;
46-
case 'token':
47+
case NodeType.token:
4748
length += node.token.value.length;
4849
if (this.isForbiddenToken(node.token)) {
4950
return Infinity;
@@ -60,9 +61,9 @@ export default class InlineBlock {
6061
}
6162

6263
private betweenWidth(node: BetweenPredicate): number {
63-
return [node.betweenToken, node.expr1, node.andToken, node.expr2]
64-
.map(token => token.value.length)
65-
.reduce((a, b) => a + b);
64+
return sum(
65+
[node.betweenToken, node.expr1, node.andToken, node.expr2].map(token => token.value.length)
66+
);
6667
}
6768

6869
// Reserved words that cause newlines, comments and semicolons

src/core/Layout.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import Indentation from './Indentation';
44

55
/** Whitespace modifiers to be used with add() method */
66
export enum WS {
7-
SPACE = 1, // Adds single space
8-
NO_SPACE = 2, // Removes preceding horizontal whitespace (if any)
9-
NEWLINE = 3, // Adds single newline (and removes any preceding whitespace)
10-
INDENT = 4, // Adds indentation (as much as needed for current indentation level)
11-
SINGLE_INDENT = 5, // Adds whitespace for single indentation step
7+
SPACE, // Adds single space
8+
NO_SPACE, // Removes preceding horizontal whitespace (if any)
9+
NEWLINE, // Adds single newline (and removes any preceding whitespace)
10+
INDENT, // Adds indentation (as much as needed for current indentation level)
11+
SINGLE_INDENT, // Adds whitespace for single indentation step
1212
}
1313

1414
export type LayoutItem = WS.SPACE | WS.SINGLE_INDENT | WS.NEWLINE | string;

src/core/Parser.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
Clause,
99
FunctionCall,
1010
LimitClause,
11+
NodeType,
1112
Parenthesis,
1213
Statement,
1314
TokenNode,
@@ -36,10 +37,10 @@ export default class Parser {
3637
while (true) {
3738
if (this.look().value === ';') {
3839
this.next();
39-
return { type: 'statement', children, hasSemicolon: true };
40+
return { type: NodeType.statement, children, hasSemicolon: true };
4041
} else if (this.look().type === TokenType.EOF) {
4142
if (children.length > 0) {
42-
return { type: 'statement', children, hasSemicolon: false };
43+
return { type: NodeType.statement, children, hasSemicolon: false };
4344
} else {
4445
return undefined;
4546
}
@@ -76,7 +77,7 @@ export default class Parser {
7677
) {
7778
children.push(this.expression());
7879
}
79-
return { type: 'clause', nameToken: name, children };
80+
return { type: NodeType.clause, nameToken: name, children };
8081
}
8182
return undefined;
8283
}
@@ -94,7 +95,7 @@ export default class Parser {
9495
) {
9596
children.push(this.expression());
9697
}
97-
return { type: 'binary_clause', nameToken: name, children };
98+
return { type: NodeType.binary_clause, nameToken: name, children };
9899
}
99100
return undefined;
100101
}
@@ -106,7 +107,7 @@ export default class Parser {
106107
!this.look(1).whitespaceBefore
107108
) {
108109
return {
109-
type: 'function_call',
110+
type: NodeType.function_call,
110111
nameToken: this.next(),
111112
parenthesis: this.parenthesis() as Parenthesis,
112113
};
@@ -120,7 +121,7 @@ export default class Parser {
120121
this.look(1).value === '['
121122
) {
122123
return {
123-
type: 'array_subscript',
124+
type: NodeType.array_subscript,
124125
arrayToken: this.next(),
125126
parenthesis: this.parenthesis() as Parenthesis,
126127
};
@@ -140,15 +141,15 @@ export default class Parser {
140141
if (this.look().type === TokenType.CLOSE_PAREN) {
141142
closeParen = this.next().value;
142143
}
143-
return { type: 'parenthesis', children, openParen, closeParen };
144+
return { type: NodeType.parenthesis, children, openParen, closeParen };
144145
}
145146
return undefined;
146147
}
147148

148149
private betweenPredicate(): BetweenPredicate | undefined {
149150
if (isToken.BETWEEN(this.look()) && isToken.AND(this.look(2))) {
150151
return {
151-
type: 'between_predicate',
152+
type: NodeType.between_predicate,
152153
betweenToken: this.next(),
153154
expr1: this.next(),
154155
andToken: this.next(),
@@ -161,15 +162,15 @@ export default class Parser {
161162
private limitClause(): LimitClause | undefined {
162163
if (isToken.LIMIT(this.look()) && this.look(2).value === ',') {
163164
return {
164-
type: 'limit_clause',
165+
type: NodeType.limit_clause,
165166
limitToken: this.next(),
166167
offsetToken: this.next(),
167168
countToken: this.next() && this.next(), // Discard comma token
168169
};
169170
}
170171
if (isToken.LIMIT(this.look())) {
171172
return {
172-
type: 'limit_clause',
173+
type: NodeType.limit_clause,
173174
limitToken: this.next(),
174175
countToken: this.next(),
175176
};
@@ -180,7 +181,7 @@ export default class Parser {
180181
private allColumnsAsterisk(): AllColumnsAsterisk | undefined {
181182
if (this.look().value === '*' && isToken.SELECT(this.look(-1))) {
182183
this.next();
183-
return { type: 'all_columns_asterisk' };
184+
return { type: NodeType.all_columns_asterisk };
184185
}
185186
return undefined;
186187
}
@@ -196,6 +197,6 @@ export default class Parser {
196197
}
197198

198199
private nextTokenNode(): TokenNode {
199-
return { type: 'token', token: this.next() };
200+
return { type: NodeType.token, token: this.next() };
200201
}
201202
}

src/core/ast.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,65 @@
11
import { Token } from './token';
22

3+
export enum NodeType {
4+
statement = 'statement',
5+
clause = 'clause',
6+
binary_clause = 'binary_clause',
7+
function_call = 'function_call',
8+
array_subscript = 'array_subscript',
9+
parenthesis = 'parenthesis',
10+
between_predicate = 'between_predicate',
11+
limit_clause = 'limit_clause',
12+
all_columns_asterisk = 'all_columns_asterisk',
13+
token = 'token',
14+
}
15+
316
export type Statement = {
4-
type: 'statement';
17+
type: NodeType.statement;
518
children: AstNode[];
619
hasSemicolon: boolean;
720
};
821

922
export type Clause = {
10-
type: 'clause';
23+
type: NodeType.clause;
1124
nameToken: Token;
1225
children: AstNode[];
1326
};
1427

1528
export type BinaryClause = {
16-
type: 'binary_clause';
29+
type: NodeType.binary_clause;
1730
nameToken: Token;
1831
children: AstNode[];
1932
};
2033

2134
// Wrapper for plain nodes inside AST
2235
export type TokenNode = {
23-
type: 'token';
36+
type: NodeType.token;
2437
token: Token;
2538
};
2639

2740
export type FunctionCall = {
28-
type: 'function_call';
41+
type: NodeType.function_call;
2942
nameToken: Token;
3043
parenthesis: Parenthesis;
3144
};
3245

3346
// <ident>[<expr>]
3447
export type ArraySubscript = {
35-
type: 'array_subscript';
48+
type: NodeType.array_subscript;
3649
arrayToken: Token;
3750
parenthesis: Parenthesis;
3851
};
3952

4053
export type Parenthesis = {
41-
type: 'parenthesis';
54+
type: NodeType.parenthesis;
4255
children: AstNode[];
4356
openParen: string;
4457
closeParen: string;
4558
};
4659

4760
// BETWEEN <expr1> AND <expr2>
4861
export type BetweenPredicate = {
49-
type: 'between_predicate';
62+
type: NodeType.between_predicate;
5063
betweenToken: Token;
5164
expr1: Token;
5265
andToken: Token;
@@ -56,15 +69,15 @@ export type BetweenPredicate = {
5669
// LIMIT <count>
5770
// LIMIT <offset>, <count>
5871
export type LimitClause = {
59-
type: 'limit_clause';
72+
type: NodeType.limit_clause;
6073
limitToken: Token;
6174
countToken: Token;
6275
offsetToken?: Token;
6376
};
6477

6578
// The "*" operator used in SELECT *
6679
export type AllColumnsAsterisk = {
67-
type: 'all_columns_asterisk';
80+
type: NodeType.all_columns_asterisk;
6881
};
6982

7083
export type AstNode =

src/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,12 @@ export const equalizeWhitespace = (s: string) => s.replace(/\s+/gu, ' ');
2525

2626
// identity function
2727
export const id = <T>(x: T) => x;
28+
29+
// Adds up all values in array
30+
export const sum = (arr: number[]): number => {
31+
let total = 0;
32+
for (const x of arr) {
33+
total += x;
34+
}
35+
return total;
36+
};

0 commit comments

Comments
 (0)