Kotlin dependency not behaving like Kotlin - gradle

I have a Kotlin dependency that I wrote and am now trying to use it in a separate project. When I add it to the other project variables declared like val hits = 0 can not be referenced by using the variable hits but by using getHits() which would make sense if I was using java in the second project but I am not. In other Kotlin projects I have worked on in the past this was not an issue and the only thing that I can think of that is different in the build is that I have set transitive = false on the gradle dependency because that was causing another issue. Anyway I am confused on what this would be caused by and appreciate any help, thanks!

In the Intellij decompiler is was considering a class that I know was written in Kotlin a java class so I tried to change some things. The problem was one of two things:
I was using the maven plugin for gradle.
I had both a compileKotlin and a compileJava when I was only using Kotlin.
I belive that the problem was caused by the former because I have used both compileKotlin and compileJava fine together before but I had never used the maven plugin but I added it because something else was complaining that it needed it.

Related

Should I shadow Kotlin when writing a Gradle Plugin

I'm writing a plugin to extract some boilerplate from a selection of existing Gradle build scripts. The existing build scripts are primarily written in Groovy and compiling Java.
To build my plugin I'm using the Gradle Kotlin DSL and figured I'd take the opportunity to write the plugin in Kotlin too. This all works but now my plugin has a huge dependency on Kotlin - and the Gradle docs specifically recommend minimizing external libraries.
Java and Groovy plugins avoid this because Java & Groovy are a shared dependency with Gradle, but Kotlin isn't a shared pre-requirement and so we then have to be concerned about potentially conflicting Kotlin versions needed by different plugins.
I figure I should move forward with one of the following approaches but am not clear which:
Just list Kotlin's stdlib as a standard dependency and trust Gradle to sort things out.
This works for one plugin, but should I expect problems when another plugin is also being used but depending on a different Kotlin?
Build some sort of uber shadowJar shadowing Kotlin libraries for my plugin
Implying that every plugin I write like this will be 10s of MB bigger than necessary.
Give up on Kotlin based plugins and rewrite in Java/Groovy
Would be a shame to give up on the new goodness but might be better to avoid the above sins.
Recommendations welcome!
Since your plugin is replacing boilerplate and is presumably not destined for public release, would it make sense to write it as a script plugin in the Gradle Kotlin DSL? That way a new enough Gradle should be able to understand it natively.
Raised this in Gradle Community Slack and was recommended to use Gradle's kotlin-dsl plugin to automatically configure dependencies on gradleApi() and embeddedKotlin() versions, and therefore whatever Kotlin version is bundled with Gradle's Kotlin DSL support.
I was concerned that this might introduce a dependency on the calling script using Kotlin DSL, but I've tested with a Groovy script and have been able to use my plugin. I assume that it does still depend on a version of Gradle with Kotlin DSL support though - i.e. 4.0+.

Gradle composite build with custom gradle plugin fails in IntelliJ: "Could not find method api() for arguments"

I have a Gradle composite build project which contains a custom Gradle plugin. This project builds fine when using Gradle CLI, but IntelliJ fails.
I tried a few different variations on the plugin version within the resolutionStrategy block: org.test:test-plugin:0.0.1 and test-plugin:test-plugin.gradle.plugin:0.0.1 as described here: https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers - both of those work from the CLI; changing to invalid values ("blah:blah") causes a failure.
I've made a sample Github project that contains the code to reproduce, here: https://github.com/mwmitchell/intellij-gradle-plugin-composite-build-bug along with instructions to reproduce and a workaround. The workaround is something that's not really feasible for me, as it requires repeating configuration code (dependencies, plugins etc.) and I have many, many projects that require the same/common configuration.
I would expect IntelliJ to load the project successfully, just like the CLI does. It seems like IntelliJ is loading the sub-project (:project-1:library-a) before the parent (:project-1), such that the java-library is not actually applied to the sub-project when it's evaluated.
Thanks for the sample project! Indeed, it is an issue in IntelliJ IDEA, see this ticket.
Gradle projects can have only one settings.gradle. You can include subproject "library-a" with include 'project-1:library-a' in the main settings.gradle.

Supporting multiple gradle versions in single build.gradle

Due to build tools, my gradle file has to be compatible both with Android Gradle 2.1.3 and the latest Android Gradle version. As the latest Android Gradle Plugin has introduced the new implementation and api configuration, and is planning to remove the compile configuration, I am trying to figure out a way to write script that it should bebe able to support both versions.
The idea would be to use something like
def _api = api
and in the dependencies use _api instead of api.
Later we plan to add add some code like;
if (oldVersion)
_api = compile
I have tried this code as is, but it is invalid code.
Any ideas how it should be coded?
Thanks in advance
The notation:
dependencies {
api "org.example:example:1.0"
}
is really syntactic sugar for
dependencies {
add("api", "org.example:example:1.0")
}
so you could solve that problem by defining String variables, whose value depends on the Gradle version.

Parent pom usage in build.gradle

I have a need to convert the maven project to gradle project. All is going fine, but there is one problem that I faced, in the current project we are using dependency management throw parent pom of maven and in gradle as long as I researched there is no possibility to do so. I was thinking to convert somehow parent pom to maven bom and use in build.gradle because I know that gradle can use maven boms.
Do anyone have better ideas how to accoplish that ?
Or may be someone also had this kind of problem, can suggest best ways to do it ?
Regards
You could use my gradle-maven-transform plugin to transform your pom.xmls into gradle scripts.
You can use the DependencyAggregator to find versions which are common across all projects and generate a root build.gradle containing the common versions.
Each project script can then reference a version variable from the root project instead of hard coding
You might choose to use nebula dependency recomnender plugin to manage common versions. The maven-transform plugin can generate scripts to support this style of declaration too
Whilst you are evaluating the gradle build you "apply" the generated gradle scripts in your gradle build. During this time both maven and gradle builds will work in parallel. Once your happy with the gradle build you copy paste the generated scripts into your build.gradle files and ditch maven for ever! Yay!

kapt: How to process test sources?

I have a project which uses kapt for annotation processing and code generation (based on the annotations). It works in the main sources, but not in the test sources.
Some sources (e.g. how to use kapt in androidTest scope) suggest to run gradle kaptTest, but this does not work either. It reports the task as "Up to date", even directly after a clean. Maybe this suggestion is unique to android.
I downloaded the example project from https://github.com/JetBrains/kotlin-examples/tree/master/gradle/kotlin-code-generation, added an annotation usage in the test sources and I got the same behaviour there. It works well for the main sources and it does not work for the test sources.
The only odd thing in the output is:
> Task :example:compileKotlin
Using kotlin incremental compilation
w: [kapt] Sources output directory is not specified, skipping annotation processing
but as you can see, this is not the test sources, but the main sources, and the annotation processor is applied on those.
I added a printout in the annotation processor. It does show up for compileKotlin, but not for compileTestKotlin.
So, what is the magic trick to make kapt work on test sources?
PS: I guess someone is going to ask for my build.gradle. It is identical to the one from the example I linked, so if you can make it work for the example, I can integrate into my buildfile.
PPS: Only similar question I found is Kotlin's kapt plugin for gradle does not work for custom source set (JMH), and they suggest to issue a bug report. So maybe it is a bug in the kapt-gradle-plugin?
Some sources (e.g. how to use kapt in androidTest scope) suggest to run gradle kaptTest, but this does not work either.
You misunderstood the suggestion. It says kaptTest should be used in place of kapt in the dependencies block, as described here, not that you should run Gradle differently. OTOH, the documentation also specifically says
Note that kaptAndroidTest and kaptTest extends kapt, so you can just provide the kapt dependency and it will be available both for production sources and tests.
So there indeed seems to be a bug there.
I've linked this question in https://youtrack.jetbrains.com/issue/KT-21891. I didn't want to file a separate bug because I don't know which Gradle/Kotlin/Kotlin Gradle plugin/etc. you had.
As suggested above, kaptTest should be added in gradle for the annotations in test folder to be processed by kapt.
for example for dagger hilt, add this to your app gradle :
kaptTest("com.google.dagger:hilt-android-compiler:$hiltVersion")
or for moshi, when you use annotations like #JsonClass(generateAdapter = true) in a file in test folder, you should add this to gradle dependencies so that kapt processes the annotation and generate the class :
kaptTest("com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion")

Resources