Extend YAML Formatter for DSL

Answered

Is it possible to extend the YAML Formatter behavior by somehow extending the YAMLFormattingContext? The bundled YAML Formatter is a currently a bit limited. One of the things I'd like to add is to remove any empty lines between a key:value map and its first indented key.

The reason for this is that we're using a mapping to determine imports, and by now implementing the 'Optimize imports' intention I can remove unused imports automagically, however, the parent block isn't formatter nicely afterwards:

import:
path-to-some-file:
- unusedMember
path-to-another-file:
- usedMember

When the unusedMember is removed and subsequently the path-to-some-file: key-value container, the result is:

import:

path-to-another-file:
- usedMember

The most consistent way to fix this (in my opinion) would be to use the document formatter and have the settings such that the number of blank lines between a key:value and its first child is always 0.

 

My first guess was to simple register another lang.formatter for yaml and have it extend the YAMLFormattingModelBuilder. Then override the createModel with:

PsiFile file = formattingContext.getContainingFile();
CodeStyleSettings settings = formattingContext.getCodeStyleSettings();
Block rootBlock = createBlock(new MyCustomYamlFormattingContext(settings, file), formattingContext.getNode());
return new DocumentBasedFormattingModel(rootBlock, settings, file);

The problem is that the MyCustomYamlFormattingContext should be able to extend the YAMLFormattingContext and YAMLFormattingContext is not public.

Since the YAML formatter is quite extensive, especially with regards to all the injected language support, I really want to re-use the current implementation as much as possible.

Any suggestions how to continue?

5 comments
Comment actions Permalink

Hi Tim,

I suggest taking a look at Formatting Post-Processor.

0
Comment actions Permalink

Hi Karol,

Thanks for the response. I had a look at that solution before but in the interface it states that it is really for non-white space modifications like wrapping stuff in parentheses. I'm happy to give it a try but the fact that it says that it isn't called in certain white-space only reformatting operations lets me believe that I might get some unexpected behavior.

Moreover, the benefit of the actual formatter is of course that I would be able to use spacingbuilder and simple state the number of blanklines between 2 element which is more robust compared to removing actual whitespace myself (which I guess is how this interface is implemented). Finally, the PsiElement input/output requires me to manually determine the Parent, Child1, Child2 relationships.

Of couse, for this single example it's all possible but I feel like I'm not using a lot of platform features that are available in the FormattingContext.

Kr, Tim

0
Comment actions Permalink

Hi Tim,

You are right about the Formatting Post-Processor, sorry for pointing it out.

Please clarify: do you want to remove the empty line between the key and value, regardless of keys and values semantics, or only in your specific cases?

In the first case, it seems that it could be a feature request for the YAML formatter. If so, please create an issue in https://youtrack.jetbrains.com/issues/IDEA.

Extending the formatter in a way you are trying is not possible, and I don't see any extension point that would allow doing what you exactly want to do. I suggest removing redundant spaces in your optimize imports action.

0
Comment actions Permalink

Hi Karol,

Thanks for the feedback. I think I'll create an issue for it. It does sound like a useful feature to remove the blank lines between the key and value. So that:

key:
    firstKey:   // no empty lines between YamlKeyValue Key and Value (a YamlMapping in this case)
    // still allow empty lines within the value itself
    secondKey:

I'll post the issue once I create it. 

0

Please sign in to leave a comment.