square / kotlinpoet

A Kotlin API for generating .kt source files.
https://square.github.io/kotlinpoet/
Apache License 2.0
3.88k stars 286 forks source link

Wrapped comments are missing the \\ prefix #1922

Open dalewking opened 3 months ago

dalewking commented 3 months ago

Describe the bug When adding a comment that has long text that is long enough to wrap, additional lines are indented and do not have the \ at the beginning

To Reproduce

val reallyLongLine = "This is a really long line of text that will have to be wrapped when it is used in a comment because it is so long"

someFileSpec.addFileComment("%L", reallyLongLine)

which produces this file comment:

// This is a really long line of text that will have to be wrapped when it is used in a comment
        because it is so long

Expected behavior It should produce this file comment:

// This is a really long line of text that will have to be wrapped when it is used in a comment
// because it is so long

Additional context I believe the issue are these 2 lines, which should probably be something more like this:

          indentLevel = if (kdoc || comment) indentLevel else indentLevel + 2,
          linePrefix = if (kdoc) " * " else if (comment) "// " else "",
dalewking commented 3 months ago

I verified the proposed change does fix it for file comments, but does not work for general comments in code.

Here are some unit tests (added to LineWrappingTest). The second one passes with the suggested change but the first one does not because comment is not set.

  private val longCommentText = """
    A really long string to verify that comments that wrap to the next line
    are properly indented and begin with the comment prefix on each line
  """.trim().replace("\\s+".toRegex(), " ")

  @Test fun commentsWrapWithPrefixOnEachLine() {
    val wrapMe = FunSpec.builder("wrapMe")
      .returns(STRING)
      .addComment("%L", longCommentText)
      .build()
    assertThat(toString(wrapMe)).isEqualTo(
      """
        |package com.squareup.tacos
        |
        |import kotlin.String
        |
        |public fun wrapMe(): String =
        |    // A really long string to verify that comments that wrap to the next line are properly indented
        |    // and begin with the comment prefix on each line
        |
      """.trimMargin(),
    )
  }

  @Test fun fileCommentsWrapWithPrefixOnEachLine() {
    val wrapMe = FileSpec.builder("com.squareup.tacos", "WrapMe.kt")
      .addFileComment("%L", longCommentText)
      .build()
    assertThat(wrapMe.toString()).isEqualTo(
      """
        |// A really long string to verify that comments that wrap to the next line are properly indented and
        |// begin with the comment prefix on each line
        |package com.squareup.tacos
        |
        |
      """.trimMargin(),
    )
  }
dalewking commented 3 months ago

Fixing it for within functions will be a much bigger job. Right now a CodeBlock has no idea that what you are adding is a comment after it is added. It is just adding text. To fix it would probably involve creating something like a CommentBlock that share some common functionality with CodeBlock and that is more work than I am signing up for.

dalewking commented 3 months ago

Fixing it for within functions will be a much bigger job. Right now a CodeBlock has no idea that what you are adding is a comment after it is added. It is just adding text. To fix it would probably involve creating something like a CommentBlock that share some common functionality with CodeBlock and that is more work than I am signing up for.

Though it might be possible to do it by adding no-arg placeholders to indicate the start of comments and one to indicate the end of comments. When it sees the start one it turns on trailingNewline and comment in the Codewriter and turns them off when it sees the end one

Egorand commented 3 months ago

I think it would be enough to fix this for comment-specific API only (like addComment and addFileComment). A possible workaround for comments added as part of method bodies is to use the non-wrapping space modifier (·) so that the comment is printed in a single line - not ideal, but I'm not sure what the use case for this is over using addComment.

dalewking commented 3 months ago

In my case i was only adding file comments, but in trying to submit a PR I was testing both cases

Egorand commented 3 months ago

Please feel free to submit separate PRs, or fix only a subset of the affected APIs!