From 9cfa98c4165be201653bbcb9bde725ec0d69116f Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Wed, 19 Aug 2020 19:13:56 +0300 Subject: [PATCH] Handle more tricky characters in deprecation message in ObjCExport --- .../objcexport/ObjCExportHeaderGenerator.kt | 20 +++++++++++++++++-- .../tests/objcexport/expectedLazy.h | 7 +++++++ backend.native/tests/objcexport/kt39206.kt | 5 ++++- backend.native/tests/objcexport/kt39206.swift | 5 +++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index b4f11958c9f..bf1bdb44f2b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -1234,7 +1234,23 @@ private fun Deprecation.toDeprecationAttribute(): String { // TODO: consider avoiding code generation for unavailable. val message = this.message.orEmpty() - .replace("\n", "\\n") - return "$attribute(\"$message\")" + return "$attribute(${quoteAsCStringLiteral(message)})" +} + +private fun quoteAsCStringLiteral(str: String): String = buildString { + append('"') + for (c in str) { + when (c) { + '\n' -> append("\\n") + + '\r' -> append("\\r") + + '"', '\\' -> append('\\').append(c) + + // TODO: handle more special cases. + else -> append(c) + } + } + append('"') } diff --git a/backend.native/tests/objcexport/expectedLazy.h b/backend.native/tests/objcexport/expectedLazy.h index b168322dcc9..126a4441c11 100644 --- a/backend.native/tests/objcexport/expectedLazy.h +++ b/backend.native/tests/objcexport/expectedLazy.h @@ -519,6 +519,13 @@ __attribute__((swift_name("JsonConfiguration"))) + (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("MoreTrickyChars"))) +@interface KtMoreTrickyChars : KtBase +- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((deprecated("'\"\\@$(){}\r\n"))); ++ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead"))); +@end; + __attribute__((objc_subclassing_restricted)) __attribute__((swift_name("Kt39206Kt"))) @interface KtKt39206Kt : KtBase diff --git a/backend.native/tests/objcexport/kt39206.kt b/backend.native/tests/objcexport/kt39206.kt index 50e4529b505..3f31038311e 100644 --- a/backend.native/tests/objcexport/kt39206.kt +++ b/backend.native/tests/objcexport/kt39206.kt @@ -11,4 +11,7 @@ fun myFunc() = 17 "Instead of storing JsonConfiguration instances of the code, Json instances can be used directly:" + "'Json(MyJsonConfiguration.copy(prettyPrint = true))' can be replaced with 'Json(from = MyApplicationJson) { prettyPrint = true }'" ) -public open class JsonConfiguration \ No newline at end of file +public open class JsonConfiguration + +@Deprecated("'\"\\@\$(){}\r\n") +class MoreTrickyChars \ No newline at end of file diff --git a/backend.native/tests/objcexport/kt39206.swift b/backend.native/tests/objcexport/kt39206.swift index bde00f72ea4..c186ede91a0 100644 --- a/backend.native/tests/objcexport/kt39206.swift +++ b/backend.native/tests/objcexport/kt39206.swift @@ -4,10 +4,15 @@ private func test1() throws { try assertEquals(actual: Kt39206Kt.myFunc(), expected: 17) } +private func test2() throws { + try assertTrue(MoreTrickyChars() as AnyObject is MoreTrickyChars) +} + class Kt39206Tests : SimpleTestProvider { override init() { super.init() test("Test1", test1) + test("Test2", test2) } } \ No newline at end of file