Skip to content

Commit 4ae6c48

Browse files
committed
Add functionCase option, make keywordCase default
1 parent 129ba96 commit 4ae6c48

File tree

8 files changed

+57
-25
lines changed

8 files changed

+57
-25
lines changed

docs/dataTypeCase.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ Note: Casing of function names like `VARCHAR(30)` are not modified - instead rel
88

99
## Options
1010

11-
- `"preserve"` (default) preserves the original case.
11+
- `"preserve"` preserves the original case.
1212
- `"upper"` converts to uppercase.
1313
- `"lower"` converts to lowercase.
1414

15+
The default is either `options.keywordCase` (if you have set it) or `"preserve"`.
16+
1517
### preserve
1618

1719
```sql

docs/functionCase.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ Converts functions to upper- or lowercase.
44

55
## Options
66

7-
- `"preserve"` (default) preserves the original case.
7+
- `"preserve"` preserves the original case.
88
- `"upper"` converts to uppercase.
99
- `"lower"` converts to lowercase.
1010

11+
The default is either `options.keywordCase` (if you have set it) or `"preserve"`.
12+
1113
### preserve
1214

1315
```sql

src/FormatOptions.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export type IdentifierCase = 'preserve' | 'upper' | 'lower';
1010

1111
export type DataTypeCase = 'preserve' | 'upper' | 'lower';
1212

13+
export type FunctionCase = 'preserve' | 'upper' | 'lower';
14+
1315
export type LogicalOperatorNewline = 'before' | 'after';
1416

1517
export interface FormatOptions {
@@ -18,6 +20,7 @@ export interface FormatOptions {
1820
keywordCase: KeywordCase;
1921
identifierCase: IdentifierCase;
2022
dataTypeCase: DataTypeCase;
23+
functionCase: FunctionCase;
2124
indentStyle: IndentStyle;
2225
logicalOperatorNewline: LogicalOperatorNewline;
2326
expressionWidth: number;

src/formatter/ExpressionFormatter.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export default class ExpressionFormatter {
140140

141141
private formatFunctionCall(node: FunctionCallNode) {
142142
this.withComments(node.nameKw, () => {
143-
this.layout.add(this.showKw(node.nameKw));
143+
this.layout.add(this.showFunctionKw(node.nameKw));
144144
});
145145
this.formatNode(node.parenthesis);
146146
}
@@ -518,6 +518,26 @@ export default class ExpressionFormatter {
518518
}
519519
}
520520

521+
private showFunctionKw(node: KeywordNode): string {
522+
if (isTabularToken(node.tokenType)) {
523+
return toTabularFormat(this.showNonTabularFunctionKw(node), this.cfg.indentStyle);
524+
} else {
525+
return this.showNonTabularFunctionKw(node);
526+
}
527+
}
528+
529+
// Like showFunctionKw(), but skips tabular formatting
530+
private showNonTabularFunctionKw(node: KeywordNode): string {
531+
switch (this.cfg.functionCase) {
532+
case 'preserve':
533+
return equalizeWhitespace(node.raw);
534+
case 'upper':
535+
return node.text;
536+
case 'lower':
537+
return node.text.toLowerCase();
538+
}
539+
}
540+
521541
private showIdentifier(node: IdentifierNode): string {
522542
if (node.quoted) {
523543
return node.text;

src/lexer/Tokenizer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { equalizeWhitespace, Optional } from '../utils.js';
2-
import { NestedComment } from './NestedComment.js';
3-
import * as regex from './regexFactory.js';
4-
import { escapeRegExp, patternToRegex } from './regexUtil.js';
51
import { Token, TokenType } from './token.js';
6-
import TokenizerEngine, { TokenRule } from './TokenizerEngine.js';
2+
import * as regex from './regexFactory.js';
73
import { ParamTypes, TokenizerOptions } from './TokenizerOptions.js';
4+
import TokenizerEngine, { TokenRule } from './TokenizerEngine.js';
5+
import { escapeRegExp, patternToRegex } from './regexUtil.js';
6+
import { equalizeWhitespace, Optional } from '../utils.js';
7+
import { NestedComment } from './NestedComment.js';
88

99
type OptionalTokenRule = Optional<TokenRule, 'regex'>;
1010

src/sqlFormatter.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as allDialects from './allDialects.js';
2-
import { createDialect, DialectOptions } from './dialect.js';
2+
33
import { FormatOptions } from './FormatOptions.js';
4+
import { createDialect, DialectOptions } from './dialect.js';
45
import Formatter from './formatter/Formatter.js';
56
import { ConfigError, validateConfig } from './validateConfig.js';
67

@@ -36,20 +37,6 @@ export type FormatOptionsWithDialect = Partial<FormatOptions> & {
3637
dialect: DialectOptions;
3738
};
3839

39-
const defaultOptions: FormatOptions = {
40-
tabWidth: 2,
41-
useTabs: false,
42-
keywordCase: 'preserve',
43-
identifierCase: 'preserve',
44-
dataTypeCase: 'preserve',
45-
indentStyle: 'standard',
46-
logicalOperatorNewline: 'before',
47-
expressionWidth: 50,
48-
linesBetweenQueries: 1,
49-
denseOperators: false,
50-
newlineBeforeSemicolon: false,
51-
};
52-
5340
/**
5441
* Format whitespace in a query to make it easier to read.
5542
*
@@ -86,6 +73,21 @@ export const formatDialect = (
8673
throw new Error('Invalid query argument. Expected string, instead got ' + typeof query);
8774
}
8875

76+
const defaultOptions: FormatOptions = {
77+
tabWidth: 2,
78+
useTabs: false,
79+
keywordCase: 'preserve',
80+
identifierCase: 'preserve',
81+
dataTypeCase: cfg.keywordCase || 'preserve',
82+
functionCase: cfg.keywordCase || 'preserve',
83+
indentStyle: 'standard',
84+
logicalOperatorNewline: 'before',
85+
expressionWidth: 50,
86+
linesBetweenQueries: 1,
87+
denseOperators: false,
88+
newlineBeforeSemicolon: false,
89+
};
90+
8991
const options = validateConfig({
9092
...defaultOptions,
9193
...cfg,

test/features/case.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ export default function supportsCase(format: FormatFn) {
7979
it('properly converts to uppercase in case statements', () => {
8080
const result = format(
8181
"case trim(sqrt(my_field)) when 'one' then 1 when 'two' then 2 when 'three' then 3 else 4 end;",
82-
{ keywordCase: 'upper' }
82+
{
83+
keywordCase: 'upper',
84+
functionCase: 'upper',
85+
}
8386
);
8487
expect(result).toBe(dedent`
8588
CASE TRIM(SQRT(my_field))

test/snowflake.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ describe('SnowflakeFormatter', () => {
167167
`);
168168
});
169169

170-
it('detects data types as data types', () => {
170+
it('detects data types', () => {
171171
expect(
172172
format(
173173
`CREATE TABLE tbl (first_column double Precision, second_column numBer (38, 0), third String);`,

0 commit comments

Comments
 (0)