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

Convert project to Gradle+Kotlin #2

Merged
merged 19 commits into from
Oct 24, 2018

Conversation

jmfayard
Copy link
Collaborator

@jmfayard jmfayard commented Oct 11, 2018

While I was doing this small pull request earlier, I realized that your project was exactly the playground I needed (neither trivial not too large, with tests) for something I had in mind :

Showing by example how to convert a Gradle project to the Kotlin DSL.

It will be a follow-up to this article I wrote and I plan to show it at a Kotlin Meetup in Berlin.

https://blog.kotlin-academy.com/gradle-kotlin-the-missing-piece-of-the-puzzle-7528a85f0d2c

If you prefer to stay with Gradle/Groovy, no hard feeling :)

It should work fine with Intellij IDEA 2018.+ and Android Studio 3.2+, tell me if you encounter problems.

Pro-Tip: add a `Gradle scope` with the pattern  `file:*.gradle||file:*.kts||file[buildSrc]:*/||file:.gitlab-ci.yml||file:*.properties`, it's immensly useful when you are messing with your gradle builds.

https://youtrack.jetbrains.com/issue/IDEA-200335

Action: `Replace in path`
Scope: `Gradle`
Replace all single quote ['] by a double quote [""]
Use the plugins {} block

  plugins {
    application
    kotlin("jvm")
  }

Groovy has no "=" but Kotlin needs it for things like
 group = "me.rozkmin.testing"
 version = "1.0-SNAPSHOT"

Groovy needs less parenthesis that Kotlin so add them as well
  testCompile Libs.junit => testCompile(Libs.junit)

Do kotlinOptions.jvmTarget = "1.8" for all projects in the root build file
That was non-trivial:

The Kotlin equivalent of

  test {
    useJUnitPlatform()
  }

is

  tasks.withType<Test>().configureEach {
    this.useJUnitPlatform()
  }
Just more of the same

plugins
parenthesis
=
Groovy:
  test {
    useJUnitPlatform()
    testLogging {
        events "passed", "skipped", "failed"
    }
 }

 Kotlin:

 tasks.withType<Test>().configureEach {
     useJUnitPlatform()
     testLogging {
         // GROOVY:
         // events "passed", "skipped", "failed"
         events = setOf(TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED)
     }
 }
@rozkminiacz
Copy link
Owner

Thats nice!
Can we have some solution, where both groovy-gradle and kotlin-gradle will be shown?

@jmfayard
Copy link
Collaborator Author

One module can have either have one.
But we can have half of the modules in groovy, half in kotlin
We can also have the kotlin build and have the groovy version with a different name like build.gradle.groovy so that it's not part of the build

@rozkminiacz
Copy link
Owner

Yeah, that's a good solution. Project built fully in Kotlin and Groovy files with .Groovy sufix excluded from build. It also requires proper explanation in readme.

@jmfayard
Copy link
Collaborator Author

jmfayard commented Oct 22, 2018

@rozkminiacz Done[1]

I even added a script ./toggle-kotlin-groovy.sh to switch between the two builds

Please check if you can merge

[1] Github has some problems today so it may not appear so

@rozkminiacz
Copy link
Owner

Looks good!
Nice work with toggle script. Merging.

@rozkminiacz rozkminiacz merged commit 7f90984 into rozkminiacz:master Oct 24, 2018
jcenter()
}

tasks.withType<KotlinCompile>().configureEach {
Copy link

Choose a reason for hiding this comment

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

You don't need configureEach in this case

}

repositories {
maven {
Copy link

Choose a reason for hiding this comment

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

you can replace it with maven(("https://dl.bintray.com/spekframework/spek-dev")


const val junit: String = "4.12" // up-to-date

const val junit_jupiter_api: String = "5.3.1" // up-to-date
Copy link

Choose a reason for hiding this comment

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

Why did you decide to violate Kotlin style guide and do not use camelCase for constants?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sorry, I forgot to reply. I follow the Kotlin style guide by default but in this case, I decided to that it was more important to be closer to what the maven coordinate is.

/**
* [kotlin-stdlib-jdk8 website](https://kotlinlang.org/) */
const val kotlin_stdlib_jdk8: String =
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:" + Versions.kotlin_stdlib_jdk8
Copy link

Choose a reason for hiding this comment

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

Why not use string templates?

version = "1.0-SNAPSHOT"

repositories {
mavenCentral()
Copy link

Choose a reason for hiding this comment

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

Why do you need both mavenCentral and jcenter? jcenter is superset of maven central

}

apply(plugin = "java")
java {
Copy link

Choose a reason for hiding this comment

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

I would rather to use plugins.withType, so you could apply java plugin specific settings only if some of modules applied java plugin, and do not force to apply it

}

dependencies {
implementation(project(":application"))
Copy link

@gildor gildor Oct 24, 2018

Choose a reason for hiding this comment

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

We also use approach when all our modules are items of enum, so access to modules became type safe, I probably share sample project that uses this approach

}

// GROOVY: test { ... }
tasks.withType<Test>().configureEach {
Copy link

@gildor gildor Oct 24, 2018

Choose a reason for hiding this comment

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

also, you don't need configureEach
If you want to configure only task "test", not all tasks with this type (same is in groovy), instead you can use tasks.named("test") {} (not sure that available before Gradle 5, than you can use some other DSL to get task, such as getByName or delegates)

jmfayard added a commit to jmfayard/KotlinUnitTesting that referenced this pull request Nov 7, 2018
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.

3 participants