Forbid calling Objective-C initializers

These methods must not be used directly, construstors and factory
methods are provided instead
This commit is contained in:
Svyatoslav Scherbina
2018-11-23 16:44:37 +03:00
committed by SvyatoslavScherbina
parent 0f67da8298
commit ed323a98b5
3 changed files with 33 additions and 4 deletions
@@ -68,7 +68,7 @@ private val charactersAllowedInKotlinStringLiterals: Set<Char> = mutableSetOf<Ch
addAll('a' .. 'z')
addAll('A' .. 'Z')
addAll('0' .. '9')
addAll(listOf('_', '@', ':', ';', '.', ',', '{', '}', '=', '[', ']', '^', '#', '*', ' '))
addAll(listOf('_', '@', ':', ';', '.', ',', '{', '}', '=', '[', ']', '^', '#', '*', ' ', '(', ')'))
}
fun block(header: String, lines: Iterable<String>) = block(header, lines.asSequence())
@@ -86,6 +86,14 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator,
when (container) {
is ObjCClass -> {
result.add(0,
deprecatedInit(
container.kotlinClassName(method.isClass),
kotlinParameters.map { it.name },
factory = false
)
)
// TODO: consider generating non-designated initializers as factories.
val designated = isDesignatedInitializer ||
stubGenerator.configuration.disableDesignatedInitializerChecks
@@ -95,13 +103,20 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator,
result.add("constructor($parameters) {}")
}
is ObjCCategory -> {
assert(!method.isClass)
val tBound = stubGenerator.declarationMapper
val className = stubGenerator.declarationMapper
.getKotlinClassFor(container.clazz, isMeta = false).type
.render(kotlinScope)
result.add(0,
deprecatedInit(
className,
kotlinParameters.map { it.name },
factory = true
)
)
// TODO: add support for type parameters to [KotlinType] etc.
val receiver = kotlinScope.reference(KotlinTypes.objCClassOf) + "<T>"
@@ -115,7 +130,7 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator,
result.add("")
result.add("@ObjCFactory".applyToStrings(bridgeName))
result.add("external fun <T : $tBound> $receiver.create($parameters): $returnType")
result.add("external fun <T : $className> $receiver.create($parameters): $returnType")
}
is ObjCProtocol -> {} // Nothing to do.
}
@@ -274,6 +289,19 @@ class ObjCMethodStub(private val stubGenerator: StubGenerator,
}
}
private fun deprecatedInit(className: String, initParameterNames: List<String>, factory: Boolean): String {
val replacement = if (factory) "$className.create" else className
val replacementKind = if (factory) "factory method" else "constructor"
val replaceWith = "$replacement(${initParameterNames.joinToString()})"
return deprecated("Use $replacementKind instead", replaceWith)
}
private fun deprecated(message: String, replaceWith: String): String =
"@Deprecated(${message.quoteAsKotlinLiteral()}, " +
"ReplaceWith(${replaceWith.quoteAsKotlinLiteral()}), " +
"DeprecationLevel.ERROR)"
private val ObjCContainer.classOrProtocol: ObjCClassOrProtocol
get() = when (this) {
is ObjCClassOrProtocol -> this
@@ -925,6 +925,7 @@ class StubGenerator(
add("EXTENSION_SHADOWED_BY_MEMBER") // For Objective-C categories represented as extensions.
add("REDUNDANT_NULLABLE") // This warning appears due to Obj-C typedef nullability incomplete support.
add("DEPRECATION") // For uncheckedCast.
add("DEPRECATION_ERROR") // For initializers.
}
}