├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.sbt
├── project
├── build.properties
└── plugins.sbt
└── src
├── main
└── scala
│ ├── Keys.scala
│ ├── KotlinCompile.scala
│ ├── KotlinPlugin.scala
│ ├── KotlinTest.scala
│ ├── KotlinVersion.scala
│ └── UpdateChecker.scala
└── sbt-test
└── kotlin
├── basic-android
├── build.sbt
├── project.properties
├── project
│ ├── android.sbt
│ └── plugins.sbt
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── MainActivity.kt
│ │ └── res
│ │ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ │ ├── layout
│ │ └── main.xml
│ │ └── values
│ │ └── strings.xml
├── test
└── tests.sbt
├── basic-tests
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── simple.kt
│ └── test
│ │ └── kotlin
│ │ └── SimpleTest.kt
└── test
├── basic
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ └── main
│ │ └── kotlin
│ │ └── simple.kt
└── test
├── extensions-android
├── build.sbt
├── project.properties
├── project
│ ├── android.sbt
│ └── plugins.sbt
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── MainActivity.kt
│ │ └── res
│ │ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ │ ├── layout
│ │ └── main.xml
│ │ └── values
│ │ └── strings.xml
├── test
└── tests.sbt
├── kotlin-1.1-compat
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ └── main
│ │ └── kotlin
│ │ ├── SimpleScript.kts
│ │ └── simple.kt
└── test
├── kotlin-1.2-compat
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ └── main
│ │ └── kotlin
│ │ ├── SimpleScript.kts
│ │ └── simple.kt
└── test
├── kotlin-1.3-compat
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ └── main
│ │ └── kotlin
│ │ ├── SimpleScript.kts
│ │ └── simple.kt
└── test
├── kotlin-script
├── build.sbt
├── project
│ ├── build.properties
│ └── plugins.sbt
├── src
│ └── main
│ │ └── kotlin
│ │ └── SimpleScript.kts
└── test
├── mixed-tests
├── build.sbt
├── project
│ └── plugins.sbt
├── src
│ ├── main
│ │ ├── java
│ │ │ └── demo
│ │ │ │ └── JavaCalculator.java
│ │ └── kotlin
│ │ │ └── Calculator.kt
│ └── test
│ │ └── kotlin
│ │ └── MixedTest.kt
└── test
└── mixed
├── build.sbt
├── project
└── plugins.sbt
├── src
└── main
│ ├── java
│ └── demo
│ │ ├── JavaA.java
│ │ └── JavaB.java
│ ├── kotlin
│ ├── a.kt
│ ├── b.kt
│ ├── script.kts
│ └── simple.kt
│ └── scala
│ └── ScalaA.scala
├── test
└── tests.sbt
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .idea
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | os:
3 | - linux
4 | jdk:
5 | - oraclejdk8
6 | cache:
7 | directories:
8 | - $HOME/.m2/repository
9 | - $HOME/.sbt
10 | - $HOME/.ivy2
11 | android:
12 | components:
13 | - build-tools-23.0.1
14 | - platform-tools
15 | - tools
16 | - extra
17 | script:
18 | - curl -o sbt-launcher.sh https://raw.githubusercontent.com/paulp/sbt-extras/master/sbt
19 | - chmod a+x ./sbt-launcher.sh
20 | - ./sbt-launcher.sh compile scripted
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Perry
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kotlin-plugin
2 |
3 | [](https://travis-ci.org/pfn/kotlin-plugin)
4 |
5 | Build kotlin code using sbt
6 |
7 | Current version 2.0.0
8 |
9 | ## Usage
10 |
11 | * for sbt 1.0.0+ `addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % "2.0.0")`
12 | * for sbt 0.13.x `addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % "1.0.9")`
13 | * Kotlin code will build automatically from `src/XXX/kotlin`
14 | * If necessary, add `kotlinLib("stdlib")`, it is not included by default.
15 | * Loading standard kotlin libraries and plugins: use `kotlinLib(NAME)` as
16 | above to load standard kotlin modules provided by JetBrains. For JetBrains
17 | kotlin compiler plugins, use `kotlinPlugin(NAME)` (e.g.
18 | `kotlinPlugin("android-extensions")`). The difference is that the latter
19 | marks the module as a `compile-internal` dependency and will be excluded
20 | from the final build product.
21 | * Any other libraries can be loaded using the normal `libraryDependencies`
22 | mechanism. Compiler plugins should be added as a normal `libraryDependency`
23 | but specified to be `% "compile-internal"`
24 | * If a non-standard Classpath key needs to be added to the kotlin compile step,
25 | it can be added using the `kotlinClasspath(KEY)` function
26 | * For example, to compile with the android platform using `android-sdk-plugin`:
27 | `kotlinClasspath(Compile, bootClasspath in Android)`
28 |
29 | ## Options
30 |
31 | * `kotlincPluginOptions`: specifies options to pass to kotlin compiler plugins.
32 | Use `val plugin = KotlinPluginOptions(PLUGINID)` and
33 | `plugin.option(KEY, VALUE)` to populate this setting
34 | * `kotlinSource`: specifies kotlin source directory, defaults to
35 | `src/main/kotlin` and `src/test/kotlin`
36 | * `kotlinVersion`: specifies versions of kotlin compiler and libraries to use,
37 | defaults to `1.3.41`
38 | * `kotlinLib(LIB)`: load a standard kotlin library, for example
39 | `kotlinLib("stdlib")`; the library will utilize the version specified in
40 | `kotlinVersion`
41 | plugin
42 | * `kotlincOptions`: options to pass to the kotlin compiler
43 |
44 | ### Examples
45 |
46 | * See the [test cases](src/sbt-test/kotlin) for this plugin
47 |
48 | ### Limitations
49 |
50 | * currently requires kotlin 1.1.4+
51 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | name := "kotlin-plugin"
2 |
3 | organization := "com.hanhuy.sbt"
4 |
5 | version := "2.0.1-SNAPSHOT"
6 |
7 | scalacOptions ++= Seq("-deprecation","-Xlint","-feature")
8 | /*
9 | libraryDependencies ++= Seq(
10 | "com.hanhuy.sbt" %% "bintray-update-checker" % "0.2"
11 | )
12 | */
13 |
14 | libraryDependencies ++= Seq(
15 | "io.argonaut" %% "argonaut" % "6.2",
16 | "org.scalaz" %% "scalaz-core" % "7.2.28"
17 | )
18 |
19 | sbtPlugin := true
20 |
21 | // build info plugin
22 |
23 | enablePlugins(BuildInfoPlugin, SbtPlugin)
24 |
25 | buildInfoPackage := "kotlin"
26 |
27 | // bintray
28 | bintrayRepository := "sbt-plugins"
29 |
30 | publishMavenStyle := false
31 |
32 | licenses += ("MIT", url("http://opensource.org/licenses/MIT"))
33 |
34 | bintrayOrganization := None
35 |
36 | // scripted
37 | scriptedLaunchOpts ++= Seq(
38 | "-Xmx1024m",
39 | "-Dplugin.version=" + version.value
40 | )
41 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.3.3
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
2 |
3 | addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.4")
4 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0")
--------------------------------------------------------------------------------
/src/main/scala/Keys.scala:
--------------------------------------------------------------------------------
1 | package kotlin
2 |
3 | import sbt._
4 |
5 | /**
6 | * @author pfnguyen
7 | */
8 | object Keys {
9 | sealed trait KotlinCompileOrder
10 |
11 | val Kotlin = config("kotlin")
12 | val KotlinInternal = config("kotlin-internal").hide
13 |
14 | val updateCheck = TaskKey[Unit]("update-check", "check for a new version of the plugin")
15 | val kotlinCompile = TaskKey[Unit]("kotlin-compile",
16 | "runs kotlin compilation, occurs before normal compilation")
17 | val kotlincPluginOptions = TaskKey[Seq[String]]("kotlinc-plugin-options",
18 | "kotlin compiler plugin options")
19 | val kotlinSource = SettingKey[File]("kotlin-source", "kotlin source directory")
20 | val kotlinVersion = SettingKey[String]("kotlin-version",
21 | "version of kotlin to use for building")
22 | val kotlincOptions = SettingKey[Seq[String]]("kotlinc-options",
23 | "options to pass to the kotlin compiler")
24 | val kotlincJvmTarget = SettingKey[String]("kotlinc-jvm-target",
25 | "jvm target to use for building")
26 |
27 | def kotlinLib(name: String) = sbt.Keys.libraryDependencies +=
28 | "org.jetbrains.kotlin" % ("kotlin-" + name) % kotlinVersion.value
29 |
30 | def kotlinPlugin(name: String) = sbt.Keys.libraryDependencies +=
31 | "org.jetbrains.kotlin" % ("kotlin-" + name) % kotlinVersion.value % "compile-internal"
32 |
33 | def kotlinClasspath(config: Configuration, classpathKey: Def.Initialize[sbt.Keys.Classpath]): Setting[_] =
34 | kotlincOptions in config ++= {
35 | "-cp" :: classpathKey.value.map(_.data.getAbsolutePath).mkString(
36 | java.io.File.pathSeparator) ::
37 | Nil
38 | }
39 |
40 | case class KotlinPluginOptions(pluginId: String) {
41 | def option(key: String, value: String) =
42 | s"plugin:$pluginId:$key=$value"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/scala/KotlinCompile.scala:
--------------------------------------------------------------------------------
1 | package kotlin
2 |
3 | import java.io.File
4 | import java.lang.reflect.{Field, Method}
5 | import java.util.jar.JarEntry
6 |
7 | import sbt.Keys.{Classpath, TaskStreams}
8 | import sbt._
9 | import sbt.io._
10 | import sbt.internal.inc.classpath.ClasspathUtilities
11 |
12 | import collection.JavaConverters._
13 | import scala.util.Try
14 |
15 | /**
16 | * @author pfnguyen
17 | */
18 | object KotlinCompile {
19 |
20 | def grepjar(jarfile: File)(pred: JarEntry => Boolean): Boolean =
21 | jarfile.isFile && Using.jarFile(false)(jarfile) { in =>
22 | in.entries.asScala exists pred
23 | }
24 |
25 | lazy val kotlinMemo = scalaz.Memo.immutableHashMapMemo[Classpath, KotlinReflection](cp =>
26 | KotlinReflection.fromClasspath(cp))
27 |
28 | def compile(options: Seq[String],
29 | jvmTarget: String,
30 | sourceDirs: Seq[File],
31 | kotlinPluginOptions: Seq[String],
32 | classpath: Classpath,
33 | compilerClasspath: Classpath,
34 | output: File, s: TaskStreams): Unit = {
35 | import language.reflectiveCalls
36 | val stub = KotlinStub(s, kotlinMemo(compilerClasspath))
37 | val args = stub.compilerArgs
38 | stub.parse(args.instance, options.toList)
39 | val kotlinFiles = "*.kt" || "*.kts"
40 | val javaFiles = "*.java"
41 |
42 | val kotlinSources = sourceDirs.flatMap(d => (d ** kotlinFiles).get).distinct
43 | val javaSources = sourceDirs.filterNot(f => sourceDirs.exists(f0 =>
44 | f0.relativeTo(f).isDefined && f != f0)) map (d =>
45 | (d, (d ** javaFiles).get)) filter (_._2.nonEmpty)
46 | if (kotlinSources.isEmpty) {
47 | s.log.debug("No sources found, skipping kotlin compile")
48 | } else {
49 | s.log.debug(s"Compiling sources $kotlinSources")
50 | def pluralizeSource(count: Int) =
51 | if (count == 1) "source" else "sources"
52 | val message =
53 | s"Compiling ${kotlinSources.size} Kotlin ${pluralizeSource(kotlinSources.size)}"
54 | s.log.info(message)
55 | args.freeArgs = (kotlinSources ++ javaSources.map(_._1)).map(_.getAbsolutePath).asJava
56 | args.noStdlib = true
57 | args.jvmTarget = jvmTarget
58 | val fcpjars = classpath.map(_.data.getAbsoluteFile)
59 | val (pluginjars, cpjars) = fcpjars.partition {
60 | grepjar(_)(_.getName.startsWith(
61 | "META-INF/services/org.jetbrains.kotlin.compiler.plugin"))
62 | }
63 | val cp = cpjars.mkString(File.pathSeparator)
64 | val pcp = pluginjars.map(_.getAbsolutePath).toArray
65 | args.classpath = Option(args.classpath[String]).fold(cp)(_ + File.pathSeparator + cp)
66 | args.pluginClasspaths = Option(args.pluginClasspaths[Array[String]]).fold(pcp)(_ ++ pcp)
67 | args.pluginOptions = Option(args.pluginOptions[Array[String]]).fold(
68 | kotlinPluginOptions.toArray)(_ ++ kotlinPluginOptions.toArray[String])
69 | output.mkdirs()
70 | args.destination = output.getAbsolutePath
71 | stub.compile(args.instance)
72 | }
73 | }
74 | }
75 |
76 | object KotlinReflection {
77 | def fromClasspath(cp: Classpath): KotlinReflection = {
78 | val cl = ClasspathUtilities.toLoader(cp.map(_.data))
79 | val compilerClass = cl.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
80 | val servicesClass = cl.loadClass("org.jetbrains.kotlin.config.Services")
81 | val messageCollectorClass = cl.loadClass("org.jetbrains.kotlin.cli.common.messages.MessageCollector")
82 | val commonCompilerArgsClass = cl.loadClass("org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments")
83 |
84 | val compilerExec = Try(
85 | compilerClass.getMethod("exec",
86 | messageCollectorClass, servicesClass, commonCompilerArgsClass)
87 | ).toOption.getOrElse {
88 |
89 | val commonToolArguments = cl.loadClass(
90 | "org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments")
91 | val clitool = cl.loadClass(
92 | "org.jetbrains.kotlin.cli.common.CLITool")
93 | clitool.getMethod("exec",
94 | messageCollectorClass, servicesClass, commonToolArguments)
95 | }
96 |
97 | KotlinReflection(
98 | cl,
99 | servicesClass,
100 | compilerClass,
101 | cl.loadClass("org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments"),
102 | messageCollectorClass,
103 | commonCompilerArgsClass,
104 | compilerExec,
105 | servicesClass.getDeclaredField("EMPTY"))
106 | }
107 | }
108 | case class KotlinReflection(cl: ClassLoader,
109 | servicesClass: Class[_],
110 | compilerClass: Class[_],
111 | compilerArgsClass: Class[_],
112 | messageCollectorClass: Class[_],
113 | commonCompilerArgsClass: Class[_],
114 | compilerExec: Method,
115 | servicesEmptyField: Field)
116 | case class KotlinStub(s: TaskStreams, kref: KotlinReflection) {
117 | import language.reflectiveCalls
118 | import kref._
119 |
120 | def messageCollector: AnyRef = {
121 | type CompilerMessageLocation = {
122 | def getPath: String
123 | def getLine: Int
124 | def getColumn: Int
125 | }
126 |
127 | import java.lang.reflect.{Proxy, InvocationHandler}
128 | val messageCollectorInvocationHandler = new InvocationHandler {
129 | override def invoke(proxy: scala.Any, method: Method, args: Array[AnyRef]) = {
130 | if (method.getName == "report") {
131 | val Array(severity, message, location) = args
132 | val l = location.asInstanceOf[CompilerMessageLocation]
133 | val msg = Option(l).map(x => x.getPath).fold(message.toString)(loc =>
134 | loc + ": " + l.getLine + ", " + l.getColumn + ": " + message)
135 | severity.toString match {
136 | case "INFO" => s.log.info(msg)
137 | case "WARNING" => s.log.warn(msg)
138 | case "STRONG_WARNING" => s.log.warn(msg)
139 | case "ERROR" | "EXCEPTION" => s.log.error(msg)
140 | case "OUTPUT" | "LOGGING" => s.log.debug(msg)
141 | }
142 | }
143 | null
144 | }
145 | }
146 |
147 | Proxy.newProxyInstance(cl, Array(messageCollectorClass), messageCollectorInvocationHandler)
148 | }
149 |
150 | def parse(args: Object, options: List[String]): Unit = {
151 | // TODO FIXME, this is much worse than it used to be, the parsing api has been
152 | // deeply in flux since 1.1.x
153 | val parser = kref.cl.loadClass(
154 | "org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt")
155 | val commonToolArguments = cl.loadClass(
156 | "org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments")
157 | val parserMethod = parser.getMethod("parseCommandLineArguments", classOf[java.util.List[java.lang.String]], commonToolArguments)
158 | import collection.JavaConverters._
159 | parserMethod.invoke(null, options.asJava, args)
160 | }
161 |
162 | def compilerArgs = {
163 | import language.dynamics
164 | new Dynamic {
165 | def withFirstUpper(string: String): String = string.head.toUpper + string.tail
166 | def getterName(field: String) = s"get${withFirstUpper(field)}"
167 | def setterName(field: String) = s"set${withFirstUpper(field)}"
168 |
169 | def selectDynamic[A](field: String): A = {
170 | val methodName = getterName(field)
171 | val getterOpt = compilerArgsClass.getMethods.find(_.getName == methodName)
172 | getterOpt match {
173 | case Some(getter) => getter.invoke(instance).asInstanceOf[A]
174 | case None => compilerArgsClass.getField(field).get(instance).asInstanceOf[A]
175 | }
176 | }
177 |
178 | def updateDynamic(field: String)(value: Any): Unit = {
179 | val methodName = setterName(field)
180 | val setterOpt = compilerArgsClass.getMethods.find(_.getName == methodName)
181 | setterOpt match {
182 | case Some(setter) => setter.invoke(instance, value.asInstanceOf[Object])
183 | case None => compilerArgsClass.getField(field).set(instance, value)
184 | }
185 | }
186 |
187 | val instance = compilerArgsClass.getDeclaredConstructor().newInstance().asInstanceOf[AnyRef]
188 | }
189 | }
190 |
191 | def compile(args: AnyRef): Unit = {
192 | val compiler = compilerClass.getDeclaredConstructor().newInstance()
193 | val result = compilerExec.invoke(compiler,
194 | messageCollector, servicesEmptyField.get(null), args: java.lang.Object)
195 | result.toString match {
196 | case "COMPILATION_ERROR" | "INTERNAL_ERROR" =>
197 | throw new MessageOnlyException("Compilation failed. See log for more details")
198 | case _ =>
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/scala/KotlinPlugin.scala:
--------------------------------------------------------------------------------
1 | package kotlin
2 |
3 | import Keys._
4 | import sbt._
5 | import sbt.Keys._
6 | import sbt.plugins.JvmPlugin
7 |
8 | /**
9 | * @author pfnguyen
10 | */
11 | object KotlinPlugin extends AutoPlugin {
12 | override def trigger = allRequirements
13 | override def requires = JvmPlugin
14 |
15 | override def projectConfigurations = KotlinInternal :: Nil
16 |
17 | override def globalSettings = (onLoad := onLoad.value andThen { s =>
18 | Project.runTask(updateCheck in Keys.Kotlin, s).fold(s)(_._1)
19 | }) :: Nil
20 |
21 | private def kotlinScriptCompilerDeps(kotlinVer: String) = {
22 | import scala.math.Ordering.Implicits.infixOrderingOps
23 |
24 | if (KotlinVersion(kotlinVer) <= KotlinVersion("1.3.21")) {
25 | Seq(
26 | "org.jetbrains.kotlin" % "kotlin-script-runtime" % kotlinVer
27 | )
28 | } else {
29 | Seq(
30 | "org.jetbrains.kotlin" % "kotlin-scripting-compiler-embeddable" % kotlinVer % KotlinInternal.name,
31 | "org.jetbrains.kotlin" % "kotlin-scripting-compiler-embeddable" % kotlinVer
32 | )
33 | }
34 | }
35 |
36 | override def projectSettings = Seq(
37 | libraryDependencies ++= Seq(
38 | "org.jetbrains.kotlin" % "kotlin-compiler-embeddable" % kotlinVersion.value % KotlinInternal.name
39 | ) ++ kotlinScriptCompilerDeps(kotlinVersion.value),
40 | managedClasspath in KotlinInternal := Classpaths.managedJars(KotlinInternal, classpathTypes.value, update.value),
41 | updateCheck in Kotlin := {
42 | val log = streams.value.log
43 | UpdateChecker("pfn", "sbt-plugins", "kotlin-plugin") {
44 | case Left(t) =>
45 | log.debug("Failed to load version info: " + t)
46 | case Right((versions, current)) =>
47 | log.debug("available versions: " + versions)
48 | log.debug("current version: " + BuildInfo.version)
49 | log.debug("latest version: " + current)
50 | if (versions(BuildInfo.version)) {
51 | if (BuildInfo.version != current) {
52 | log.warn(
53 | s"UPDATE: A newer kotlin-plugin is available:" +
54 | s" $current, currently running: ${BuildInfo.version}")
55 | }
56 | }
57 | }
58 | },
59 | kotlinVersion := "1.3.50",
60 | kotlincJvmTarget := "1.6",
61 | kotlincOptions := Nil,
62 | kotlincPluginOptions := Nil,
63 | watchSources ++= {
64 | import language.postfixOps
65 | val kotlinSources = "*.kt" || "*.kts"
66 | (sourceDirectories in Compile).value.flatMap(_ ** kotlinSources get) ++
67 | (sourceDirectories in Test).value.flatMap(_ ** kotlinSources get)
68 | }
69 | ) ++ inConfig(Compile)(kotlinCompileSettings) ++
70 | inConfig(Test)(kotlinCompileSettings)
71 |
72 | val autoImport = Keys
73 |
74 | // public to allow kotlin compile in other configs beyond Compile and Test
75 | val kotlinCompileSettings = List(
76 | unmanagedSourceDirectories += kotlinSource.value,
77 | kotlincOptions := kotlincOptions.value,
78 | kotlincJvmTarget := kotlincJvmTarget.value,
79 | kotlincPluginOptions := kotlincPluginOptions.value,
80 | kotlinCompile := Def.task {
81 | KotlinCompile.compile(kotlincOptions.value,
82 | kotlincJvmTarget.value,
83 | sourceDirectories.value, kotlincPluginOptions.value,
84 | dependencyClasspath.value, (managedClasspath in KotlinInternal).value,
85 | classDirectory.value, streams.value)
86 | }.dependsOn (compileInputs in (Compile,compile)).value,
87 | compile := (compile dependsOn kotlinCompile).value,
88 | kotlinSource := sourceDirectory.value / "kotlin",
89 | definedTests in Test ++= KotlinTest.kotlinTests.value
90 | )
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/scala/KotlinTest.scala:
--------------------------------------------------------------------------------
1 | package sbt
2 |
3 | import sbt.Keys._
4 | import sbt.internal.inc.classfile.Analyze
5 | import sbt.internal.inc.classpath.ClasspathUtilities
6 | import sbt.internal.inc._
7 | import xsbti.compile._
8 |
9 | object KotlinTest {
10 | private object EmptyLookup extends Lookup {
11 | def changedClasspathHash: Option[Vector[FileHash]] = None
12 |
13 | def analyses: Vector[CompileAnalysis] = Vector.empty
14 |
15 | def lookupOnClasspath(binaryClassName: String): Option[File] = None
16 |
17 | def lookupAnalysis(binaryClassName: String): Option[CompileAnalysis] = None
18 | def changedBinaries(previousAnalysis: xsbti.compile.CompileAnalysis): Option[Set[java.io.File]] = None
19 | def changedSources(previousAnalysis: xsbti.compile.CompileAnalysis): Option[xsbti.compile.Changes[java.io.File]] = None
20 | def removedProducts(previousAnalysis: xsbti.compile.CompileAnalysis): Option[Set[java.io.File]] = None
21 | def shouldDoIncrementalCompilation(changedClasses: Set[String],analysis: xsbti.compile.CompileAnalysis): Boolean = true
22 |
23 | def hashClasspath(x$1: Array[java.io.File]): java.util.Optional[Array[xsbti.compile.FileHash]] = java.util.Optional.empty()
24 | }
25 |
26 | val kotlinTests = Def.task {
27 | val out = ((target in Test).value ** "scala-*").get.head / "test-classes"
28 | val srcs = ((sourceDirectory in Test).value ** "*.kt").get.toList
29 | val xs = (out ** "*.class").get.toList
30 |
31 | val loader = ClasspathUtilities.toLoader((fullClasspath in Test).value map {
32 | _.data
33 | })
34 | val log = streams.value.log
35 | val output = new SingleOutput {
36 | def getOutputDirectory: File = out
37 | }
38 | val a0 = IncrementalCompile(
39 | srcs.toSet,
40 | EmptyLookup,
41 | (fs, changs, callback, clsFileMgr) => {
42 | def readAPI(source: File, classes: Seq[Class[_]]): Set[(String, String)] = {
43 | val (apis, mainClasses, inherits) = ClassToAPI.process(classes)
44 | apis.foreach(callback.api(source, _))
45 | mainClasses.foreach(callback.mainClass(source, _))
46 | inherits.map {
47 | case (from, to) => (from.getName, to.getName)
48 | }
49 | }
50 |
51 | Analyze(xs, srcs, log, output, None)(callback, loader, readAPI)
52 | },
53 | Analysis.Empty,
54 | output,
55 | log,
56 | incOptions.value,
57 | JarUtils.createOutputJarContent(output))._2
58 | val frameworks = (loadedTestFrameworks in Test).value.values.toList
59 | log.info(s"Compiling ${srcs.length} Kotlin source to $out...")
60 | Tests.discover(frameworks, a0, log)._1
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/scala/KotlinVersion.scala:
--------------------------------------------------------------------------------
1 | package kotlin
2 |
3 | import scala.math.Ordering
4 |
5 | case class KotlinVersion(versionString: String) extends AnyVal
6 |
7 | object KotlinVersion {
8 | implicit val versionOrdering: Ordering[KotlinVersion] =
9 | Ordering.by { _.versionString.split("[.-]").map(_.toInt).toIterable }
10 | }
--------------------------------------------------------------------------------
/src/main/scala/UpdateChecker.scala:
--------------------------------------------------------------------------------
1 | package kotlin
2 |
3 | import java.io.{InputStreamReader, BufferedReader, StringWriter}
4 |
5 | import argonaut._, Argonaut._
6 |
7 | import scala.concurrent.Future
8 | import scala.util.{Failure, Success}
9 |
10 | object UpdateChecker {
11 | import scala.concurrent.ExecutionContext.Implicits.global
12 | type Result = (Set[String],String)
13 | type Callback[A] = Either[Throwable,Result] => A
14 |
15 | def apply[A](user: String, repo: String, name: String)(result: Callback[A]): Unit = {
16 | val bintray = new java.net.URL(
17 | s"https://api.bintray.com/packages/$user/$repo/$name")
18 | Future {
19 | val uc = bintray.openConnection()
20 | val in = new BufferedReader(new InputStreamReader(uc.getInputStream, "utf-8"))
21 | try {
22 | val sw = new StringWriter
23 | val buf = Array.ofDim[Char](8192)
24 | Stream.continually(in.read(buf, 0, 8192)) takeWhile (
25 | _ != -1) foreach (sw.write(buf, 0, _))
26 | sw.toString
27 | } finally {
28 | in.close()
29 | }
30 | } onComplete {
31 | case Success(json) =>
32 | val decoded = json.decode[PackageInfo]
33 | val res: Either[Throwable, Result] = decoded match {
34 | case Left(Left(str)) =>
35 | Left(new IllegalArgumentException(str))
36 | case Left(Right(cursorHistory)) =>
37 | Left(new IllegalArgumentException(cursorHistory._1))
38 | case Right(packageInfo) =>
39 | Right(packageInfo.versions.toSet -> packageInfo.version)
40 | }
41 | result(res)
42 | case Failure(t) => result(Left(t))
43 | }
44 | }
45 |
46 | implicit def PackageInfoCodecJson: CodecJson[PackageInfo] = casecodec3(
47 | PackageInfo.apply, PackageInfo.unapply)("name", "latest_version", "versions")
48 |
49 | case class PackageInfo(name: String, version: String, versions: List[String])
50 | }
51 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/build.sbt:
--------------------------------------------------------------------------------
1 | enablePlugins(AndroidApp)
2 |
3 | kotlinClasspath(Compile, bootClasspath in Android)
4 |
5 | kotlinLib("stdlib")
6 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/project.properties:
--------------------------------------------------------------------------------
1 | target=android-22
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/project/android.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scala-android" % "sbt-android" % "2.0.0-SNAPSHOT")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package sbt.kotlin.test
2 |
3 | import android.app.Activity
4 | import android.os.Bundle
5 |
6 | class MainActivity : Activity()
7 | {
8 | /** Called when the activity is first created. */
9 | override fun onCreate(savedInstanceState: Bundle?)
10 | {
11 | super.onCreate(savedInstanceState)
12 | setContentView(R.layout.main)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/basic-android/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/basic-android/src/main/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/basic-android/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/basic-android/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainActivity
4 |
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/test:
--------------------------------------------------------------------------------
1 | > android:package
2 | $ exists target/android/output/basic-android-debug.apk
3 | > checkDex
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-android/tests.sbt:
--------------------------------------------------------------------------------
1 | import android.Keys._
2 | import sys.process._
3 |
4 | val androidBuilder = SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android
5 |
6 | TaskKey[Unit]("checkDex") := {
7 | val p = androidBuilder.value
8 | val s = streams.value
9 | val layout = (projectLayout in Android).value
10 | implicit val out = outputLayout.value
11 | val tools = p(s.log).getTargetInfo.getBuildTools.getLocation
12 | val dexdump = tools / "dexdump"
13 | val lines = Seq(
14 | dexdump.getAbsolutePath, "-i",
15 | (layout.dex / "classes.dex").getAbsolutePath).lineStream
16 | val hasKotlinClasses = lines map (_.trim) exists { l =>
17 | l.startsWith("Class descriptor") && l.endsWith("'Lkotlin/Unit;'")
18 | }
19 | if (!hasKotlinClasses) {
20 | lines filter (_.trim.startsWith("Class descriptor")) foreach (l => s.log.info(l))
21 | sys.error("Kotlin classes not found")
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-tests/build.sbt:
--------------------------------------------------------------------------------
1 | import sbt.complete.Parsers.spaceDelimited
2 |
3 | import scala.xml.{NodeSeq, XML}
4 |
5 | kotlinLib("stdlib")
6 |
7 | libraryDependencies ++= Seq(
8 | "com.novocode" % "junit-interface" % "0.11" % Test
9 | )
10 |
11 | lazy val checkTestPass = inputKey[Unit]("Check if a given test-report has one success test")
12 | checkTestPass := {
13 | val args: Seq[String] = spaceDelimited("").parsed
14 | val testName = args.head
15 |
16 | val xml = XML.load(s"target/test-reports/$testName.xml")
17 | val totalTests = getInt(xml \\ "testsuite" \ "@tests")
18 | val failures = getInt(xml \\ "testsuite" \ "@failures")
19 | val errors = getInt(xml \\ "testsuite" \ "@errors")
20 | val skipped = getInt(xml \\ "testsuite" \ "@skipped")
21 |
22 | if (totalTests == 0 || failures > 0 || errors > 0 || skipped > 0) {
23 | sys.error("Tests not passed")
24 | }
25 | }
26 |
27 | def getInt(path: NodeSeq): Int = path.text.toInt
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-tests/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-tests/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | fun main(args: Array) {
4 | println("Hello, world!")
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-tests/src/test/kotlin/SimpleTest.kt:
--------------------------------------------------------------------------------
1 | import org.junit.Test
2 | import junit.framework.TestCase.assertEquals
3 |
4 | class SimpleTest {
5 |
6 | @Test
7 | fun `should works`() {
8 | assertEquals(4, 2 + 2)
9 | }
10 |
11 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic-tests/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > test
3 | > "checkTestPass SimpleTest"
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | val listClasses = taskKey[Unit]("listClasses")
4 |
5 | listClasses := {
6 | val classes = (classDirectory in Compile).value.listFiles()
7 | streams.value.log.info("classes: " + classes)
8 | }
9 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | fun main(args: Array) {
3 | println("Hello, world!")
4 | }
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/basic/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > listClasses
3 | $ exists target/scala-2.12/classes/demo/SimpleKt.class
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/build.sbt:
--------------------------------------------------------------------------------
1 | enablePlugins(AndroidApp)
2 | javacOptions in Compile ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil
3 |
4 | kotlinClasspath(Compile, bootClasspath in Android)
5 | kotlinPlugin("android-extensions")
6 | kotlinLib("stdlib")
7 | kotlincPluginOptions in Compile ++= {
8 | val plugin = KotlinPluginOptions("org.jetbrains.kotlin.android")
9 | val layout = (projectLayout in Android).value
10 | plugin.option("package", applicationId.value) ::
11 | plugin.option("variant", "main;" + layout.res.getCanonicalPath) ::
12 | Nil
13 | }
14 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/project.properties:
--------------------------------------------------------------------------------
1 | target=android-22
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/project/android.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scala-android" % "sbt-android" % "2.0.0-SNAPSHOT")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/kotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package sbt.kotlin.test
2 |
3 | import android.app.Activity
4 | import android.os.Bundle
5 |
6 | import kotlinx.android.synthetic.main.main.*
7 |
8 | class MainActivity : Activity()
9 | {
10 | /** Called when the activity is first created. */
11 | override fun onCreate(savedInstanceState: Bundle?)
12 | {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.main)
15 | this_is_test.setText("Wow?")
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pfn/kotlin-plugin/c5b0fe4f66982821520b2c4853830cf34d8ecc29/src/sbt-test/kotlin/extensions-android/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainActivity
4 |
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/test:
--------------------------------------------------------------------------------
1 | > android:package
2 | $ exists target/android/output/extensions-android-debug.apk
3 | > checkDex
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/extensions-android/tests.sbt:
--------------------------------------------------------------------------------
1 | import android.Keys._
2 | import sys.process._
3 |
4 | val androidBuilder = SettingKey[Logger => com.android.builder.core.AndroidBuilder]("android-builder") in Android
5 |
6 | TaskKey[Unit]("checkDex") := {
7 | implicit val out = outputLayout.value
8 | val p = androidBuilder.value
9 | val s = streams.value
10 | val layout = (projectLayout in Android).value
11 | val tools = p(s.log).getTargetInfo.getBuildTools.getLocation
12 | val dexdump = tools / "dexdump"
13 | val lines = Seq(
14 | dexdump.getAbsolutePath, "-i",
15 | (layout.dex / "classes.dex").getAbsolutePath).lineStream
16 | val hasKotlinClasses = lines map (_.trim) exists { l =>
17 | l.startsWith("Class descriptor") && l.endsWith("'Lkotlin/Unit;'")
18 | }
19 | if (!hasKotlinClasses) {
20 | lines filter (_.trim.startsWith("Class descriptor")) foreach (l => s.log.info(l))
21 | sys.error("Kotlin classes not found")
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.1-compat/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | kotlinVersion := "1.1.4-3"
4 |
5 | val listClasses = taskKey[Unit]("listClasses")
6 |
7 | listClasses := {
8 | val classes = (classDirectory in Compile).value.listFiles()
9 | streams.value.log.info("classes: " + classes)
10 | }
11 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.1-compat/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % sys.props("plugin.version"))
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.1-compat/src/main/kotlin/SimpleScript.kts:
--------------------------------------------------------------------------------
1 | println("Hello world!")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.1-compat/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | fun main(args: Array) {
3 | val map = mapOf("key" to 42)
4 | val emptyMap = map - "key"
5 |
6 | val list1 = listOf("a", "b")
7 | val list2 = listOf("x", "y", "z")
8 | val minSize = minOf(list1.size, list2.size)
9 | val longestList = maxOf(list1, list2, compareBy { it.size })
10 | }
11 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.1-compat/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > listClasses
3 | $ exists target/scala-2.12/classes/demo/SimpleKt.class
4 | $ exists target/scala-2.12/classes/SimpleScript.class
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.2-compat/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | kotlinVersion := "1.2.71"
4 |
5 | val listClasses = taskKey[Unit]("listClasses")
6 |
7 | listClasses := {
8 | val classes = (classDirectory in Compile).value.listFiles()
9 | streams.value.log.info("classes: " + classes)
10 | }
11 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.2-compat/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % sys.props("plugin.version"))
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.2-compat/src/main/kotlin/SimpleScript.kts:
--------------------------------------------------------------------------------
1 | println("Hello world!")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.2-compat/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | fun main(args: Array) {
3 | // Test some Kotlin 1.2 features
4 | val items = (1..9).map { it * it }
5 |
6 | val chunkedIntoLists = items.chunked(4)
7 | val points3d = items.chunked(3) { (x, y, z) -> Triple(x, y, z) }
8 | val windowed = items.windowed(4)
9 | val slidingAverage = items.windowed(4) { it.average() }
10 | val pairwiseDifferences = items.zipWithNext { a, b -> b - a }
11 |
12 | println("Hello, world!")
13 | }
14 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.2-compat/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > listClasses
3 | $ exists target/scala-2.12/classes/demo/SimpleKt.class
4 | $ exists target/scala-2.12/classes/SimpleScript.class
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.3-compat/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | kotlinVersion := "1.3.41"
4 |
5 | val listClasses = taskKey[Unit]("listClasses")
6 |
7 | listClasses := {
8 | val classes = (classDirectory in Compile).value.listFiles()
9 | streams.value.log.info("classes: " + classes)
10 | }
11 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.3-compat/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % sys.props("plugin.version"))
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.3-compat/src/main/kotlin/SimpleScript.kts:
--------------------------------------------------------------------------------
1 | println("Hello world!")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.3-compat/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | fun main(args: Array) {
3 | // Test some Kotlin 1.3 features
4 | val keys = 'a'..'f'
5 | val map = keys.associateWith { it.toString().repeat(5).capitalize() }
6 | map.forEach { println(it) }
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-1.3-compat/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > listClasses
3 | $ exists target/scala-2.12/classes/demo/SimpleKt.class
4 | $ exists target/scala-2.12/classes/SimpleScript.class
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-script/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | kotlinVersion := "1.3.21"
4 |
5 | val listClasses = taskKey[Unit]("listClasses")
6 |
7 | listClasses := {
8 | val classes = (classDirectory in Compile).value.listFiles()
9 | streams.value.log.info("classes: " + classes)
10 | }
11 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-script/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.2.8
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-script/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % sys.props("plugin.version"))
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-script/src/main/kotlin/SimpleScript.kts:
--------------------------------------------------------------------------------
1 | println("Hello world!")
2 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/kotlin-script/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > listClasses
3 | $ exists target/scala-2.12/classes/SimpleScript.class
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/build.sbt:
--------------------------------------------------------------------------------
1 | import sbt.complete.Parsers.spaceDelimited
2 |
3 | import scala.xml.{NodeSeq, XML}
4 |
5 | kotlinLib("stdlib")
6 |
7 | libraryDependencies ++= Seq(
8 | "com.novocode" % "junit-interface" % "0.11" % Test
9 | )
10 |
11 | lazy val checkTestPass = inputKey[Unit]("Check if a given test-report has one success test")
12 | checkTestPass := {
13 | val args: Seq[String] = spaceDelimited("").parsed
14 | val testName = args.head
15 |
16 | val xml = XML.load(s"target/test-reports/$testName.xml")
17 | val totalTests = getInt(xml \\ "testsuite" \ "@tests")
18 | val failures = getInt(xml \\ "testsuite" \ "@failures")
19 | val errors = getInt(xml \\ "testsuite" \ "@errors")
20 | val skipped = getInt(xml \\ "testsuite" \ "@skipped")
21 |
22 | if (totalTests == 0 || failures > 0 || errors > 0 || skipped > 0) {
23 | sys.error("Tests not passed")
24 | }
25 | }
26 |
27 | def getInt(path: NodeSeq): Int = path.text.toInt
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/src/main/java/demo/JavaCalculator.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | public class JavaCalculator {
4 |
5 | public int sum(int a, int b) {
6 | return a + b;
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/src/main/kotlin/Calculator.kt:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | class Calculator(private val calculator: JavaCalculator) {
4 |
5 | fun sum(a: Int, b: Int): Int = calculator.sum(a, b)
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/src/test/kotlin/MixedTest.kt:
--------------------------------------------------------------------------------
1 | import org.junit.Test
2 | import junit.framework.TestCase.assertEquals
3 | import demo.Calculator
4 | import demo.JavaCalculator
5 |
6 | class MixedTest {
7 |
8 | @Test
9 | fun `should sum 2 plus 2`() {
10 | val calculator = Calculator(JavaCalculator())
11 | assertEquals(4, calculator.sum(2, 2))
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed-tests/test:
--------------------------------------------------------------------------------
1 | > compile
2 | > test
3 | > "checkTestPass MixedTest"
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/build.sbt:
--------------------------------------------------------------------------------
1 | kotlinLib("stdlib")
2 |
3 | kotlincOptions += "-verbose"
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | {
2 | val ver = System.getProperty("plugin.version")
3 | if (ver == null)
4 | throw new RuntimeException("""
5 | |The system property 'plugin.version' is not defined.
6 | |Specify this property using scriptedLaunchOpts -Dplugin.version."""
7 | .stripMargin)
8 | else addSbtPlugin("com.hanhuy.sbt" % "kotlin-plugin" % ver)
9 | }
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/java/demo/JavaA.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | public class JavaA {
4 | }
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/java/demo/JavaB.java:
--------------------------------------------------------------------------------
1 | package demo;
2 |
3 | public class JavaB extends KotlinA {
4 | }
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/kotlin/a.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | open class KotlinA {
3 | }
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/kotlin/b.kt:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | class KotlinB : JavaA() {
4 | }
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/kotlin/script.kts:
--------------------------------------------------------------------------------
1 |
2 | println("Hello from Kotlin script")
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/kotlin/simple.kt:
--------------------------------------------------------------------------------
1 | package demo
2 | fun main(args: Array) {
3 | println("Hello, world!")
4 | }
5 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/src/main/scala/ScalaA.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | class ScalaA extends KotlinA
4 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/test:
--------------------------------------------------------------------------------
1 | > debug
2 | > compile
3 | > info
4 | $ exists target/scala-2.12/classes/demo/SimpleKt.class
5 | > checkClasses
6 |
--------------------------------------------------------------------------------
/src/sbt-test/kotlin/mixed/tests.sbt:
--------------------------------------------------------------------------------
1 | TaskKey[Unit]("check-classes") := {
2 | val classes = (classDirectory in Compile).value
3 | val classList = (classes ** "*.class").get
4 | if (classList.size != 7) {
5 | throw new MessageOnlyException(s"Incorrect number of classes: ${classList.size} =>\n${classList.mkString("\n")}")
6 | }
7 | }
8 |
--------------------------------------------------------------------------------