[ObjCExport] Constructors fixes, cloneables handling, annotations
This commit is contained in:
committed by
Space Team
parent
545753ff4c
commit
0ec9f2a8b9
+1
-1
@@ -47,7 +47,7 @@ context(KtAnalysisSession)
|
||||
private val KtCallableSymbol.receiverType: MethodBridgeReceiver
|
||||
get() = if (isArrayConstructor) {
|
||||
MethodBridgeReceiver.Factory
|
||||
} else if (isTopLevel) {
|
||||
} else if (!isConstructor && isTopLevel) {
|
||||
MethodBridgeReceiver.Static
|
||||
} else {
|
||||
MethodBridgeReceiver.Instance
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.jetbrains.kotlin.objcexport.analysisApiUtils
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotated
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
private val ExportForCompilerAnnotationClassId = ClassId.topLevel(FqName("kotlin.native.internal.ExportForCompiler"))
|
||||
|
||||
/**
|
||||
* [kotlin.native.internal.ExportForCompiler] is an internal compiler annotation. Annotated symbols must not be exposed.
|
||||
*/
|
||||
internal val KtAnnotated.hasExportForCompilerAnnotation: Boolean
|
||||
get() {
|
||||
return this.hasAnnotation(ExportForCompilerAnnotationClassId)
|
||||
}
|
||||
+29
@@ -1,8 +1,28 @@
|
||||
package org.jetbrains.kotlin.objcexport.analysisApiUtils
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
context(KtAnalysisSession)
|
||||
internal val KtDeclarationSymbol?.implementsCloneable: Boolean
|
||||
get() {
|
||||
return (this as? KtClassOrObjectSymbol)?.implementsCloneable ?: false
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
internal val KtClassOrObjectSymbol.implementsCloneable: Boolean
|
||||
get() {
|
||||
return superTypes.any {
|
||||
it.expandedClassSymbol?.isCloneable ?: false
|
||||
}
|
||||
}
|
||||
|
||||
internal val KtClassOrObjectSymbol.isCloneable: Boolean
|
||||
get() {
|
||||
@@ -12,4 +32,13 @@ internal val KtClassOrObjectSymbol.isCloneable: Boolean
|
||||
internal val ClassId.isCloneable: Boolean
|
||||
get() {
|
||||
return asSingleFqName() == StandardNames.FqNames.cloneable.toSafe()
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
internal val KtFunctionSymbol.isClone: Boolean
|
||||
get() {
|
||||
val cloneCallableId = CallableId(StandardClassIds.Cloneable, Name.identifier("clone"))
|
||||
if (this.callableIdIfNonLocal == cloneCallableId) return true
|
||||
|
||||
return this.getAllOverriddenSymbols().any { it.callableIdIfNonLocal == cloneCallableId }
|
||||
}
|
||||
+4
-2
@@ -8,11 +8,12 @@ import org.jetbrains.kotlin.analysis.api.symbols.nameOrAnonymous
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.hasExportForCompilerAnnotation
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
fun KtClassOrObjectSymbol.translateToObjCClass(): ObjCClass? {
|
||||
require(classKind == KtClassKind.CLASS)
|
||||
require(classKind == KtClassKind.CLASS || classKind == KtClassKind.ENUM_CLASS)
|
||||
if (!isVisibleInObjC()) return null
|
||||
|
||||
val enumKind = this.classKind == KtClassKind.ENUM_CLASS
|
||||
@@ -26,8 +27,9 @@ fun KtClassOrObjectSymbol.translateToObjCClass(): ObjCClass? {
|
||||
|
||||
val superClass = translateSuperClass()
|
||||
val superProtocols: List<String> = superProtocols()
|
||||
val constructors = getMemberScope().getConstructors().filter { !it.hasExportForCompilerAnnotation }
|
||||
|
||||
val members: List<ObjCExportStub> = getMemberScope().getCallableSymbols().plus(getMemberScope().getConstructors())
|
||||
val members: List<ObjCExportStub> = getMemberScope().getCallableSymbols().plus(constructors)
|
||||
.sortedWith(StableCallableOrder)
|
||||
.flatMap { it.translateToObjCExportStubs() }
|
||||
.toList()
|
||||
|
||||
+6
-4
@@ -6,9 +6,7 @@
|
||||
package org.jetbrains.kotlin.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
@@ -97,12 +95,16 @@ private fun renderAnnotation(clazz: ClassId, arguments: List<KtNamedAnnotationVa
|
||||
append(clazz.asSingleFqName())
|
||||
if (arguments.isNotEmpty()) {
|
||||
append('(')
|
||||
arguments.joinTo(this)
|
||||
arguments.joinTo(this) { arg -> arg.render() }
|
||||
append(')')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtNamedAnnotationValue.render(): String {
|
||||
return "$name=${expression.renderAsSourceCode()}"
|
||||
}
|
||||
|
||||
/**
|
||||
* Not implemented [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportTranslatorImpl.getEffectiveThrows]
|
||||
*/
|
||||
|
||||
+43
-11
@@ -4,6 +4,9 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCInstanceType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCMethod
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCParameter
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCRawType
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isArrayConstructor
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
|
||||
context(KtAnalysisSession, KtObjCExportSession)
|
||||
@@ -13,19 +16,48 @@ fun KtConstructorSymbol.translateToObjCConstructors(): List<ObjCMethod> {
|
||||
|
||||
result.add(buildObjCMethod())
|
||||
|
||||
result.add(
|
||||
ObjCMethod(
|
||||
comment = null,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
isInstanceMethod = false,
|
||||
returnType = ObjCInstanceType,
|
||||
selectors = listOf("new"),
|
||||
parameters = emptyList(),
|
||||
attributes = listOf(
|
||||
"availability(swift, unavailable, message=\"use object initializers instead\")"
|
||||
if (isArrayConstructor) {
|
||||
|
||||
result.add(
|
||||
ObjCMethod(
|
||||
comment = null,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
isInstanceMethod = false,
|
||||
returnType = ObjCInstanceType,
|
||||
selectors = listOf("alloc"),
|
||||
parameters = emptyList(),
|
||||
attributes = listOf("unavailable")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
result.add(
|
||||
ObjCMethod(
|
||||
comment = null,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
isInstanceMethod = false,
|
||||
returnType = ObjCInstanceType,
|
||||
selectors = listOf("allocWithZone:"),
|
||||
parameters = listOf(ObjCParameter("zone", null, ObjCRawType("struct _NSZone *"), null)),
|
||||
attributes = listOf("unavailable")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (result.size == 1 && result.first().name == "init") {
|
||||
result.add(
|
||||
ObjCMethod(
|
||||
comment = null,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
isInstanceMethod = false,
|
||||
returnType = ObjCInstanceType,
|
||||
selectors = listOf("new"),
|
||||
parameters = emptyList(),
|
||||
attributes = listOf(
|
||||
"availability(swift, unavailable, message=\"use object initializers instead\")"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
+1
@@ -51,6 +51,7 @@ fun translateToObjCHeader(files: List<KtFile>): ObjCHeader {
|
||||
KtClassKind.INTERFACE -> symbol.translateToObjCProtocol()
|
||||
KtClassKind.CLASS -> symbol.translateToObjCClass()
|
||||
KtClassKind.OBJECT -> symbol.translateToObjCObject()
|
||||
KtClassKind.ENUM_CLASS -> symbol.translateToObjCClass()
|
||||
else -> return result
|
||||
} ?: return result
|
||||
|
||||
|
||||
+5
-6
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.backend.konan.objcexport.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.objcexport.Predefined.anyMethodSelectors
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getFunctionMethodBridge
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isArrayConstructor
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal val KtCallableSymbol.isConstructor: Boolean
|
||||
@@ -25,6 +23,7 @@ fun KtFunctionSymbol.translateToObjCMethod(
|
||||
): ObjCMethod? {
|
||||
if (!isVisibleInObjC()) return null
|
||||
if (anyMethodSelectors.containsKey(this.name)) return null //temp, find replacement for org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.isReal
|
||||
if (isClone) return null
|
||||
|
||||
return buildObjCMethod()
|
||||
}
|
||||
@@ -78,7 +77,7 @@ internal fun KtFunctionLikeSymbol.buildObjCMethod(
|
||||
return ObjCMethod(
|
||||
comment = comment,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
isInstanceMethod = bridge.isInstance || isConstructor,
|
||||
isInstanceMethod = bridge.isInstance,
|
||||
returnType = returnType,
|
||||
selectors = selectors,
|
||||
parameters = parameters,
|
||||
@@ -280,7 +279,7 @@ private fun String.mangleIfSpecialFamily(prefix: String): String {
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamerImpl.startsWithWords]
|
||||
*/
|
||||
private fun String.startsWithWords(words: String) = this.startsWith(words) &&
|
||||
(this.length == words.length || !this[words.length].isLowerCase())
|
||||
(this.length == words.length || !this[words.length].isLowerCase())
|
||||
|
||||
/**
|
||||
* [org.jetbrains.kotlin.backend.konan.objcexport.MethodBrideExtensionsKt.valueParametersAssociated]
|
||||
@@ -322,7 +321,7 @@ fun KtFunctionLikeSymbol.mapReturnType(returnBridge: MethodBridge.ReturnValue):
|
||||
if (!returnBridge.successMayBeZero) {
|
||||
check(
|
||||
successReturnType is ObjCNonNullReferenceType
|
||||
|| (successReturnType is ObjCPointerType && !successReturnType.nullable)
|
||||
|| (successReturnType is ObjCPointerType && !successReturnType.nullable)
|
||||
) {
|
||||
"Unexpected return type: $successReturnType in $this"
|
||||
}
|
||||
|
||||
+3
-1
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.objcexport
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCIdType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCProperty
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCType
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.swiftNameAttribute
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.getPropertyMethodBridge
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isVisibleInObjC
|
||||
@@ -57,7 +59,7 @@ fun KtPropertySymbol.buildProperty(): ObjCProperty {
|
||||
name = name,
|
||||
comment = null,
|
||||
origin = getObjCExportStubOrigin(),
|
||||
type = type!!,
|
||||
type = type ?: ObjCIdType, //[ObjCIdType] temp fix, should be translated properly, see KT-65709
|
||||
propertyAttributes = attributes,
|
||||
setterName = setterName,
|
||||
getterName = getterName,
|
||||
|
||||
+2
-2
@@ -61,6 +61,6 @@ fun KtScope.getPropertyOrFail(name: String): KtPropertySymbol {
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
fun KtClassOrObjectSymbol.getFunctionOrFail(name: String) : KtFunctionSymbol {
|
||||
fun KtClassOrObjectSymbol.getFunctionOrFail(name: String): KtFunctionSymbol {
|
||||
return this.getMemberScope().getFunctionOrFail(name)
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package org.jetbrains.kotlin.objcexport.tests
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.hasExportForCompilerAnnotation
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.getPropertyOrFail
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
class HasExportForCompilerAnnotationTest(
|
||||
private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis,
|
||||
) {
|
||||
@Test
|
||||
fun `test - has ExportForCompiler annotation`() {
|
||||
val ktFile = inlineSourceCodeAnalysis.createKtFile(
|
||||
"""
|
||||
class Foo
|
||||
val array: Array<Int>
|
||||
val iterator: Iterator<Int>
|
||||
val foo: Foo
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
analyze(ktFile) {
|
||||
assertTrue(
|
||||
verifyHasExportForCompilerAnnotation(ktFile.getPropertyOrFail("array"))
|
||||
)
|
||||
assertFalse(
|
||||
verifyHasExportForCompilerAnnotation(ktFile.getPropertyOrFail("iterator"))
|
||||
)
|
||||
assertFalse(
|
||||
verifyHasExportForCompilerAnnotation(ktFile.getPropertyOrFail("foo"))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
private fun verifyHasExportForCompilerAnnotation(property: KtPropertySymbol): Boolean {
|
||||
return property
|
||||
.returnType
|
||||
.getTypeScope()?.getConstructors()?.toList()?.any { it.hasExportForCompilerAnnotation }
|
||||
?: fail("Property return type has no constructors: ${property.returnType}")
|
||||
}
|
||||
+77
-13
@@ -1,15 +1,16 @@
|
||||
package org.jetbrains.kotlin.objcexport.tests
|
||||
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyze
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.implementsCloneable
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isClone
|
||||
import org.jetbrains.kotlin.objcexport.analysisApiUtils.isCloneable
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysis
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.getClassOrFail
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.getFunctionOrFail
|
||||
import org.jetbrains.kotlin.objcexport.testUtils.getPropertyOrFail
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class IsCloneableTest(
|
||||
private val inlineSourceCodeAnalysis: InlineSourceCodeAnalysis,
|
||||
@@ -20,7 +21,7 @@ class IsCloneableTest(
|
||||
val file = inlineSourceCodeAnalysis.createKtFile("val foo: Cloneable")
|
||||
analyze(file) {
|
||||
val foo = file.getPropertyOrFail("foo")
|
||||
assertTrue(foo.type.isCloneable)
|
||||
assertTrue(foo.getter?.returnType?.expandedClassSymbol?.isCloneable ?: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +35,76 @@ class IsCloneableTest(
|
||||
)
|
||||
analyze(file) {
|
||||
val foo = file.getPropertyOrFail("foo")
|
||||
assertFalse(foo.type.isCloneable)
|
||||
assertFalse(foo.getter?.returnType?.expandedClassSymbol?.isCloneable ?: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context(KtAnalysisSession)
|
||||
private val KtPropertySymbol.type: KtClassOrObjectSymbol
|
||||
get() {
|
||||
return getter?.returnType?.expandedClassSymbol!!
|
||||
}
|
||||
@Test
|
||||
fun `test - fake clone method`() {
|
||||
val file = inlineSourceCodeAnalysis.createKtFile(
|
||||
"""
|
||||
interface FakeCloneable {
|
||||
fun clone(): Any
|
||||
}
|
||||
class Foo : FakeCloneable {
|
||||
override fun clone(): Any {
|
||||
return "any"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
analyze(file) {
|
||||
val foo = file.getClassOrFail("Foo")
|
||||
assertFalse(foo.getFunctionOrFail("clone").isClone)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - implements cloneable`() {
|
||||
val file = inlineSourceCodeAnalysis.createKtFile(
|
||||
"""
|
||||
class Foo : Cloneable {
|
||||
override fun clone(): Foo {
|
||||
return this
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
analyze(file) {
|
||||
val foo = file.getClassOrFail("Foo")
|
||||
assertTrue(foo.implementsCloneable)
|
||||
assertTrue(foo.getFunctionOrFail("clone").isClone)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - fake clone function`() {
|
||||
val file = inlineSourceCodeAnalysis.createKtFile(
|
||||
"""
|
||||
fun clone(): Any {}
|
||||
""".trimIndent()
|
||||
)
|
||||
analyze(file) {
|
||||
val clone = file.getFunctionOrFail("clone")
|
||||
assertFalse(clone.isClone)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - clone method`() {
|
||||
val file = inlineSourceCodeAnalysis.createKtFile(
|
||||
"""
|
||||
val array: Array<Int>
|
||||
""".trimIndent()
|
||||
)
|
||||
analyze(file) {
|
||||
assertTrue(
|
||||
file
|
||||
.getPropertyOrFail("array")
|
||||
.getter?.returnType?.expandedClassSymbol?.getMemberScope()
|
||||
?.getFunctionOrFail("clone")
|
||||
?.isClone ?: false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-6
@@ -26,8 +26,6 @@ class ObjCDependenciesTypesTest(
|
||||
) {
|
||||
|
||||
/**
|
||||
* - Wrong translation of constructors KT-65365
|
||||
* - Bad parsing of versions (SinceKotlin Annotation)
|
||||
* - Missing implementation of mangling
|
||||
*/
|
||||
@Test
|
||||
@@ -41,14 +39,27 @@ class ObjCDependenciesTypesTest(
|
||||
doTest(dependenciesDir.resolve("iterator"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - array`() {
|
||||
doTest(dependenciesDir.resolve("array"))
|
||||
}
|
||||
|
||||
/**
|
||||
* - Wrong translation of constructors KT-65365
|
||||
* - Exposing unwanted 'clone' method KT-65629
|
||||
* Fails because of KT-65709
|
||||
*/
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - array`() {
|
||||
doTest(dependenciesDir.resolve("array"))
|
||||
fun `test - arrayList`() {
|
||||
doTest(dependenciesDir.resolve("arrayList"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Int* type conversion issue: KT-65687
|
||||
*/
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - implementIterator`() {
|
||||
doTest(dependenciesDir.resolve("implementIterator"))
|
||||
}
|
||||
|
||||
private fun doTest(root: File) {
|
||||
|
||||
+19
@@ -101,6 +101,11 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) {
|
||||
doTest(headersTestDataDir.resolve("classImplementingInterface"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - classExtendsAbstractClass`() {
|
||||
doTest(headersTestDataDir.resolve("classExtendsAbstractClass"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - interfaceImplementingInterface`() {
|
||||
@@ -258,6 +263,20 @@ class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) {
|
||||
doTest(headersTestDataDir.resolve("objectWithGenericSuperclass"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test - since version annotation`() {
|
||||
doTest(headersTestDataDir.resolve("sinceVersionAnnotation"))
|
||||
}
|
||||
|
||||
/**
|
||||
* - requires mangling
|
||||
*/
|
||||
@TodoAnalysisApi
|
||||
@Test
|
||||
fun `test - constructors`() {
|
||||
doTest(headersTestDataDir.resolve("constructors"))
|
||||
}
|
||||
|
||||
private fun doTest(root: File, configuration: Configuration = Configuration()) {
|
||||
if (!root.isDirectory) fail("Expected ${root.absolutePath} to be directory")
|
||||
val generatedHeaders = generator.generateHeaders(root, configuration).toString()
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wincompatible-property-type"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#pragma push_macro("_Nullable_result")
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
#undef _Nullable_result
|
||||
#define _Nullable_result _Nullable
|
||||
#endif
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface FooKt : Base
|
||||
@property (class, readonly) NSMutableArray<Int *> *a __attribute__((swift_name("a")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1 @@
|
||||
val a: ArrayList<Int>
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
@protocol Iterator;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wincompatible-property-type"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#pragma push_macro("_Nullable_result")
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
#undef _Nullable_result
|
||||
#define _Nullable_result _Nullable
|
||||
#endif
|
||||
|
||||
@protocol Iterator
|
||||
@required
|
||||
- (BOOL)hasNext __attribute__((swift_name("hasNext()")));
|
||||
- (id _Nullable)next __attribute__((swift_name("next()")));
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface Foo : Base <Iterator>
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
- (BOOL)hasNext __attribute__((swift_name("hasNext()")));
|
||||
- (Int *)next __attribute__((swift_name("next()")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
class Foo: Iterator<Int> {
|
||||
override fun hasNext(): Boolean { return false }
|
||||
override fun next(): Int { return 0 }
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
@class A;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wincompatible-property-type"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#pragma push_macro("_Nullable_result")
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
#undef _Nullable_result
|
||||
#define _Nullable_result _Nullable
|
||||
#endif
|
||||
|
||||
@interface A : Base
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
- (void)a0 __attribute__((swift_name("a0()")));
|
||||
- (void)a1I:(int32_t)i __attribute__((swift_name("a1(i:)")));
|
||||
- (void)a2B:(BOOL)b a:(id)a __attribute__((swift_name("a2(b:a:)")));
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface B : A
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
- (void)a0 __attribute__((swift_name("a0()")));
|
||||
- (void)a1I:(int32_t)i __attribute__((swift_name("a1(i:)")));
|
||||
- (void)a2B:(BOOL)b a:(id)a __attribute__((swift_name("a2(b:a:)")));
|
||||
- (void)b0 __attribute__((swift_name("b0()")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
abstract class A {
|
||||
abstract fun a0()
|
||||
abstract fun a1(i: Int)
|
||||
abstract fun a2(b: Boolean, a: Any)
|
||||
}
|
||||
|
||||
class B: A() {
|
||||
override fun a0() {}
|
||||
override fun a1(i: Int) {}
|
||||
override fun a2(b: Boolean, a: Any) {}
|
||||
|
||||
fun b0() {}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wincompatible-property-type"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#pragma push_macro("_Nullable_result")
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
#undef _Nullable_result
|
||||
#define _Nullable_result _Nullable
|
||||
#endif
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface Constructor : Base
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface ConstructorDouble : Base
|
||||
- (instancetype)initWithA:(int32_t)a __attribute__((swift_name("init(a:)"))) __attribute__((objc_designated_initializer));
|
||||
- (instancetype)initWithA_:(int32_t)a __attribute__((swift_name("init(a_:)"))) __attribute__((objc_designated_initializer));
|
||||
- (instancetype)initWithA:(int32_t)a b:(int32_t)b __attribute__((swift_name("init(a:b:)"))) __attribute__((objc_designated_initializer));
|
||||
- (instancetype)initWithA:(int32_t)a b:(int32_t)b c:(int32_t)c __attribute__((swift_name("init(a:b:c:)"))) __attribute__((objc_designated_initializer));
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface ConstructorParam0 : Base
|
||||
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
|
||||
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface ConstructorParam1 : Base
|
||||
- (instancetype)initWithA:(int32_t)a __attribute__((swift_name("init(a:)"))) __attribute__((objc_designated_initializer));
|
||||
@property (readonly) int32_t a __attribute__((swift_name("a")));
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface ConstructorParam2 : Base
|
||||
- (instancetype)initWithA:(int32_t)a b:(int32_t)b __attribute__((swift_name("init(a:b:)"))) __attribute__((objc_designated_initializer));
|
||||
@property (readonly) int32_t a __attribute__((swift_name("a")));
|
||||
@property (readonly) int32_t b __attribute__((swift_name("b")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,10 @@
|
||||
class Constructor private constructor() {}
|
||||
class ConstructorParam0() {}
|
||||
class ConstructorParam1(val a: Int) {}
|
||||
class ConstructorParam2(val a: Int, val b: Int) {}
|
||||
|
||||
class ConstructorDouble(a: Int) {
|
||||
constructor(a: Int): this(a)
|
||||
constructor(a: Int, b: Int): this(b)
|
||||
constructor(a: Int, b: Int, c: Int): this(c)
|
||||
}
|
||||
native/objcexport-header-generator/testData/headers/sinceVersionAnnotation/!sinceVersionAnnotation.h
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#pragma clang diagnostic ignored "-Wincompatible-property-type"
|
||||
#pragma clang diagnostic ignored "-Wnullability"
|
||||
|
||||
#pragma push_macro("_Nullable_result")
|
||||
#if !__has_feature(nullability_nullable_result)
|
||||
#undef _Nullable_result
|
||||
#define _Nullable_result _Nullable
|
||||
#endif
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface FooKt : Base
|
||||
|
||||
/**
|
||||
* @note annotations
|
||||
* kotlin.SinceKotlin(version="1.4")
|
||||
*/
|
||||
+ (void)foo __attribute__((swift_name("foo()")));
|
||||
@end
|
||||
|
||||
#pragma pop_macro("_Nullable_result")
|
||||
#pragma clang diagnostic pop
|
||||
NS_ASSUME_NONNULL_END
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
@SinceKotlin(version="1.4")
|
||||
fun foo() {}
|
||||
Reference in New Issue
Block a user