diff --git a/libraries/pom.xml b/libraries/pom.xml index 8d195b0aa9b..c6d40d23937 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -101,6 +101,7 @@ tools/kotlin-js-tests-junit tools/kotlin-annotation-processing tools/kotlin-allopen + tools/kotlin-maven-allopen tools/kotlin-gradle-plugin tools/kotlin-gradle-plugin-api diff --git a/libraries/tools/kotlin-maven-allopen/pom.xml b/libraries/tools/kotlin-maven-allopen/pom.xml new file mode 100755 index 00000000000..2cad2065bcb --- /dev/null +++ b/libraries/tools/kotlin-maven-allopen/pom.xml @@ -0,0 +1,131 @@ + + + + 4.0.0 + + 3.0.5 + ${basedir}/../../../plugins/allopen/allopen-cli/src + ${basedir}/src/main/kotlin + ${basedir}/src/main/resources + ${basedir}/target/src/main/kotlin + ${basedir}/target/resource + + + + org.jetbrains.kotlin + kotlin-project + 1.1-SNAPSHOT + ../../pom.xml + + + kotlin-maven-allopen + jar + + All-open plugin for Maven + + + + jetbrains-utils + http://repository.jetbrains.com/utils + + + + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${project.version} + provided + + + + + ${allopen.target-src} + + + ${allopen.target-resources} + + + + + + maven-resources-plugin + 3.0.0 + + + copy-sources + validate + + copy-resources + + + ${allopen.target-src} + + ${allopen.src} + ${allopen.maven.plugin.src} + + + + + copy-resources + validate + + copy-resources + + + ${allopen.target-resources}/META-INF + + ${allopen.src}/META-INF + ${allopen.maven.plugin.resources}/META-INF + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + + compile + compile + compile + + + ${allopen.target-src} + + + + + + + org.codehaus.plexus + plexus-component-metadata + 1.7.1 + + + process-classes + + generate-metadata + + + + process-test-classes + + generate-test-metadata + + + + + + + diff --git a/libraries/tools/kotlin-maven-allopen/src/main/kotlin/AllOpenMavenPluginExtensions.kt b/libraries/tools/kotlin-maven-allopen/src/main/kotlin/AllOpenMavenPluginExtensions.kt new file mode 100644 index 00000000000..15b3c451cd3 --- /dev/null +++ b/libraries/tools/kotlin-maven-allopen/src/main/kotlin/AllOpenMavenPluginExtensions.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.test + +import org.apache.maven.plugin.* +import org.apache.maven.project.* +import org.codehaus.plexus.component.annotations.* +import org.codehaus.plexus.logging.* +import org.jetbrains.kotlin.maven.* + +val ALLOPEN_COMPILER_PLUGIN_ID = "org.jetbrains.kotlin.allopen" + +@Component(role = KotlinMavenPluginExtension::class, hint = "all-open") +class KotlinAllOpenMavenPluginExtension : KotlinMavenPluginExtension { + @Requirement + lateinit var logger: Logger + + override fun getCompilerPluginId() = ALLOPEN_COMPILER_PLUGIN_ID + + override fun isApplicable(project: MavenProject, execution: MojoExecution) = true + + override fun getPluginOptions(project: MavenProject, execution: MojoExecution): List { + logger.debug("Loaded Maven plugin " + javaClass.name) + return emptyList() + } +} + +@Component(role = KotlinMavenPluginExtension::class, hint = "spring") +class KotlinSpringMavenPluginExtension : KotlinMavenPluginExtension { + private companion object { + val ANNOTATIONS_ARG_NAME = "annotation" + + val SPRING_ANNOTATIONS = listOf( + "org.springframework.stereotype.Component", + "org.springframework.transaction.annotation.Transactional", + "org.springframework.scheduling.annotation.Async", + "org.springframework.cache.annotation.Cacheable" + ) + } + + override fun getCompilerPluginId() = ALLOPEN_COMPILER_PLUGIN_ID + + @Requirement + lateinit var logger: Logger + + override fun isApplicable(project: MavenProject, execution: MojoExecution) = true + + override fun getPluginOptions(project: MavenProject, execution: MojoExecution): List { + logger.debug("Loaded Maven plugin " + javaClass.name) + return SPRING_ANNOTATIONS.map { PluginOption(ALLOPEN_COMPILER_PLUGIN_ID, ANNOTATIONS_ARG_NAME, it) } + } +} diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/pom.xml new file mode 100644 index 00000000000..2ef7cca6d42 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + org.jetbrains.kotlin + test-allopen-simple + 1.0-SNAPSHOT + + + + junit + junit + 4.9 + + + org.jetbrains.kotlin + kotlin-runtime + ${kotlin.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + process-sources + + compile + + + + test-compile + process-test-sources + + test-compile + + + + + + + all-open + + + + + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/main/kotlin/test.kt b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/main/kotlin/test.kt new file mode 100644 index 00000000000..0c867a01f88 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/main/kotlin/test.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test + +annotation class AllOpen + +annotation class AllClose + +@AllOpen +class OpenClass + +@AllClose +class ClosedClass \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/test/java/test/AllOpenSimpleTest.java b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/test/java/test/AllOpenSimpleTest.java new file mode 100644 index 00000000000..8485235d301 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/src/test/java/test/AllOpenSimpleTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import java.lang.reflect.Modifier; + +public class AllOpenSimpleTest { + + @Test + public void greeting() { + assertEquals(false, Modifier.isFinal(OpenClass.class.getModifiers())); + assertEquals(true, Modifier.isFinal(ClosedClass.class.getModifiers())); + } +} diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/verify.bsh new file mode 100644 index 00000000000..9d58ae3030d --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-simple/verify.bsh @@ -0,0 +1,6 @@ +import java.io.*; + +File file = new File(basedir, "target/test-allopen-simple-1.0-SNAPSHOT.jar"); +if (!file.exists() || !file.isFile()) { + throw new FileNotFoundException("Could not find generated JAR: " + file); +} diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/pom.xml b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/pom.xml new file mode 100644 index 00000000000..46eff7616d8 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + org.jetbrains.kotlin + test-allopen-spring + 1.0-SNAPSHOT + + + + junit + junit + 4.9 + + + org.jetbrains.kotlin + kotlin-runtime + ${kotlin.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + + + ${project.basedir}/src/main/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + process-sources + + compile + + + + test-compile + process-test-sources + + test-compile + + + + + + + spring + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/java/org/springframework/stereotype/Component.java b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/java/org/springframework/stereotype/Component.java new file mode 100644 index 00000000000..dda67f42e26 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/java/org/springframework/stereotype/Component.java @@ -0,0 +1,60 @@ +/** + * This file was copied from the spring framework: + * https://github.com/spring-projects/spring-framework + */ + +/* + * Copyright 2002-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.stereotype; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates that an annotated class is a "component". + * Such classes are considered as candidates for auto-detection + * when using annotation-based configuration and classpath scanning. + * + *

Other class-level annotations may be considered as identifying + * a component as well, typically a special kind of component: + * e.g. the {@link Repository @Repository} annotation or AspectJ's + * {@link org.aspectj.lang.annotation.Aspect @Aspect} annotation. + * + * @ author Mark Fisher + * @since 2.5 + * @see Repository + * @see Service + * @see Controller + * @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Indexed +public @interface Component { + + /** + * The value may indicate a suggestion for a logical component name, + * to be turned into a Spring bean in case of an autodetected component. + * @return the suggested component name, if any + */ + String value() default ""; + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/Component.kt b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/Component.kt new file mode 100644 index 00000000000..25867c33932 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/Component.kt @@ -0,0 +1,5 @@ +package org.springframework.stereotype + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class Component \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/test.kt b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/test.kt new file mode 100644 index 00000000000..dd6205ea1e3 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/main/kotlin/test.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test + +@org.springframework.stereotype.Component +class OpenClass + +class ClosedClass \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/test/java/test/AllOpenSimpleTest.java b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/test/java/test/AllOpenSimpleTest.java new file mode 100644 index 00000000000..8485235d301 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/src/test/java/test/AllOpenSimpleTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; +import java.lang.reflect.Modifier; + +public class AllOpenSimpleTest { + + @Test + public void greeting() { + assertEquals(false, Modifier.isFinal(OpenClass.class.getModifiers())); + assertEquals(true, Modifier.isFinal(ClosedClass.class.getModifiers())); + } +} diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/verify.bsh b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/verify.bsh new file mode 100644 index 00000000000..33f18f14908 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-allopen-spring/verify.bsh @@ -0,0 +1,6 @@ +import java.io.*; + +File file = new File(basedir, "target/test-allopen-spring-1.0-SNAPSHOT.jar"); +if (!file.exists() || !file.isFile()) { + throw new FileNotFoundException("Could not find generated JAR: " + file); +} diff --git a/libraries/tools/kotlin-maven-plugin/src/it/plugins/expected.log b/libraries/tools/kotlin-maven-plugin/src/it/plugins/expected.log index b04da699ab2..9f24154b2ca 100644 --- a/libraries/tools/kotlin-maven-plugin/src/it/plugins/expected.log +++ b/libraries/tools/kotlin-maven-plugin/src/it/plugins/expected.log @@ -7,8 +7,8 @@ [INFO] Compiling Kotlin sources from [/use-test-extension/src/main/kotlin] [INFO] Module name is use-test-extension [INFO] Applicability test for project use-test-extension -[INFO] Applying plugin test-me [INFO] Configuring test plugin with arguments +[INFO] Options for plugin test-me: [plugin:org.jetbrains.kotlin.test.test-plugin:test-option=my-special-value] [INFO] Plugin applied [INFO] Option value: my-special-value [INFO] Kotlin Compiler version @snapshot@ diff --git a/libraries/tools/kotlin-maven-plugin/src/it/plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt b/libraries/tools/kotlin-maven-plugin/src/it/plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt index fe881b9fd01..522068ffbd1 100644 --- a/libraries/tools/kotlin-maven-plugin/src/it/plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt +++ b/libraries/tools/kotlin-maven-plugin/src/it/plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt @@ -17,9 +17,14 @@ class MavenPluginComponent : KotlinMavenPluginExtension { return true } - override fun getPluginArguments(project: MavenProject, execution: MojoExecution): MutableList { + override fun getCompilerPluginId() = TestCommandLineProcessor.TestPluginId + + override fun getPluginOptions(project: MavenProject, execution: MojoExecution): List { logger.info("Configuring test plugin with arguments") - return mutableListOf("plugin:${TestCommandLineProcessor.TestPluginId}:${TestCommandLineProcessor.MyTestOption.name}=my-special-value") + return listOf(PluginOption( + TestCommandLineProcessor.TestPluginId, + TestCommandLineProcessor.MyTestOption.name, + "my-special-value")) } -} +} \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin/src/it/plugins/use-test-extension/pom.xml b/libraries/tools/kotlin-maven-plugin/src/it/plugins/use-test-extension/pom.xml index c68e5ff6e99..58c44c1ed71 100644 --- a/libraries/tools/kotlin-maven-plugin/src/it/plugins/use-test-extension/pom.xml +++ b/libraries/tools/kotlin-maven-plugin/src/it/plugins/use-test-extension/pom.xml @@ -58,11 +58,6 @@ test-me - - - plugin:test-me:...=.... - - 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 eab556ee70c..03890118097 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 @@ -24,10 +24,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.model.Dependency; -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.plugin.*; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; @@ -43,9 +40,9 @@ import org.jetbrains.kotlin.config.Services; import java.io.File; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public abstract class KotlinCompileMojoBase extends AbstractMojo { @Component @@ -70,16 +67,14 @@ public abstract class KotlinCompileMojoBase e private List compilerPlugins; /** - * A classpaths required for kotlin compiler plugin(s). Useful if you don't use extensions due to some reason + * A list of plugin options in format (pluginId):(parameter)=(value) */ @Parameter - private List compilerPluginsClassPaths; + private List pluginOptions; - /** - * A list of plugin options in format plugin:(pluginId):(parameter)=(value) - */ - @Parameter - private List pluginArguments; + private List getAppliedCompilerPlugins() { + return (compilerPlugins == null) ? Collections.emptyList() : compilerPlugins; + } protected List getSourceFilePaths() { if (sourceDirs != null && !sourceDirs.isEmpty()) return sourceDirs; @@ -150,6 +145,8 @@ public abstract class KotlinCompileMojoBase e @Parameter public List args; + private final static Pattern OPTION_PATTERN = Pattern.compile("([^:]+):([^=]+)=(.*)"); + @Override public void execute() throws MojoExecutionException, MojoFailureException { @@ -231,13 +228,9 @@ public abstract class KotlinCompileMojoBase e protected abstract void configureSpecificCompilerArguments(@NotNull A arguments) throws MojoExecutionException; - protected List getCompilerPluginsClassPaths() { + private List getCompilerPluginClassPaths() { ArrayList result = new ArrayList(); - if (compilerPluginsClassPaths != null) { - result.addAll(compilerPluginsClassPaths); - } - List files = new ArrayList(); for (Dependency dependency : mojoExecution.getPlugin().getDependencies()) { @@ -260,38 +253,88 @@ public abstract class KotlinCompileMojoBase e return result; } - protected List getCompilerPluginArguments() throws ComponentLookupException { - return configureCompilerPlugins(); + @NotNull + private Map loadCompilerPlugins() throws PluginNotFoundException { + Map loadedPlugins = new HashMap(); + for (String pluginName : getAppliedCompilerPlugins()) { + getLog().debug("Looking for plugin " + pluginName); + try { + KotlinMavenPluginExtension extension = container.lookup(KotlinMavenPluginExtension.class, pluginName); + loadedPlugins.put(pluginName, extension); + getLog().debug("Got plugin instance" + pluginName + " of type " + extension.getClass().getName()); + + } catch (ComponentLookupException e) { + getLog().debug("Unable to get plugin instance" + pluginName); + throw new PluginNotFoundException(pluginName, e); + } + } + return loadedPlugins; } - private List configureCompilerPlugins() throws ComponentLookupException { + @NotNull + private List renderCompilerPluginOptions(@NotNull List options) { + List renderedOptions = new ArrayList(options.size()); + for (PluginOption option : options) { + renderedOptions.add(option.toString()); + } + return renderedOptions; + } + + @NotNull + private List getCompilerPluginOptions() throws PluginNotFoundException, PluginOptionIllegalFormatException { if (mojoExecution == null) { throw new IllegalStateException("No mojoExecution injected"); } - List pluginArguments = new ArrayList(); + List pluginOptions = new ArrayList(); - if (this.pluginArguments != null) { - pluginArguments.addAll(this.pluginArguments); - } + Map plugins = loadCompilerPlugins(); - 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()); + // Get options for extension-provided compiler plugins - 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 + for (Map.Entry pluginEntry : plugins.entrySet()) { + String pluginName = pluginEntry.getKey(); + KotlinMavenPluginExtension plugin = pluginEntry.getValue(); - container.getComponentDescriptor(KotlinMavenPluginExtension.class.getName(), pluginId).getRealm(); - } + if (plugin.isApplicable(project, mojoExecution)) { + List optionsForPlugin = plugin.getPluginOptions(project, mojoExecution); + getLog().info("Options for plugin " + pluginName + ": " + optionsForPlugin); + pluginOptions.addAll(optionsForPlugin); } } - return pluginArguments; + if (this.pluginOptions != null) { + pluginOptions.addAll(parseUserProvidedPluginOptions(this.pluginOptions, plugins)); + } + + return pluginOptions; + } + + @NotNull + private static List parseUserProvidedPluginOptions( + @NotNull List rawOptions, + @NotNull Map plugins + ) throws PluginOptionIllegalFormatException, PluginNotFoundException { + List pluginOptions = new ArrayList(rawOptions.size()); + + for (String rawOption : rawOptions) { + Matcher matcher = OPTION_PATTERN.matcher(rawOption); + if (!matcher.matches()) { + throw new PluginOptionIllegalFormatException(rawOption); + } + + String pluginName = matcher.group(1); + String key = matcher.group(2); + String value = matcher.group(3); + KotlinMavenPluginExtension plugin = plugins.get(pluginName); + if (plugin == null) { + throw new PluginNotFoundException(pluginName); + } + + pluginOptions.add(new PluginOption(plugin.getCompilerPluginId(), key, value)); + } + + return pluginOptions; } private void configureCompilerArguments(@NotNull A arguments, @NotNull CLICompiler compiler) throws MojoExecutionException { @@ -334,26 +377,45 @@ public abstract class KotlinCompileMojoBase e 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()]); + List pluginClassPaths = getCompilerPluginClassPaths(); + if (pluginClassPaths != null && !pluginClassPaths.isEmpty()) { + if (getLog().isDebugEnabled()) { + getLog().debug("Plugin classpaths are: " + Joiner.on(", ").join(pluginClassPaths)); } - } catch (ComponentLookupException e) { - throw new MojoExecutionException("Failed to lookup kotlin compiler plugins", e); + arguments.pluginClasspaths = pluginClassPaths.toArray(new String[pluginClassPaths.size()]); } - List classPaths = getCompilerPluginsClassPaths(); + List pluginArguments; + try { + pluginArguments = renderCompilerPluginOptions(getCompilerPluginOptions()); + } catch (PluginNotFoundException e) { + throw new MojoExecutionException(e.getMessage(), e); + } catch (PluginOptionIllegalFormatException e) { + throw new MojoExecutionException(e.getMessage(), e); + } - if (classPaths != null && !classPaths.isEmpty()) { + if (!pluginArguments.isEmpty()) { if (getLog().isDebugEnabled()) { - getLog().debug("Plugin classpaths are: " + Joiner.on(", ").join(classPaths)); + getLog().debug("Plugin options are: " + Joiner.on(", ").join(pluginArguments)); } - arguments.pluginClasspaths = classPaths.toArray(new String[classPaths.size()]); + + arguments.pluginOptions = pluginArguments.toArray(new String[pluginArguments.size()]); + } + } + + public static class PluginNotFoundException extends Exception { + PluginNotFoundException(String pluginId, Throwable cause) { + super("Plugin not found: " + pluginId, cause); + } + + PluginNotFoundException(String pluginId) { + super("Plugin not found: " + pluginId); + } + } + + public static class PluginOptionIllegalFormatException extends Exception { + PluginOptionIllegalFormatException(String option) { + super("Plugin option has an illegal format: " + option); } } } 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 index 3ce8f760cb2..1535ea5e777 100644 --- 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 @@ -9,6 +9,8 @@ import java.util.List; public interface KotlinMavenPluginExtension { boolean isApplicable(@NotNull MavenProject project, @NotNull MojoExecution execution); + String getCompilerPluginId(); + @NotNull - List getPluginArguments(@NotNull MavenProject project, @NotNull MojoExecution execution); + List getPluginOptions(@NotNull MavenProject project, @NotNull MojoExecution execution); } diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/PluginOption.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/PluginOption.java new file mode 100644 index 00000000000..7f7674decdc --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/PluginOption.java @@ -0,0 +1,18 @@ +package org.jetbrains.kotlin.maven; + +public class PluginOption { + public final String pluginId; + public final String key; + public final String value; + + public PluginOption(String pluginId, String key, String value) { + this.pluginId = pluginId; + this.key = key; + this.value = value; + } + + @Override + public String toString() { + return "plugin:" + pluginId + ":" + key + "=" + value; + } +} \ No newline at end of file