eclipse-langium/langium

Formatter break document with single line comments

Closed this issue · 2 comments

Hello,

When the formatter prepend/append oneSpace or noSpace on a token, it break the document if a single line is between the 2 tokens

Langium version: 3.1.0
Package name: langium-lsp

Steps To Reproduce

  1. Simple HelloWorld grammar
grammar HelloWorld

entry Model:
    (persons+=Person | greetings+=Greeting)*;

Person:
    'person' name=ID;

Greeting:
    'Hello' person=[Person:ID] '!';

hidden terminal WS: /\s+/;
terminal ID: /[_a-zA-Z][\w_]*/;

hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
  1. one space between 'person' keyword and 'name' property
export class HelloFormatter extends AbstractFormatter {

    protected format(node: AstNode): void {
        if (ast.isPerson(node)) {
            const formatter = this.getNodeFormatter(node);
            formatter.property('name').prepend(Formatting.oneSpace())
        } 
    }

}
  1. simple hello file with a single line comment between person and name
person //comment
John

The current behavior

After the formatting the name is moved at the end of the single line comment

person //commentJohn

The expected behavior

person //comment
John

Here is a temporary workaround that works only if rule name is SL_COMMENT:

const nodeEdits = this.createTextEdit(lastNode, node, prependFormatting, context);

Skip the prepend formatting if the lastNode rule is SL_COMMENT

if (!lastNode?.hidden || isLeafCstNode(lastNode) && lastNode.tokenType.name !== 'SL_COMMENT') {
    const nodeEdits = this.createTextEdit(lastNode, node, prependFormatting, context);
    for (const edit of nodeEdits) {
        if (edit && this.insideRange(edit.range, range)) {
            edits.push(edit);
        }
    }
}

fixed by #1628