Formatter and Indentation




I know here are some answers already regarding this question, but unfortunately the answers are way too old or did not resolve the problem.

So here we go.


I have a simple Lua Grammar and all i want to get every Child Block indented by 1 tab. As you can see, as far as the parent is not the File itself, i want to get a normal Indent. The "return parent.getIndent();" was already a Indent.getNoneIndent() and null, always with the same result: nothing...


My FormattingBlock where the indentation is built, inherited from AbstractBlock:

spacing rules:

PsiTree (CoronaBlockImpl(BLOCK) starting from the second layer should be indented):

and now the result i get from the indentation:


so can someone please explain to me, why this stuff is not indented as expected? As far as I have read through forums, Documentations and internets this should be correct?


The indent in a formatter block is always relative to it's parent. If you want a child block be unindented to it's parent, you simply return Indent.getNoneIndent(), not parent.getIndent(). In you case BLOCK element may be indented if it's located, for example, inside another BLOCK element, right? The code then would look something like that:

if (parent.getNode().getElementType() == BLOCK) {
    return Indent.getNormalIndent(); // Indent every child inside BLOCK element including another BLOCK.
return Indent.getNoneIndent(); // Do not indent otherwise.

Also be careful with "instanceof". Perhaps "FileElemeent" is of class PsiElement while getNode() will return ASTNode. So to get a corresponding PSI element you may need to call getNode().getPsi(), otherwise the condition may be always false.


I didn't test your example code yet, I have just a question:

wouldn't it make more sense to apply the indentation to the Block Element at creation-point? So, if i create my new AbstractBlock (in my case, CoronaFormatBlock), i want the whole Block to be indented, right?

so if i say:

new CoronaFormatBlock(astNode, wrap, alignment, CoronaIndent.getIndent(astNode));

where astNode.getElementType() == BLOCK!

So, in my intention, the whole block should be indented right?


From what i unterstood from your post, i would apply the indentation only to the childs of the Block-Element.


Correct. You can definitely assign the indentation type at block creation time. In reality child blocks are created lazily on demand but at this point they may get some fixed assigned indentation.


So, i applied the indentation to what your example code gave me.


result (i am on a different pc now, so the code in the result looks different):


edit: tab (or indent) size is set to 4 spaces, this are 8!


Ok, but why is this not working then? :D


edit: as you can see, the question is not answered. Would you mind removing that flag please?


You have still missed one thing: the last statement is still wrong, it should be "return Indent.getNoneIndent()",  not "return parent.getIndent()". I have already explained it above.


Saw that already, fixed that already, still won't work...


Any more suggestions please, since it is still not working as expected? :/


it is possible to use spacing instead of Indent: 

add Extension Point: lang.formatter : implement FormattingModelBuilder

implement FormattingModel

implement Block:

public List<Block> getSubBlocks();

public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2){
return Spacing.createSpacing(...);


the last getSpacing method would need to handle both indents and spacing between symbols, punctuation. Indent logic can get quite complex.


In my initial post I already posted the Spacing Blocks/Builder. The "horizontal" Spaces are not acknowledged as well, unfortunately. For example, if i change my "NO_SPACING_WITH_NEWLINE" from .createSpacing(0, 0, 1, false, 0) to .createSpacing(4, 4, 1, false, 0) nothing happens 


did you register FormattingModelBuilder and implement FormattingModel, Block?

 if you decide to try this solution (which will take time and may not work for you), 

  FormattingModel's initRootBlock should return your Block implementation.

  getSubBlocks should return your Block implementations (cast as Block as you add them to the List).


yes, it is registered.


I can only guess, but i think my blocks are in the solution, because new lines are working. For example the NO_SPACING_EXTRA_LINE thing works fine. Or at least fine enough since only lines and no spaces are added.


try this in Block impl:

public Indent getIndent() {return null;}


try putting a breakpoint in getSpacing to see when it is called.


another thing: Block implementation methods should not be static but instance methods. I am not sure from where in code your static methods are called.


did that, what is supposed to happen?


getSpacing is supposed to be called for every block in a file: for beginning of line, between symbols etc.

this is Block implementation's getSpacing - not static getSpacing


ah ok, yes, that is happening. And that is why I can't wrap my head around it, why it is not working and stuff


is this formatting code online somewhere?


more or less, yes. I posted nearly everything that is to it in this thread as screenshots. If I have missed something, I can screenshot that as well. If that is not enough, I can upload that to the upload.jetbrains-thing as well


FormattingModel uses Block instances.

in the screenshots many methods are static. I am not sure how this is supposed to work. It may be possible but this is a very different approach. This, or key code parts are missing from the picture.


ah ok, I am terribly sorry. Yes, Keyparts are missing. 

the getSpacing() and getIndet() functions are in helper classes (CoronaSpacing and CoronaIndent) and therefore static. In the second picture in the initial post you can see the call.

The FormatBlock is a derivation from AbstractBlock (taken from here:


here is the whole FormatBlock:

the rest should be here already


try to leave AbstractBlock out and implement original Block interface.

here is a hint where you are likely to pause:

public ChildAttributes getChildAttributes(int i) {
return new ChildAttributes((Indent)null, (Alignment)null);




thank you for your help so far.

I just changed to your suggestions (worked on my grammar, so i couldn't earlier) and set my breakpoint in that function but that is not even called. The "getSubBlocks()" instead is. 

So I guess my models are not saved somehow?



wait nevermind, it is called, but not when i hit the autoformat command (ctrl+alt+L)


could you post somewhere (here, git, pastebin, ...)   

your implementations of:




(as text, please.Images are blurred for some reason)  








FormattingModel is created by the ModelProvider, so no Code there


if you were to implement everything without FormattingModelProvider, here are a couple more steps:



    createModel - returns implementation of FormattingModel.


Implementation of FormattingModel :

   getRootBlock -  returns implementation of Block

   getDocumentModel - returns implementation of FormattingDocumentModel


if you do all this and indenting still does not work as expected, try to 

public Indent getIndent() {
return null;

in Block.

Then set all spacing (including indent) with 

public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) 


it is a bit of work but it works.


actually, try "getIndent returns null" first. It is less work.


well, yeah, no ;/ did not work


and "new" SpacingHleper:

rest is unoticeable changed


does  FormattingModelBuilder createModel return CoronaFormatModel?

did you try to not use Indent altogether? return null, and let getSpacing handle indenting?

if I understand correctly, you are looking to fix indenting, yes?


@1: yes, one of the unnoticeable changes. I though a new pastebin wasn't necessary for that change

@2: yes, tried both, with Indent, without Indent:

@3: basically yes. But i would call it "create" first since it was not even running properly till now :D