Skip to content

Commit

Permalink
fix: does not remove non-redundant parentheses
Browse files Browse the repository at this point in the history
  • Loading branch information
shouwn committed Oct 29, 2023
1 parent da5115f commit d2cbb65
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,21 @@ interface JpqlWriter {
*
* @param iterable The elements to write.
* @param separator It is inserted between each element.
* @param prefix It is inserted before the first element.
* @param postfix It is inserted after the last element.
* @param write It is called for each element.
*/
@SinceJdsl("3.0.0")
fun <T> writeEach(
iterable: Iterable<T>,
separator: String = ", ",
prefix: String = "",
postfix: String = "",
write: (T) -> Unit,
)

/**
* Writes parentheses.
* They are only written once if they are redundant.
* For example, the ((value)) is written as (value).
*
* Redundant parentheses added manually by [write] or [writeIfAbsent] can be written repeatedly.
*/
@SinceJdsl("3.0.0")
fun writeParentheses(inner: () -> Unit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,31 @@ internal class DefaultJpqlWriter private constructor(
) : JpqlWriter {
constructor(params: Map<String, Any?>) : this(InternalJpqlWriter(params))

private var nodes: Nodes = Nodes()

override fun write(string: String) {
internal.write(string)
nodes.add(Node.String())
}

override fun writeIfAbsent(string: String) {
internal.writeIfAbsent(string)
if (!internal.stringBuilder.endsWith(string)) {
write(string)
}
}

override fun <T> writeEach(
iterable: Iterable<T>,
separator: String,
prefix: String,
postfix: String,
write: (T) -> Unit,
) {
write(prefix)

for ((index, element) in iterable.withIndex()) {
if (index > 0) {
write(separator)
}

write(element)
}

write(postfix)
}

override fun writeParentheses(inner: () -> Unit) {
Expand All @@ -42,12 +41,27 @@ internal class DefaultJpqlWriter private constructor(

internal = innerWriter

val parentheses = Node.Parentheses()

val open = parentheses.open
nodes.add(open)

inner()

val close = parentheses.close
nodes.add(close)

val nextOfOpen = open.next
val previousOfClose = close.previous

val innerQuery = innerWriter.stringBuilder.toString()
val innerParams = innerWriter.params

if (innerQuery.startsWith("(") && innerQuery.endsWith(")")) {
if (
nextOfOpen is Node.Parenthesis &&
previousOfClose is Node.Parenthesis &&
nextOfOpen.isSibling(previousOfClose)
) {
originWriter.write(innerQuery)
} else {
originWriter.write("(")
Expand Down Expand Up @@ -75,6 +89,44 @@ internal class DefaultJpqlWriter private constructor(
fun getParams(): JpqlRenderedParams {
return JpqlRenderedParams(internal.params)
}

private class Nodes {
private var current: Node = Node.Null()

fun add(node: Node) {
current.let {
it.next = node
node.previous = it
}

current = node
}
}

private abstract class Node {
var previous: Node? = null
var next: Node? = null

class Null : Node()

class String : Node()

class Parentheses {
val open: OpenParenthesis = OpenParenthesis(this)
val close: CloseParenthesis = CloseParenthesis(this)
}

abstract class Parenthesis(
private val parentheses: Parentheses,
) : Node() {
fun isSibling(other: Parenthesis): Boolean {
return this.parentheses == other.parentheses
}
}

class OpenParenthesis(parentheses: Parentheses) : Parenthesis(parentheses)
class CloseParenthesis(parentheses: Parentheses) : Parenthesis(parentheses)
}
}

private class InternalJpqlWriter(
Expand All @@ -93,12 +145,6 @@ private class InternalJpqlWriter(
stringBuilder.append(string)
}

fun writeIfAbsent(string: String) {
if (!stringBuilder.endsWith(string)) {
stringBuilder.append(string)
}
}

fun writeParam(value: Any?) {
val name = "param${incrementer.getNext()}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class JpqlAndSerializerTest : WithAssertions {

// then
verifySequence {
writer.writeEach(predicates, " AND ", "", "", any())
writer.writeEach(predicates, " AND ", any())
serializer.serialize(predicate1, writer, context)
serializer.serialize(predicate2, writer, context)
serializer.serialize(predicate3, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class JpqlCaseValueSerializerTest : WithAssertions {
writer.write(" ")
serializer.serialize(stringPath1, writer, context)
writer.write(" ")
writer.writeEach(expressionAndExpressions.entries, " ", "", "", any())
writer.writeEach(expressionAndExpressions.entries, " ", any())
writer.write("WHEN")
writer.write(" ")
serializer.serialize(stringExpression1, writer, context)
Expand Down Expand Up @@ -108,7 +108,7 @@ class JpqlCaseValueSerializerTest : WithAssertions {
writer.write(" ")
serializer.serialize(stringPath1, writer, context)
writer.write(" ")
writer.writeEach(expressionAndExpressions.entries, " ", "", "", any())
writer.writeEach(expressionAndExpressions.entries, " ", any())
writer.write("WHEN")
writer.write(" ")
serializer.serialize(stringExpression1, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class JpqlCaseWhenSerializerTest : WithAssertions {
verifySequence {
writer.write("CASE")
writer.write(" ")
writer.writeEach(predicateAndExpressions.entries, " ", "", "", any())
writer.writeEach(predicateAndExpressions.entries, " ", any())
writer.write("WHEN")
writer.write(" ")
serializer.serialize(predicate1, writer, context)
Expand Down Expand Up @@ -101,7 +101,7 @@ class JpqlCaseWhenSerializerTest : WithAssertions {
verifySequence {
writer.write("CASE")
writer.write(" ")
writer.writeEach(predicateAndExpressions.entries, " ", "", "", any())
writer.writeEach(predicateAndExpressions.entries, " ", any())
writer.write("WHEN")
writer.write(" ")
serializer.serialize(predicate1, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class JpqlCoalesceSerializerTest : WithAssertions {
verifySequence {
writer.write("COALESCE")
writer.writeParentheses(any())
writer.writeEach(listOf(expression1, expression2, expression3), ", ", "", "", any())
writer.writeEach(listOf(expression1, expression2, expression3), ", ", any())
serializer.serialize(expression1, writer, context)
serializer.serialize(expression2, writer, context)
serializer.serialize(expression3, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class JpqlFunctionSerializerTest : WithAssertions {
writer.write(functionName1)
writer.write(",")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(expression1, writer, context)
serializer.serialize(expression2, writer, context)
serializer.serialize(expression3, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class JpqlInSerializerTest : WithAssertions {
writer.write("IN")
writer.write(" ")
writer.writeParentheses(any())
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(expression2, writer, context)
serializer.serialize(expression3, writer, context)
serializer.serialize(expression4, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class JpqlNewSerializerTest : WithAssertions {
writer.write(" ")
writer.write(Row::class.java.name)
writer.writeParentheses(any())
writer.writeEach(expressions, separator = ", ", prefix = "", postfix = "", any())
writer.writeEach(expressions, separator = ", ", any())
serializer.serialize(expression1, writer, context)
serializer.serialize(expression2, writer, context)
}
Expand All @@ -86,7 +86,7 @@ class JpqlNewSerializerTest : WithAssertions {
writer.write(" ")
writer.write(Row::class.java.name)
writer.writeParentheses(any())
writer.writeEach(emptyList<Expression<*>>(), separator = ", ", prefix = "", postfix = "", any())
writer.writeEach(emptyList<Expression<*>>(), separator = ", ", any())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class JpqlNotInSerializerTest : WithAssertions {
writer.write("NOT IN")
writer.write(" ")
writer.writeParentheses(any())
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(expression2, writer, context)
serializer.serialize(expression3, writer, context)
serializer.serialize(expression4, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class JpqlOrSerializerTest : WithAssertions {

// then
verifySequence {
writer.writeEach(predicates, " OR ", "", "", any())
writer.writeEach(predicates, " OR ", any())
serializer.serialize(predicate1, writer, context)
serializer.serialize(predicate2, writer, context)
serializer.serialize(predicate3, writer, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
verifySequence {
writer.write("SELECT")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -94,7 +94,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand Down Expand Up @@ -138,7 +138,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("DISTINCT")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -152,7 +152,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand Down Expand Up @@ -195,7 +195,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
verifySequence {
writer.write("SELECT")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -209,7 +209,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand Down Expand Up @@ -265,7 +265,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
verifySequence {
writer.write("SELECT")
writer.write(" ")
writer.writeEach(expressions1, ", ", "", "", any())
writer.writeEach(expressions1, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -279,7 +279,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand All @@ -293,7 +293,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("GROUP BY")
writer.write(" ")
writer.writeEach(expressions2, ", ", "", "", any())
writer.writeEach(expressions2, ", ", any())
serializer.serialize(
expression3,
writer,
Expand Down Expand Up @@ -336,7 +336,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
verifySequence {
writer.write("SELECT")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -350,7 +350,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand Down Expand Up @@ -406,7 +406,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
verifySequence {
writer.write("SELECT")
writer.write(" ")
writer.writeEach(expressions, ", ", "", "", any())
writer.writeEach(expressions, ", ", any())
serializer.serialize(
expression1,
writer,
Expand All @@ -420,7 +420,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("FROM")
writer.write(" ")
writer.writeEach(entities, separator = ", ", "", "", any())
writer.writeEach(entities, separator = ", ", any())
serializer.serialize(
entity1,
writer,
Expand All @@ -434,7 +434,7 @@ class JpqlSelectQuerySerializerTest : WithAssertions {
writer.write(" ")
writer.write("ORDER BY")
writer.write(" ")
writer.writeEach(sorts, ", ", "", "", any())
writer.writeEach(sorts, ", ", any())
serializer.serialize(
sort1,
writer,
Expand Down
Loading

0 comments on commit d2cbb65

Please sign in to comment.