Skip to content

Cannot get the fully qualified name of an annotation not on the classpath #783

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

Open
jameskleeh opened this issue Dec 23, 2021 · 7 comments
Labels
api API changes may be involved
Milestone

Comments

@jameskleeh
Copy link
Contributor

Currently KSAnnotation only supports shortName. In the case where an annotation is not on the classpath, we should still be able to determine the fully qualified name of the annotation.

Calling annotation.annotationType.resolve() returns an error type in this case so it cannot be retrieved from the declaration

@ting-yuan
Copy link
Collaborator

KSAnnotation is essentially a reference + arguments. It's FQN depends on the context. For example, the following Foo can be a.b.Foo or c.d.Foo, depending on the classpath:

// It's an error if both libraries provide Foo.
import a.b.*
import c.d.*

@Foo()
class SomeClass

Therefore, if it cannot be resolved, there is no way to determine its FQN precisely.

@jameskleeh
Copy link
Contributor Author

@ting-yuan I understand there may be cases where the FQN is not available, but in the case I was describing, it is.

Screen Shot 2022-01-30 at 12 47 04 PM

In that case calling annotationMirror.annotationType.resolve() returns an error type, however the fully qualified name is obviously known.

@ting-yuan
Copy link
Collaborator

This is an interesting use case. Unfortunately KSP doesn't support it for now; We'll need to add something like resolveQualifiedName. Could you work it around by supplying the definition in the classpath?

@jameskleeh
Copy link
Contributor Author

jameskleeh commented Jan 31, 2022 via email

@ting-yuan ting-yuan added this to the 1.1 milestone Mar 3, 2022
@ting-yuan ting-yuan added the api API changes may be involved label Mar 3, 2022
@jameskleeh
Copy link
Contributor Author

@ting-yuan Do you have a recommendation on how I would add a test for this?

@ting-yuan
Copy link
Collaborator

You could build a library A which has a reference R to a class C in library B. Then apply processor P to an arbitrary source module S. In this module S, you use compileClasspath instead of implementation or api (which are transitive) to bring library A into classpath but not B. In the processor you get the class containing R via Resolver.getClassDeclarationByName() and then resovle R. All of these can be setup in a Gradle project as an integration test.

May I know how you're going to solve this? If you're thinking of introducing a new API, would you mind to discuss with @neetopia before investing in implementation?

@cgruber
Copy link

cgruber commented May 30, 2023

This is turning out to be pretty necessary, especially if you're in a loop with other processors, where you need to rely on those types. The information should be available to build these symbols - if the FQCN isn't available in the text of the class passed into an annotation parameter, there's an import statement in the file that should have its qualifier, so that should be discoverable by something analyzing its source. Indeed, if it came in from a class file, it would have FQCN because all the imports are normalized-away during compilation.

In my own case, I have GRPC service sources being generated, and my annotation references them. Those sources are part of the compilation job, but even if they weren't, the type I'm evaluating during processing should have all the breadcrumbs. Heck, I'm considering literally processing the file to look for the import statement as a stop-gap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api API changes may be involved
Projects
None yet
Development

No branches or pull requests

3 participants