From 5c37ecf3f5c92b75d24c15dc8c02a93f82a2a518 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Fri, 14 Jun 2024 17:00:34 -0400 Subject: [PATCH] fix formatting of block quotes with **/ closing characters --- src/lexer/NestedComment.ts | 34 ++++++++++++++++++++-------------- test/features/comments.ts | 6 ++++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/lexer/NestedComment.ts b/src/lexer/NestedComment.ts index 983f0e3f28..4db128f329 100644 --- a/src/lexer/NestedComment.ts +++ b/src/lexer/NestedComment.ts @@ -2,8 +2,6 @@ import { RegExpLike } from './TokenizerEngine.js'; const START = /\/\*/uy; // matches: /* -const MIDDLE = /([^/*]|\*[^/]|\/[^*])+/uy; // matches text NOT containing /* or */ -const END = /\*\//uy; // matches: */ /** * An object mimicking a regular expression, @@ -15,29 +13,37 @@ export class NestedComment implements RegExpLike { public exec(input: string): string[] | null { let result = ''; let match: string | null; - let nestLevel = 0; if ((match = this.matchSection(START, input))) { result += match; - nestLevel++; } else { return null; } - while (nestLevel > 0) { - if ((match = this.matchSection(START, input))) { - result += match; - nestLevel++; - } else if ((match = this.matchSection(END, input))) { - result += match; + let nestLevel = 1; + // start at the last index, break if we find a closing */ that matches + for (let i = this.lastIndex; i < input.length; i++) { + if (input[i] === '*' && input[i + 1] === '/') { nestLevel--; - } else if ((match = this.matchSection(MIDDLE, input))) { - result += match; + result += '*/'; + i++; + if (nestLevel === 0) { + this.lastIndex = i; + return [result]; + } else if (nestLevel < 0) { + return null; + } + } else if (input[i] === '/' && input[i + 1] === '*') { + nestLevel++; + result += '/*'; + i++; } else { - return null; + result += input[i]; } } - + if (nestLevel > 0) { + return null; + } return [result]; } diff --git a/test/features/comments.ts b/test/features/comments.ts index 47b51ac957..4394123cbf 100644 --- a/test/features/comments.ts +++ b/test/features/comments.ts @@ -239,6 +239,12 @@ export default function supportsComments(format: FormatFn, opts: CommentsConfig `); }); + // Regression test for https://github.com/sql-formatter-org/sql-formatter/issues/747 + it('handles block comments with /** and **/ patterns', () => { + const sql = `/** This is a block comment **/`; + expect(format(sql)).toBe(sql); + }); + if (opts.hashComments) { it('supports # line comment', () => { const result = format('SELECT alpha # commment\nFROM beta');