Merge pull request #25 from hsyed/module-naming

#8 now use package in the default module names, and add module_name attr
diff --git a/docs/kotlin/kotlin.html b/docs/kotlin/kotlin.html
index 38077ff..9569070 100644
--- a/docs/kotlin/kotlin.html
+++ b/docs/kotlin/kotlin.html
@@ -162,9 +162,6 @@
           <pre>kotlin_repositories(<a href="#kotlin_repositories.kotlin_release_version">kotlin_release_version</a>)</pre>
 
           <p>Call this in the WORKSPACE file to setup the Kotlin rules.</p>
-<p>Args:a
-  kotlin_release_version: The kotlin compiler release version. If this is not set the latest release version is
-  chosen by default.</p>
 
 
           <h3 id="kotlin_repositories_args">Attributes</h3>
@@ -179,7 +176,8 @@
       <td><code>kotlin_release_version</code></td>
       <td>
         <p><code>Unknown; Optional</code></p>
-        
+        <p>The kotlin compiler release version. If this is not set the latest release version is
+chosen by default.</p>
       </td>
     </tr>
   </tbody>
@@ -197,7 +195,7 @@
 
           <h2 id="kt_jvm_binary">kt_jvm_binary</h2>
 
-          <pre>kt_jvm_binary(<a href="#kt_jvm_binary.name">name</a>, <a href="#kt_jvm_binary.deps">deps</a>, <a href="#kt_jvm_binary.data">data</a>, <a href="#kt_jvm_binary.resources">resources</a>, <a href="#kt_jvm_binary.srcs">srcs</a>, <a href="#kt_jvm_binary.jvm_flags">jvm_flags</a>, <a href="#kt_jvm_binary.main_class">main_class</a>, <a href="#kt_jvm_binary.plugins">plugins</a>, <a href="#kt_jvm_binary.resource_jars">resource_jars</a>, <a href="#kt_jvm_binary.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_binary.runtime_deps">runtime_deps</a>)</pre>
+          <pre>kt_jvm_binary(<a href="#kt_jvm_binary.name">name</a>, <a href="#kt_jvm_binary.deps">deps</a>, <a href="#kt_jvm_binary.data">data</a>, <a href="#kt_jvm_binary.resources">resources</a>, <a href="#kt_jvm_binary.srcs">srcs</a>, <a href="#kt_jvm_binary.jvm_flags">jvm_flags</a>, <a href="#kt_jvm_binary.main_class">main_class</a>, <a href="#kt_jvm_binary.module_name">module_name</a>, <a href="#kt_jvm_binary.plugins">plugins</a>, <a href="#kt_jvm_binary.resource_jars">resource_jars</a>, <a href="#kt_jvm_binary.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_binary.runtime_deps">runtime_deps</a>)</pre>
 
           <p>Builds a Java archive ("jar file"), plus a wrapper shell script with the same name as the rule. The wrapper shell script uses a classpath that includes,
 among other things, a jar file for each library on which the binary depends.</p>
@@ -263,6 +261,14 @@
         <p>Name of class with main() method to use as entry point.</p>
       </td>
     </tr>
+    <tr id="kt_jvm_binary.module_name">
+      <td><code>module_name</code></td>
+      <td>
+        <p><code>String; Optional; Default is ''</code></p>
+        <p>The name of the module, if not provided the module name is derived from the label. --e.g., <code>//some/package/path:label_name</code> is translated to
+<code>some_package_path-label_name</code>.</p>
+      </td>
+    </tr>
     <tr id="kt_jvm_binary.plugins">
       <td><code>plugins</code></td>
       <td>
@@ -361,7 +367,7 @@
 
           <h2 id="kt_jvm_library">kt_jvm_library</h2>
 
-          <pre>kt_jvm_library(<a href="#kt_jvm_library.name">name</a>, <a href="#kt_jvm_library.deps">deps</a>, <a href="#kt_jvm_library.data">data</a>, <a href="#kt_jvm_library.resources">resources</a>, <a href="#kt_jvm_library.srcs">srcs</a>, <a href="#kt_jvm_library.exports">exports</a>, <a href="#kt_jvm_library.plugins">plugins</a>, <a href="#kt_jvm_library.resource_jars">resource_jars</a>, <a href="#kt_jvm_library.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_library.runtime_deps">runtime_deps</a>)</pre>
+          <pre>kt_jvm_library(<a href="#kt_jvm_library.name">name</a>, <a href="#kt_jvm_library.deps">deps</a>, <a href="#kt_jvm_library.data">data</a>, <a href="#kt_jvm_library.resources">resources</a>, <a href="#kt_jvm_library.srcs">srcs</a>, <a href="#kt_jvm_library.exports">exports</a>, <a href="#kt_jvm_library.module_name">module_name</a>, <a href="#kt_jvm_library.plugins">plugins</a>, <a href="#kt_jvm_library.resource_jars">resource_jars</a>, <a href="#kt_jvm_library.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_library.runtime_deps">runtime_deps</a>)</pre>
 
           <p>This rule compiles and links Kotlin and Java sources into a .jar file.</p>
 
@@ -419,6 +425,14 @@
 This is not true for regular (non-exported) deps.</p>
       </td>
     </tr>
+    <tr id="kt_jvm_library.module_name">
+      <td><code>module_name</code></td>
+      <td>
+        <p><code>String; Optional; Default is ''</code></p>
+        <p>The name of the module, if not provided the module name is derived from the label. --e.g., <code>//some/package/path:label_name</code> is translated to
+<code>some_package_path-label_name</code>.</p>
+      </td>
+    </tr>
     <tr id="kt_jvm_library.plugins">
       <td><code>plugins</code></td>
       <td>
@@ -455,7 +469,7 @@
 
           <h2 id="kt_jvm_test">kt_jvm_test</h2>
 
-          <pre>kt_jvm_test(<a href="#kt_jvm_test.name">name</a>, <a href="#kt_jvm_test.deps">deps</a>, <a href="#kt_jvm_test.data">data</a>, <a href="#kt_jvm_test.resources">resources</a>, <a href="#kt_jvm_test.srcs">srcs</a>, <a href="#kt_jvm_test.jvm_flags">jvm_flags</a>, <a href="#kt_jvm_test.plugins">plugins</a>, <a href="#kt_jvm_test.resource_jars">resource_jars</a>, <a href="#kt_jvm_test.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_test.runtime_deps">runtime_deps</a>, <a href="#kt_jvm_test.test_class">test_class</a>)</pre>
+          <pre>kt_jvm_test(<a href="#kt_jvm_test.name">name</a>, <a href="#kt_jvm_test.deps">deps</a>, <a href="#kt_jvm_test.data">data</a>, <a href="#kt_jvm_test.resources">resources</a>, <a href="#kt_jvm_test.srcs">srcs</a>, <a href="#kt_jvm_test.jvm_flags">jvm_flags</a>, <a href="#kt_jvm_test.module_name">module_name</a>, <a href="#kt_jvm_test.plugins">plugins</a>, <a href="#kt_jvm_test.resource_jars">resource_jars</a>, <a href="#kt_jvm_test.resource_strip_prefix">resource_strip_prefix</a>, <a href="#kt_jvm_test.runtime_deps">runtime_deps</a>, <a href="#kt_jvm_test.test_class">test_class</a>)</pre>
 
           <p>Setup a simple kotlin_test.</p>
 <p><strong>Notes:</strong></p>
@@ -515,6 +529,14 @@
         <p>A list of flags to embed in the wrapper script generated for running this binary. Note: does not yet support make variable substitution.</p>
       </td>
     </tr>
+    <tr id="kt_jvm_test.module_name">
+      <td><code>module_name</code></td>
+      <td>
+        <p><code>String; Optional; Default is ''</code></p>
+        <p>The name of the module, if not provided the module name is derived from the label. --e.g., <code>//some/package/path:label_name</code> is translated to
+<code>some_package_path-label_name</code>.</p>
+      </td>
+    </tr>
     <tr id="kt_jvm_test.plugins">
       <td><code>plugins</code></td>
       <td>
diff --git a/kotlin/kotlin.bzl b/kotlin/kotlin.bzl
index 5d74015..0d2b5b0 100644
--- a/kotlin/kotlin.bzl
+++ b/kotlin/kotlin.bzl
@@ -200,6 +200,7 @@
         default = [],
         aspects = [_kt_jvm_plugin_aspect],
     ),
+    "module_name": attr.string()
 }.items())
 
 _runnable_common_attr = dict(_common_attr.items() + {
@@ -259,7 +260,7 @@
 
 kt_jvm_library = rule(
     attrs = dict(_common_attr.items() + {
-        "exports": attr.label_list(default = []),
+        "exports": attr.label_list(default = [])
     }.items()),
     outputs = _common_outputs,
     implementation = _kotlin_library_impl,
@@ -282,6 +283,8 @@
     unlike them, not on the compile-time classpath.
   data: The list of files needed by this rule at runtime. See general comments about `data` at [Attributes common to all build rules](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
   deps: A list of dependencies of this rule.See general comments about `deps` at [Attributes common to all build rules](https://docs.bazel.build/versions/master/be/common-definitions.html#common-attributes).
+  module_name: The name of the module, if not provided the module name is derived from the label. --e.g., `//some/package/path:label_name` is translated to
+    `some_package_path-label_name`.
 """
 
 kt_jvm_binary = rule(
diff --git a/kotlin/rules/compile.bzl b/kotlin/rules/compile.bzl
index 59348bb..5000d20 100644
--- a/kotlin/rules/compile.bzl
+++ b/kotlin/rules/compile.bzl
@@ -56,7 +56,8 @@
         "--kotlin_jvm_target", tc.jvm_target,
         "--kotlin_api_version", tc.api_version,
         "--kotlin_language_version", tc.language_version,
-        "--kotlin_passthrough_flags", "-Xcoroutines=%s" % tc.coroutines 
+        "--kotlin_module_name", getattr(ctx.attr, "module_name", ""),
+        "--kotlin_passthrough_flags", "-Xcoroutines=%s" % tc.coroutines
     ]
     # Collect and prepare plugin descriptor for the worker.
     plugin_info=_merge_plugin_infos(ctx.attr.plugins + ctx.attr.deps)
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt
index 578a48c..de78269 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/compilers/jvm/actions/KotlinMainCompile.kt
@@ -27,6 +27,7 @@
 import io.bazel.ruleskotlin.workers.model.Metas
 import io.bazel.ruleskotlin.workers.utils.addAll
 import io.bazel.ruleskotlin.workers.utils.annotationProcessingGeneratedJavaSources
+import io.bazel.ruleskotlin.workers.utils.moduleName
 
 // The Kotlin compiler is not suited for javac compilation as of 1.2.21. The errors are not conveyed directly and would need to be preprocessed, also javac
 // invocations Configured via Kotlin use eager analysis in some corner cases this can result in classpath exceptions from the Java Compiler..
@@ -58,7 +59,7 @@
         }
 
         args
-                .addAll("-module-name", Metas.TARGET[ctx])
+                .addAll("-module-name", ctx.moduleName)
                 .addAll("-d", compileDirectories.classes.toString())
 
         Flags.KOTLIN_PASSTHROUGH_FLAGS[ctx]?.takeIf { it.isNotBlank() }?.also { args.addAll(it.split(" ")) }
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/model/Flags.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/model/Flags.kt
index 9e8deb5..5b2461e 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/model/Flags.kt
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/model/Flags.kt
@@ -34,9 +34,12 @@
     val KOTLIN_API_VERSION = Flag.Optional("--kotlin_api_version", "-api-version")
     val KOTLIN_LANGUAGE_VERSION = Flag.Optional("--kotlin_language_version", "-language-version")
     val KOTLIN_JVM_TARGET = Flag.Optional("--kotlin_jvm_target", "-jvm-target")
+
     /**
      * These flags are passed through to the compiler verbatim, the rules ensure they are safe. These flags are to toggle features or they carry a single value
      * so the string is tokenized by space.
      */
     val KOTLIN_PASSTHROUGH_FLAGS = Flag.Optional("--kotlin_passthrough_flags")
+
+    val KOTLIN_MODULE_NAME = Flag.Optional("--kotlin_module_name")
 }
\ No newline at end of file
diff --git a/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/MiscUtils.kt b/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/MiscUtils.kt
index 5ec7d8d..3e76387 100644
--- a/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/MiscUtils.kt
+++ b/kotlin/workers/src/io/bazel/ruleskotlin/workers/utils/MiscUtils.kt
@@ -16,4 +16,13 @@
 
 package io.bazel.ruleskotlin.workers.utils
 
-fun <T, C: MutableCollection<T>> C.addAll(vararg entries: T): C = this.also { addAll(entries) }
\ No newline at end of file
+import io.bazel.ruleskotlin.workers.Context
+import io.bazel.ruleskotlin.workers.model.Flags
+import io.bazel.ruleskotlin.workers.model.Metas
+
+fun <T, C: MutableCollection<T>> C.addAll(vararg entries: T): C = this.also { addAll(entries) }
+
+fun String?.supplyIfNullOrBlank(s: () -> String): String = this?.takeIf { it.isNotBlank() } ?: s()
+
+val Context.moduleName: String
+    get() = Flags.KOTLIN_MODULE_NAME[this].supplyIfNullOrBlank { "${Metas.PKG[this].trimStart { it == '/' }.replace('/', '_')}-${Metas.TARGET[this]}" }
diff --git a/tests/smoke/BUILD b/tests/smoke/BUILD
index 77c4b5e..3d61449 100644
--- a/tests/smoke/BUILD
+++ b/tests/smoke/BUILD
@@ -103,6 +103,12 @@
     data=glob(["data/*"]),
 )
 
+kt_jvm_library(
+    name="modulename",
+    srcs=glob(["helloworld/Main.kt"]),
+    module_name = "hello-module"
+)
+
 genrule(
     name="helloworld_host_config_test",
     tools=["//tests/smoke:helloworld"],
diff --git a/tests/smoke/basic_tests.py b/tests/smoke/basic_tests.py
index 47589c3..f9b1d5f 100644
--- a/tests/smoke/basic_tests.py
+++ b/tests/smoke/basic_tests.py
@@ -41,7 +41,12 @@
     def test_uses_target_name_as_default_module_name(self):
         """tests that the target name is used as the default module name."""
         jar = self.buildJarGetZipFile("helloworld", "jar")
-        self.assertJarContains(jar, "META-INF/helloworld.kotlin_module")
+        self.assertJarContains(jar, "META-INF/tests_smoke-helloworld.kotlin_module")
+
+    def test_module_name_is_used_if_provided(self):
+        """tests that the target name is used as the default module name."""
+        jar = self.buildJarGetZipFile("modulename", "jar")
+        self.assertJarContains(jar, "META-INF/hello-module.kotlin_module")
 
     def test_conventional_strip_resources(self):
         jar = self.buildJarGetZipFile("conventional_strip_resources", "jar")