Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate OriginatingElementsHolder and Taggable from JVM to common #2040

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

ForteScarlet
Copy link
Contributor

Part of #304, #1959

Migrate OriginatingElementsHolder and Taggable from JVM to common

Copy link
Collaborator

@Egorand Egorand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, left a few nits! Thanks!

import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement

/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: docs in this file feel redundant, they more or less just restate what the code says.

message = "An expected type for JVM to `typealias` only." +
" Don't implement or use it in non-JVM platforms.",
)
public annotation class JvmTypeAliasKotlinPoetApi
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe call it JvmOnlyKotlinPoetApi? IMO this makes it a bit more clear that this type only exists in KotlinPoet for JVM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

public expect class JvmClass<T : Any>

/**
* Convert [JvmClass] to [KClass].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: redundant comment.

public actual typealias JvmClass<T> = Class<T>

/**
* Convert [JvmClass] to [KClass].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: redundant comment.

import kotlin.reflect.KClass

/**
* An expected typealias for [Class].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: redundant comment.

Comment on lines 21 to 22
public actual class JvmClass<@Suppress("unused")
T : Any,> private constructor()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
public actual class JvmClass<@Suppress("unused")
T : Any,> private constructor()
public actual class JvmClass<@Suppress("unused") T : Any> private constructor()

package com.squareup.kotlinpoet.jvm.alias

/**
* A typealias annotation for [kotlin.jvm.JvmDefaultWithCompatibility].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: redundant comment.

/**
* Convert [JvmClass] to [KClass].
*/
public expect val <T : Any> JvmClass<T>.kotlin: KClass<T>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this val internal? It shouldn't really be used outside of the library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, it doesn't seem to be used outside. I would change it to internal .

import javax.lang.model.element.Element
import com.squareup.kotlinpoet.jvm.alias.JvmDefaultWithCompatibility
import com.squareup.kotlinpoet.jvm.alias.JvmElement
import kotlin.jvm.JvmInline

/** A type that can have originating [elements][Element]. */
public interface OriginatingElementsHolder {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an JVM-only API. I don't see a reason to move it.

Copy link
Contributor Author

@ForteScarlet ForteScarlet Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is implemented by many other types, e.g. FunSpec, TypeSpec, PropertySpec. I think even though it's JVM-only, it still needs to be in the common

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expect/actual mechanism allows actuals on the JVM to implement interfaces not exposed by the expect.

Here's an example in Okio:

We should not expose JVM-only APIs in common. The need to create a ton of dummy typealiases to JVM types is a good indicator for an API that should not be in common.

Copy link
Contributor Author

@ForteScarlet ForteScarlet Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of FunSpec, for example, if you want to use the expect/actual mechanism to make FunSpec in the JVM implement OriginatingElementsHolder in a way that other platforms don't, then FunSpec itself must be expect/actual (unless the extra in the interface is not abstract).

This can create a lot of duplicate logic or generate a lot of extra work. That's what I use typealias for: to reduce the amount of work due to compatibility.

If we don't accept any JVM-only typealias exposed in common, then almost all major types will become expect/actual, even though their logic doesn't really differ.

This is the same problem you mentioned in #304 (comment), and I'm trying to get around it with typealias.

Exposing JVM-only types in common I think is a compromise for compatibility and maybe acceptable? 🤔 If it's unacceptable, that's fine too, except that later migrations to those major types will become more difficult.

There doesn't seem to be any best of both worlds until KT-20427 is resolved? 😢

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that require expect/actuals of FunSpec and co?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If an interface is expect/actual and there is an extra abstract method in the JVM, then FunSpec must also be expect/actual. Otherwise, in common it can't know about that extra part of the JVM and thus can't implement it.

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

Successfully merging this pull request may close these issues.

3 participants