3

Straightforward; is there a way to generate a valid Kotlin string literal (non-raw, as in non-triple-quote) from a string; I'm currently trying to accomplish this with KotlinPoet.

For clarity sake, example input:

Hello, how are you?
I'm doing "great"!
I hope you are too!
It'll cost you $2.

Desired example output:

"Hello, how are you?\nI'm doing \"great\"!\nI hope you are too!\nIt'll cost you \$2."

With KotlinPoet, the best I can manage from the API I've learned thus far is:

"""
|Hello, how are you?
|I'm doing "great"!
|I hope you are too!
|It'll cost you ${'$'}2.
|""".trimMargin()

Which, while functional, is not what I'm trying to achieve.


I've been able to accomplish something functionally close, with Jackson's ObjectMapper::writeValueAsString, however, I'm sure there's plenty of caveats with using this to generate valid Kotlin code.

Dan Lugg
  • 20,192
  • 19
  • 110
  • 174

1 Answers1

1

Unfortunately, the relevant function in KotlinPoet is internal, or you could just call it with isConstantContext = true as in this test.

So as a workaround, you can put the string in a constant context, such as const val x = ... or @A(...) (where ... is your string), generate code for it and then remove everything but the literal.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • 2
    KotlinPoet doesn't expose that function in the API on purpose cause that functionality is outside of the scope of the library. Since it's open source though, it's totally fine to just copy the code into your codebase and use it. – Egor Feb 19 '20 at 15:23
  • Well, I think one could argue that generating string literals *is* within the scope of a library for code generation (at least on the utility side), but I can understand internalizing that API. Nevertheless, thanks @AlexeyRomanov for you answer. I'm not tied to using KotlinPoet (though it supports other things I may need) -- if you have any non-KotlinPoet recommendations, I'm all ears. – Dan Lugg Feb 19 '20 at 15:42
  • Just to follow up; I compared the EBNF of JSON/Kotlin for strings, and as they’re similar enough, escaping `$` in the resulting JSON string seems to cover all but 0.1% of edge cases. I’m leaving it for now (as I have an `ObjectMapper` in scope where this is done anyway) but I’ll likely have to “borrow” the internal KotlinPoet function in the future. – Dan Lugg Mar 12 '20 at 21:29