Formatter Problem
Opened this issue · 0 comments
cdietrich commented
Given the grammar
entry ContextDefinition:
packages+=ContextPackage+;
ContextPackage:
'package' packageName=ID '{'
('nodes' '{' '}')?
('files' '{' '}')?
'}';
hidden terminal WS: /\s+/;
terminal ID: /[_a-zA-Z][\w_]*/;
hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
and formatter
const FormatingOptions = {
lineBreak: Formatting.newLine({ allowMore: true }),
lineBreakOne: Formatting.newLines(1, { allowMore: false }),
emptyLine: Formatting.newLines(2, { allowMore: true }),
newLineAllowMore: Formatting.newLine({ allowMore: true }),
oneSpace: Formatting.spaces(1),
noSpace: Formatting.noSpace(),
indent: Formatting.indent({ allowMore: true }),
noIndent: Formatting.noIndent({ allowMore: true }),
noNewLines: Formatting.newLines(0),
}
function formatNestedBody(_: AstNode, formatter: NodeFormatter<AstNode>) {
console.log("formatNestedBody")
const opens = formatter.keywords("{")
const closes = formatter.keywords("}")
if (opens.nodes.length === closes.nodes.length && opens.nodes.length > 0) {
const [outerOpen, ...innerOpens] = opens.nodes
const outerClose = closes.nodes[closes.nodes.length - 1]
const innerCloses = closes.nodes.slice(0, closes.nodes.length - 1)
// format the outer {}
console.log(outerOpen.range.start.line, outerClose.range.start.line)
const bracesOpenOuter = formatter.cst([outerOpen])
const bracesCloseOuter = formatter.cst([outerClose])
formatter.interior(bracesOpenOuter, bracesCloseOuter).prepend(FormatingOptions.indent)
bracesCloseOuter.prepend(FormatingOptions.lineBreakOne)
bracesOpenOuter.prepend(FormatingOptions.oneSpace)
// format the inner ones inputs {} ...
for (let i = 0; i < innerOpens.length; i++) {
const c1 = innerOpens[i]
const c2 = innerCloses[i]
console.log(c1.range.start.line, c2.range.start.line)
const bracesOpen = formatter.cst([c1])
const bracesClose = formatter.cst([c2])
formatter.interior(bracesOpen, bracesClose).prepend(FormatingOptions.indent)
bracesClose.prepend(FormatingOptions.lineBreakOne)
bracesOpen.prepend(FormatingOptions.oneSpace)
}
}
}
export class CustomFormatter extends AbstractFormatter {
protected format(node: AstNode): void {
if (node.$type === 'ContextPackage') {
const formatter = this.getNodeFormatter(node);
formatNestedBody(node, formatter)
formatter
.keywords(",")
.append(FormatingOptions.lineBreakOne)
.prepend(FormatingOptions.noIndent)
.prepend(FormatingOptions.noNewLines)
.prepend(FormatingOptions.noSpace)
}
}
}
sample file
package sample {
nodes {} files {}
}
is not formatted as expected (nicely indented)
when i refactor the grammar to use fragments, it suddenly works.
any idea what the problem could be
ContextPackage:
'package' packageName=ID '{'
(ContextNodeList)?
(ContextFileList)?
'}';
fragment ContextFileList:
x?='files' '{' '}';
fragment ContextNodeList*:
y?='nodes' '{' '}';
unfortunately the workaround cannot be applied in production cause of the
AST node has no document
bug