Kotlin repeatable #annotations don't work on jdk-8 - annotations

I have declared a repeatable annotation #Parameter in kotlin as below:
#Repeatable
annotation class Parameter(val name: String);
but when I use it as below the compiler reports an Error:
Only annotations with SOURCE retention can be repeated on JVM version before 1.8
#Parameter("foo")
#Parameter("bar")
fun repeat() = 1;
I'm sure I'm working with jdk-8 in kotlin. and the option jvmTarget also is set to 1.8 for kotlin-1.1.2 gradle plugin.
Q: Why it doesn't works fine?
sourceCompatibility = 1.8
targetCompatibility = 1.8
compileKotlin {
kotlinOptions{
jvmTarget = "1.8"
}
}

If I'm not mistaken, Kotlin compiler currently targets the JDK 1.6 class file format. This means that, on Java, it can't write multiple annotations to the class file.
While conceptually Kotlin supports multiple annotations, until there's proper 1.8 targeting, it can't do so because of the output restrictions.

It is currently not possible with Kotlin. There is a bug opened, please feel free to vote for it: https://youtrack.jetbrains.com/issue/KT-12794

Yes, you can. Just use the "long form" of the annotation.
Follow the end of this thread:
https://discuss.kotlinlang.org/t/issue-with-repeated-java-8-annotations/1667/11

Check the Kotlin compiler settings in IntelliJ. IntelliJ doesn't use gradle to build and run your project by default. It uses the IDEA Kotlin plugin.

Related

How to add java compiler "release" flag to scala project using gradle

I have a scala based project built with gradle, it contains java and scala code. We are upgrading to OpenJDK11 from oracle jdk 8. We are upgrading with binaries compatible with JDK8 by adding release flag to compiler.
I achieved that for java files by
if(JavaVersion.current() > JavaVersion.VERSION_1_9) {
subprojects {
tasks.withType(JavaCompile) {
options.compilerArgs += ["--release", "8"]
}
tasks.withType(ScalaCompile) {
options.compilerArgs += ["--release", "8"]
}
}
}
in build.gradle. This works fine ie the build seems to add the release flag, to test this I added a JDK 11 specific change to java class. ie Used String.repeat in java class and compiler throws error but if I add the same to a scala class it compiles without reporting the error that repeat() is not an method available.
What am I missing does adding release flag to scala compilation mean nothing or how can I achieve this?
The intention is to have binaries that run on JDK 8 or JDK11 we are ok for now to compromise on using JDK11 based new features. So I need to make sure no other developers add jdk11 specific code so that we end up on runtime issues.

Cross-compiled with an incompatible version

I am using eclipse with m2eclipse-scala plugin. Currently, I get the following error message:
exampleA_2.10-2.0.1.jar of module build path is cross-compiled with an incompatible version of Scala (2.10.0). In case this report is mistaken, this check can be disabled in the compiler preference page
It looks like the versions of extracted Scala and Scala IDE match. I just wanted to make sure that this is a "false-negative" as described here and can be safely turned off.
As #The Archetypal Paul suggested, it was because I was using wrong Scala library.
If you are using Scala 2.11 (check at About Scala IDE -> installation details), you can downgrade by following instruction here. It's a lot easier than uninstalling and re-installing Scala IDE as other Stackoverflow posts recommend.
I also faced the same issue->
I am trying to use casbah jar in scala to integrate with mongodb.
After analyzing the problem i found that ->
i am trying to use casbah 2.9.1 version and my scala version is 2.11.8
Root-Cause of such error is : your jar is compiled in 2.9.0 version and you are using scala 2.11.8 version
So, to resolve that i use the jar that is compiled into 2.11 scala version-
<groupId>org.mongodb</groupId>
<artifactId>casbah-core_2.11</artifactId>
<version>3.1.1</version>
I was facing similar issue in Eclipse IDE where I had built a Spark scala project in Maven. The scala version was set to 2.11.
Later, I upgraded Scala-Ide plugin in Eclipse after which my project marked below errors,
exampleA_2.10-2.0.1.jar of module build path is cross-compiled with an incompatible version of Scala (2.10.0). In case this report is mistaken, this check can be disabled in the compiler preference page
Right click project folder > scala > set scala version. Here my scala version was displayed as 2.10. I selected 2.11 and removed all the error messages.

IntelliJ overrides Scala additional compiler options when synced from Gradle

I'm working on a Scala project in IntelliJ IDEA, and using Gradle for configuration and dependency management.
Every time I add some new dependency and sync it into IDEA, it rewrites Additional compiler options into -target:jvm-1.8, what results in a error when I try to make it with IDEA:
Error:scalac: 'jvm-1.8' is not a valid choice for '-target'
Error:scalac: bad option: '-target:jvm-1.8'
So I need to fix it manually.
Can I set target JVM version or compiler parameters (need also -feature option) in my build.gradle, so it would take them from there?
Thanks!
You can add sourceCompatibility = '1.7' to your gradle build file and then refresh, the project will build normally. Note that this way you cannot have Java 8 source in your code, this is a temporary hack until Gradleware or JetBrains solve the issue.
You can also tamper with the IDEA project XML that is generated when running gradle idea. That would give you the option to include additional flags as well. You can check your current xml by opening the project .iml file and identifying what needs to be changed, then use the following code:
apply plugin: 'idea'
idea {
module {
iml {
withXml {
def node = it.asNode()
//modify xml
}
}
}
}
Would not recommend it though, as you will have to stick with using gradle idea and won't be able to properly import straight from the IDEA, but currently there is no better way to have additional flags. Documentation - idea plugin and idea module
I was searching for a solution for this for ages, finally found it - sharing for anyone else reading this.
Taken from: https://devnet.jetbrains.com/message/5523902
subprojects {
tasks.withType(ScalaCompile) {
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
}
}

How to instruct gradle's scala plugin to pick specific JVM among installed ones?

I want to run scala compilation with specific JVM. I'm using Scalatra, and my default JVM is 1.8. With such setup, I run into this problem: Compilation failed: error while loading AnnotatedElement, ConcurrentMap, CharSequence from Java 8 under Scala 2.10?
So I want to use JVM 1.7 for this, how to set it up for gradle "scala" plugin?
How to instruct gradle's scala plugin to pick specific JVM among installed ones?
This isn't currently supported. The best solution is to run Gradle itself with the desired JVM. It might be possible to instead set a different JVM bootstrap class path via...
tasks.withType(ScalaCompile) {
scalaCompileOptions.with {
useAnt = false
fork = true
forkOptions.jvmArgs = [...]
}
}
..., but you would have to figure out the details yourself (see JVM docs). Also you would have to know the JVM installation path.
The scalac compiler has special parameters
–javabootclasspath path
Override Java boot classpath.
–javaextdirs path
Override Java extdirs classpath.
You have to pass those parameters from gradle scala plugin using an additionalParameters parameter
this approach does not requires forking
allprojects {
tasks.withType(ScalaCompile) {
if (sourceCompatibility == '1.7') {
scalaCompileOptions.with {
def jdk7rt = new File("$System.env.JAVA7_HOME", "jre/lib/rt.jar").canonicalPath
def jdk7ext = new File("$System.env.JAVA7_HOME", "jre/lib/ext").canonicalPath
additionalParameters = ["-javabootclasspath $jdk7rt".toString(), "-javaextdirs $jdk7ext".toString()]
}
}
}
}
I used this approach on my OS with JVM 1.7 as default for compiling with JDK8 some subprojects that requires javafx8. So it should work in your case.

Cross build scala using gradle

I've got a Scala project that is built with Gradle. The Scala code is source compatible with scala 2.9 and 2.10 and I'd like to cross build it to both major Scala versions. Does Gradle support this?
For example, my gradle project will have a single module:
build.gradle
src/main/scala/foo.scala
and I'd like the resulting published jars to be:
org-foo_2.9-0.1.jar (with dependency on scala-library 2.9)
org-foo_2.10-0.1.jar (with dependency on scala-library 2.10)
Gradle's Scala plugin doesn't currently support cross-building. It's possible to implement it yourself, though. In my Polyglot Gradle talk, I presented a proof-of-concept.
I am searching for a good example of this. The Gradle manual doesn't mention how to specify Scala version but looking at the source code for the Scala plugin it seems to infer it from the Scala library jar that you specify.
The best example I could find is the Apache Kafka build system. It specifies the Scala version and then uses some additional logic to resolve the correct version of the Scala libraries. It also uses some logic to attach the correct label to the jars its builds to correspond to the correct Scala version.
This feels like a lot of work and something that the build system should do for you like in SBT.