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

Regression: Types no longer validating #961

Closed
gdude2002 opened this issue Apr 17, 2022 · 17 comments
Closed

Regression: Types no longer validating #961

gdude2002 opened this issue Apr 17, 2022 · 17 comments
Assignees
Labels
bug Something isn't working
Milestone

Comments

@gdude2002
Copy link

gdude2002 commented Apr 17, 2022

Consider the following class definition (taken from this file)

@Converter(
    names = ["j8Duration"],
    types = [ConverterType.DEFAULTING, ConverterType.OPTIONAL, ConverterType.SINGLE],
    imports = ["java.time.*"],

    builderFields = [
        "public var longHelp: Boolean = true",
        "public var positiveOnly: Boolean = true",
    ],
)
public class J8DurationConverter(
    public val longHelp: Boolean = true,
    public val positiveOnly: Boolean = true,
    override var validator: Validator<ChronoContainer> = null
) : SingleConverter<ChronoContainer>() {

KSP will happily parse this under Kotlin 1.6.10, using version 1.6.10-1.0.4. There are no issues.

Under Kotlin 1.6.20 and KSP 1.6.20-1.0.5, this class no longer validates - attempting to get the super types will result in a list with a single <Error object> entry. Even worse, this seems to sporadically only happens on a clean build - running build again right after will sometimes result in validation passing perfectly, and the output being generated correctly.

I have a bunch of classes that are structured the same way and are generally quite similar that parse just fine under 1.0.5. Some examples are below, but everything in the same directory works perfectly. Click here for the annotation processor code.

Working:

Broken:


This makes absolutely no sense to me whatsoever. I can't see any significant differences, and I'm entirely out of ideas. For the time being, I've pushed a copy of the repo using last known working versions of Kotlin and KSP, simply updating them will cause this issue.

Since I really don't know how to dig further, I've pushed a branch which exhibits this issue. Simply clone it and run gradlew build.

@gdude2002
Copy link
Author

gdude2002 commented Apr 17, 2022

For a second example, I've noticed the same problem in another class (#950 was submitted by one of my users regarding it, but just to quickly recap...)

Consider the following class definition (taken from this file)

@WiredPlugin(
    "test",
    "0.0.1"
)
class TestPlugin(wrapper: PluginWrapper) : KordExPlugin(wrapper) {
    override suspend fun setup() {
        extension(::TestExtension)
    }
}

This one uses a different processor (which can be found here), but has a similar result - validation fails and, after some digging, the super types list contains Error type synthetic declaration. It's worth noting that adding a second super type definition - for example, KoinComponent - will result in that one showing up correctly in the list, so it's definitely related to the specific type in this instance.

@neetopia
Copy link
Contributor

does 1.6.20-1.0.4 work?

@gdude2002
Copy link
Author

does 1.6.20-1.0.4 work?

Unfortunately no, it does not - precisely the same problems.

@gdude2002
Copy link
Author

I thought that Kotlin 1.6.21 might help (as they fixed some compiler bugs that were also causing me issues), but that's not the case, unfortunately.

@neetopia
Copy link
Contributor

Since 1.6.20-1.0.4 is also not working, I doubt it is a compiler issue, likely a regression. Can you try to reduce your reproduce project into a small one? You don't have to but if that is possible, it will help with my debugging.

@gdude2002
Copy link
Author

1.6.21-1.0.5 - not working, but that's expected

I'd like to do that, but I think part of my problem is I don't know how to properly debug a KSP processor - since, short of unit tests, I couldn't figure out how to attach a debugger to it.

Any ideas on that? If I can zero in on this somehow, I may be able to write some unit tests for this.

@OliverO2
Copy link

OliverO2 commented Apr 22, 2022

I could successfully debug KSP plugins this way:

  1. Create a Remote JVM Debug run configuration in IntelliJ IDEA (in Attach to remote JVM mode)
  2. Run ./gradlew --stop
  3. Run ./gradlew run --no-daemon -Dorg.gradle.debug=true -Dkotlin.compiler.execution.strategy=in-process (or whatever task fits)
  4. Start the debugger with the Remote JVM Debug run configuration

Somewhat slow, but works.

More details: #31

@OliverO2
Copy link

Re-checked the alternative, which is way faster:

  1. Run this (or whatever task fits)
./gradlew -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket\,address=8765\,server=y\,suspend=n" run
  1. Choose menu Run – Attach to Process
  2. Select process KotlinCompileDaemon

If the Gradle task completed before you could attach to the Kotlin compiler daemon, just leave the debugger attached and restart the Gradle task.

@gdude2002
Copy link
Author

Huh, interesting - when I next have some spare time I'll give that a go, thanks!

@gdude2002
Copy link
Author

Alright, I'm looking into this at the moment.

Having attached a debugger (took a few tries but @OliverO2's instructions worked, thank you!), I've learned a few things about the situation.

  1. A super type with the correct class name exists.

    image

  2. Attempting to call .resolve() returns an error type. The properties are all empty, implying that the type doesn't actually exist when it clearly does - I can see it in my source tree.

    image

  3. Attempting to call .validate() returns false. This is true on the parent type as well.

I wonder if this is because the supertype was declared in a different sourceset. It's part of the same module, but my TestPlugin is part of test whereas the KordExPlugin type is part of main.

@gdude2002
Copy link
Author

I wonder if this is because the supertype was declared in a different sourceset. It's part of the same module, but my TestPlugin is part of test whereas the KordExPlugin type is part of main.

This does seem to be relevant. Creating a similar test plugin in the main sourceset will result in a success, and it's worth noting that all the unresolvable types given by the other annotation processor are in other modules.

It seems to me that this issue is related to the unresolvable supertypes being in other modules and sourcesets.

@gdude2002
Copy link
Author

Doing some further messing around, I worked around the plugin processor issue by using the superType.element.toString() for now - massive hack, but it at least works.

During this, I've noticed that the PluginProcessor's process function is being called twice. I'm not sure if this is related - I suspect it isn't - but it's a problem unless I also work around it, because KSP refuses to overwrite a file I've already generated.

As for the other processor, I can't think of any useful workarounds because it needs that type info - but I'm noticing that it will consistently work if I run the build twice. It'll fail the first time and, assuming I don't clean build, it'll pass thereafter.

@neetopia neetopia self-assigned this May 3, 2022
@neetopia neetopia added the bug Something isn't working label May 3, 2022
@neetopia neetopia added this to the 1.0.6 milestone May 3, 2022
@neetopia
Copy link
Contributor

it is expected to run process() at least twice, due to multiround processing requirements. Ideally if you are only processing on symbols with annotations, you shouldn't be processing the same valid annotation multiple times. If that's not the case for you, you can try to add some state to your processor to be shared across rounds, and check the stored state to see whether your processor has generated certain files.

@neetopia neetopia modified the milestones: 1.0.6, 1.0.7 Jun 8, 2022
@DRSchlaubi
Copy link

DRSchlaubi commented Jul 8, 2022

So after some testing it seems like, validation fails because the types actually can't be resolved at this time, as they are defined in a different module, this could be

  • An issue in KSPs resolving
  • An issue in dependencies of the kspKotlin task (Gradle plugin issue)
    however,

I found the following workaround (where :kord-extensions being the module defining the supertype) to force Gradle running the necessary parent tasks first

Relevant commit: mikbot/kord-extensions@7a16526

tasks {
    afterEvaluate {
        "kspKotlin" {
            dependsOn(":kord-extensions:build")
        }
    }
}

@gdude2002
Copy link
Author

I can confirm @DRSchlaubi's fix. It doesn't help regarding my TestPlugin report, and I believe that's because that was in the test source set rather than main.

I've removed it in our codebase as our test bot is in a different module now, and things are working, but it's worth considering whether this is intentional KSP behaviour.

@neetopia
Copy link
Contributor

neetopia commented Sep 9, 2022

Can you revive the reproduce branch? I was trying to look into this but found the link is now dead.

@gdude2002
Copy link
Author

Unfortunately, I've moved to a new machine since the branch was cleaned up, so I no longer have a copy of it. However, I am happy to state that as of the latest versions of KSP and Kotlin, we no longer have this problem.

Apologies, I completely forgot about this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants