From 231455576dc6fbd8ea8cfe04a18fec755ba4dce1 Mon Sep 17 00:00:00 2001 From: Jon Schneider Date: Mon, 6 Feb 2017 13:46:59 -0800 Subject: [PATCH] Fix optional empty parentheses after annotation with no parameters --- .../rewrite/parse/OracleJdkParserVisitor.kt | 16 +++++++++++++--- .../com/netflix/rewrite/ast/AnnotationTest.kt | 12 ++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/rewrite-core/src/main/kotlin/com/netflix/rewrite/parse/OracleJdkParserVisitor.kt b/rewrite-core/src/main/kotlin/com/netflix/rewrite/parse/OracleJdkParserVisitor.kt index b94894f..4dcd9cf 100644 --- a/rewrite-core/src/main/kotlin/com/netflix/rewrite/parse/OracleJdkParserVisitor.kt +++ b/rewrite-core/src/main/kotlin/com/netflix/rewrite/parse/OracleJdkParserVisitor.kt @@ -73,7 +73,17 @@ class OracleJdkParserVisitor(val path: Path, val source: String): TreePathScanne } Tr.Annotation.Arguments(args, format(argsPrefix)) - } else null + } else { + val remaining = source.substring(cursor, node.endPos()) + + // NOTE: technically, if there is code like this, we have a bug, but seems exceedingly unlikely: + // @MyAnnotation /* Comment () that contains parentheses */ () + + if(remaining.contains("(") && remaining.contains(")")) { + val parenPrefix = sourceBefore("(") + Tr.Annotation.Arguments(listOf(Tr.Empty(format(sourceBefore(")")))), format(parenPrefix)) + } else null + } return Tr.Annotation(name, args, node.type(), fmt) } @@ -1178,7 +1188,7 @@ class OracleJdkParserVisitor(val path: Path, val source: String): TreePathScanne * and if not found in the remaining source, the empty String. If stop is reached before * untilDelim return the empty String. */ - private fun sourceBefore(untilDelim: String, stop: Char? = null): String { + private fun sourceBefore(untilDelim: String, stop: Char? = null, stopIndex: Int? = null): String { val delimIndex = positionOfNext(untilDelim, stop) if(delimIndex < 0) { return "" // unable to find this delimiter @@ -1189,7 +1199,7 @@ class OracleJdkParserVisitor(val path: Path, val source: String): TreePathScanne return prefix } - private fun positionOfNext(untilDelim: String, stop: Char? = null): Int { + private fun positionOfNext(untilDelim: String, stop: Char? = null, stopIndex: Int? = null): Int { var delimIndex = cursor var inMultiLineComment = false var inSingleLineComment = false diff --git a/rewrite-core/src/test/kotlin/com/netflix/rewrite/ast/AnnotationTest.kt b/rewrite-core/src/test/kotlin/com/netflix/rewrite/ast/AnnotationTest.kt index 2f8c29f..14d3e13 100644 --- a/rewrite-core/src/test/kotlin/com/netflix/rewrite/ast/AnnotationTest.kt +++ b/rewrite-core/src/test/kotlin/com/netflix/rewrite/ast/AnnotationTest.kt @@ -46,6 +46,18 @@ abstract class AnnotationTest(p: Parser): Parser by p { assertEquals("@SuppressWarnings(\"ALL\")", ann.printTrimmed()) } + @Test + fun preserveOptionalEmptyParentheses() { + val a = parse(""" + |@Deprecated ( ) + |public class A {} + """) + + val ann = a.classes[0].annotations[0] + + assertEquals("@Deprecated ( )", ann.printTrimmed()) + } + @Test fun default() { val a = parse("""