Skip to content
22 changes: 19 additions & 3 deletions packages/language-support/src/formatting/formattingHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ export function isComment(token: Token) {
);
}

export const isInlineComment = (chunk: Chunk) =>
chunk.comment && chunk.comment.startsWith('/*');

// Variables or property names that have the same name as a keyword should not be
// treated as keywords
function isSymbolicName(node: TerminalNode): boolean {
Expand Down Expand Up @@ -163,20 +166,33 @@ export function fillInRegularChunkGroupSizes(
throw new Error(INTERNAL_FORMAT_ERROR_MESSAGE);
}
group.size += chunk.text.length;
if (isInlineComment(chunk)) {
const inlineComment = ' ' + chunk.comment + ' ';
group.size += inlineComment.length;
group.dbgText += inlineComment;
}

// PERF: Right now we include dbgText always, even though it's only used for debugging.
// It does not seem to have any significant performance downsides, but only doing so
// when e.g. a flag is set might be a more prudent choice.
group.dbgText += chunk.text;
if (!chunk.noSpace && shouldAddSpace(chunk, chunk)) {
if (
!chunk.noSpace &&
shouldAddSpace(chunk, chunk) &&
!isInlineComment(chunk)
) {
group.size++;
group.dbgText += ' ';
}
if (chunk.comment && !groupsEnding.has(group.id)) {
if (
chunk.comment &&
!groupsEnding.has(group.id) &&
!isInlineComment(chunk)
) {
group.shouldBreak = true;
}
}
}

export function verifyGroupSizes(chunkList: Chunk[]) {
for (const chunk of chunkList) {
for (const group of chunk.groupsStarting) {
Expand Down
14 changes: 14 additions & 0 deletions packages/language-support/src/formatting/layoutEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
Group,
IndentationModifier,
INTERNAL_FORMAT_ERROR_MESSAGE,
isInlineComment,
shouldAddSpace,
} from './formattingHelpers';

Expand Down Expand Up @@ -122,7 +123,20 @@ function appendChunkText(state: State, chunk: Chunk) {
}

function handleComments(state: State, chunk: Chunk) {
if (isInlineComment(chunk)) {
// Inline comment - append directly
state.formatted += ' ';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are spaces added here if they are also added before and after the inlineComment in formattingHelpers line 170?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are confusing the debug text with this one. In formattingHelpers the space are added for debug and to the group size, while it is added here to be included in the result.

state.formatted += chunk.comment;
state.column += chunk.comment.length;
// Always include space after, even if the chunk has noSpace
if (chunk.type === 'REGULAR' && chunk.noSpace) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure how something can be a regular chunk if it is an inline comment? Why is it not a commentchunk?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No an inline comment is part of the regular chunk. It is only the comment which are completely on their own rows which are comment chunks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now when I look at it, you might be able to do chunk?.noSpace instead, unsure though and not really able to test anymore

state.formatted += ' ';
state.column++;
}
return;
}
if (chunk.comment) {
// For regular comments, we store them to append later
state.pendingComments.push(chunk.comment);
}
}
Expand Down
59 changes: 42 additions & 17 deletions packages/language-support/src/tests/formatting/comments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,11 @@ RETURN n`;
});

test('weird inline comments', () => {
const inlinemultiline = `MERGE (n) /* Ensuring the node exists */
const inlinemultiline = `MERGE /* Ensuring the node exists */ (n)
ON CREATE SET n.prop = 0 /* Set default property */
MERGE (a:A) /* Create or match 'a:A' */
-[:T]-> (b:B) /* Link 'a' to 'b' */
RETURN a.prop /* Return the property of 'a' */
`;
const expected = `MERGE (n) /* Ensuring the node exists */
ON CREATE SET n.prop = 0 /* Set default property */
MERGE
(a:A)- /* Create or match 'a:A' */
[:T]->
(b:B) /* Link 'a' to 'b' */
MERGE /* Create or match 'a:A' */ (a:A)-[:T]->(b:B) // test
RETURN a.prop /* Return the property of 'a' */`;
const expected = inlinemultiline;
verifyFormatting(inlinemultiline, expected);
});

Expand Down Expand Up @@ -302,12 +294,8 @@ RETURN n`;
const query = `
MATCH (a:Node) // first match
WITH a, /* intermediate comment */ a.property AS prop
RETURN prop; // final return`;
const expected = `MATCH (a:Node) // first match
WITH
a, /* intermediate comment */
a.property AS prop
RETURN prop; // final return`;
RETURN prop; // final return`.trimStart();
const expected = query;
verifyFormatting(query, expected);
});

Expand Down Expand Up @@ -569,6 +557,43 @@ RETURN m, n`.trim();
const expected = query;
verifyFormatting(query, expected);
});

test('inline comment', () => {
const query = `
MATCH /* One comment. */ (m)-[:RELATION]->(n)
RETURN m, n`.trim();
const expected = query;
verifyFormatting(query, expected);
});

test('inline comment within a chunk', () => {
const query = `MATCH (m/*comment*/)-[:RELATION]->(n)
RETURN m, n`;
const expected = `MATCH (m)- /*comment*/ [:RELATION]->(n)
RETURN m, n`;
verifyFormatting(query, expected);
});

test('long inline comment within a chunk', () => {
const query = `MATCH (m/*commentcommentcommentcommentcommentcommentcommentcom*/)-[:RELATION]->(n)
RETURN m, n`;
const expected = `MATCH
(m)- /*commentcommentcommentcommentcommentcommentcommentcom*/ [:RELATION]->(n)
RETURN m, n`;
verifyFormatting(query, expected);
});

test('long inline comment within a chunk should break everything', () => {
// See the extra m at the end of the comment compared to above test, that m makes it over 80 characters
const query = `MATCH (m/*commentcommentcommentcommentcommentcommentcommentcomm*/)-[:RELATION]->(n)
RETURN m, n`;
const expected = `MATCH
(m)- /*commentcommentcommentcommentcommentcommentcommentcomm*/ [:RELATION]->
(n)
RETURN m, n`;
verifyFormatting(query, expected);
});

test('long list in a return with comment', () => {
const query = `
RETURN // test
Expand Down