From d1c5bfb332e12a5f71cd98d9dbe4054911cd0bff Mon Sep 17 00:00:00 2001 From: tomasnyberg Date: Tue, 11 Mar 2025 10:59:37 +0100 Subject: [PATCH 1/5] group listitems and parenthesized paths --- .../src/formatting/formatting.ts | 21 +++++++++++++++++-- .../src/tests/formatting/linebreaks.test.ts | 13 ++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/packages/language-support/src/formatting/formatting.ts b/packages/language-support/src/formatting/formatting.ts index 7f516f255..89007a564 100644 --- a/packages/language-support/src/formatting/formatting.ts +++ b/packages/language-support/src/formatting/formatting.ts @@ -38,6 +38,7 @@ import { NumberLiteralContext, ParameterContext, ParenthesizedExpressionContext, + ParenthesizedPathContext, PathLengthContext, PatternContext, PatternListContext, @@ -801,6 +802,20 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { } }; + visitParenthesizedPath = (ctx: ParenthesizedPathContext) => { + this.visit(ctx.LPAREN()); + this.avoidBreakBetween(); + const parenthesizedPathGrp = this.startGroup(); + this.visit(ctx.pattern()); + if (ctx.WHERE()) { + this.visit(ctx.WHERE()); + this.visit(ctx.expression()); + } + this.endGroup(parenthesizedPathGrp); + this.visit(ctx.RPAREN()); + this.visitIfNotNull(ctx.quantifier()); + }; + visitArrowLine = (ctx: ArrowLineContext) => { this.visitRawIfNotNull(ctx.MINUS()); this.visitRawIfNotNull(ctx.ARROW_LINE()); @@ -871,10 +886,10 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { this.visit(ctx.EQ()); this.avoidBreakBetween(); } + const selectorAnonymousPatternGrp = this.startGroup(); this.visitIfNotNull(ctx.selector()); - const anonymousPatternGrp = this.startGroup(); this.visit(ctx.anonymousPattern()); - this.endGroup(anonymousPatternGrp); + this.endGroup(selectorAnonymousPatternGrp); }; visitPatternList = (ctx: PatternListContext) => { @@ -1248,6 +1263,7 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { }; visitListItemsPredicate = (ctx: ListItemsPredicateContext) => { + const wholeListItemGrp = this.startGroup(); this.visitRawIfNotNull(ctx.ALL()); this.visitRawIfNotNull(ctx.ANY()); this.visitRawIfNotNull(ctx.NONE()); @@ -1265,6 +1281,7 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { } this.endGroup(listGrp); this.visit(ctx.RPAREN()); + this.endGroup(wholeListItemGrp); }; visitListLiteral = (ctx: ListLiteralContext) => { diff --git a/packages/language-support/src/tests/formatting/linebreaks.test.ts b/packages/language-support/src/tests/formatting/linebreaks.test.ts index 2bb1dac10..a6d49bb61 100644 --- a/packages/language-support/src/tests/formatting/linebreaks.test.ts +++ b/packages/language-support/src/tests/formatting/linebreaks.test.ts @@ -413,6 +413,19 @@ RETURN DISTINCT abcde.qwertyuiopa, abcde.zxcvbnmasdfgh, abcde.zxcvbnml, ORDER BY lm.lkjhgfdswert ASC`; verifyFormatting(query, expected); }); + + test('path length example', () => { + const query = `MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ + (:Station {name: 'Cheltenham Spa'}) WHERE none( + stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) +RETURN [stop IN n[.. -1] | stop.name] AS stops`; + const expected = ` +MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ + (:Station {name: 'Cheltenham Spa'}) WHERE + none(stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) +RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); + verifyFormatting(query, expected); + }); }); describe('tests for respcecting user line breaks', () => { From aa898f127e16b7c12fab6029e8348bf344ac8317 Mon Sep 17 00:00:00 2001 From: tomasnyberg Date: Tue, 11 Mar 2025 11:07:17 +0100 Subject: [PATCH 2/5] group the selector to avoid splitting it --- .../src/formatting/formatting.ts | 6 +++++- .../src/tests/formatting/linebreaks.test.ts | 20 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/language-support/src/formatting/formatting.ts b/packages/language-support/src/formatting/formatting.ts index 89007a564..f91d9b567 100644 --- a/packages/language-support/src/formatting/formatting.ts +++ b/packages/language-support/src/formatting/formatting.ts @@ -887,7 +887,11 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { this.avoidBreakBetween(); } const selectorAnonymousPatternGrp = this.startGroup(); - this.visitIfNotNull(ctx.selector()); + if (ctx.selector()) { + const selectorGroup = this.startGroup(); + this.visitIfNotNull(ctx.selector()); + this.endGroup(selectorGroup); + } this.visit(ctx.anonymousPattern()); this.endGroup(selectorAnonymousPatternGrp); }; diff --git a/packages/language-support/src/tests/formatting/linebreaks.test.ts b/packages/language-support/src/tests/formatting/linebreaks.test.ts index a6d49bb61..0cfc39075 100644 --- a/packages/language-support/src/tests/formatting/linebreaks.test.ts +++ b/packages/language-support/src/tests/formatting/linebreaks.test.ts @@ -414,15 +414,29 @@ RETURN DISTINCT abcde.qwertyuiopa, abcde.zxcvbnmasdfgh, abcde.zxcvbnml, verifyFormatting(query, expected); }); - test('path length example', () => { + test('selector example', () => { const query = `MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ (:Station {name: 'Cheltenham Spa'}) WHERE none( stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) RETURN [stop IN n[.. -1] | stop.name] AS stops`; const expected = ` -MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ - (:Station {name: 'Cheltenham Spa'}) WHERE +MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) + (()--(n:Station))+(:Station {name: 'Cheltenham Spa'}) WHERE none(stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) +RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); + verifyFormatting(query, expected); + }); + + test('selector example with path', () => { + const query = `MATCH p = SHORTEST 1 ((:Station {name: 'Thisisanabsurdlylongnametomakeitawkward'}) + (()--(n:Station))+(:Station {name: 'Cheltenham Spa'}) WHERE + none(stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) +RETURN [stop IN n[.. -1] | stop.name] AS stops`; + const expected = ` +MATCH p = SHORTEST 1 + ((:Station {name: 'Thisisanabsurdlylongnametomakeitawkward'}) + (()--(n:Station))+(:Station {name: 'Cheltenham Spa'}) WHERE + none(stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); verifyFormatting(query, expected); }); From 3493034e6d73a9100b7b176257e6a4de282264b8 Mon Sep 17 00:00:00 2001 From: tomasnyberg Date: Tue, 11 Mar 2025 11:10:02 +0100 Subject: [PATCH 3/5] add another test --- .../src/tests/formatting/linebreaks.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/language-support/src/tests/formatting/linebreaks.test.ts b/packages/language-support/src/tests/formatting/linebreaks.test.ts index 0cfc39075..e3e570f64 100644 --- a/packages/language-support/src/tests/formatting/linebreaks.test.ts +++ b/packages/language-support/src/tests/formatting/linebreaks.test.ts @@ -440,6 +440,17 @@ MATCH p = SHORTEST 1 RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); verifyFormatting(query, expected); }); + + test('selector and quantifier example', () => { + const query = `MATCH path = ANY + (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+(b:Station {name: 'Bromsgrove'}) +RETURN [r IN relationships(path) | r.distance] AS distances`; + const expected = ` +MATCH path = ANY (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+ + (b:Station {name: 'Bromsgrove'}) +RETURN [r IN relationships(path) | r.distance] AS distances`.trimStart(); + verifyFormatting(query, expected); + }); }); describe('tests for respcecting user line breaks', () => { From fdedf54e3db6173ee9160a5611d193c4b77ddea6 Mon Sep 17 00:00:00 2001 From: tomasnyberg Date: Tue, 11 Mar 2025 11:11:58 +0100 Subject: [PATCH 4/5] another test for simple selector --- .../src/tests/formatting/linebreaks.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/language-support/src/tests/formatting/linebreaks.test.ts b/packages/language-support/src/tests/formatting/linebreaks.test.ts index e3e570f64..24f89491a 100644 --- a/packages/language-support/src/tests/formatting/linebreaks.test.ts +++ b/packages/language-support/src/tests/formatting/linebreaks.test.ts @@ -414,7 +414,19 @@ RETURN DISTINCT abcde.qwertyuiopa, abcde.zxcvbnmasdfgh, abcde.zxcvbnml, verifyFormatting(query, expected); }); - test('selector example', () => { + test('simple selector example', () => { + const query = `MATCH SHORTEST 1 + (:Station {name: 'Hartlebury'}) + (()--(n))+ + (:Station {name: 'Cheltenham Spa'}) +RETURN [stop in n[..-1] | stop.name] AS stops`; + const expected = `MATCH SHORTEST 1 (:Station {name: 'Hartlebury'}) (()--(n))+ + (:Station {name: 'Cheltenham Spa'}) +RETURN [stop IN n[.. -1] | stop.name] AS stops`; + verifyFormatting(query, expected); + }); + + test('complex selector example', () => { const query = `MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ (:Station {name: 'Cheltenham Spa'}) WHERE none( stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) From eb7b54642a22903805c904edc1ecf1a6cbd413a0 Mon Sep 17 00:00:00 2001 From: tomasnyberg Date: Tue, 11 Mar 2025 13:04:38 +0100 Subject: [PATCH 5/5] extra group in pattern to get nicer alignment --- .../language-support/src/formatting/formatting.ts | 2 ++ .../src/tests/formatting/linebreaks.test.ts | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/language-support/src/formatting/formatting.ts b/packages/language-support/src/formatting/formatting.ts index f91d9b567..5c77c0478 100644 --- a/packages/language-support/src/formatting/formatting.ts +++ b/packages/language-support/src/formatting/formatting.ts @@ -892,7 +892,9 @@ export class TreePrintVisitor extends CypherCmdParserVisitor { this.visitIfNotNull(ctx.selector()); this.endGroup(selectorGroup); } + const anonymousPatternGrp = this.startGroup(); this.visit(ctx.anonymousPattern()); + this.endGroup(anonymousPatternGrp); this.endGroup(selectorAnonymousPatternGrp); }; diff --git a/packages/language-support/src/tests/formatting/linebreaks.test.ts b/packages/language-support/src/tests/formatting/linebreaks.test.ts index 24f89491a..5026e7244 100644 --- a/packages/language-support/src/tests/formatting/linebreaks.test.ts +++ b/packages/language-support/src/tests/formatting/linebreaks.test.ts @@ -420,9 +420,10 @@ RETURN DISTINCT abcde.qwertyuiopa, abcde.zxcvbnmasdfgh, abcde.zxcvbnml, (()--(n))+ (:Station {name: 'Cheltenham Spa'}) RETURN [stop in n[..-1] | stop.name] AS stops`; - const expected = `MATCH SHORTEST 1 (:Station {name: 'Hartlebury'}) (()--(n))+ - (:Station {name: 'Cheltenham Spa'}) -RETURN [stop IN n[.. -1] | stop.name] AS stops`; + const expected = ` +MATCH SHORTEST 1 (:Station {name: 'Hartlebury'}) (()--(n))+ + (:Station {name: 'Cheltenham Spa'}) +RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); verifyFormatting(query, expected); }); @@ -432,8 +433,8 @@ RETURN [stop IN n[.. -1] | stop.name] AS stops`; stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) RETURN [stop IN n[.. -1] | stop.name] AS stops`; const expected = ` -MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) - (()--(n:Station))+(:Station {name: 'Cheltenham Spa'}) WHERE +MATCH SHORTEST 1 ((:Station {name: 'Hartlebury'}) (()--(n:Station))+ + (:Station {name: 'Cheltenham Spa'}) WHERE none(stop IN n[.. -1] WHERE stop.name = 'Bromsgrove')) RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); verifyFormatting(query, expected); @@ -459,7 +460,7 @@ RETURN [stop IN n[.. -1] | stop.name] AS stops`.trimStart(); RETURN [r IN relationships(path) | r.distance] AS distances`; const expected = ` MATCH path = ANY (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+ - (b:Station {name: 'Bromsgrove'}) + (b:Station {name: 'Bromsgrove'}) RETURN [r IN relationships(path) | r.distance] AS distances`.trimStart(); verifyFormatting(query, expected); });