Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
107f602
fix(formatter): normalize compact Watcom IF statements
MayerTim Jun 9, 2026
0ff841a
fix(formatter): split Watcom parenthesized lists
MayerTim Jun 9, 2026
49c6cb0
fix(formatter): keep union all on separate lines
MayerTim Jun 9, 2026
4593714
fix(formatter): preserve Watcom IF expressions
MayerTim Jun 10, 2026
6d9927b
feat(formatter): split Watcom query clauses
MayerTim Jun 10, 2026
6cfae0d
feat(formatter): indent Watcom cursor loops
MayerTim Jun 10, 2026
9eb0a0e
feat(formatter): format Watcom CASE expressions
MayerTim Jun 10, 2026
4402492
feat(syntax): highlight quoted Watcom built-in functions
MayerTim Jun 10, 2026
1a6927b
feat(formatter): format Watcom exception handlers
MayerTim Jun 10, 2026
29f38c8
feat(metadata): support legacy durch aliases and short dates
MayerTim Jun 10, 2026
6d79be0
perf(formatter): guard large Watcom SQL documents
MayerTim Jun 10, 2026
e68291c
fix(formatter): handle stacked Watcom block endings
MayerTim Jun 10, 2026
f1f05d5
fix(formatter): count same-line block indentation changes
MayerTim Jun 10, 2026
b93a762
fix(formatter): preserve split Watcom IF expressions
MayerTim Jun 10, 2026
0a8fce7
fix(formatter): indent Watcom query continuations
MayerTim Jun 10, 2026
338c4ad
fix(formatter): treat Watcom ELSEIF as branch keyword
MayerTim Jun 10, 2026
b740f0b
fix(formatter): preserve order by IF expression separators
MayerTim Jun 10, 2026
8f17ebf
fix(formatter): clean up Watcom statement continuations
MayerTim Jun 10, 2026
dc927f3
fix(formatter): align Watcom DDL closing parentheses
MayerTim Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
# Dependencies and build output
node_modules/
out/
dist/
out/
*.vsix
*.zip
*.tsbuildinfo

# VS Code test state
.vscode-test/
.history/

# OS files
.DS_Store
Thumbs.db

# Local audit output
licenses-*.json
22 changes: 20 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,31 @@

## Unreleased

- Fixed Watcom DDL/list parenthesis cleanup so temporary-table closing parentheses align with the declaration and safe trailing DDL commas before `)` are removed.
- Fixed Watcom statement continuation cleanup for multiline `UPDATE ... SET` assignments, compact `SELECT` comma spacing and arithmetic operator spacing outside strings/comments.
- Fixed split Watcom `ORDER BY IF ... ENDIF` expression continuations so following sort keys keep their comma separator.
- Fixed Watcom `ELSEIF` indentation so branch conditions do not add an extra block level before `THEN`.
- Fixed Watcom continuation indentation for multiline `SELECT` / `INTO` / `ORDER BY` lists and predicate function arguments.
- Fixed split Watcom `IF ... THEN ... ELSE ... ENDIF` expressions so formatter output keeps them expression-style instead of treating `THEN` / `END IF` as procedural block indentation.
- Fixed Watcom formatter indentation state when one physical line contains multiple block openings or endings, so same-line `BEGIN ... END` and compact nested `IF ... END IF` statements do not leak indentation.
- Fixed Watcom formatter indentation after stacked block endings such as `END IF END IF;` and `END IF END IF END FOR;`.
- Added formatter safety guards for very large Watcom SQL documents and very long physical lines, with cancellation checks and output-channel notes when expensive rewrite passes are skipped.
- Added Watcom `EXCEPTION` / `WHEN ... THEN` handler formatting with stable indentation while preserving `ON EXCEPTION RESUME` and exception declarations.
- Added syntax highlighting for quoted Watcom built-in function calls such as `"isnull"(...)`, `"string"(...)`, `"date"(...)`, `"substr"(...)` and `"xmlelement"(...)`.
- Added Watcom `CASE WHEN THEN ELSE END` expression formatting with stable indentation and nested CASE support.
- Added Watcom cursor `FOR ... CURSOR FOR ... DO ... END FOR` formatting with stable query/body indentation.
- Added Watcom query-clause formatting for top-level `SELECT`, `FROM`, `WHERE`, `JOIN`, `ON`, `GROUP BY`, `HAVING` and `ORDER BY` clauses, including logical predicate continuations.
- Fixed Watcom formatter handling for expression-style `IF ... THEN ... ELSE ... ENDIF` constructs so they are not rewritten as procedural IF blocks.
- Added SQL formatter normalization that keeps `UNION ALL` on its own physical line.
- Fixed Watcom formatter indentation after compact inline `IF ... THEN ... END IF` statements by expanding them into stable block form.
- Added Watcom parenthesis formatting for parameters and nested calls outside strings/comments, with indentation for multiline argument lists.
- Added dedicated syntax scopes for generated metadata headers, including markers, fields, values, dates, TODO placeholders, update authors and history entries.
- Added normalization of loose legacy metadata-style comment headers to the current SQLovely metadata format.
- Added metadata-header processing for every detected procedure, function and trigger in multi-object SQL scripts.
- Added version/history synchronization so `Version` matches the latest history entry and invalid version jumps are coerced to one-step bumps.
- Added multiline metadata descriptions with automatic wrapping to the configured line-length limit while preserving manual line breaks.
- Added `Updated By` metadata support, including migration from legacy updated-by aliases such as `geändert von` and `geupdated von`.
- Normalized metadata date values and history dates to `YYYY-MM-DD`, including common day-first and year-first separators.
- Added `Updated By` metadata support, including migration from legacy updated-by aliases such as `geändert von`, `geändert durch` and `geupdated von`.
- Normalized metadata date values and history dates to `YYYY-MM-DD`, including common day-first and year-first separators plus two-digit legacy years with a documented pivot rule.
- Expanded metadata regression coverage for legacy headers, multiline descriptions, date normalization, version synchronization and multi-object scripts.

## 0.1.7
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ npm run package:vsix

## Guidelines

- Keep formatter behavior conservative.
- Keep formatter behavior conservative. New rewrite passes should be lexical, bounded and compatible with the formatter safety guards for large SQL files.
- Add regression tests for behavior changes.
- Keep `README.md` user-facing.
- Put maintainer/developer details in `docs/`.
Expand Down
1 change: 1 addition & 0 deletions PACKAGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Before publishing or attaching a VSIX to a release:
7. Install the generated VSIX in VS Code and open a `.sql` file.
8. Verify highlighting, the active dialect command, formatting, metadata-header quick fixes and the packaging output.
9. Smoke-test metadata headers for multi-object scripts, legacy-header migration, description wrapping, date normalization and `Updated By` values.
10. Smoke-test formatter safety guards with a generated/large SQL file and confirm the SQLovely output channel records skipped expensive passes instead of freezing VS Code.
36 changes: 31 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ It is focused on Watcom SQL by default and also includes a small MSSQL-oriented

## Features

- SQL syntax highlighting for regular `.sql` files
- SQL syntax highlighting for regular `.sql` files, including quoted Watcom built-in calls
- Conservative SQL formatting
- Optional metadata-header extras for every detected procedure, function and trigger in a script
- Diagnostics and quick fixes for supported SQLovely rules
Expand Down Expand Up @@ -55,11 +55,37 @@ SQLovely formats conservatively. It keeps SQL structure intact and focuses on re

- keyword and function casing
- basic block indentation
- compact Watcom `IF ... THEN ... END IF` control-flow normalization
- Watcom `IF ... THEN ... ELSE ... ENDIF` expression preservation, including split expression normalization and `ORDER BY` separator recovery
- `UNION ALL` normalization to its own physical line
- top-level Watcom query-clause line breaks for `SELECT`, `FROM`, `WHERE`, `JOIN`, `ON`, `GROUP BY`, `HAVING` and `ORDER BY`, including continuation indentation for multiline lists, predicate function calls, `UPDATE ... SET` assignments and DDL/list closing parentheses
- Watcom cursor `FOR ... CURSOR FOR ... DO ... END FOR` indentation
- Watcom `CASE WHEN THEN ELSE END` expression line breaks and indentation
- Watcom `EXCEPTION` / `WHEN ... THEN` handler line breaks and indentation
- trailing whitespace removal
- limiting consecutive blank lines
- final newline handling
- performance safety guards that skip expensive Watcom rewrite passes for very large documents or very long lines

The formatter does not rewrite queries, split statements, align joins or migrate SQL between dialects.
Apart from normalizing compact Watcom `IF ... THEN ... END IF` control-flow statements, preserving and normalizing expression-style `IF ... THEN ... ELSE ... ENDIF` constructs, keeping `UNION ALL` on its own line, splitting Watcom parenthesized argument/parameter lists across indented lines, placing top-level Watcom query clauses on stable physical lines with continuation indentation, cleaning multiline `UPDATE ... SET` assignments plus compact comma/operator spacing and DDL/list closing parentheses, recovering separators after split `ORDER BY IF ... ENDIF` expression continuations, indenting cursor `FOR ... DO` loops, formatting Watcom `CASE` expressions and aligning Watcom exception handlers, splitting/counting stacked Watcom block endings before indentation, and treating `ELSEIF` as a branch keyword instead of a nested block opener, the formatter does not perform schema-aware rewrites or migrate SQL between dialects.


### Formatter safety guards

SQLovely includes safety guards for very large generated SQL files. When a document exceeds the configured safety limits, expensive Watcom rewrite passes such as query-clause splitting, parenthesis splitting, cursor-loop splitting, CASE formatting and compact IF expansion are skipped. Lightweight cleanup such as keyword casing, whitespace cleanup and indentation still runs.

Default limits:

```json
{
"sqlovely.format.safety.enabled": true,
"sqlovely.format.safety.maxComplexDocumentLength": 1000000,
"sqlovely.format.safety.maxComplexDocumentLines": 5000,
"sqlovely.format.safety.maxComplexLineLength": 5000
}
```

When a guard triggers, SQLovely writes a short note to the SQLovely output channel.

### Format one file

Expand Down Expand Up @@ -103,9 +129,9 @@ END;

Headers are inserted directly before each detected object's first `BEGIN` line. Repeated runs update existing SQLovely blocks instead of duplicating them.

When SQLovely finds a loose legacy metadata-style comment block for a detected object, it normalizes the block to the generated SQLovely format instead of adding a second header. Legacy detection supports common `--`, `//`, `/` and simple block-comment styles, but stays conservative and requires a recognizable version field so regular explanatory comments are left in place.
When SQLovely finds a loose legacy metadata-style comment block for a detected object, it normalizes the block to the generated SQLovely format instead of adding a second header. Legacy detection supports common `--`, `//`, `/`, `//*` and simple block-comment styles, but stays conservative and requires a recognizable version field so regular explanatory comments are left in place. German legacy aliases such as `erstellt durch` and `geändert durch` are migrated into `Author` and `Updated By`.

Metadata updates also normalize date values to `YYYY-MM-DD`, preserve multiline descriptions, wrap long description lines to `sqlovely.diagnostics.maxLineLength.limit`, and keep manual description line breaks. `Version` is synchronized with the latest history entry: newer valid history entries update the field, version bumps add missing history entries, and invalid jumps are coerced to a one-step bump.
Metadata updates also normalize date values to `YYYY-MM-DD`, including common two-digit legacy years using `00`-`49` as `2000`-`2049` and `50`-`99` as `1950`-`1999`. They preserve multiline descriptions, wrap long description lines to `sqlovely.diagnostics.maxLineLength.limit`, and keep manual description line breaks. `Version` is synchronized with the latest history entry: newer valid history entries update the field, version bumps add missing history entries, and invalid jumps are coerced to a one-step bump.

Extras are applied during normal SQLovely formatting by default:

Expand Down Expand Up @@ -146,7 +172,7 @@ Supported values:
- `watcom`: default dialect
- `mssql`: small secondary dialect surface

The syntax grammar is intentionally broad. Dialect-specific behavior is handled by formatting, object detection, extras, diagnostics and quick fixes.
The syntax grammar is intentionally broad. It highlights regular built-in function calls and common quoted Watcom built-in calls such as `"isnull"(...)`, `"string"(...)`, `"date"(...)`, `"substr"(...)` and `"xmlelement"(...)` while still treating other double-quoted names as identifiers. Dialect-specific behavior is handled by formatting, object detection, extras, diagnostics and quick fixes.

## Diagnostics

Expand Down
24 changes: 21 additions & 3 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,18 @@ Useful smoke tests:
- run **SQLovely: Show Active Dialect**
- run **SQLovely: Format Current SQL File**
- run **SQLovely: Format SQL Files in Directory**
- verify compact Watcom inline `IF ... THEN ... END IF` statements expand without leaking indentation
- verify Watcom parenthesized parameter lists and nested calls split without touching strings, comments or type lengths
- verify multiline `SELECT` / `INTO` / `ORDER BY` lists and predicate function arguments keep continuation indentation
- verify split `ORDER BY IF ... ENDIF` expression continuations keep the comma before the next sort key
- run **SQLovely: Insert or Update Metadata Header**
- verify diagnostics and quick fixes
- verify metadata headers in a script with multiple procedures, functions or triggers
- verify loose legacy metadata headers are normalized only when they contain a recognizable version field
- verify long metadata descriptions are wrapped without removing manual line breaks
- verify formatter safety guards skip expensive rewrites for generated/large SQL while keeping lightweight cleanup
- verify formatter smoke samples cover multiline `UPDATE ... SET` continuations, compact comma/operator spacing and temporary-table DDL parenthesis alignment
- verify multiline Watcom `ELSEIF` conditions align with the matching `IF` and do not leak indentation into following objects

## Settings during development

Expand All @@ -68,6 +75,7 @@ A practical development workspace setup is:
"sqlovely.format.keywordCase": "upper",
"sqlovely.format.indentSize": 2,
"sqlovely.format.insertSpaces": true,
"sqlovely.format.safety.enabled": true,
"sqlovely.extras.applyWithFormatting": true,
"sqlovely.extras.applyOnSave": false,
"[sql]": {
Expand All @@ -93,7 +101,7 @@ For MSSQL-oriented smoke tests:

**SQLovely: Format SQL Files in Directory** uses the normal `sqlovely.format.*` settings.

It intentionally does not apply SQLovely Extras. Keep this behavior conservative because the command can touch many files at once.
It intentionally does not apply SQLovely Extras. Keep this behavior conservative because the command can touch many files at once. Directory formatting forwards VS Code cancellation requests into the formatter and uses the same safety guards as normal document formatting.

## Metadata-header regression focus

Expand All @@ -103,6 +111,16 @@ When changing metadata-header behavior, add or update regression tests for:
- loose legacy header normalization
- multi-object scripts
- version/history synchronization
- `Updated By` migration and preservation
- date normalization
- `Updated By` migration and preservation, including legacy `durch` aliases
- date normalization, including two-digit legacy years
- multiline description wrapping and manual line-break preservation


## Formatter performance regression focus

When adding formatter passes, keep them lexical and linear where possible. Add or update tests for:

- large documents that exceed `sqlovely.format.safety.maxComplexDocumentLines`
- very long physical lines that exceed `sqlovely.format.safety.maxComplexLineLength`
- cancellation before formatting applies edits
- normal-sized files that should still receive the full Watcom formatting pipeline
Loading
Loading