mirror of
https://github.com/apple/pkl.git
synced 2026-03-27 11:31:11 +01:00
Format interpolated expressions as single line (#1247)
This forces iterpolated expressions to be single-line, so that newline literals within the bounds of two string delimiters can be seen as verbatime newlines in the resulting string. Edge case: in the case of a line comment, it's not possible to keep this as a single line expression. These are kept as multi-line expressions. Also: * Remove `ForceWrap`, this node is not used. * Rename `StringConstant` -> `StringChars`
This commit is contained in:
@@ -37,6 +37,9 @@ internal class Builder(sourceText: String) {
|
||||
private var id: Int = 0
|
||||
private val source: CharArray = sourceText.toCharArray()
|
||||
private var prevNode: Node? = null
|
||||
private var noNewlines = false
|
||||
|
||||
private class CannotAvoidNewline : RuntimeException()
|
||||
|
||||
fun format(node: Node): FormatNode {
|
||||
prevNode = node
|
||||
@@ -49,9 +52,8 @@ internal class Builder(sourceText: String) {
|
||||
NodeType.TERMINAL,
|
||||
NodeType.MODIFIER,
|
||||
NodeType.IDENTIFIER,
|
||||
NodeType.STRING_CONSTANT,
|
||||
NodeType.STRING_CHARS,
|
||||
NodeType.STRING_ESCAPE,
|
||||
NodeType.SINGLE_LINE_STRING_LITERAL_EXPR,
|
||||
NodeType.INT_LITERAL_EXPR,
|
||||
NodeType.FLOAT_LITERAL_EXPR,
|
||||
NodeType.BOOL_LITERAL_EXPR,
|
||||
@@ -64,9 +66,10 @@ internal class Builder(sourceText: String) {
|
||||
NodeType.NOTHING_TYPE,
|
||||
NodeType.SHEBANG,
|
||||
NodeType.OPERATOR -> Text(node.text(source))
|
||||
NodeType.STRING_NEWLINE -> ForceLine
|
||||
NodeType.STRING_NEWLINE -> mustForceLine()
|
||||
NodeType.MODULE_DECLARATION -> formatModuleDeclaration(node)
|
||||
NodeType.MODULE_DEFINITION -> formatModuleDefinition(node)
|
||||
NodeType.SINGLE_LINE_STRING_LITERAL_EXPR -> formatSingleLineString(node)
|
||||
NodeType.MULTI_LINE_STRING_LITERAL_EXPR -> formatMultilineString(node)
|
||||
NodeType.ANNOTATION -> formatAnnotation(node)
|
||||
NodeType.TYPEALIAS -> formatTypealias(node)
|
||||
@@ -77,13 +80,13 @@ internal class Builder(sourceText: String) {
|
||||
NodeType.PARAMETER_LIST_ELEMENTS -> formatParameterListElements(node)
|
||||
NodeType.TYPE_PARAMETER_LIST -> formatTypeParameterList(node)
|
||||
NodeType.TYPE_PARAMETER_LIST_ELEMENTS -> formatParameterListElements(node)
|
||||
NodeType.TYPE_PARAMETER -> Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
NodeType.TYPE_PARAMETER -> Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
NodeType.PARAMETER -> formatParameter(node)
|
||||
NodeType.EXTENDS_CLAUSE,
|
||||
NodeType.AMENDS_CLAUSE -> formatAmendsExtendsClause(node)
|
||||
NodeType.IMPORT_LIST -> formatImportList(node)
|
||||
NodeType.IMPORT -> formatImport(node)
|
||||
NodeType.IMPORT_ALIAS -> Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
NodeType.IMPORT_ALIAS -> Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
NodeType.CLASS -> formatClass(node)
|
||||
NodeType.CLASS_HEADER -> formatClassHeader(node)
|
||||
NodeType.CLASS_HEADER_EXTENDS -> formatClassHeaderExtends(node)
|
||||
@@ -167,7 +170,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatModule(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
if (prev.linesBetween(next) > 1) TWO_NEWLINES else ForceLine
|
||||
if (prev.linesBetween(next) > 1) TWO_NEWLINES else forceLine()
|
||||
}
|
||||
return Nodes(nodes)
|
||||
}
|
||||
@@ -179,7 +182,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatModuleDefinition(node: Node): FormatNode {
|
||||
val (prefixes, nodes) = splitPrefixes(node.children)
|
||||
val fnodes =
|
||||
formatGenericWithGen(nodes, SpaceOrLine) { node, next ->
|
||||
formatGenericWithGen(nodes, spaceOrLine()) { node, next ->
|
||||
if (next == null) {
|
||||
indent(format(node))
|
||||
} else {
|
||||
@@ -191,7 +194,7 @@ internal class Builder(sourceText: String) {
|
||||
res
|
||||
} else {
|
||||
val sep = getSeparator(prefixes.last(), nodes.first())
|
||||
Nodes(formatGeneric(prefixes, SpaceOrLine) + listOf(sep, res))
|
||||
Nodes(formatGeneric(prefixes, spaceOrLine()) + listOf(sep, res))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,10 +220,10 @@ internal class Builder(sourceText: String) {
|
||||
// short circuit
|
||||
if (node.children.size == 1) return format(node.children[0])
|
||||
|
||||
val first = listOf(format(node.children[0]), Line)
|
||||
val first = listOf(format(node.children[0]), line())
|
||||
val nodes =
|
||||
formatGeneric(node.children.drop(1)) { n1, _ ->
|
||||
if (n1.type == NodeType.TERMINAL) null else Line
|
||||
if (n1.type == NodeType.TERMINAL) null else line()
|
||||
}
|
||||
return Group(newId(), first + listOf(Indent(nodes)))
|
||||
}
|
||||
@@ -240,28 +243,28 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatAmendsExtendsClause(node: Node): FormatNode {
|
||||
val prefix = formatGeneric(node.children.dropLast(1), SpaceOrLine)
|
||||
val prefix = formatGeneric(node.children.dropLast(1), spaceOrLine())
|
||||
// string constant
|
||||
val suffix = Indent(listOf(format(node.children.last())))
|
||||
return Group(newId(), prefix + listOf(SpaceOrLine) + suffix)
|
||||
return Group(newId(), prefix + listOf(spaceOrLine()) + suffix)
|
||||
}
|
||||
|
||||
private fun formatImport(node: Node): FormatNode {
|
||||
return Group(
|
||||
newId(),
|
||||
formatGenericWithGen(node.children, SpaceOrLine) { node, _ ->
|
||||
formatGenericWithGen(node.children, spaceOrLine()) { node, _ ->
|
||||
if (node.isTerminal("import")) format(node) else indent(format(node))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatAnnotation(node: Node): FormatNode {
|
||||
return Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
return Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatTypealias(node: Node): FormatNode {
|
||||
val nodes =
|
||||
groupNonPrefixes(node) { children -> Group(newId(), formatGeneric(children, SpaceOrLine)) }
|
||||
groupNonPrefixes(node) { children -> Group(newId(), formatGeneric(children, spaceOrLine())) }
|
||||
return Nodes(nodes)
|
||||
}
|
||||
|
||||
@@ -270,19 +273,19 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatTypealiasBody(node: Node): FormatNode {
|
||||
return Indent(formatGeneric(node.children, SpaceOrLine))
|
||||
return Indent(formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatClass(node: Node): FormatNode {
|
||||
return Nodes(formatGeneric(node.children, SpaceOrLine))
|
||||
return Nodes(formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatClassHeader(node: Node): FormatNode {
|
||||
return groupOnSpace(formatGeneric(node.children, SpaceOrLine))
|
||||
return groupOnSpace(formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatClassHeaderExtends(node: Node): FormatNode {
|
||||
return indent(Group(newId(), formatGeneric(node.children, SpaceOrLine)))
|
||||
return indent(Group(newId(), formatGeneric(node.children, spaceOrLine())))
|
||||
}
|
||||
|
||||
private fun formatClassBody(node: Node): FormatNode {
|
||||
@@ -291,14 +294,14 @@ internal class Builder(sourceText: String) {
|
||||
// no members
|
||||
return Nodes(formatGeneric(children, null))
|
||||
}
|
||||
return Group(newId(), formatGeneric(children, ForceLine))
|
||||
return Group(newId(), formatGeneric(children, forceLine()))
|
||||
}
|
||||
|
||||
private fun formatClassBodyElements(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
val lineDiff = prev.linesBetween(next)
|
||||
if (lineDiff > 1 || lineDiff == 0) TWO_NEWLINES else ForceLine
|
||||
if (lineDiff > 1 || lineDiff == 0) TWO_NEWLINES else forceLine()
|
||||
}
|
||||
return Indent(nodes)
|
||||
}
|
||||
@@ -313,8 +316,9 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
groupNonPrefixes(node) { children ->
|
||||
val nodes =
|
||||
formatGenericWithGen(children, { _, _ -> if (sameLine) Space else SpaceOrLine }) { node, _
|
||||
->
|
||||
formatGenericWithGen(children, { _, _ -> if (sameLine) Space else spaceOrLine() }) {
|
||||
node,
|
||||
_ ->
|
||||
if ((node.isExpressionOrPropertyBody()) && !sameLine) {
|
||||
indent(format(node))
|
||||
} else format(node)
|
||||
@@ -330,11 +334,11 @@ internal class Builder(sourceText: String) {
|
||||
type == NodeType.OBJECT_PROPERTY_BODY
|
||||
|
||||
private fun formatClassPropertyHeader(node: Node): FormatNode {
|
||||
return Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
return Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatClassPropertyHeaderBegin(node: Node): FormatNode {
|
||||
return Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
return Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatClassPropertyBody(node: Node): FormatNode {
|
||||
@@ -349,7 +353,7 @@ internal class Builder(sourceText: String) {
|
||||
val idx = node.children.indexOfFirst { it.type == NodeType.CLASS_METHOD_HEADER }
|
||||
val prefixNodes = node.children.subList(0, idx)
|
||||
prefixes += formatGeneric(prefixNodes, null)
|
||||
prefixes += getSeparator(prefixNodes.last(), node.children[idx], ForceLine)
|
||||
prefixes += getSeparator(prefixNodes.last(), node.children[idx], forceLine())
|
||||
node.children.subList(idx, node.children.size)
|
||||
}
|
||||
|
||||
@@ -359,7 +363,7 @@ internal class Builder(sourceText: String) {
|
||||
val headerGroupId = newId()
|
||||
val methodGroupId = newId()
|
||||
val headerNodes =
|
||||
formatGenericWithGen(header, SpaceOrLine) { node, _ ->
|
||||
formatGenericWithGen(header, spaceOrLine()) { node, _ ->
|
||||
if (node.type == NodeType.PARAMETER_LIST) {
|
||||
formatParameterList(node, id = headerGroupId)
|
||||
} else {
|
||||
@@ -385,7 +389,7 @@ internal class Builder(sourceText: String) {
|
||||
if (isSameLineBody) {
|
||||
formatGeneric(bodyNodes, Space)
|
||||
} else {
|
||||
formatGenericWithGen(bodyNodes, SpaceOrLine) { node, next ->
|
||||
formatGenericWithGen(bodyNodes, spaceOrLine()) { node, next ->
|
||||
if (next == null) indent(format(node)) else format(node)
|
||||
}
|
||||
}
|
||||
@@ -409,7 +413,7 @@ internal class Builder(sourceText: String) {
|
||||
|
||||
private fun formatParameter(node: Node): FormatNode {
|
||||
if (node.children.size == 1) return format(node.children[0]) // underscore
|
||||
return Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
return Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatParameterList(node: Node, id: Int? = null): FormatNode {
|
||||
@@ -420,9 +424,9 @@ internal class Builder(sourceText: String) {
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) {
|
||||
if (next.isTerminal(")")) {
|
||||
// trailing comma
|
||||
IfWrap(groupId, nodes(Text(","), Line), Line)
|
||||
} else Line
|
||||
} else SpaceOrLine
|
||||
ifWrap(groupId, nodes(Text(","), line()), line())
|
||||
} else line()
|
||||
} else spaceOrLine()
|
||||
}
|
||||
return if (id != null) Nodes(nodes) else Group(groupId, nodes)
|
||||
}
|
||||
@@ -436,12 +440,12 @@ internal class Builder(sourceText: String) {
|
||||
node.children,
|
||||
{ prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) {
|
||||
val node = if (hasTrailingLambda) Empty else Line
|
||||
val node = if (hasTrailingLambda) Empty else line()
|
||||
if (next.isTerminal(")") && !hasTrailingLambda) {
|
||||
// trailing comma
|
||||
IfWrap(groupId, nodes(Text(","), node), node)
|
||||
ifWrap(groupId, nodes(Text(","), node), node)
|
||||
} else node
|
||||
} else SpaceOrLine
|
||||
} else spaceOrLine()
|
||||
},
|
||||
) { node, _ ->
|
||||
if (node.type == NodeType.ARGUMENT_LIST_ELEMENTS) {
|
||||
@@ -460,9 +464,9 @@ internal class Builder(sourceText: String) {
|
||||
return if (twoBy2) {
|
||||
val pairs = pairArguments(children)
|
||||
val nodes =
|
||||
formatGenericWithGen(pairs, SpaceOrLine) { node, _ ->
|
||||
formatGenericWithGen(pairs, spaceOrLine()) { node, _ ->
|
||||
if (node.type == NodeType.ARGUMENT_LIST_ELEMENTS) {
|
||||
Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
} else {
|
||||
format(node)
|
||||
}
|
||||
@@ -473,17 +477,17 @@ internal class Builder(sourceText: String) {
|
||||
val splitIndex = children.indexOfLast { it.type in SAME_LINE_EXPRS }
|
||||
val normalParams = children.subList(0, splitIndex)
|
||||
val lastParam = children.subList(splitIndex, children.size)
|
||||
val trailingNode = if (endsWithClosingBracket(children[splitIndex])) Empty else Line
|
||||
val lastNodes = formatGeneric(lastParam, SpaceOrLine)
|
||||
val trailingNode = if (endsWithClosingBracket(children[splitIndex])) Empty else line()
|
||||
val lastNodes = formatGeneric(lastParam, spaceOrLine())
|
||||
if (normalParams.isEmpty()) {
|
||||
nodes(Group(newId(), lastNodes), trailingNode)
|
||||
} else {
|
||||
val separator = getSeparator(normalParams.last(), lastParam[0], Space)
|
||||
val paramNodes = formatGeneric(normalParams, SpaceOrLine)
|
||||
val paramNodes = formatGeneric(normalParams, spaceOrLine())
|
||||
nodes(Group(newId(), paramNodes), separator, Group(newId(), lastNodes), trailingNode)
|
||||
}
|
||||
} else {
|
||||
Indent(formatGeneric(children, SpaceOrLine))
|
||||
Indent(formatGeneric(children, spaceOrLine()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +535,7 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatParameterListElements(node: Node): FormatNode {
|
||||
return Indent(formatGeneric(node.children, SpaceOrLine))
|
||||
return Indent(formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatTypeParameterList(node: Node): FormatNode {
|
||||
@@ -542,9 +546,9 @@ internal class Builder(sourceText: String) {
|
||||
if (prev.isTerminal("<") || next.isTerminal(">")) {
|
||||
if (next.isTerminal(">")) {
|
||||
// trailing comma
|
||||
IfWrap(id, nodes(Text(","), Line), Line)
|
||||
} else Line
|
||||
} else SpaceOrLine
|
||||
ifWrap(id, nodes(Text(","), line()), line())
|
||||
} else line()
|
||||
} else spaceOrLine()
|
||||
}
|
||||
return Group(id, nodes)
|
||||
}
|
||||
@@ -552,10 +556,10 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatObjectParameterList(node: Node): FormatNode {
|
||||
// object param lists don't have trailing commas, as they have a trailing ->
|
||||
val groupId = newId()
|
||||
val nonWrappingNodes = Nodes(formatGeneric(node.children, SpaceOrLine))
|
||||
val nonWrappingNodes = Nodes(formatGeneric(node.children, spaceOrLine()))
|
||||
// double indent the params if they wrap
|
||||
val wrappingNodes = indent(Indent(listOf(Line) + nonWrappingNodes))
|
||||
return Group(groupId, listOf(IfWrap(groupId, wrappingNodes, nodes(Space, nonWrappingNodes))))
|
||||
val wrappingNodes = indent(Indent(listOf(line()) + nonWrappingNodes))
|
||||
return Group(groupId, listOf(ifWrap(groupId, wrappingNodes, nodes(Space, nonWrappingNodes))))
|
||||
}
|
||||
|
||||
private fun formatObjectBody(node: Node): FormatNode {
|
||||
@@ -568,8 +572,8 @@ internal class Builder(sourceText: String) {
|
||||
if (next.type == NodeType.OBJECT_PARAMETER_LIST) Empty
|
||||
else if (prev.isTerminal("{") || next.isTerminal("}")) {
|
||||
val lines = prev.linesBetween(next)
|
||||
if (lines == 0) SpaceOrLine else ForceLine
|
||||
} else SpaceOrLine
|
||||
if (lines == 0) spaceOrLine() else forceSpaceyLine()
|
||||
} else spaceOrLine()
|
||||
},
|
||||
) { node, _ ->
|
||||
if (node.type == NodeType.OBJECT_MEMBER_LIST) {
|
||||
@@ -584,8 +588,8 @@ internal class Builder(sourceText: String) {
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
val lines = prev.linesBetween(next)
|
||||
when (lines) {
|
||||
0 -> IfWrap(groupId, Line, Text("; "))
|
||||
1 -> ForceLine
|
||||
0 -> ifWrap(groupId, line(), Text("; "))
|
||||
1 -> forceLine()
|
||||
else -> TWO_NEWLINES
|
||||
}
|
||||
}
|
||||
@@ -593,7 +597,7 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatObjectEntryHeader(node: Node): FormatNode {
|
||||
return Group(newId(), formatGeneric(node.children, SpaceOrLine))
|
||||
return Group(newId(), formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatForGenerator(node: Node): FormatNode {
|
||||
@@ -603,7 +607,7 @@ internal class Builder(sourceText: String) {
|
||||
prev.type == NodeType.FOR_GENERATOR_HEADER || next.type == NodeType.FOR_GENERATOR_HEADER
|
||||
) {
|
||||
Space
|
||||
} else SpaceOrLine
|
||||
} else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -611,7 +615,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatForGeneratorHeader(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) Line else null
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else null
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -620,7 +624,7 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ _, next -> if (next.type in SAME_LINE_EXPRS) Space else SpaceOrLine },
|
||||
{ _, next -> if (next.type in SAME_LINE_EXPRS) Space else spaceOrLine() },
|
||||
) { node, _ ->
|
||||
if (node.type.isExpression && node.type !in SAME_LINE_EXPRS) indent(format(node))
|
||||
else format(node)
|
||||
@@ -629,7 +633,7 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatForGeneratorHeaderDefinitionHeader(node: Node): FormatNode {
|
||||
val nodes = formatGeneric(node.children, SpaceOrLine)
|
||||
val nodes = formatGeneric(node.children, spaceOrLine())
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
|
||||
@@ -643,7 +647,7 @@ internal class Builder(sourceText: String) {
|
||||
) {
|
||||
Space
|
||||
} else {
|
||||
SpaceOrLine
|
||||
spaceOrLine()
|
||||
}
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
@@ -653,7 +657,9 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ prev, next -> if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine },
|
||||
{ prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
},
|
||||
) { node, _ ->
|
||||
if (!node.type.isAffix && node.type != NodeType.TERMINAL) {
|
||||
indent(format(node))
|
||||
@@ -664,7 +670,7 @@ internal class Builder(sourceText: String) {
|
||||
|
||||
private fun formatMemberPredicate(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGenericWithGen(node.children, SpaceOrLine) { node, next ->
|
||||
formatGenericWithGen(node.children, spaceOrLine()) { node, next ->
|
||||
if (next == null && node.type != NodeType.OBJECT_BODY) {
|
||||
indent(format(node))
|
||||
} else format(node)
|
||||
@@ -672,8 +678,46 @@ internal class Builder(sourceText: String) {
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
|
||||
private fun formatStringParts(nodes: List<Node>): List<FormatNode> {
|
||||
return buildList {
|
||||
var isInStringInterpolation = false
|
||||
val cursor = nodes.iterator().peekable()
|
||||
var prev: Node? = null
|
||||
while (cursor.hasNext()) {
|
||||
if (isInStringInterpolation) {
|
||||
val prevNoNewlines = noNewlines
|
||||
noNewlines = true
|
||||
val elems = cursor.takeUntilBefore { it.isTerminal(")") }
|
||||
getSeparator(prev!!, elems.first(), { _, _ -> null })?.let { add(it) }
|
||||
val formatted =
|
||||
try {
|
||||
formatGeneric(elems, null)
|
||||
} catch (_: CannotAvoidNewline) {
|
||||
noNewlines = false
|
||||
formatGeneric(elems, null)
|
||||
}
|
||||
addAll(formatted)
|
||||
getSeparator(elems.last(), cursor.peek(), { _, _ -> null })?.let { add(it) }
|
||||
noNewlines = prevNoNewlines
|
||||
isInStringInterpolation = false
|
||||
continue
|
||||
}
|
||||
val elem = cursor.next()
|
||||
if (elem.type == NodeType.TERMINAL && elem.text().endsWith("(")) {
|
||||
isInStringInterpolation = true
|
||||
}
|
||||
add(format(elem))
|
||||
prev = elem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatSingleLineString(node: Node): FormatNode {
|
||||
return Group(newId(), formatStringParts(node.children))
|
||||
}
|
||||
|
||||
private fun formatMultilineString(node: Node): FormatNode {
|
||||
val nodes = formatGeneric(node.children, null)
|
||||
val nodes = formatStringParts(node.children)
|
||||
return MultilineStringGroup(node.children.last().span.colBegin, nodes)
|
||||
}
|
||||
|
||||
@@ -682,7 +726,7 @@ internal class Builder(sourceText: String) {
|
||||
formatGeneric(node.children) { _, next ->
|
||||
if (next.type == NodeType.IF_ELSE_EXPR && next.children[0].type == NodeType.IF_EXPR) {
|
||||
Space
|
||||
} else SpaceOrLine
|
||||
} else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -690,7 +734,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatIfHeader(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { _, next ->
|
||||
if (next.type == NodeType.IF_CONDITION) Space else SpaceOrLine
|
||||
if (next.type == NodeType.IF_CONDITION) Space else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -698,7 +742,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatIfCondition(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -723,12 +767,12 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatNewExpr(node: Node): FormatNode {
|
||||
val nodes = formatGeneric(node.children, SpaceOrLine)
|
||||
val nodes = formatGeneric(node.children, spaceOrLine())
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
|
||||
private fun formatNewHeader(node: Node): FormatNode {
|
||||
val nodes = formatGeneric(node.children, SpaceOrLine)
|
||||
val nodes = formatGeneric(node.children, spaceOrLine())
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
|
||||
@@ -737,7 +781,9 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ prev, next -> if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine },
|
||||
{ prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
},
|
||||
) { node, _ ->
|
||||
if (node.type.isExpression) indent(format(node)) else format(node)
|
||||
}
|
||||
@@ -757,7 +803,7 @@ internal class Builder(sourceText: String) {
|
||||
val expr = body.children.find { it.type.isExpression }!!
|
||||
isSameLineExpr(expr)
|
||||
}
|
||||
val sep = if (sameLine) Space else SpaceOrLine
|
||||
val sep = if (sameLine) Space else spaceOrLine()
|
||||
val bodySep = getSeparator(params.last(), rest.first(), sep)
|
||||
|
||||
val nodes = formatGeneric(params, sep)
|
||||
@@ -775,7 +821,7 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ _, next -> if (next.type == NodeType.LET_PARAMETER_DEFINITION) Space else SpaceOrLine },
|
||||
{ _, next -> if (next.type == NodeType.LET_PARAMETER_DEFINITION) Space else spaceOrLine() },
|
||||
) { node, next ->
|
||||
if (next == null) {
|
||||
if (node.type == NodeType.LET_EXPR) {
|
||||
@@ -791,7 +837,7 @@ internal class Builder(sourceText: String) {
|
||||
private fun formatLetParameterDefinition(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -810,17 +856,17 @@ internal class Builder(sourceText: String) {
|
||||
when (prev.text()) {
|
||||
".",
|
||||
"?." -> null
|
||||
"-" -> SpaceOrLine
|
||||
"-" -> spaceOrLine()
|
||||
else -> Space
|
||||
}
|
||||
} else if (next.type == NodeType.OPERATOR) {
|
||||
when (next.text()) {
|
||||
".",
|
||||
"?." -> if (hasMultipleLambdas) ForceLine else Line
|
||||
"?." -> if (hasMultipleLambdas) forceLine() else line()
|
||||
"-" -> Space
|
||||
else -> SpaceOrLine
|
||||
else -> spaceOrLine()
|
||||
}
|
||||
} else SpaceOrLine
|
||||
} else spaceOrLine()
|
||||
}
|
||||
val shouldGroup = node.children.size == flat.size
|
||||
return Group(newId(), indentAfterFirstNewline(nodes, shouldGroup))
|
||||
@@ -843,7 +889,7 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ prev, next -> if (prev.isTerminal("(") || next.isTerminal(")")) Line else null },
|
||||
{ prev, next -> if (prev.isTerminal("(") || next.isTerminal(")")) line() else null },
|
||||
) { node, _ ->
|
||||
if (node.type.isExpression) indent(format(node)) else format(node)
|
||||
}
|
||||
@@ -851,13 +897,13 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
|
||||
private fun formatDeclaredType(node: Node): FormatNode {
|
||||
return Nodes(formatGeneric(node.children, SpaceOrLine))
|
||||
return Nodes(formatGeneric(node.children, spaceOrLine()))
|
||||
}
|
||||
|
||||
private fun formatConstrainedType(node: Node): FormatNode {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { _, next ->
|
||||
if (next.type == NodeType.CONSTRAINED_TYPE_CONSTRAINT) null else SpaceOrLine
|
||||
if (next.type == NodeType.CONSTRAINED_TYPE_CONSTRAINT) null else spaceOrLine()
|
||||
}
|
||||
return Group(newId(), nodes)
|
||||
}
|
||||
@@ -866,7 +912,7 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
when {
|
||||
next.isTerminal("|") -> SpaceOrLine
|
||||
next.isTerminal("|") -> spaceOrLine()
|
||||
prev.isTerminal("|") -> Space
|
||||
else -> null
|
||||
}
|
||||
@@ -878,7 +924,9 @@ internal class Builder(sourceText: String) {
|
||||
val nodes =
|
||||
formatGenericWithGen(
|
||||
node.children,
|
||||
{ prev, next -> if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine },
|
||||
{ prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
},
|
||||
) { node, next ->
|
||||
if (next == null) indent(format(node)) else format(node)
|
||||
}
|
||||
@@ -890,13 +938,13 @@ internal class Builder(sourceText: String) {
|
||||
val groupId = newId()
|
||||
val nodes =
|
||||
formatGeneric(node.children) { prev, next ->
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) Line else SpaceOrLine
|
||||
if (prev.isTerminal("(") || next.isTerminal(")")) line() else spaceOrLine()
|
||||
}
|
||||
return Group(groupId, nodes)
|
||||
}
|
||||
|
||||
private fun formatParenthesizedTypeElements(node: Node): FormatNode {
|
||||
return indent(Group(newId(), formatGeneric(node.children, SpaceOrLine)))
|
||||
return indent(Group(newId(), formatGeneric(node.children, spaceOrLine())))
|
||||
}
|
||||
|
||||
private fun formatTypeAnnotation(node: Node): FormatNode {
|
||||
@@ -907,7 +955,7 @@ internal class Builder(sourceText: String) {
|
||||
val nodes = mutableListOf<FormatNode>()
|
||||
val children = node.children.groupBy { it.type.isAffix }
|
||||
if (children[true] != null) {
|
||||
nodes += formatGeneric(children[true]!!, SpaceOrLine)
|
||||
nodes += formatGeneric(children[true]!!, spaceOrLine())
|
||||
}
|
||||
val modifiers = children[false]!!.sortedBy(::modifierPrecedence)
|
||||
nodes += formatGeneric(modifiers, Space)
|
||||
@@ -918,8 +966,8 @@ internal class Builder(sourceText: String) {
|
||||
val nodes = mutableListOf<FormatNode>()
|
||||
val children = node.children.groupBy { it.type.isAffix }
|
||||
if (children[true] != null) {
|
||||
nodes += formatGeneric(children[true]!!, SpaceOrLine)
|
||||
nodes += ForceLine
|
||||
nodes += formatGeneric(children[true]!!, spaceOrLine())
|
||||
nodes += forceLine()
|
||||
}
|
||||
|
||||
val allImports = children[false]!!
|
||||
@@ -952,27 +1000,27 @@ internal class Builder(sourceText: String) {
|
||||
|
||||
if (absolute != null) {
|
||||
for ((i, imp) in absolute.withIndex()) {
|
||||
if (i > 0) nodes += ForceLine
|
||||
if (i > 0) nodes += forceLine()
|
||||
nodes += format(imp)
|
||||
}
|
||||
if (projects != null || relatives != null) nodes += ForceLine
|
||||
if (projects != null || relatives != null) nodes += forceLine()
|
||||
shouldNewline = true
|
||||
}
|
||||
|
||||
if (projects != null) {
|
||||
if (shouldNewline) nodes += ForceLine
|
||||
if (shouldNewline) nodes += forceLine()
|
||||
for ((i, imp) in projects.withIndex()) {
|
||||
if (i > 0) nodes += ForceLine
|
||||
if (i > 0) nodes += forceLine()
|
||||
nodes += format(imp)
|
||||
}
|
||||
if (relatives != null) nodes += ForceLine
|
||||
if (relatives != null) nodes += forceLine()
|
||||
shouldNewline = true
|
||||
}
|
||||
|
||||
if (relatives != null) {
|
||||
if (shouldNewline) nodes += ForceLine
|
||||
if (shouldNewline) nodes += forceLine()
|
||||
for ((i, imp) in relatives.withIndex()) {
|
||||
if (i > 0) nodes += ForceLine
|
||||
if (i > 0) nodes += forceLine()
|
||||
nodes += format(imp)
|
||||
}
|
||||
}
|
||||
@@ -1005,7 +1053,7 @@ internal class Builder(sourceText: String) {
|
||||
// skip semicolons
|
||||
val children = children.filter { !it.isSemicolon() }
|
||||
// short circuit
|
||||
if (children.isEmpty()) return listOf(SpaceOrLine)
|
||||
if (children.isEmpty()) return listOf(spaceOrLine())
|
||||
if (children.size == 1) return listOf(format(children[0]))
|
||||
|
||||
val nodes = mutableListOf<FormatNode>()
|
||||
@@ -1046,19 +1094,19 @@ internal class Builder(sourceText: String) {
|
||||
val prefixes = children.subList(0, index)
|
||||
val nodes = children.subList(index, children.size)
|
||||
val res = mutableListOf<FormatNode>()
|
||||
res += formatGeneric(prefixes, SpaceOrLine)
|
||||
res += formatGeneric(prefixes, spaceOrLine())
|
||||
res += getSeparator(prefixes.last(), nodes.first())
|
||||
res += groupFn(nodes)
|
||||
return res
|
||||
}
|
||||
|
||||
private fun getImportUrl(node: Node): String =
|
||||
node.findChildByType(NodeType.STRING_CONSTANT)!!.text().drop(1).dropLast(1)
|
||||
node.findChildByType(NodeType.STRING_CHARS)!!.text().drop(1).dropLast(1)
|
||||
|
||||
private fun getSeparator(
|
||||
prev: Node,
|
||||
next: Node,
|
||||
separator: FormatNode = SpaceOrLine,
|
||||
separator: FormatNode = spaceOrLine(),
|
||||
): FormatNode {
|
||||
return getSeparator(prev, next) { _, _ -> separator }!!
|
||||
}
|
||||
@@ -1073,19 +1121,21 @@ internal class Builder(sourceText: String) {
|
||||
if (prev.linesBetween(next) > 1) {
|
||||
TWO_NEWLINES
|
||||
} else {
|
||||
ForceLine
|
||||
mustForceLine()
|
||||
}
|
||||
}
|
||||
hasTrailingAffix(prev, next) -> Space
|
||||
prev.type == NodeType.DOC_COMMENT || prev.type == NodeType.ANNOTATION -> ForceLine
|
||||
prev.type == NodeType.DOC_COMMENT -> mustForceLine()
|
||||
prev.type == NodeType.ANNOTATION -> forceLine()
|
||||
prev.type in FORCE_LINE_AFFIXES || next.type.isAffix -> {
|
||||
if (prev.linesBetween(next) > 1) {
|
||||
TWO_NEWLINES
|
||||
} else {
|
||||
ForceLine
|
||||
mustForceLine()
|
||||
}
|
||||
}
|
||||
prev.type == NodeType.BLOCK_COMMENT -> if (prev.linesBetween(next) > 0) ForceLine else Space
|
||||
prev.type == NodeType.BLOCK_COMMENT ->
|
||||
if (prev.linesBetween(next) > 0) forceSpaceyLine() else Space
|
||||
next.type in EMPTY_SUFFIXES ||
|
||||
prev.isTerminal("[", "!", "@", "[[") ||
|
||||
next.isTerminal("]", "?", ",") -> null
|
||||
@@ -1098,6 +1148,30 @@ internal class Builder(sourceText: String) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun line(): FormatNode {
|
||||
return if (noNewlines) Empty else Line
|
||||
}
|
||||
|
||||
private fun spaceOrLine(): FormatNode {
|
||||
return if (noNewlines) Space else SpaceOrLine
|
||||
}
|
||||
|
||||
private fun mustForceLine(): FormatNode {
|
||||
return if (noNewlines) throw CannotAvoidNewline() else ForceLine
|
||||
}
|
||||
|
||||
private fun forceLine(): FormatNode {
|
||||
return if (noNewlines) Empty else ForceLine
|
||||
}
|
||||
|
||||
private fun forceSpaceyLine(): FormatNode {
|
||||
return if (noNewlines) Space else ForceLine
|
||||
}
|
||||
|
||||
private fun ifWrap(id: Int, ifWrap: FormatNode, ifNotWrap: FormatNode): FormatNode {
|
||||
return if (noNewlines) ifNotWrap else IfWrap(id, ifWrap, ifNotWrap)
|
||||
}
|
||||
|
||||
private fun hasTrailingAffix(node: Node, next: Node): Boolean {
|
||||
if (node.span.lineEnd < next.span.lineBegin) return false
|
||||
var n: Node? = next
|
||||
@@ -1201,8 +1275,8 @@ internal class Builder(sourceText: String) {
|
||||
|
||||
private class ImportComparator(private val source: CharArray) : Comparator<Node> {
|
||||
override fun compare(o1: Node, o2: Node): Int {
|
||||
val import1 = o1.findChildByType(NodeType.STRING_CONSTANT)?.text(source)
|
||||
val import2 = o2.findChildByType(NodeType.STRING_CONSTANT)?.text(source)
|
||||
val import1 = o1.findChildByType(NodeType.STRING_CHARS)?.text(source)
|
||||
val import2 = o2.findChildByType(NodeType.STRING_CHARS)?.text(source)
|
||||
if (import1 == null || import2 == null) {
|
||||
// should never happen
|
||||
throw RuntimeException("ImportComparator: not an import")
|
||||
@@ -1222,7 +1296,7 @@ internal class Builder(sourceText: String) {
|
||||
// returns true if this node is not an affix or terminal
|
||||
private fun Node.isProper(): Boolean = !type.isAffix && type != NodeType.TERMINAL
|
||||
|
||||
private fun <T> List<T>.splitOn(pred: (T) -> Boolean): Pair<List<T>, List<T>> {
|
||||
private inline fun <T> List<T>.splitOn(pred: (T) -> Boolean): Pair<List<T>, List<T>> {
|
||||
val index = indexOfFirst { pred(it) }
|
||||
return if (index == -1) {
|
||||
Pair(this, emptyList())
|
||||
@@ -1243,6 +1317,52 @@ internal class Builder(sourceText: String) {
|
||||
return false
|
||||
}
|
||||
|
||||
class PeekableIterator<T>(private val iterator: Iterator<T>) : Iterator<T> {
|
||||
private var peek: T? = null
|
||||
|
||||
private var hasPeek = false
|
||||
|
||||
override fun next(): T {
|
||||
return if (hasPeek) {
|
||||
hasPeek = false
|
||||
peek!!
|
||||
} else {
|
||||
iterator.next()
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return if (hasPeek) true else iterator.hasNext()
|
||||
}
|
||||
|
||||
fun peek(): T {
|
||||
if (!hasNext()) {
|
||||
throw NoSuchElementException()
|
||||
}
|
||||
if (hasPeek) {
|
||||
return peek!!
|
||||
}
|
||||
peek = iterator.next()
|
||||
hasPeek = true
|
||||
return peek!!
|
||||
}
|
||||
|
||||
inline fun takeUntilBefore(predicate: (T) -> Boolean): List<T> {
|
||||
return buildList {
|
||||
while (true) {
|
||||
if (!hasNext() || predicate(peek())) {
|
||||
return@buildList
|
||||
}
|
||||
add(next())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Iterator<T>.peekable(): PeekableIterator<T> {
|
||||
return PeekableIterator(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val ABSOLUTE_URL_REGEX = Regex("""\w+:.*""")
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.pkl.formatter
|
||||
|
||||
import org.pkl.formatter.ast.Empty
|
||||
import org.pkl.formatter.ast.ForceLine
|
||||
import org.pkl.formatter.ast.ForceWrap
|
||||
import org.pkl.formatter.ast.FormatNode
|
||||
import org.pkl.formatter.ast.Group
|
||||
import org.pkl.formatter.ast.IfWrap
|
||||
@@ -56,11 +55,6 @@ internal class Generator {
|
||||
}
|
||||
node.nodes.forEach { node(it, wrap) }
|
||||
}
|
||||
is ForceWrap -> {
|
||||
wrapped += node.id
|
||||
val wrap = Wrap.ENABLED
|
||||
node.nodes.forEach { node(it, wrap) }
|
||||
}
|
||||
is IfWrap -> {
|
||||
if (wrapped.contains(node.id)) {
|
||||
node(node.ifWrap, Wrap.ENABLED)
|
||||
|
||||
@@ -30,14 +30,14 @@ sealed interface FormatNode {
|
||||
is Nodes -> nodes.sumOf { it.width(wrapped) }
|
||||
is Group -> nodes.sumOf { it.width(wrapped) }
|
||||
is Indent -> nodes.sumOf { it.width(wrapped) }
|
||||
is ForceWrap -> nodes.sumOf { it.width(wrapped + id) }
|
||||
is IfWrap -> if (id in wrapped) ifWrap.width(wrapped) else ifNotWrap.width(wrapped)
|
||||
is Text -> text.length
|
||||
is SpaceOrLine,
|
||||
is Space -> 1
|
||||
is ForceLine,
|
||||
SpaceOrLine,
|
||||
Space -> 1
|
||||
ForceLine,
|
||||
is MultilineStringGroup -> Generator.MAX
|
||||
else -> 0
|
||||
Empty -> 0
|
||||
Line -> 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +59,6 @@ data class Nodes(val nodes: List<FormatNode>) : FormatNode
|
||||
|
||||
data class Group(val id: Int, val nodes: List<FormatNode>) : FormatNode
|
||||
|
||||
data class ForceWrap(val id: Int, val nodes: List<FormatNode>) : FormatNode
|
||||
|
||||
data class MultilineStringGroup(val endQuoteCol: Int, val nodes: List<FormatNode>) : FormatNode
|
||||
|
||||
data class IfWrap(val id: Int, val ifWrap: FormatNode, val ifNotWrap: FormatNode) : FormatNode
|
||||
|
||||
7
pkl-formatter/src/test/files/FormatterSnippetTests/input/single-line-strings.pkl
vendored
Normal file
7
pkl-formatter/src/test/files/FormatterSnippetTests/input/single-line-strings.pkl
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
foo1 = "some string"
|
||||
|
||||
foo2 = "some string with \( new { x = 1; y = 2 }) interpolation"
|
||||
|
||||
foo3 = "some reeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long string with \( new { x = 1; y = 2 } ) interpolation"
|
||||
|
||||
foo4 = "some reeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long string with \( foo.bar.baz() ) qualified access"
|
||||
51
pkl-formatter/src/test/files/FormatterSnippetTests/input/string-interpolation.pkl
vendored
Normal file
51
pkl-formatter/src/test/files/FormatterSnippetTests/input/string-interpolation.pkl
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
prop1 =
|
||||
"""
|
||||
asd \(new { bar = 1 }) asd
|
||||
"""
|
||||
|
||||
prop2 =
|
||||
"""
|
||||
\(let (bar = 15) bar + new { qux = 15 }.toString())
|
||||
"""
|
||||
|
||||
prop3 =
|
||||
"""
|
||||
\(new {
|
||||
// some comment
|
||||
foo = 1
|
||||
|
||||
// some comment
|
||||
bar = 2
|
||||
})
|
||||
"""
|
||||
|
||||
prop4 =
|
||||
"""
|
||||
\(1 + /* block comment */ 2)
|
||||
"""
|
||||
|
||||
prop5 =
|
||||
"""
|
||||
\("""
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
""")
|
||||
"""
|
||||
|
||||
prop6 = "\(// some line comment
|
||||
/* some block comment */
|
||||
"\("""
|
||||
one
|
||||
two
|
||||
three
|
||||
""")"
|
||||
// some line comment again
|
||||
)"
|
||||
|
||||
prop7 = "\(
|
||||
5
|
||||
// trailing line comment
|
||||
)"
|
||||
|
||||
prop8 = "\(new { foo = 1 bar = 2 baz = 3 })"
|
||||
@@ -1,8 +1,6 @@
|
||||
foo =
|
||||
"""
|
||||
asd \(new {
|
||||
bar = 1
|
||||
}) asd
|
||||
asd \(new { bar = 1 }) asd
|
||||
"""
|
||||
|
||||
bar =
|
||||
|
||||
9
pkl-formatter/src/test/files/FormatterSnippetTests/output/single-line-strings.pkl
vendored
Normal file
9
pkl-formatter/src/test/files/FormatterSnippetTests/output/single-line-strings.pkl
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
foo1 = "some string"
|
||||
|
||||
foo2 = "some string with \(new { x = 1; y = 2 }) interpolation"
|
||||
|
||||
foo3 =
|
||||
"some reeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long string with \(new { x = 1; y = 2 }) interpolation"
|
||||
|
||||
foo4 =
|
||||
"some reeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally long string with \(foo.bar.baz()) qualified access"
|
||||
52
pkl-formatter/src/test/files/FormatterSnippetTests/output/string-interpolation.pkl
vendored
Normal file
52
pkl-formatter/src/test/files/FormatterSnippetTests/output/string-interpolation.pkl
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
prop1 =
|
||||
"""
|
||||
asd \(new { bar = 1 }) asd
|
||||
"""
|
||||
|
||||
prop2 =
|
||||
"""
|
||||
\(let (bar = 15) bar + new { qux = 15 }.toString())
|
||||
"""
|
||||
|
||||
prop3 =
|
||||
"""
|
||||
\(new {
|
||||
// some comment
|
||||
foo = 1
|
||||
|
||||
// some comment
|
||||
bar = 2
|
||||
})
|
||||
"""
|
||||
|
||||
prop4 =
|
||||
"""
|
||||
\(1 + /* block comment */ 2)
|
||||
"""
|
||||
|
||||
prop5 =
|
||||
"""
|
||||
\("""
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
""")
|
||||
"""
|
||||
|
||||
prop6 =
|
||||
"\( // some line comment
|
||||
/* some block comment */
|
||||
"\("""
|
||||
one
|
||||
two
|
||||
three
|
||||
""")"
|
||||
// some line comment again
|
||||
)"
|
||||
|
||||
prop7 =
|
||||
"\(5
|
||||
// trailing line comment
|
||||
)"
|
||||
|
||||
prop8 = "\(new { foo = 1; bar = 2; baz = 3 })"
|
||||
Reference in New Issue
Block a user