Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

Objective-C Framework interop headers may contain incorrect code #1447

Closed
sandwwraith opened this issue Mar 27, 2018 · 11 comments
Closed

Objective-C Framework interop headers may contain incorrect code #1447

sandwwraith opened this issue Mar 27, 2018 · 11 comments

Comments

@sandwwraith
Copy link
Member

I've compiled some Kotlin code to use it as a framework for ios application in swift. Some code in Framework header was not valid objective C code:

  1. I've used a pair of klibs, one of them is named http-client-native-ios and it contains class called HttpMethod. In produced header, it was declared as class KSFHttp-client-nativeHttpMethod – dashes were not removed, and it became invalid identifier.

  2. In kotlinx.serialization, I have a enum class KSerialClassDesc and one of its members is ENUM. Member name was translated directly into objective C and broke compilation. I've experimented with some Objective C reserved keywords:

enum class SomeUtil {
    ENUM,
    CLASS,
    BREAK,
    CASE,
    CONST
}

object Default {
    val default: String = "a"
    val extern: String = "a"
    val restrict: String = "a"
    val goto: String = "a"
}

became

@interface KSFSomeUtil : KSFStdlibEnum
// <...>
@property (class, readonly) KSFSomeUtil* enum;
@property (class, readonly) KSFSomeUtil* class_;
@property (class, readonly) KSFSomeUtil* break;
@property (class, readonly) KSFSomeUtil* case;
@property (class, readonly) KSFSomeUtil* const;
//<...>
@interface KSFDefault : KotlinBase
//<...>
@property (readonly) NSString* default;
@property (readonly) NSString* extern;
@property (readonly) NSString* restrict;
@property (readonly) NSString* goto;

Seems that no keywords except class_ are escaped, and there are a lot of errors.

@SvyatoslavScherbina
Copy link
Collaborator

Currently this issue is to be workarounded by renaming Kotlin declarations, and we have plans to provide annotation to change Objective-C/Swift name. After that automatic mangling will be disabled at all being considered as bad practice.

@sandwwraith
Copy link
Member Author

sandwwraith commented Mar 30, 2018

I'm personally not against disabling automatic mangling – since we have @JvmName and @JsName in case of clashes, it would be consistent to have @ObjCName too. However, it would be nice to have lint suggestion/compiler warning on name clash, as in Kotlin/JVM.

So now I'm more concerned about first part of the issue – module names. It's a common practice to have a name for published artifact with dashes, and it's very strange to annotate some buildscript files.

@SvyatoslavScherbina
Copy link
Collaborator

For a workaround on module name issue please see #1396 (comment)
Also we are planning to rework class naming too, and considering removing prefix from class names.

@ptmt
Copy link

ptmt commented Jun 20, 2018

@SvyatoslavScherbina, is there any plans to support @ObjCName or another recommended way to resolve conflicts with ObjC keywords? I'm having the exact same issue @sandwwraith had with:

enum class SomeUtil {
   ENUM,
   CLASS,
   BREAK,
   CASE,
   CONST
}

@adrianniebla
Copy link

Has there been an update on this issue, currently having this issue. These lines of code are being converted in the framework header from this

enum class ChartTypes {
    BAR,
    HORIZONTAL_BAR,
    PIE,
    LINE,
    SCATTER,
    BUBBLE,
    DONUT,
    STACKED_BAR,
    STACKED_HORIZONTAL_BAR,
    AREA,
    RADAR,
    TABLE,
    DEFAULT,
    WORLD_CLOUD,
    BOX_PLOT,
    AGGREGATE_TREE_MAP,
    TREE_MAP,
    AGGREGATE_BAR,
    OTHER
}

to this


@property (class, readonly) SharedCodeChartTypes *bar;
@property (class, readonly) SharedCodeChartTypes *horizontalBar;
@property (class, readonly) SharedCodeChartTypes *pie;
@property (class, readonly) SharedCodeChartTypes *line;
@property (class, readonly) SharedCodeChartTypes *scatter;
@property (class, readonly) SharedCodeChartTypes *bubble;
@property (class, readonly) SharedCodeChartTypes *donut;
@property (class, readonly) SharedCodeChartTypes *stackedBar;
@property (class, readonly) SharedCodeChartTypes *stackedHorizontalBar;
@property (class, readonly) SharedCodeChartTypes *area;
@property (class, readonly) SharedCodeChartTypes *radar;
@property (class, readonly) SharedCodeChartTypes *table;
@property (class, readonly) SharedCodeChartTypes *default;
@property (class, readonly) SharedCodeChartTypes *worldCloud;
@property (class, readonly) SharedCodeChartTypes *boxPlot;
@property (class, readonly) SharedCodeChartTypes *aggregateTreeMap;
@property (class, readonly) SharedCodeChartTypes *treeMap;
@property (class, readonly) SharedCodeChartTypes *aggregateBar;
@property (class, readonly) SharedCodeChartTypes *other;

Which causes an Could not build Objective-C module 'framework_name' because the lowercase default is reserved.

@SvyatoslavScherbina
Copy link
Collaborator

Has there been an update on this issue

No. It is still required to use the name that don't clash with any platform keywords. Just like when calling Kotlin from Java.
However Kotlin/Native still lacks an annotation similar to @JvmName, so currently you have only one option -- to use proper Kotlin name for your declarations.

@olonho
Copy link
Contributor

olonho commented Mar 7, 2019

Does #2747 helps with all problems here?

@Thomas-Vos
Copy link
Contributor

Does #2747 helps with all problems here?

I just tried the code in the first comment and had no issues. However, I found another name which gives an error, a DEBUG val. This Kotlin code:

class Example {
    val DEBUG = ""
}

generates this ObjectiveC code:

@interface GreetingExample : KotlinBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@property (readonly) NSString *DEBUG __attribute__((swift_name("DEBUG")));
@end;

Which produces the following error:
headers error

@sandwwraith
Copy link
Member Author

I can confirm that I do not have problems with

public sealed class SomeKind {
    public object ENUM: SomeKind()

    public val enum = ENUM

    public val double = ENUM
}

but have problems when I add val DEBUG = ENUM to the SomeKind class. Is this a separate issue and this can be closed, or what?

@SvyatoslavScherbina
Copy link
Collaborator

SvyatoslavScherbina commented Mar 18, 2020

I guess one issue is enough.

@SvyatoslavScherbina
Copy link
Collaborator

According migration to YouTrack, closing this issue in favour of https://youtrack.jetbrains.com/issue/KT-33092. Please continue any discussions there.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants