From f59377011c4db6114c4cbf100c101fd4710a7a95 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Fri, 7 Oct 2016 22:22:15 +0300 Subject: [PATCH] Initial Kotlin plugin support in Maven --- .../kotlin/cli/jvm/PluginCliParser.kt | 2 +- libraries/tools/kotlin-maven-plugin/pom.xml | 11 ++ .../kotlin/maven/KotlinCompileMojoBase.java | 115 ++++++++++++++++-- .../maven/KotlinMavenPluginExtension.java | 14 +++ 4 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinMavenPluginExtension.java diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/PluginCliParser.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/PluginCliParser.kt index 345cd4ed1a7..d5ebb3e0fbb 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/PluginCliParser.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/PluginCliParser.kt @@ -125,4 +125,4 @@ private class PluginURLClassLoader(urls: Array, parent: ClassLoader) : Clas } } -} \ No newline at end of file +} diff --git a/libraries/tools/kotlin-maven-plugin/pom.xml b/libraries/tools/kotlin-maven-plugin/pom.xml index ccf40c08717..62e501277cc 100644 --- a/libraries/tools/kotlin-maven-plugin/pom.xml +++ b/libraries/tools/kotlin-maven-plugin/pom.xml @@ -7,6 +7,7 @@ 1.4.1 3.0.5 + 1.0.4 @@ -57,6 +58,16 @@ 3.3.0 test + + org.eclipse.aether + aether-impl + 1.1.0 + + + org.apache.maven + maven-artifact + ${maven.version} + diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java index bad426a6b0c..e6ec481743a 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompileMojoBase.java @@ -16,14 +16,19 @@ package org.jetbrains.kotlin.maven; +import com.google.common.base.Joiner; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.CLICompiler; import org.jetbrains.kotlin.cli.common.ExitCode; @@ -38,16 +43,11 @@ import java.util.Arrays; import java.util.List; public abstract class KotlinCompileMojoBase extends AbstractMojo { - // TODO it would be nice to avoid using 2 injected fields for sources - // but I've not figured out how to have a defaulted parameter value - // which is also customisable inside an in a maven pom.xml - // so for now lets just use 2 fields + @Component + protected PlexusContainer container; - /** - * The default source directories containing the sources to be compiled. - */ - @Parameter(defaultValue = "${project.compileSourceRoots}", required = true) - private List defaultSourceDirs; + @Component + protected MojoExecution mojoExecution; /** * The source directories containing the sources to be compiled. @@ -55,9 +55,27 @@ public abstract class KotlinCompileMojoBase e @Parameter private List sourceDirs; + /** + * A list of kotlin compiler plugins to be applied. + */ + @Parameter + private List compilerPlugins; + + /** + * A classpaths required for kotlin compiler plugin(s). Useful if you don't use extensions due to some reason + */ + @Parameter + private List compilerPluginsClassPaths; + + /** + * A list of plugin options in format plugin:(pluginId):(parameter)=(value) + */ + @Parameter + private List pluginArguments; + protected List getSourceFilePaths() { if (sourceDirs != null && !sourceDirs.isEmpty()) return sourceDirs; - return defaultSourceDirs; + return project.getCompileSourceRoots(); } public List getSourceDirs() { @@ -205,6 +223,61 @@ public abstract class KotlinCompileMojoBase e protected abstract void configureSpecificCompilerArguments(@NotNull A arguments) throws MojoExecutionException; + protected List getCompilerPluginsClassPaths() { + ArrayList result = new ArrayList(); + + if (compilerPluginsClassPaths != null) { + result.addAll(compilerPluginsClassPaths); + } + + // TODO do that once we have compiler running in the separate process +// URL[] urls = mojoExecution.getMojoDescriptor().getRealm().getURLs(); +// for (URL url : urls) { +// if ("file".equals(url.getProtocol())) { +// try { +// result.add(new File(url.toURI()).getAbsolutePath()); +// } catch (URISyntaxException ignore) { +// } +// } +// } + + return result; + } + + protected List getCompilerPluginArguments() throws ComponentLookupException { + return configureCompilerPlugins(); + } + + private List configureCompilerPlugins() throws ComponentLookupException { + if (mojoExecution == null) { + throw new IllegalStateException("No mojoExecution injected"); + } + + List pluginArguments = new ArrayList(); + + if (this.pluginArguments != null) { + pluginArguments.addAll(this.pluginArguments); + } + + if (compilerPlugins != null) { + for (String pluginId : compilerPlugins) { + getLog().debug("Looking for plugin " + pluginId); + KotlinMavenPluginExtension extension = container.lookup(KotlinMavenPluginExtension.class, pluginId); + getLog().debug("Got plugin instance" + pluginId + " of type " + extension.getClass().getName()); + + if (extension.isApplicable(project, mojoExecution)) { + getLog().info("Applying plugin " + pluginId); + pluginArguments.addAll(extension.getPluginArguments(project, mojoExecution)); + // TODO here we can use artifact resolver to build exact dependency tree + + container.getComponentDescriptor(KotlinMavenPluginExtension.class.getName(), pluginId).getRealm(); + } + } + } + + return pluginArguments; + } + private void configureCompilerArguments(@NotNull A arguments, @NotNull CLICompiler compiler) throws MojoExecutionException { if (getLog().isDebugEnabled()) { arguments.verbose = true; @@ -244,5 +317,27 @@ public abstract class KotlinCompileMojoBase e if (arguments.noInline) { getLog().info("Method inlining is turned off"); } + + try { + List pluginArguments = getCompilerPluginArguments(); + if (pluginArguments != null && !pluginArguments.isEmpty()) { + if (getLog().isDebugEnabled()) { + getLog().debug("Plugin options are: " + Joiner.on(", ").join(pluginArguments)); + } + + arguments.pluginOptions = pluginArguments.toArray(new String[pluginArguments.size()]); + } + } catch (ComponentLookupException e) { + throw new MojoExecutionException("Failed to lookup kotlin compiler plugins", e); + } + + List classPaths = getCompilerPluginsClassPaths(); + + if (classPaths != null && !classPaths.isEmpty()) { + if (getLog().isDebugEnabled()) { + getLog().debug("Plugin classpaths are: " + Joiner.on(", ").join(classPaths)); + } + arguments.pluginClasspaths = classPaths.toArray(new String[classPaths.size()]); + } } } diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinMavenPluginExtension.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinMavenPluginExtension.java new file mode 100644 index 00000000000..3ce8f760cb2 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinMavenPluginExtension.java @@ -0,0 +1,14 @@ +package org.jetbrains.kotlin.maven; + +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.project.MavenProject; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface KotlinMavenPluginExtension { + boolean isApplicable(@NotNull MavenProject project, @NotNull MojoExecution execution); + + @NotNull + List getPluginArguments(@NotNull MavenProject project, @NotNull MojoExecution execution); +}