diff --git a/core/src/main/java/com/facebook/ktfmt/KotlinInputAstVisitor.kt b/core/src/main/java/com/facebook/ktfmt/KotlinInputAstVisitor.kt index 6d5ac476..b890a34b 100644 --- a/core/src/main/java/com/facebook/ktfmt/KotlinInputAstVisitor.kt +++ b/core/src/main/java/com/facebook/ktfmt/KotlinInputAstVisitor.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtAnnotatedExpression import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.kotlin.psi.KtAnnotationEntry +import org.jetbrains.kotlin.psi.KtAnnotationUseSiteTarget import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS @@ -1159,13 +1160,42 @@ class KotlinInputAstVisitor( } } + /** For example, @field:[Inject Named("WEB_VIEW")] */ + override fun visitAnnotation(annotation: KtAnnotation) { + builder.sync(annotation) + builder.block(ZERO) { + builder.token("@") + annotation.useSiteTarget?.accept(this) + builder.token(":") + builder.block(expressionBreakIndent) { + builder.token("[") + forEachCommaSeparated( + annotation.entries, + delimiter = { builder.breakOp(Doc.FillMode.INDEPENDENT, " ", ZERO) }, + function = { it.accept(this) }) + } + builder.token("]") + } + builder.forcedBreak() + } + + /** For example, 'field' in @field:[Inject Named("WEB_VIEW")] */ + override fun visitAnnotationUseSiteTarget( + annotationTarget: KtAnnotationUseSiteTarget, data: Void? + ): Void? { + builder.token(annotationTarget.getAnnotationUseSiteTarget().renderName) + return null + } + /** For example `@Magic` or `@Fred(1, 5)` */ override fun visitAnnotationEntry(annotationEntry: KtAnnotationEntry) { builder.sync(annotationEntry) - builder.token("@") - val useSiteTarget = annotationEntry.useSiteTarget?.getAnnotationUseSiteTarget() - if (useSiteTarget != null) { - builder.token(useSiteTarget.renderName) + if (annotationEntry.atSymbol != null) { + builder.token("@") + } + val useSiteTarget = annotationEntry.useSiteTarget + if (useSiteTarget != null && useSiteTarget.parent == annotationEntry) { + useSiteTarget.accept(this) builder.token(":") } visitCallElement( diff --git a/core/src/test/java/com/facebook/ktfmt/FormatterKtTest.kt b/core/src/test/java/com/facebook/ktfmt/FormatterKtTest.kt index 7fa98be8..28cf1666 100644 --- a/core/src/test/java/com/facebook/ktfmt/FormatterKtTest.kt +++ b/core/src/test/java/com/facebook/ktfmt/FormatterKtTest.kt @@ -2084,6 +2084,24 @@ class FormatterKtTest { |""".trimMargin(), deduceMaxWidth = true) + @Test + fun `handle multi-annotations with use-site targets`() = + assertFormatted( + """ + |class Something { + | @field:[Inject Named("WEB_VIEW")] + | internal lateinit var httpClient: OkHttpClient + | + | @field:[Inject Named("WEB_VIEW")] + | var httpClient: OkHttpClient + | + | @Px + | @field:[Inject Named("WEB_VIEW")] + | var httpClient: OkHttpClient + |} + | + """.trimMargin()) + @Test fun `handle lambda types`() = assertFormatted(