diff --git a/libraries/tools/kotlin-maven-plugin/pom.xml b/libraries/tools/kotlin-maven-plugin/pom.xml index d89bd2fe19f..ccf40c08717 100644 --- a/libraries/tools/kotlin-maven-plugin/pom.xml +++ b/libraries/tools/kotlin-maven-plugin/pom.xml @@ -46,6 +46,17 @@ 2.4.4 test + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + 3.3.0 + test + diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureException.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureException.java new file mode 100644 index 00000000000..f74ba8ec0d2 --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureException.java @@ -0,0 +1,22 @@ +package org.jetbrains.kotlin.maven; + +import org.apache.maven.plugin.compiler.CompilationFailureException; +import org.codehaus.plexus.compiler.CompilerMessage; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class KotlinCompilationFailureException extends CompilationFailureException { + private List compilerMessages; + + public KotlinCompilationFailureException(@NotNull List compilerMessages) { + super(compilerMessages); + this.compilerMessages = Collections.unmodifiableList(compilerMessages); + } + + public List getCompilerMessages() { + return compilerMessages; + } +} + 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 fb42191f8e1..f77427a5317 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 @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.cli.common.CLICompiler; import org.jetbrains.kotlin.cli.common.ExitCode; import org.jetbrains.kotlin.cli.common.KotlinVersion; import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments; -import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.config.Services; import java.io.File; @@ -133,16 +132,12 @@ public abstract class KotlinCompileMojoBase e configureCompilerArguments(arguments, compiler); printCompilerArgumentsIfDebugEnabled(arguments, compiler); - MessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); + MavenPluginLogMessageCollector messageCollector = new MavenPluginLogMessageCollector(getLog()); ExitCode exitCode = compiler.exec(messageCollector, Services.EMPTY, arguments); - switch (exitCode) { - case COMPILATION_ERROR: - throw new MojoExecutionException("Compilation error. See log for more details"); - case INTERNAL_ERROR: - throw new MojoExecutionException("Internal compiler error. See log for more details"); - default: + if (exitCode != ExitCode.OK) { + messageCollector.throwKotlinCompilerException(); } } diff --git a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java index 6a7a5078c02..8304175aab4 100644 --- a/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java +++ b/libraries/tools/kotlin-maven-plugin/src/main/java/org/jetbrains/kotlin/maven/MavenPluginLogMessageCollector.java @@ -16,23 +16,38 @@ package org.jetbrains.kotlin.maven; +import com.intellij.openapi.util.Pair; +import kotlin.collections.CollectionsKt; +import kotlin.jvm.functions.Function1; import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.compiler.CompilerMessage; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; import org.jetbrains.kotlin.cli.common.messages.MessageCollector; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + public class MavenPluginLogMessageCollector implements MessageCollector { private final Log log; - private boolean hasErrors = false; + private final ArrayList> collectedErrors = new ArrayList>(); public MavenPluginLogMessageCollector(Log log) { - this.log = log; + this.log = checkNotNull(log, "log shouldn't be null"); } @Override public boolean hasErrors() { - return hasErrors; + return !collectedErrors.isEmpty(); + } + + @NotNull + public List> getCollectedErrors() { + return Collections.unmodifiableList(collectedErrors); } @Override @@ -45,7 +60,7 @@ public class MavenPluginLogMessageCollector implements MessageCollector { if (CompilerMessageSeverity.VERBOSE.contains(severity)) { log.debug(text); } else if (CompilerMessageSeverity.ERRORS.contains(severity)) { - hasErrors = true; + collectedErrors.add(new Pair(location, message)); log.error(text); } else if (severity == CompilerMessageSeverity.INFO) { log.info(text); @@ -53,4 +68,35 @@ public class MavenPluginLogMessageCollector implements MessageCollector { log.warn(text); } } + + public void throwKotlinCompilerException() throws KotlinCompilationFailureException { + throw new KotlinCompilationFailureException( + CollectionsKt.map(getCollectedErrors(), new Function1, CompilerMessage>() { + @Override + public CompilerMessage invoke(Pair pair) { + CompilerMessageLocation location = pair.getFirst(); + String message = pair.getSecond(); + String lineContent = location.getLineContent(); + int lineContentLength = lineContent == null ? 0 : lineContent.length(); + + return new CompilerMessage( + location.getPath(), + CompilerMessage.Kind.ERROR, + fixLocation(location.getLine()), + fixLocation(location.getColumn()), + fixLocation(location.getLine()), + Math.min(fixLocation(location.getColumn()), lineContentLength), + message + ); + } + }) + ); + } + + private static int fixLocation(int n) { + if (n < 0) { + return 0; + } + return n; + } } diff --git a/libraries/tools/kotlin-maven-plugin/src/test/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureExceptionTest.java b/libraries/tools/kotlin-maven-plugin/src/test/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureExceptionTest.java new file mode 100644 index 00000000000..252577d593b --- /dev/null +++ b/libraries/tools/kotlin-maven-plugin/src/test/java/org/jetbrains/kotlin/maven/KotlinCompilationFailureExceptionTest.java @@ -0,0 +1,64 @@ +package org.jetbrains.kotlin.maven; + +import org.apache.maven.plugin.testing.SilentLog; +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class KotlinCompilationFailureExceptionTest { + + @Test + public void testNoLocation() throws Exception { + MavenPluginLogMessageCollector collector = new MavenPluginLogMessageCollector(new SilentLog()); + collector.report(CompilerMessageSeverity.ERROR, "Something went wrong", CompilerMessageLocation.NO_LOCATION); + + try { + collector.throwKotlinCompilerException(); + fail(); + } catch (KotlinCompilationFailureException e) { + assertEquals("Something went wrong", e.getLongMessage().trim()); + } + } + + @Test + public void testLocationNoLineNoColumn() throws Exception { + MavenPluginLogMessageCollector collector = new MavenPluginLogMessageCollector(new SilentLog()); + collector.report(CompilerMessageSeverity.ERROR, "Error in file", CompilerMessageLocation.create("myfile.txt", -1, -1, "nothing")); + + try { + collector.throwKotlinCompilerException(); + fail(); + } catch (KotlinCompilationFailureException e) { + assertEquals("myfile.txt: Error in file", e.getLongMessage().trim()); + } + } + + @Test + public void testLocationNoColumn() throws Exception { + MavenPluginLogMessageCollector collector = new MavenPluginLogMessageCollector(new SilentLog()); + collector.report(CompilerMessageSeverity.ERROR, "Error in file", CompilerMessageLocation.create("myfile.txt", 777, -1, "nothing")); + + try { + collector.throwKotlinCompilerException(); + fail(); + } catch (KotlinCompilationFailureException e) { + assertEquals("myfile.txt:[777] Error in file", e.getLongMessage().trim()); + } + } + + @Test + public void testLocationWithLocation() throws Exception { + MavenPluginLogMessageCollector collector = new MavenPluginLogMessageCollector(new SilentLog()); + collector.report(CompilerMessageSeverity.ERROR, "Error in file", CompilerMessageLocation.create("myfile.txt", 777, 9, "nothing")); + + try { + collector.throwKotlinCompilerException(); + fail(); + } catch (KotlinCompilationFailureException e) { + assertEquals("myfile.txt:[777,9] Error in file", e.getLongMessage().trim()); + } + } +}