Skip to content

Commit c140dae

Browse files
Merge pull request #12 from inferrinizzard/typescript
Add extra configs for ESLint and Typescript support
2 parents ac0a045 + cfc10c1 commit c140dae

23 files changed

+152
-128
lines changed

.eslintrc

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
{
22
"parser": "@typescript-eslint/parser",
33
"parserOptions": { "project": "./tsconfig.json", "ecmaVersion": 6, "sourceType": "module" },
4-
"extends": ["airbnb-base", "plugin:import/typescript", "prettier"],
4+
"extends": ["airbnb-base", "airbnb-typescript/base", "plugin:import/typescript", "prettier"],
55
"plugins": ["@typescript-eslint", "prettier"],
66
"rules": {
7-
"prettier/prettier": ["error"],
7+
"class-methods-use-this": "off",
88
"curly": ["error", "all"],
9-
"require-unicode-regexp": ["error"],
10-
"func-names": "error",
119
"eqeqeq": "warn",
12-
"no-useless-concat": "off",
13-
"class-methods-use-this": "off",
10+
"func-names": "error",
1411
"no-param-reassign": "off",
15-
"prefer-template": "off",
1612
"no-plusplus": "off",
1713
"no-else-return": "off",
1814
"no-use-before-define": "warn",
19-
"lines-between-class-members": "off",
15+
"no-useless-concat": "off",
16+
"prefer-template": "off",
17+
"prettier/prettier": ["error"],
18+
"require-unicode-regexp": ["error"],
2019
"@typescript-eslint/naming-convention": "warn",
21-
"@typescript-eslint/semi": "warn"
20+
"@typescript-eslint/indent": "off",
21+
"@typescript-eslint/semi": "warn",
22+
"@typescript-eslint/lines-between-class-members": "off",
23+
"@typescript-eslint/comma-dangle": "off",
24+
"@typescript-eslint/quotes": [
25+
"warn",
26+
"single",
27+
{ "avoidEscape": true, "allowTemplateLiterals": true }
28+
]
2229
},
2330
"settings": {
2431
"import/resolver": {

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,15 @@
6161
"lint": "eslint .",
6262
"pretty": "prettier --write .",
6363
"pretty:check": "prettier --check .",
64+
"fix": "npm run pretty && eslint --fix .",
6465
"test": "jest",
6566
"test:watch": "npm run test -- --watch",
6667
"check": "npm run pretty:check && npm run lint && npm run test",
6768
"build": "npm run build:commonjs && npm run build:umd && npm run build:umd:min",
6869
"build:commonjs": "babel src --out-dir lib",
6970
"build:umd": "webpack --config webpack.dev.js",
7071
"build:umd:min": "webpack --config webpack.prod.js",
71-
"prepare": "npm run clean && npm run check && npm run build"
72+
"prepare": "npm run clean && npm run fix && npm run check && npm run build"
7273
},
7374
"repository": {
7475
"type": "git",
@@ -85,14 +86,15 @@
8586
"@babel/preset-typescript": "^7.15.0",
8687
"@types/babel__core": "^7.1.15",
8788
"@typescript-eslint/eslint-plugin": "^4.31.2",
88-
"@typescript-eslint/parser": "^4.29.1",
89+
"@typescript-eslint/parser": "^4.32.0",
8990
"babel-eslint": "^10.1.0",
9091
"babel-jest": "^26.1.0",
9192
"babel-loader": "^8.1.0",
9293
"babel-plugin-add-module-exports": "^1.0.2",
9394
"dedent-js": "^1.0.1",
9495
"eslint": "^7.4.0",
9596
"eslint-config-airbnb-base": "^14.2.0",
97+
"eslint-config-airbnb-typescript": "^14.0.0",
9698
"eslint-config-prettier": "^6.11.0",
9799
"eslint-plugin-import": "^2.22.0",
98100
"eslint-plugin-prettier": "^3.1.4",

src/core/Formatter.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
Token,
1616
} from './token';
1717
import Tokenizer from './Tokenizer';
18-
import { FormatOptions } from '../sqlFormatter';
18+
import type { FormatOptions } from '../sqlFormatter';
1919

2020
export default class Formatter {
2121
cfg: FormatOptions;
@@ -144,8 +144,9 @@ export default class Formatter {
144144
) {
145145
formattedQuery = this.formatWithSpaces(token, formattedQuery, 'after');
146146
} else {
147-
if (this.cfg.aliasAs !== 'never')
147+
if (this.cfg.aliasAs !== 'never') {
148148
formattedQuery = this.formatAliases(token, formattedQuery);
149+
}
149150
formattedQuery = this.formatWithSpaces(token, formattedQuery);
150151
}
151152
});
@@ -167,17 +168,22 @@ export default class Formatter {
167168
(prevToken?.type === tokenTypes.WORD &&
168169
(nextToken?.value === ',' || isTopLevel(nextToken))));
169170

170-
if (missingTableAlias || missingSelectColumnAlias) return this.formatWithSpaces(asToken, query);
171+
if (missingTableAlias || missingSelectColumnAlias) {
172+
return this.formatWithSpaces(asToken, query);
173+
}
171174
return query;
172175
}
173176

174177
checkNewline = (index: number) => {
175178
if (
176179
this.newline.mode === 'always' ||
177180
this.tokens.some(({ type, value }) => type === tokenTypes.OPEN_PAREN && value.length > 1) // auto break on CASE statements
178-
)
181+
) {
179182
return true;
180-
if (this.newline.mode === 'never') return false;
183+
}
184+
if (this.newline.mode === 'never') {
185+
return false;
186+
}
181187
const tail = this.tokens.slice(index + 1);
182188
const nextTokens = tail.slice(
183189
0,
@@ -191,24 +197,34 @@ export default class Formatter {
191197

192198
const numItems = nextTokens.reduce(
193199
(acc, { type, value }) => {
194-
if (value == ',' && !acc.inParen) return { ...acc, count: acc.count + 1 }; // count commas between items in clause
195-
if (type === tokenTypes.OPEN_PAREN) return { ...acc, inParen: true }; // don't count commas in functions
196-
if (type === tokenTypes.CLOSE_PAREN) return { ...acc, inParen: false };
200+
if (value === ',' && !acc.inParen) {
201+
return { ...acc, count: acc.count + 1 };
202+
} // count commas between items in clause
203+
if (type === tokenTypes.OPEN_PAREN) {
204+
return { ...acc, inParen: true };
205+
} // don't count commas in functions
206+
if (type === tokenTypes.CLOSE_PAREN) {
207+
return { ...acc, inParen: false };
208+
}
197209
return acc;
198210
},
199211
{ count: 1, inParen: false } // start with 1 for first word
200212
).count;
201213

202-
if (this.newline.mode === 'itemCount') return numItems > this.newline.itemCount!;
214+
if (this.newline.mode === 'itemCount') {
215+
return numItems > this.newline.itemCount!;
216+
}
203217

204218
// calculate length if it were all inline
205219
const inlineWidth = `${this.tokens[index].whitespaceBefore}${
206220
this.tokens[index].value
207221
} ${nextTokens.map(({ value }) => (value === ',' ? value + ' ' : value)).join('')}`.length;
208222

209-
if (this.newline.mode === 'lineWidth') return inlineWidth > this.lineWidth;
210-
else if (this.newline.mode == 'hybrid')
223+
if (this.newline.mode === 'lineWidth') {
224+
return inlineWidth > this.lineWidth;
225+
} else if (this.newline.mode === 'hybrid') {
211226
return numItems > this.newline.itemCount! || inlineWidth > this.lineWidth;
227+
}
212228

213229
return true;
214230
};
@@ -239,8 +255,11 @@ export default class Formatter {
239255
this.indentation.increaseTopLevel();
240256

241257
query += this.equalizeWhitespace(this.show(token));
242-
if (this.currentNewline) query = this.addNewline(query);
243-
else query += ' ';
258+
if (this.currentNewline) {
259+
query = this.addNewline(query);
260+
} else {
261+
query += ' ';
262+
}
244263
return query;
245264
}
246265

@@ -305,9 +324,10 @@ export default class Formatter {
305324
return query;
306325
} else if (isLimit(this.previousReservedToken)) {
307326
return query;
327+
} else if (this.currentNewline) {
328+
return this.addNewline(query);
308329
} else {
309-
if (this.currentNewline) return this.addNewline(query);
310-
else return query;
330+
return query;
311331
}
312332
}
313333

@@ -334,12 +354,16 @@ export default class Formatter {
334354
token.type === tokenTypes.CLOSE_PAREN
335355
) {
336356
return this.cfg.uppercase ? token.value.toUpperCase() : token.value.toLowerCase();
337-
} else return token.value;
357+
} else {
358+
return token.value;
359+
}
338360
}
339361

340362
addNewline(query: string) {
341363
query = trimSpacesEnd(query);
342-
if (!query.endsWith('\n')) query += '\n';
364+
if (!query.endsWith('\n')) {
365+
query += '\n';
366+
}
343367
return query + this.indentation.getIndent();
344368
}
345369

src/core/InlineBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Token } from './token';
1+
import type { Token } from './token';
22
import tokenTypes from './tokenTypes';
33

44
/**

src/core/Params.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Token } from './token';
1+
import type { Token } from './token';
22

33
export type ParamItems = { [k: string]: string };
44

@@ -23,9 +23,13 @@ export default class Params {
2323
* @return {String} param or token.value when params are missing
2424
*/
2525
get({ key, value }: Token): string {
26-
if (!this.params) return value;
26+
if (!this.params) {
27+
return value;
28+
}
2729

28-
if (key) return (this.params as ParamItems)[key];
30+
if (key) {
31+
return (this.params as ParamItems)[key];
32+
}
2933
return (this.params as string[])[this.index++];
3034
}
3135
}

src/core/Tokenizer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
/* eslint-disable @typescript-eslint/naming-convention */
2-
31
import tokenTypes from './tokenTypes';
42
import * as regexFactory from './regexFactory';
53
import { escapeRegExp } from '../utils';
6-
import { Token, TokenType } from './token';
4+
import type { Token, TokenType } from './token';
75

86
interface TokenizerOptions {
97
reservedWords: string[];
@@ -107,7 +105,7 @@ export default class Tokenizer {
107105
*/
108106
tokenize(input: string) {
109107
const tokens: Token[] = [];
110-
let token: Token | undefined = undefined;
108+
let token: Token | undefined;
111109

112110
// Keep processing the string until it is empty
113111
while (input.length) {
@@ -313,7 +311,9 @@ export default class Tokenizer {
313311
}
314312

315313
getTokenOnFirstMatch({ input, type, regex }: { input: string; type: TokenType; regex?: RegExp }) {
316-
if (!regex) return undefined;
314+
if (!regex) {
315+
return undefined;
316+
}
317317
const matches = input.match(regex);
318318
return matches ? ({ type, value: matches[1] } as Token) : undefined;
319319
}

src/core/regexFactory.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/* eslint-disable @typescript-eslint/naming-convention */
2-
31
import { escapeRegExp, isEmpty, sortByLengthDesc } from '../utils';
42

53
export function createOperatorRegex(multiLetterOperators: string[]) {
@@ -33,10 +31,6 @@ export function createWordRegex(specialChars: string[] = []) {
3331
);
3432
}
3533

36-
export function createStringRegex(stringTypes: StringPatternType[]) {
37-
return new RegExp('^(' + createStringPattern(stringTypes) + ')', 'u');
38-
}
39-
4034
// This enables the following string patterns:
4135
// 1. backtick quoted string using `` to escape
4236
// 2. square bracket quoted string (SQL Server) using ]] to escape
@@ -62,8 +56,8 @@ export function createStringPattern(stringTypes: StringPatternType[]) {
6256
return stringTypes.map(t => patterns[t]).join('|');
6357
}
6458

65-
export function createParenRegex(parens: string[]) {
66-
return new RegExp('^(' + parens.map(escapeParen).join('|') + ')', 'iu');
59+
export function createStringRegex(stringTypes: StringPatternType[]) {
60+
return new RegExp('^(' + createStringPattern(stringTypes) + ')', 'u');
6761
}
6862

6963
function escapeParen(paren: string) {
@@ -76,6 +70,10 @@ function escapeParen(paren: string) {
7670
}
7771
}
7872

73+
export function createParenRegex(parens: string[]) {
74+
return new RegExp('^(' + parens.map(escapeParen).join('|') + ')', 'iu');
75+
}
76+
7977
export function createPlaceholderRegex(types: string[], pattern: string) {
8078
if (isEmpty(types)) {
8179
return undefined;

src/languages/PlSqlFormatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Formatter from '../core/Formatter';
2-
import { isBy, isSet, Token } from '../core/token';
2+
import { isBy, isSet, Token } from '../core/token'; // convert to partial type import in TS 4.5
33
import Tokenizer from '../core/Tokenizer';
44
import tokenTypes from '../core/tokenTypes';
55

src/languages/SparkSqlFormatter.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Formatter from '../core/Formatter';
2-
import { isEnd, isWindow, Token } from '../core/token';
2+
import { isEnd, isWindow, Token } from '../core/token'; // convert to partial type import in TS 4.5
33
import Tokenizer from '../core/Tokenizer';
44
import tokenTypes from '../core/tokenTypes';
55

@@ -253,16 +253,15 @@ export default class SparkSqlFormatter extends Formatter {
253253
// Fix cases where names are ambiguously keywords or functions
254254
if (isWindow(token)) {
255255
const aheadToken = this.tokenLookAhead();
256-
if (aheadToken && aheadToken.type === tokenTypes.OPEN_PAREN) {
256+
if (aheadToken?.type === tokenTypes.OPEN_PAREN) {
257257
// This is a function call, treat it as a reserved word
258258
return { type: tokenTypes.RESERVED, value: token.value };
259259
}
260260
}
261261

262-
// Fix cases where names are ambiguously keywords or properties
263262
if (isEnd(token)) {
264263
const backToken = this.tokenLookBehind();
265-
if (backToken && backToken.type === tokenTypes.OPERATOR && backToken.value === '.') {
264+
if (backToken?.type === tokenTypes.OPERATOR && backToken?.value === '.') {
266265
// This is window().end (or similar) not CASE ... END
267266
return { type: tokenTypes.WORD, value: token.value };
268267
}

src/sqlFormatter.d.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)