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

Make hierarchy in KSP API sealed (attempt 2) #1592

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions api/api.base
Expand Up @@ -141,7 +141,7 @@ package com.google.devtools.ksp.processing {
property @NonNull public abstract String targetName;
}

public interface PlatformInfo {
public sealed interface PlatformInfo {
method @NonNull public String getPlatformName();
property @NonNull public abstract String platformName;
}
Expand Down Expand Up @@ -262,7 +262,7 @@ package com.google.devtools.ksp.symbol {
enum_constant public static final com.google.devtools.ksp.symbol.FunctionKind TOP_LEVEL;
}

public interface KSAnnotated extends com.google.devtools.ksp.symbol.KSNode {
public sealed interface KSAnnotated extends com.google.devtools.ksp.symbol.KSNode {
method @NonNull public kotlin.sequences.Sequence<com.google.devtools.ksp.symbol.KSAnnotation> getAnnotations();
property @NonNull public abstract kotlin.sequences.Sequence<com.google.devtools.ksp.symbol.KSAnnotation> annotations;
}
Expand Down Expand Up @@ -313,7 +313,7 @@ package com.google.devtools.ksp.symbol {
property @Nullable public abstract com.google.devtools.ksp.symbol.KSClassifierReference qualifier;
}

public interface KSDeclaration extends com.google.devtools.ksp.symbol.KSModifierListOwner com.google.devtools.ksp.symbol.KSAnnotated com.google.devtools.ksp.symbol.KSExpectActual {
public sealed interface KSDeclaration extends com.google.devtools.ksp.symbol.KSModifierListOwner com.google.devtools.ksp.symbol.KSAnnotated com.google.devtools.ksp.symbol.KSExpectActual {
method @Nullable public com.google.devtools.ksp.symbol.KSFile getContainingFile();
method @Nullable public String getDocString();
method @NonNull public com.google.devtools.ksp.symbol.KSName getPackageName();
Expand All @@ -330,7 +330,7 @@ package com.google.devtools.ksp.symbol {
property @NonNull public abstract java.util.List<com.google.devtools.ksp.symbol.KSTypeParameter> typeParameters;
}

public interface KSDeclarationContainer extends com.google.devtools.ksp.symbol.KSNode {
public sealed interface KSDeclarationContainer extends com.google.devtools.ksp.symbol.KSNode {
method @NonNull public kotlin.sequences.Sequence<com.google.devtools.ksp.symbol.KSDeclaration> getDeclarations();
property @NonNull public abstract kotlin.sequences.Sequence<com.google.devtools.ksp.symbol.KSDeclaration> declarations;
}
Expand Down Expand Up @@ -390,7 +390,7 @@ package com.google.devtools.ksp.symbol {
property @Nullable public abstract com.google.devtools.ksp.symbol.KSTypeReference returnType;
}

public interface KSModifierListOwner extends com.google.devtools.ksp.symbol.KSNode {
public sealed interface KSModifierListOwner extends com.google.devtools.ksp.symbol.KSNode {
method @NonNull public java.util.Set<com.google.devtools.ksp.symbol.Modifier> getModifiers();
property @NonNull public abstract java.util.Set<com.google.devtools.ksp.symbol.Modifier> modifiers;
}
Expand All @@ -401,7 +401,7 @@ package com.google.devtools.ksp.symbol {
method @NonNull public String getShortName();
}

public interface KSNode {
public sealed interface KSNode {
method public <D, R> R accept(@NonNull com.google.devtools.ksp.symbol.KSVisitor<D,R> visitor, D data);
method @NonNull public com.google.devtools.ksp.symbol.Location getLocation();
method @NonNull public com.google.devtools.ksp.symbol.Origin getOrigin();
Expand All @@ -416,7 +416,7 @@ package com.google.devtools.ksp.symbol {
property @NonNull public abstract com.google.devtools.ksp.symbol.KSReferenceElement element;
}

public interface KSPropertyAccessor extends com.google.devtools.ksp.symbol.KSDeclarationContainer com.google.devtools.ksp.symbol.KSAnnotated com.google.devtools.ksp.symbol.KSModifierListOwner {
public sealed interface KSPropertyAccessor extends com.google.devtools.ksp.symbol.KSDeclarationContainer com.google.devtools.ksp.symbol.KSAnnotated com.google.devtools.ksp.symbol.KSModifierListOwner {
method @NonNull public com.google.devtools.ksp.symbol.KSPropertyDeclaration getReceiver();
property @NonNull public abstract com.google.devtools.ksp.symbol.KSPropertyDeclaration receiver;
}
Expand Down Expand Up @@ -449,7 +449,7 @@ package com.google.devtools.ksp.symbol {
property @NonNull public abstract com.google.devtools.ksp.symbol.KSValueParameter parameter;
}

public interface KSReferenceElement extends com.google.devtools.ksp.symbol.KSNode {
public sealed interface KSReferenceElement extends com.google.devtools.ksp.symbol.KSNode {
method @NonNull public java.util.List<com.google.devtools.ksp.symbol.KSTypeArgument> getTypeArguments();
property @NonNull public abstract java.util.List<com.google.devtools.ksp.symbol.KSTypeArgument> typeArguments;
}
Expand Down
Expand Up @@ -20,7 +20,7 @@ package com.google.devtools.ksp.processing
/**
* Platform specific information
*/
interface PlatformInfo {
sealed interface PlatformInfo {
val platformName: String
}

Expand Down
Expand Up @@ -19,7 +19,7 @@ package com.google.devtools.ksp.symbol
/**
* A symbol that can be annotated with annotations.
*/
interface KSAnnotated : KSNode {
sealed interface KSAnnotated : KSNode {

/**
* All annotations on this symbol.
Expand Down
Expand Up @@ -19,7 +19,7 @@ package com.google.devtools.ksp.symbol
/**
* A declaration, can be function declaration, class declaration and property declaration, or a type alias.
*/
interface KSDeclaration : KSModifierListOwner, KSAnnotated, KSExpectActual {
sealed interface KSDeclaration : KSModifierListOwner, KSAnnotated, KSExpectActual {
/**
* Simple name of this declaration, usually the name identifier at the declaration site.
*/
Expand Down
Expand Up @@ -19,7 +19,7 @@ package com.google.devtools.ksp.symbol
/**
* A declaration container can have a list of declarations declared in it.
*/
interface KSDeclarationContainer : KSNode {
sealed interface KSDeclarationContainer : KSNode {
/**
* Declarations that are lexically declared inside the current container.
*/
Expand Down
Expand Up @@ -19,7 +19,7 @@ package com.google.devtools.ksp.symbol
/**
* A [KSModifierListOwner] can have zero or more modifiers.
*/
interface KSModifierListOwner : KSNode {
sealed interface KSModifierListOwner : KSNode {
/**
* The set of modifiers on this element.
*/
Expand Down
Expand Up @@ -19,7 +19,7 @@ package com.google.devtools.ksp.symbol
/**
* Base class of every visitable program elements.
*/
interface KSNode {
sealed interface KSNode {
val origin: Origin
val location: Location
val parent: KSNode?
Expand Down
Expand Up @@ -21,7 +21,7 @@ package com.google.devtools.ksp.symbol
* Note that annotation use-site targets such as @get: @set: is not copied to accessor's annotations attribute.
* Use KSAnnotated.findAnnotationFromUseSiteTarget() to ensure annotations from parent is obtained.
*/
interface KSPropertyAccessor : KSDeclarationContainer, KSAnnotated, KSModifierListOwner {
sealed interface KSPropertyAccessor : KSDeclarationContainer, KSAnnotated, KSModifierListOwner {
/**
* The owner of the property accessor.
*/
Expand Down
Expand Up @@ -21,7 +21,7 @@ package com.google.devtools.ksp.symbol
*
* KSReferenceElement can specify, for example, a class, interface, or function, etc.
*/
interface KSReferenceElement : KSNode {
sealed interface KSReferenceElement : KSNode {
/**
* Type arguments in the type reference.
*/
Expand Down
Expand Up @@ -662,6 +662,8 @@ class IncrementalContext(
when (declaration) {
is KSPropertyDeclarationJavaImpl -> recordLookupForJavaField(declaration.psi)
is KSFunctionDeclarationJavaImpl -> recordLookupForJavaMethod(declaration.psi)
is KSClassDeclaration, is KSFunctionDeclaration, is KSPropertyDeclaration, is KSTypeAlias,
is KSTypeParameter -> Unit
}
}

Expand Down
Expand Up @@ -627,6 +627,11 @@ class ResolverImpl(
resolverContext = resolverContext
.childForClassOrPackage(resolveJavaDeclaration(e.psi) as ClassDescriptor, JavaClassImpl(e.psi))
}
is KSClassDeclaration, is KSFunctionDeclaration, is KSPropertyDeclaration, is KSTypeAlias,
is KSTypeParameter, is KSFile, is KSPropertyGetter, is KSPropertySetter, is KSTypeArgument,
is KSTypeReference, is KSValueArgument, is KSValueParameter, is KSAnnotation, is KSCallableReference,
is KSClassifierReference, is KSDefNonNullReference, is KSDynamicReference, is KSParenthesizedReference,
-> Unit
}
}
return if (javaType is JavaArrayTypeImpl)
Expand Down Expand Up @@ -1192,6 +1197,7 @@ class ResolverImpl(
if (declaration.isAbstract)
modifiers.add(Modifier.ABSTRACT)
}
is KSTypeAlias, is KSTypeParameter -> Unit
}
}
Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
Expand All @@ -1208,6 +1214,7 @@ class ResolverImpl(
if (declaration.jvmAccessFlag and Opcodes.ACC_SYNCHRONIZED != 0)
modifiers.add(Modifier.JAVA_SYNCHRONIZED)
}
is KSClassDeclaration, is KSTypeAlias, is KSTypeParameter -> Unit
}
}
else -> Unit
Expand Down
Expand Up @@ -49,6 +49,8 @@ class KSClassDeclarationDescriptorImpl private constructor(val descriptor: Class
}
}

override fun asKSDeclaration(): KSDeclaration = this

override val classKind: ClassKind by lazy {
when (descriptor.kind) {
KtClassKind.INTERFACE -> ClassKind.INTERFACE
Expand Down
Expand Up @@ -30,21 +30,23 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.parents
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull

abstract class KSDeclarationDescriptorImpl(private val descriptor: DeclarationDescriptor) : KSDeclaration {
abstract class KSDeclarationDescriptorImpl(private val descriptor: DeclarationDescriptor) /*: KSDeclaration*/ {
abstract fun asKSDeclaration(): KSDeclaration

override val origin by lazy {
open /*override*/ val origin by lazy {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit concerned with this. Having to cast the implementations is not only inconvenient, but also error prone and hard to maintain. Is there a better way to do it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this approach was the one with minimal changes. another one i can think of is to have these abstract classes but override and upcall in all implementation classes. this would be a bigger change but also less error prone.

Copy link
Contributor Author

@lukellmann lukellmann Nov 9, 2023

Choose a reason for hiding this comment

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

what about this: cda8056 (replacing casts with abstract functions with the desired return type that are overridden to simply return this)

descriptor.origin
}

override val containingFile: KSFile? = null
open /*override*/ val containingFile: KSFile? = null

override val location: Location = NonExistLocation
open /*override*/ val location: Location = NonExistLocation

override val annotations: Sequence<KSAnnotation> by lazy {
descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }.memoized()
open /*override*/ val annotations: Sequence<KSAnnotation> by lazy {
descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this.asKSDeclaration()) }
.memoized()
}

override val parentDeclaration: KSDeclaration? by lazy {
open /*override*/ val parentDeclaration: KSDeclaration? by lazy {
val containingDescriptor = descriptor.parents.first()
when (containingDescriptor) {
is ClassDescriptor -> KSClassDeclarationDescriptorImpl.getCached(containingDescriptor)
Expand All @@ -53,27 +55,27 @@ abstract class KSDeclarationDescriptorImpl(private val descriptor: DeclarationDe
}
}

override val parent: KSNode? by lazy {
open /*override*/ val parent: KSNode? by lazy {
parentDeclaration
}

override val packageName: KSName by lazy {
open /*override*/ val packageName: KSName by lazy {
KSNameImpl.getCached(descriptor.findPackage().fqName.asString())
}

override val qualifiedName: KSName by lazy {
open /*override*/ val qualifiedName: KSName by lazy {
KSNameImpl.getCached(descriptor.fqNameSafe.asString())
}

override val simpleName: KSName by lazy {
open /*override*/ val simpleName: KSName by lazy {
KSNameImpl.getCached(descriptor.name.asString())
}

override fun toString(): String {
return this.simpleName.asString()
}

override val docString = null
open /*override*/ val docString: String? = null
}

val DeclarationDescriptor.origin: Origin
Expand Down
Expand Up @@ -37,6 +37,8 @@ class KSFunctionDeclarationDescriptorImpl private constructor(val descriptor: Fu
cache.getOrPut(descriptor) { KSFunctionDeclarationDescriptorImpl(descriptor) }
}

override fun asKSDeclaration(): KSDeclaration = this

override fun findOverridee(): KSDeclaration? {
return descriptor?.findClosestOverridee()?.toKSDeclaration()
}
Expand Down

This file was deleted.

Expand Up @@ -25,8 +25,10 @@ import com.google.devtools.ksp.symbol.impl.toKSPropertyDeclaration
import com.google.devtools.ksp.toKSModifiers
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor

abstract class KSPropertyAccessorDescriptorImpl(val descriptor: PropertyAccessorDescriptor) : KSPropertyAccessor {
override val origin: Origin by lazy {
abstract class KSPropertyAccessorDescriptorImpl(val descriptor: PropertyAccessorDescriptor) /*: KSPropertyAccessor*/ {
protected abstract fun asKSPropertyAccessor(): KSPropertyAccessor

open /*override*/ val origin: Origin by lazy {
when (receiver.origin) {
// if receiver is kotlin source, that means we are a synthetic where developer
// didn't declare an explicit accessor so we used the descriptor instead
Expand All @@ -35,26 +37,28 @@ abstract class KSPropertyAccessorDescriptorImpl(val descriptor: PropertyAccessor
}
}

override val receiver: KSPropertyDeclaration by lazy {
open /*override*/ val receiver: KSPropertyDeclaration by lazy {
descriptor.correspondingProperty.toKSPropertyDeclaration()
}

override val parent: KSNode? by lazy {
open /*override*/ val parent: KSNode? by lazy {
receiver
}

override val location: Location
open /*override*/ val location: Location
get() {
// if receiver is kotlin source, that means `this` is synthetic hence we want the property's location
// Otherwise, receiver is also from a .class file where the location will be NoLocation
return receiver.location
}

override val annotations: Sequence<KSAnnotation> by lazy {
descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }.memoized()
open /*override*/ val annotations: Sequence<KSAnnotation> by lazy {
descriptor.annotations.asSequence()
.map { KSAnnotationDescriptorImpl.getCached(it, this.asKSPropertyAccessor()) }
.memoized()
}

override val modifiers: Set<Modifier> by lazy {
open /*override*/ val modifiers: Set<Modifier> by lazy {
val modifiers = mutableSetOf<Modifier>()
modifiers.addAll(descriptor.toKSModifiers())
modifiers.addAll(descriptor.toFunctionKSModifiers())
Expand Down
Expand Up @@ -36,6 +36,8 @@ class KSPropertyDeclarationDescriptorImpl private constructor(val descriptor: Pr
}
}

override fun asKSDeclaration(): KSDeclaration = this

override val extensionReceiver: KSTypeReference? by lazy {
if (descriptor.extensionReceiverParameter != null) {
KSTypeReferenceDescriptorImpl.getCached(descriptor.extensionReceiverParameter!!.type, origin, this)
Expand Down
Expand Up @@ -29,6 +29,8 @@ class KSPropertyGetterDescriptorImpl private constructor(descriptor: PropertyGet
}
}

override fun asKSPropertyAccessor(): KSPropertyAccessor = this

override val returnType: KSTypeReference? by lazy {
if (descriptor.returnType != null) {
KSTypeReferenceDescriptorImpl.getCached(descriptor.returnType!!, origin, this)
Expand Down
Expand Up @@ -29,6 +29,8 @@ class KSPropertySetterDescriptorImpl private constructor(descriptor: PropertySet
}
}

override fun asKSPropertyAccessor(): KSPropertyAccessor = this

override val parameter: KSValueParameter by lazy {
descriptor.valueParameters.singleOrNull()?.let { KSValueParameterDescriptorImpl.getCached(it, this) }
?: throw IllegalStateException("Failed to resolve property type")
Expand Down
Expand Up @@ -16,6 +16,8 @@ class KSTypeAliasDescriptorImpl(descriptor: TypeAliasDescriptor) :
}
}

override fun asKSDeclaration(): KSDeclaration = this

override val name: KSName by lazy {
KSNameImpl.getCached(descriptor.name.asString())
}
Expand Down
Expand Up @@ -39,6 +39,8 @@ class KSTypeParameterDescriptorImpl private constructor(val descriptor: TypePara
}
}

override fun asKSDeclaration(): KSDeclaration = this

override val bounds: Sequence<KSTypeReference> by lazy {
descriptor.upperBounds.asSequence().map { KSTypeReferenceDescriptorImpl.getCached(it, origin, this) }
}
Expand Down
Expand Up @@ -40,6 +40,8 @@ class KSClassDeclarationJavaEnumEntryImpl private constructor(val psi: PsiEnumCo
fun getCached(psi: PsiEnumConstant) = cache.getOrPut(psi) { KSClassDeclarationJavaEnumEntryImpl(psi) }
}

override fun asKSDeclaration(): KSDeclaration = this

override val origin = Origin.JAVA

override val location: Location by lazy {
Expand Down
Expand Up @@ -47,6 +47,8 @@ class KSClassDeclarationJavaImpl private constructor(val psi: PsiClass) :
fun getCached(psi: PsiClass) = cache.getOrPut(psi) { KSClassDeclarationJavaImpl(psi) }
}

override fun asKSDeclaration(): KSDeclaration = this

override val origin = Origin.JAVA

override val location: Location by lazy {
Expand Down