Skip to content

Support KSP in ContributesSubcomponentGenerator#828

Merged
JoelWilcox merged 10 commits intosquare:mainfrom
ZacSweers:z/ksp/contributesSubcomponentGenerator
Feb 6, 2024
Merged

Support KSP in ContributesSubcomponentGenerator#828
JoelWilcox merged 10 commits intosquare:mainfrom
ZacSweers:z/ksp/contributesSubcomponentGenerator

Conversation

@ZacSweers
Copy link
Collaborator

Ref #751

@ZacSweers ZacSweers mentioned this pull request Dec 24, 2023
15 tasks
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I renamed this file without code changes first before proceeding, but github still shows them as a separate file. Sorry :/, idk what else to do about this case

Copy link
Contributor

Choose a reason for hiding this comment

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

You're good, I can still see the diff by viewing the chunk of commits after the rename. Thanks for splitting it up!

Copy link
Contributor

Choose a reason for hiding this comment

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

You're good, I can still see the diff by viewing the chunk of commits after the rename. Thanks for splitting it up!

Comment on lines +98 to +107
internal fun KSAnnotation.replaces(): List<KSClassDeclaration> =
(argumentAt("replaces")?.value as? List<KSType>).orEmpty().mapNotNull {
it.resolveKSClassDeclaration()
}

@Suppress("UNCHECKED_CAST")
internal fun KSAnnotation.exclude(): List<KSClassDeclaration> =
(argumentAt("exclude")?.value as? List<KSType>).orEmpty().mapNotNull {
it.resolveKSClassDeclaration()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you come across any cases here where it was expected to get a null back? I'm thinking we should throw an exception if one of the replaces/exclude types can't be resolved, otherwise if I'm reading correctly we'll silently skip one or more types.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's possible if it refers to a type that's not yet been generated. In theory, the correct thing to do here would be to track this original type and return it to KSP to defer them to a later round. We don't currently support this in embedded code gen though, and there's not currently a way to easily defer these. This matches the current embedded behavior, and would be worth a wider cleanup in a later PR to add support for deferring unresolved types.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree on the first part around deferring eventually 👍. Can you point me to the equivalent skipping logic in the embedded impl (or relevant test if you came across one)? When I reviewed before I didn't see that, and it looked like this case would bubble up as an exception somewhere along the line while creating the reference classes for the annotation arguments. It's possible I missed it since the embedded impl has a lot more levels of abstraction before getting to specifically looking for the exclude arguments, just want to verify that the behavior is the same.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It will accept the ClassReference list as-is here, but default to empty if that value is null.

PSI will offer an error element for this case, but ClassReference doesn't ever account for these. Instead, the pattern I see is more or less that behavior is either undefined or it gracefully avoids those situations. In this case I think it's the latter, but tbh I'm not super sure how the PSI lookups for classreferences work just glancing at the code. We can make them error if you want though 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

(Note that exclude() is not used in this PR, just opportunistically added it since it was missing. replaces() is what's used.)

Copy link
Contributor

Choose a reason for hiding this comment

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

It will accept the ClassReference list as-is here, but default to empty if that value is null.

PSI will offer an error element for this case, but ClassReference doesn't ever account for these. Instead, the pattern I see is more or less that behavior is either undefined or it gracefully avoids those situations. In this case I think it's the latter, but tbh I'm not super sure how the PSI lookups for classreferences work just glancing at the code. We can make them error if you want though 👍

Gotcha, yea the default to empty on the argument itself makes sense since it might not have been set. My main concern is around if one of the types in a provided argument list isn't resolvable resulting in a null value.

I would say let's go ahead throw an exception in that case for the KSP impl for now (unless it reveals some tests covering this case where we don't throw an exception with the embedded impl). It's simple enough to change it back later if we find that there are cases where we want to ignore an unresolvable type. Basically just:

map {
  it.resolveKSClassDeclaration() ?: throw ...
}

clazz.getKSAnnotationsByType(ContributesSubcomponent::class)
.forEach { annotation ->
for (it in annotation.replaces()) {
val scope = annotation.scope().resolveKSClassDeclaration() ?: continue
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar thought here on throwing an exception if the type isn't found

@ZacSweers
Copy link
Collaborator Author

@JoelWilcox sorry for the delay. I've merged latest main and added the throwing behavior requested: 1717ce5

@JoelWilcox
Copy link
Contributor

@JoelWilcox sorry for the delay. I've merged latest main and added the throwing behavior requested: 1717ce5

No worries, thanks for updating it!

@JoelWilcox JoelWilcox enabled auto-merge (squash) February 6, 2024 00:51
@JoelWilcox JoelWilcox merged commit 0679595 into square:main Feb 6, 2024
@ZacSweers ZacSweers deleted the z/ksp/contributesSubcomponentGenerator branch February 6, 2024 05:36
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.

2 participants