Formatter and Indentation
Hey,
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.
code:
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:
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:
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: http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/formatter.html )
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:
Hey,
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)
sure:
Block: http://pastebin.com/CUDBfKKn
FormatModelBuilder: http://pastebin.com/vDEbsKLz
IndentationHelper: http://pastebin.com/rhck4A3r
SpacingHelper: http://pastebin.com/kVMj6j8n
FormattingModel is created by the ModelProvider, so no Code there
if you were to implement everything without FormattingModelProvider, here are a couple more steps:
FormattingModelBuilder:
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
in Block.
Then set all spacing (including indent) with
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
FormattingModel: http://pastebin.com/TfUHpHXi
and "new" SpacingHleper: http://pastebin.com/jyGFuemd
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