Ktlint ignores .editorconfig - kotlin

I wanted to try out Kotlin and ktlint and I was happy to see that it supports tab indentation via the editorconfig file (since this PR). Sadly it doesn't seem to work for me. I haven't used editorconfig before, I might have made some simple mistake.
My .editorconfig in the root folder:
indent_style = tab
My gradle file:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val koinVersion: String by project
val junitVersion: String by project
plugins {
application
kotlin("jvm") version "1.4.30"
id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
}
group = "me.me"
version = "1.0-SNAPSHOT"
application {
mainClassName = "de.me.bot.translate.MainKt"
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation("com.sksamuel.hoplite:hoplite-core:+")
implementation("org.koin:koin-core:$koinVersion")
testImplementation("org.koin:koin-test:$koinVersion")
testImplementation(kotlin("test-junit5"))
testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile>() {
kotlinOptions.jvmTarget = "13"
}
However running gradle ktlintCheck still throws exceptions because of unexpected tab characters. I don't understand why. I ran it with --debug, but it didn't give me any useful information.
Here is my project: github.com

EditorConfig specification states:
With the exception of the root key, all pairs MUST be located under a section to take effect.
So your .editorconfig file should be:
root = true
[*.{kt,kts}]
indent_style = tab

Related

How can I find the main class of my app when selecting it to create a JAR ? Kotlin

I want to make a JAR to test and deploy my app but it doesn't work, locally it can't find the main attribute in the manifest file, and in the deployement it starts but i have this error :
java.lang.noclassdeffounderror: kotlinx/coroutines/slf4j/mdccontex
W
hen I do it locally using the artifact Jar I can't find the MainClass of my app, it recommands me all sorts of other modules.
I tried modying my gradle, the manifest, the configuration but really nothing works it's depressing, it looks so easy on some youtube videos but it just doesn't work
what I do to make the JAR
The classes i have access to when i try to select them
Here is my Gradle
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.5.10"
application
kotlin("plugin.serialization") version "1.6.10"
}
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
maven(url = "https://jitpack.io")
}
val ktor_version: String by project
dependencies {
// Fix HTML issue on some responses
implementation("org.apache.commons:commons-text:1.10.0")
// Ktor dependencies
implementation("io.ktor:ktor-client-auth:$ktor_version")
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-cio:$ktor_version")
implementation("io.ktor:ktor-client-resources:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
implementation("io.ktor:ktor-client-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-client-logging:$ktor_version")
// Logging dependencies
implementation("ch.qos.logback:logback-classic:1.4.0")
implementation(kotlin("stdlib-jdk8"))
// Database
implementation ("mysql:mysql-connector-java:8.0.30")
implementation ("org.ktorm:ktorm-core:3.5.0")
implementation ("org.ktorm:ktorm-support-mysql:3.5.0")
}
application {
mainClass.set("MainKt")
}
val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions {
jvmTarget = "1.8"
}
val compileTestKotlin: KotlinCompile by tasks
compileTestKotlin.kotlinOptions {
jvmTarget = "1.8"
}
tasks {
jar {
manifest {
attributes["Main-Class"] = application.mainClass
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
configurations.compileClasspath.get().forEach {
from(if (it.isDirectory) it else zipTree(it))
}
}
compileKotlin{
kotlinOptions.jvmTarget = "1.8"
}
}
Thanks in advance
My project had a lot of issues and inconsistency so I started a new one and copied all the files / packages, spent an hour redoing all the imports and plugins that my code actually needed to run and it finally worked, the same comments don't work on the previous project

How can I apply a plugin to itself using Kotlin DSL?

We have an existing plugin project which configures various things (including static analysis), where we want to apply the plugin to the project itself.
The way this currently works for plugins written in Java is, you add the Java src dir to the buildSrc project, and then classes built there can be used in the main project. So I'm trying to get the same thing working for plugins written as Kotlin scripts.
But when I try to build it, compiling buildSrc fails with:
e: C:\Users\Trejkaz\Documents\test\self-applying-gradle-plugin\src\main\kotlin\example.common.gradle.kts: (1, 1): Unresolved reference: allprojects
> Task :buildSrc:compileKotlin FAILED
What's missing in order to make this work?
Further investigation:
If I put a copy of the files in buildSrc/src/main/kotlin, that works.
If I put a copy of the files in buildSrc/src/main/kotlin2 and use srcDirs to set that directory, that fails too. So it really looks like something isn't letting me relocate sources at all.
I pushed a repo to play with this here but what follows is the contents of the build scripts in case it's ever deleted.
The main build.gradle.kts:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
`java-gradle-plugin`
`kotlin-dsl`
// Matching version in Gradle
kotlin("jvm") version "1.5.31"
}
apply(from = "common-build.gradle.kts")
apply(plugin = "example.common") // 👈 trying to apply the compiled plugin here
group = "org.example"
version = "1.0-SNAPSHOT"
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
In buildSrc/build.gradle.kts, we have this - note that it adds a source dir for the sources in the main directory:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
`java-gradle-plugin`
`kotlin-dsl`
// Matching version in Gradle
kotlin("jvm") version "1.5.31"
}
apply(from = "../common-build.gradle.kts")
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
kotlin {
sourceSets["main"].kotlin.srcDir("../src/main/kotlin")
}
common-build.gradle.kts has everything common to both build scripts which we've figured out how to move to a common location (notably, the KotlinCompile isn't there, later I'll figure out why I can't move that as well):
repositories {
mavenCentral()
}
dependencies {
// Needed to compile Kotlin stuff but not added by the plugin for some reason
"implementation"("org.jetbrains.kotlin:kotlin-scripting-jvm")
}
The plugin script, src/main/kotlin/example.common.gradle.kts, contains:
allprojects {
// Configure something
}
This turns out to be a bug in Gradle's kotlin-dsl plugin.
The workaround is to add the source dirs before applying the plugin.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
`java-gradle-plugin`
`kotlin-dsl` apply false
// Matching version in Gradle
kotlin("jvm") version "1.5.31"
}
apply(from = "../common-build.gradle.kts")
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
kotlin {
sourceSets["main"].kotlin.srcDir("../src/main/kotlin")
}
// Workaround for https://github.com/gradle/gradle/issues/21052 -
// apply kotlin-dsl plugin last, because it erroneously fetches source dirs eagerly.
apply(plugin = "org.gradle.kotlin.kotlin-dsl")

Specify kotlin version in buildSrc kotlin convention plugin

I am developing a Kotlin project with multiple subprojects as explained here
Building Kotlin Applications with libraries Sample (gradle.org)
Is it correct to specify the kotlin version as as shown below?
file: buildSrc/build.gradle.kts
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:<kotlin-version>")
}
Also, is it possible to move this kotlin version to a central location for declaring project-wide dependency version (for example gradle.properties or buildSrc/**/Dependencies.kt or versions catalog)? None of the approaches mentioned seems to be supported in buildSrc/build.gradle.kts.
There are many approaches to specify the kotlin version (or versions of any dependency) at a centralized location in a Gradle Multimodule Project.
gradle.properties
buildSrc/**/Dependency.kt
versions catalog
However, if you are defining a Kotlin Convention Plugin in buildSrc, the kotlin version is not available in buildSrc/build.gradle.kts using any of the methods mentioned above so as to pick the right kotlin-gradle-plugin.
For a workaround solution, use the following.
# file:<root>/gradle.properties
kotlinVersion=1.5.31
// file:<root>/buildSrc/build.gradle.kts
import java.io.*
import java.util.*
// read gradle.properties programmatically
val props = Properties()
FileInputStream(file("../gradle.properties")).use {
props.load(it)
}
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
}
dependencies {
val kotlinVersion = props.getProperty("kotlinVersion")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
}
In all other <root>/**/<subproject>/build.gradle.kts files access the kotlinVersion like
val kotlinVersion = project.properties["kotlinVersion"]
In settings.gradle.kts, access the kotlinVersion like
val kotlinVersion:String by settings
If anyone from the Gradle team reading this, please provide an API to access gradle.properties consistently across any of the build script files.
in app gradle
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
and project gradle
ext.kotlin_version = "1.6.0"
I have solved this issue by specifying kotlinVersion in gradle.properties file as below.
kotlinVersion=1.6.10
Keep gradle.properties file at outermost project level.
You can access kotlinVersion in any submodules and project as
//top level declaration
val kotlinVersion by extra(project.property("kotlinVersion"))
//usage in dependency block
"org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}"
To verify whether you are able to read it, you can specify following
println(project.property("kotlinVersion"))
This should print kotlin version as
> Configure project :
1.6.10
build.gradle.kts file
val kotlinVersion by extra(project.property("kotlinVersion"))
println("${kotlinVersion}")
group = "com.company"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
mavenLocal()
maven { url = uri("https://repo.spring.io/milestone") }
maven { url = uri("https://repo.spring.io/snapshot") }
gradlePluginPortal()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
}
gradle.properties file
kotlin.code.style=official
#kotlin.parallel.tasks.in.project=true
#kapt.incremental.apt=true
org.gradle.parallel=true
org.gradle.caching=false
org.gradle.daemon=true
org.gradle.jvmargs=-Dfile.encoding=UTF-8
kotlinVersion=1.6.10
Ref:
project_properties
extra_properties

How to set up Kotlin PSI for IntelliJ IDEA Gradle Plugin?

I'm building a Plugin for the IntelliJ IDE to manipulate Kotlin files in a project. I've been able to write a bunch of tests to take a Kotlin file and generate a new file based on its contents. When I run this plugin in the IDE I'm unable to detect files as Kotlin files. When looking at the debugger my file says that it is a KtFile from the org.jetbrains.kotlin.psi library. But if I try to cast it to a KtFile I get an error:
java.lang.ClassCastException: org.jetbrains.kotlin.psi.KtFile cannot be cast to org.jetbrains.kotlin.psi.KtFile
So apparently the library version is off between runtime and compile time. What do I have to do to configure my plugin to use the correct Kotlin PSI at plugin runtime?
My plugin.xml looks like this:
<idea-plugin>
<id>...</id>
<name>...</name>
<vendor email="..." url="...">...</vendor>
<description><...</description>
<depends>com.intellij.modules.all</depends>
<depends>org.jetbrains.kotlin</depends>
<actions>...</actions>
</idea-plugin>
My build.gradle.kts looks like:
plugins {
id("org.jetbrains.intellij") version "0.4.16"
kotlin("jvm") version "1.3.61"
}
group = "..."
version = "..."
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("compiler-embeddable", "1.3.61"))
implementation(kotlin("gradle-plugin", "1.3.61"))
testImplementation(group = "junit", name = "junit", version = "4.12")
}
buildscript {
repositories { mavenCentral() }
dependencies {
classpath(kotlin("compiler-embeddable", "1.3.61"))
classpath(kotlin("gradle-plugin", "1.3.61"))
}
}
intellij {
version = "2019.1.4"
setPlugins("Kotlin")
}
tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
}
tasks.getByName<org.jetbrains.intellij.tasks.PatchPluginXmlTask>("patchPluginXml") {
changeNotes("...")
}
I already am aware of How to include Kotlin PSI classes (e.g. KtClass) in Intellij IDEA Gradle plugin project written in Kotlin? and How to add Kotlin PSI source files to IDEA Plugin project configuration which is essentially what I want to be answered but haven't gotten anything to fix my issue. Maybe there is some documentation on this issue but it evades my searches.
Your dependencies should include implementation(kotlin("reflect")) and plugin.xml should include <depends>org.jetbrains.kotlin</depends>

Create fat jar from kotlin multiplatform project

I recently switched from old 1.2 multiplatform into 1.3. Difference is, there's one one build.gradle file per multiplatform module (I got 5 of them) so a lot less configuration.
However I can't seem to be able to configure creating runnable fat jar with all dependencies from jvm platform.
I used to use standard "application" plugin in my jvm project and jar task, but that does not work anymore. I found there's "jvmJar" task and I modified it (set Main-class), but created jar doesn't contain dependencies and crashes on ClassNotFoundException. How do I do it?
This is what I have now:
jvm() {
jvmJar {
manifest {
attributes 'Main-Class': 'eu.xx.Runner'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
I did hit that bump and used this work around.
1. Restructure your project
Lets call your project Project.
create another submodule say subA, which will have the gradle notation Project:subA
now, subA has your multiplatform code in it (It is the gradle project with apply :kotlin-multiplafrom) in its build.gradle
2. Add Another submodule
create another submodule which targets only jvm say subB, which will have the gradle notation Project:subB
So, subB will have plugins: 'application' and 'org.jetbrains.kotlin.jvm'
3. Add your module as a gradle dependency (see my build.gradle)
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.31'
id "application"
}
apply plugin: "kotlinx-serialization"
group 'tz.or.self'
version '0.0.0'
mainClassName = "com.example.MainKt"
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
dependencies {
implementation project(':subA')
}
you can proceed and build subB as you would a regular java project or even use the existing plugins, it will work
Got it working with the multiplatform plugin in kotlin 1.3.61:
The following works for a main file in src/jvmMain/kotlin/com/example/Hello.kt
Hello.kt must also specify its package as package com.example
I configured my jvm target in this way:
kotlin {
targets {
jvm()
configure([jvm]) {
withJava()
jvmJar {
manifest {
attributes 'Main-Class': 'com.example.HelloKt'
}
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
}
}
Got it to work with a slightly modified version of what luca992 did:
kotlin {
jvm() {
withJava()
jvmJar {
manifest {
attributes 'Main-Class': 'sample.MainKt'
}
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
...
}
The only way to get gradle/multiplatform working appears to be endless trial and error; It's a nightmare, it's not being built as a "build" system so much as a "build system"; to put it another way, these two tools (together or in isolation) are a means of implementing only a single software development life cycle that the plugin maker intended, however, if you've engineered a desired software lifecycle and CI/CD system and now your trying to implement that engineering, it will be MUCH harder to do it with these tools than it would be to do it with scripts, code or maven. There are a number of reasons for this:
Massive changing in coding convention due to the plugin makers only exposing bar minimum configurability, probably only giving access to the things they need for their own personal project.
Very poor documentation updates; Kotlin, gradle and plugins are changing so rapidly I have begun to seriously question the usefulness of these tools.
Thus, at the time of writing this seems to be the correct syntax to use when using kotlin 1.3.72, multiplatform 1.3.72, ktor 1.3.2 and gradle 6.2.2 (using the kts format).
Note the fatJar seems to assemble correctly but won't run, it can't find the class, so I included the second runLocally task I've been using in the mean time.
This isn't a complete solution so I hate posting it on here, but from what I can tell... it is the most complete and up to date solution I can find documented anywhere.
//Import variables from gradle.properties
val environment: String by project
val kotlinVersion: String by project
val ktorVersion: String by project
val kotlinExposedVersion: String by project
val mySqlConnectorVersion: String by project
val logbackVersion: String by project
val romeToolsVersion: String by project
val klaxonVersion: String by project
val kotlinLoggingVersion: String by project
val skrapeItVersion: String by project
val jsoupVersion: String by project
val devWebApiServer: String by project
val devWebApiServerVersion: String by project
//Build File Configuration
plugins {
java
kotlin("multiplatform") version "1.3.72"
}
group = "com.app"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
jcenter()
jcenter {
url = uri("https://kotlin.bintray.com/kotlin-js-wrappers")
}
maven {
url = uri("https://jitpack.io")
}
}
//Multiplatform Configuration
kotlin {
jvm {
compilations {
val main = getByName("main")
tasks {
register<Jar>("buildFatJar") {
group = "application"
manifest {
attributes["Implementation-Title"] = "Gradle Jar File Example"
attributes["Implementation-Version"] = archiveVersion
attributes["Main-Class"] = "com.app.BackendAppKt"
}
archiveBaseName.set("${project.name}-fat")
from(main.output.classesDirs, main.compileDependencyFiles)
with(jar.get() as CopySpec)
}
register<JavaExec>("runLocally") {
group = "application"
setMain("com.app.BackendAppKt")
classpath = main.output.classesDirs
classpath += main.compileDependencyFiles
}
}
}
}
js {
browser { EXCLUDED FOR LENGTH }
}
sourceSets { EXCLUDED FOR LENGTH }
}