Skip to content

Commit

Permalink
Fix lambda expressions with no parameters and blocks as right side ex…
Browse files Browse the repository at this point in the history
…pressions
  • Loading branch information
jkschneider committed Feb 2, 2017
1 parent 438623b commit ddfdaa8
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
2 changes: 1 addition & 1 deletion rewrite/src/main/kotlin/com/netflix/rewrite/ast/Tree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ sealed class Tr : Serializable, Tree {
data class Arrow(override val formatting: Formatting = Formatting.Empty, override val id: Long = id()): Tr()

data class Parameters(val parenthesized: Boolean,
val params: List<VariableDecls>,
val params: List<Tree>, // Tr.VariableDecls or Tr.Empty
override val formatting: Formatting = Formatting.Empty,
override val id: Long = id()): Tr()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class TransformVisitor(val transformations: Iterable<AstTransform<*>>) : AstVisi
}

override fun visitLambda(lambda: Tr.Lambda): Tree {
val params = lambda.paramSet.params.mapIfNecessary { visit(it) as Tr.VariableDecls }
val params = lambda.paramSet.params.mapIfNecessary { visit(it) as Tree }
val paramSet = if(params !== lambda.paramSet.params) {
lambda.paramSet.copy(params = params)
} else lambda.paramSet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,12 +468,34 @@ class OracleJdkParserVisitor(val path: Path, val source: String): TreePathScanne
override fun visitLambdaExpression(node: LambdaExpressionTree, fmt: Formatting.Reified): Tree {
val parenthesized = source[cursor] == '('
skip("(")

val paramList = if(parenthesized && node.parameters.isEmpty()) {
listOf(Tr.Empty(format(sourceBefore(")"))))
} else {
node.parameters.convertAll(COMMA_DELIM, { if (parenthesized) sourceBefore(")") else "" })
}

val params = Tr.Lambda.Parameters(parenthesized, paramList)
val arrow = Tr.Lambda.Arrow(format(sourceBefore("->")))

val body = when(node.body) {
is JCTree.JCBlock -> {
// This compensates for a bug in the Oracle AST in which the startPos of JCBlock statements
// that are on the right side of lambda expressions evaluates at the start of the lambda expression.
// All other AST elements that can occur at the right side of lambda expressions correctly evluate startPos
// after the arrow.
val prefix = sourceBefore("{")
cursor--
val blockBody = node.body.convert<Tr.Block<*>>()
blockBody.changeFormatting(blockBody.formatting.withPrefix(prefix))
}
else -> node.body.convert<Tree>()
}

return Tr.Lambda(
Tr.Lambda.Parameters(parenthesized, node.parameters.convertAll(COMMA_DELIM, {
if(parenthesized) sourceBefore(")") else ""
})),
Tr.Lambda.Arrow(format(sourceBefore("->"))),
node.body.convert(),
params,
arrow,
body,
node.type(),
fmt
)
Expand Down
16 changes: 16 additions & 0 deletions rewrite/src/test/kotlin/com/netflix/rewrite/ast/LambdaTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,20 @@ abstract class LambdaTest(p: Parser): Parser by p {
assertEquals("list.stream().filter((s) -> s.isEmpty())",
a.classes[0].methods()[0].body!!.statements[0].printTrimmed())
}

@Test
fun lambdaWithBlock() {
val a = parse("""
public class A {
Action a = ( ) -> { };
}
interface Action {
void call();
}
""")

val lambda = a.classes[0].fields()[0].vars[0].initializer!!
assertEquals("( ) -> { }", lambda.printTrimmed())
}
}

0 comments on commit ddfdaa8

Please sign in to comment.