autaut03 / kottle

Kotlin language provider for Forge 1.13.2+
GNU Lesser General Public License v3.0
30 stars 13 forks source link

IntelliJ IDEA unable to resolve packages #30

Open gdude2002 opened 4 years ago

gdude2002 commented 4 years ago

This is an odd one, and I'm not entirely sure it's your fault.

I followed the instructions in the README. My mod compiles and works as expected. Strangely, though, IDEA has no idea what Kottle is.

image

I did have to depend on Kotlin myself, so I suspect that Kottle 1.5.2 isn't exposing it as an api dependency. Still, I'm not sure what's wrong with this setup.

image

Any ideas?

gdude2002 commented 4 years ago

It's worth noting that switching to Kottle 1.4.0 does fix this problem.

bloxgate commented 4 years ago

I'm having the same problem as well, using both Kottle 1.5.1 and 1.5.2. 1.5.0 seems to work fine.

It is worth noting that in the module settings IntelliJ states that Kottle 1.5.2 has a broken path.

SamiSaves commented 4 years ago

I am having the same issue as well. Intellj can't find kottle 1.5.2 but with 1.5.0 the imports work fine.

The repositorys KottleTest.kt example doesn't contain import for the FMLKotlinModLoadingContext at all. Are we missing some important build step here, or is there an error in the test mod too?

https://github.com/autaut03/kottle/blob/master/src/test/kotlin/net/alexwells/kottle/KottleTest.kt

SamiSaves commented 4 years ago

If the first broken version is 1.5.1, then PR https://github.com/autaut03/kottle/pull/26 is probably the issue

SamiSaves commented 4 years ago

Googling shading and IntelliJ Idea brings a lot of topics saying that it doesn't work. https://youtrack.jetbrains.com/issue/IDEA-163411

I also found some articles saying that shading Kotlin is not a good idea. https://discuss.kotlinlang.org/t/what-is-the-proper-way-to-repackage-shade-kotlin-dependencies/10869/3

I don't understand much about the topic so those articles might be irrelevant to this issue. I'll next try to figure out that are we doing the shading correctly and is shading the correct way to solve the issue in pr #26.

gdude2002 commented 4 years ago

For libraries, shading is absolutely not the way to go.

The proper approach for this is probably to split Kottle into two modules - the mod, and the API. The API is the dependency used by other mods, whereas the mod itself implements that API.

Shading Kotlin isn't entirely unreasonable for the mod itself - however, I believe Forge has a way to download dependencies at runtime as well. Might be worth looking into.

gdude2002 commented 4 years ago

I did a bunch of research and have to conclude that Forge does not have a way to download runtime dependencies. Sadface.

I note that @autaut03 (or any other contributor) hasn't chimed in on this one yet. Do we know if they're aware of this issue?

gdude2002 commented 4 years ago

Looking at #26, the way shading has been set up there is all wrong. The shade configuration isn't one Gradle understands by default, so what needs to be done here is to replace the shade dependencies with api dependencies (assuming those existed in this ancient version of Gradle), and configure the shadow plugin to make use of that configuration.

We're not getting any dependencies showing up in our IDEs because shade isn't a valid configuration!


EDIT: api is not a valid configuration in this version of Gradle.

autaut03 commented 4 years ago

Yes, I am aware @gdude2002. I've also researched Forge's deps system and haven't found anything that can download deps at runtime.

We could force mod devs to shade Kotlin & other deps they need, given major & minor versions match, allowing devs to use whichever patch version they want, but this is for another topic.

Otherwise, I don't think I've got enough experience with Gradle to solve this myself.

Also, why do you say api isn't available? It works for me?

gdude2002 commented 4 years ago

If you use the api scope in the current version of Gradle, you get an exception thrown when it comes to shading it - you're not allowed to directly resolve the dependencies in that scope.

And I don't think we should require developers to shade Kotlin in - that's the main reason one would wish to use something like Kottle, I think.

gdude2002 commented 4 years ago

OK, having done some more tinkering with this, here's what I've noted so far:

Part of the problem is likely to be the fact that Curse isn't a real Maven repo and doesn't support proper Maven/Gradle metadata. It's likely that the best approach for this is the approach I suggested in https://github.com/autaut03/kottle/issues/30#issuecomment-655447048

Because the minecraft scope does end up being treated as a compile scope, we can't just include the compile scope in our shading - even if we explicitly exclude Forge, its transitive dependencies will be pulled into the final JAR. Obviously, this is far from ideal, and I expect it's the reason that the inclusions were done how they were prior to #26 being merged.


So, here's what I'd like to propose:

  1. Split Kottle into two projects - the mod, and the API.

    The API will contain all of the additional APIs Kottle provides, as well as api-marked dependencies (which means they'll be inherited by any projects that depend on it). It will not shade anything.

    The mod will depend on the API, as well as providing everything Forge needs that the individual mod developer shouldn't be touching. It will shade the API into the JAR as is currently done, including all transitive dependencies, but excluding Forge.

  2. Get set up on a real Maven repo for the API JAR. This means that we'll have the correct metadata present in the repository, and everything should resolve properly for everyone.

  3. Upload the mod to Curse, as is currently done. Tell developers to use the API instead of the mod when they're writing their mods.

This presents an issue, though: The API will need to depend on parts of Forge, most likely - this presents a tricky problem because that means we still need ForgeGradle (in order to handle remapping everything) and we still need to compile the API as if it were a mod. I'm not sure if there's a way around this.


I'm really not 100% sure of the best approach, or if this proposition is even a good one. That said, I do feel like a big part of our issue is that when using Curse as a Maven repo, our dependencies aren't declared in a format that Gradle understands. Build systems are designed to handle transitive dependencies separately from directly-declared dependencies; the build system should download and manage those dependencies itself. Curse's Maven endpoint is simply a wrapper around their project distribution system and doesn't meet the requirements of a real maven repo, to the best of my knowledge.