Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatter shows cyclic behaviour #1362

Closed
insafuhrmann opened this issue Jan 29, 2024 · 0 comments · Fixed by #1550
Closed

Formatter shows cyclic behaviour #1362

insafuhrmann opened this issue Jan 29, 2024 · 0 comments · Fixed by #1550
Assignees
Labels
bug Something isn't working
Milestone

Comments

@insafuhrmann
Copy link
Contributor

insafuhrmann commented Jan 29, 2024

I am implementing a code formatter for a language that has a number of constructs with code regions enclosed in keywords, in a nested fashion, for example a minimal program could be something like:

BEGIN_NAMESPACE
    myNamespace
    BEGIN_STRUCT
        myStruct
    END_STRUCT
END_NAMESPACE

I would like to have a free line before the opening BEGIN_STRUCT keyword and if there already is one or more than one, I wish to keep those lines, but when I implement it according to the documentation (at least to my understanding of it) and apply the auto format multiple times, the formatting changes back and forth, adding and removing the desired line.

Langium version: current development (3.0 candidate)

Steps To Reproduce

For example just add this to the domain-model.langium grammar:

Structure:
    'BEGIN_STRUCT' 
    name=QualifiedName
    'END_STRUCT';

NameSpace:
    'BEGIN_NAMESPACE'
    name=QualifiedName
    (elements+=AbstractElement)*
    'END_NAMESPACE';

and register the two as AbstractElement:

AbstractElement:
    PackageDeclaration | Type | Structure | NameSpace;

then add this to the format function of the DomainModelFormatter:

} else if (ast.isStructure(node)) {
            const formatter = this.getNodeFormatter(node);
            const structOpen = formatter.keyword('BEGIN_STRUCT');
            const structClose = formatter.keyword('END_STRUCT');
            formatter.interior(structOpen, structClose).prepend(Formatting.indent());
            structOpen.prepend(Formatting.newLines(2, {allowMore: true}));
            structClose.prepend(Formatting.newLine());
  } else if (ast.isNameSpace(node)) {
            const formatter = this.getNodeFormatter(node);
            const nsOpen = formatter.keyword('BEGIN_NAMESPACE');
            const nsClose = formatter.keyword('END_NAMESPACE');
            formatter.interior(nsOpen, nsClose).prepend(Formatting.indent());
            nsClose.prepend(Formatting.newLine());
  }

Then apply Format Document repeatedly to a document with the minimal program I wrote above.

The current behavior

The line before BEGIN_STRUCT alternatingly appears and is removed. More than one line is initially removed, after that same behaviour: alternate between empty line and no empty line before BEGIN_STRUCT.

The expected behavior

Depending on whether there already is a free line it should get added or simply left in the formatted code. Multiple applications of the format should not change anything after the first time. More than one free line should also be respected and not removed.

@insafuhrmann insafuhrmann added the bug Something isn't working label Jan 29, 2024
@insafuhrmann insafuhrmann assigned insafuhrmann and unassigned msujew Feb 15, 2024
@insafuhrmann insafuhrmann assigned msujew and unassigned insafuhrmann Feb 26, 2024
@spoenemann spoenemann added this to the v3.1.0 milestone Jun 20, 2024
@msujew msujew mentioned this issue Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants