diff --git a/.idea/runConfigurations/IDEA_JPS_Debug.xml b/.idea/runConfigurations/IDEA_JPS_Debug.xml
index ed9acd170..6f4356779 100644
--- a/.idea/runConfigurations/IDEA_JPS_Debug.xml
+++ b/.idea/runConfigurations/IDEA_JPS_Debug.xml
@@ -1,14 +1,15 @@
-
+
-
+
+
-
+
\ No newline at end of file
diff --git a/classlib/pom.xml b/classlib/pom.xml
index feb133eec..53898bc71 100644
--- a/classlib/pom.xml
+++ b/classlib/pom.xml
@@ -48,6 +48,7 @@
org.teavm
teavm-core
${project.version}
+ provided
org.teavm
@@ -77,6 +78,7 @@
org.ow2.asm
asm-util
+ provided
com.google.code.gson
diff --git a/jso/impl/pom.xml b/jso/impl/pom.xml
index 7d076f6b5..0d58066fc 100644
--- a/jso/impl/pom.xml
+++ b/jso/impl/pom.xml
@@ -33,6 +33,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
org.teavm
teavm-core
${project.version}
+ provided
org.teavm
diff --git a/metaprogramming/impl/pom.xml b/metaprogramming/impl/pom.xml
index ada51eb94..009228526 100644
--- a/metaprogramming/impl/pom.xml
+++ b/metaprogramming/impl/pom.xml
@@ -38,6 +38,7 @@
org.teavm
teavm-core
${project.version}
+ provided
org.teavm
diff --git a/platform/pom.xml b/platform/pom.xml
index 5693a3652..f253a7922 100644
--- a/platform/pom.xml
+++ b/platform/pom.xml
@@ -34,6 +34,7 @@
org.teavm
teavm-core
${project.version}
+ provided
org.teavm
diff --git a/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java
deleted file mode 100644
index cf1e0ca28..000000000
--- a/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2015 Alexey Andreev.
- *
- * 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.teavm.tooling;
-
-import java.io.File;
-import java.util.List;
-import java.util.Properties;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.tooling.sources.SourceFileProvider;
-
-public interface BaseTeaVMTool {
- void setTargetDirectory(File targetDirectory);
-
- void setMinifying(boolean minifying);
-
- void setIncremental(boolean incremental);
-
- void setDebugInformationGenerated(boolean debugInformationGenerated);
-
- void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated);
-
- void setSourceFilesCopied(boolean sourceFilesCopied);
-
- Properties getProperties();
-
- List getTransformers();
-
- void setLog(TeaVMToolLog log);
-
- void setClassLoader(ClassLoader classLoader);
-
- void addSourceFileProvider(SourceFileProvider sourceFileProvider);
-}
diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
index 8288e45b7..e3285d7a9 100644
--- a/tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
+++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
@@ -21,6 +21,7 @@ import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite;
import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem;
+import org.teavm.diagnostics.ProblemProvider;
import org.teavm.model.CallLocation;
import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation;
@@ -31,9 +32,12 @@ public final class TeaVMProblemRenderer {
}
public static void describeProblems(TeaVM vm, TeaVMToolLog log) {
- CallGraph cg = vm.getDependencyInfo().getCallGraph();
+ describeProblems(vm.getDependencyInfo().getCallGraph(), vm.getProblemProvider(), log);
+ }
+
+ public static void describeProblems(CallGraph cg, ProblemProvider problems, TeaVMToolLog log) {
DefaultProblemTextConsumer consumer = new DefaultProblemTextConsumer();
- for (Problem problem : vm.getProblemProvider().getProblems()) {
+ for (Problem problem : problems.getProblems()) {
consumer.clear();
problem.render(consumer);
StringBuilder sb = new StringBuilder();
diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
index c717a67d6..2b27e2f9d 100644
--- a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
+++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
@@ -22,6 +22,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
@@ -61,7 +63,7 @@ import org.teavm.vm.TeaVMOptimizationLevel;
import org.teavm.vm.TeaVMProgressListener;
import org.teavm.vm.TeaVMTarget;
-public class TeaVMTool implements BaseTeaVMTool {
+public class TeaVMTool {
private File targetDirectory = new File(".");
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
private String targetFileName = "";
@@ -73,7 +75,7 @@ public class TeaVMTool implements BaseTeaVMTool {
private boolean sourceFilesCopied;
private boolean incremental;
private File cacheDirectory = new File("./teavm-cache");
- private List transformers = new ArrayList<>();
+ private List transformers = new ArrayList<>();
private List classesToPreserve = new ArrayList<>();
private TeaVMToolLog log = new EmptyTeaVMToolLog();
private ClassLoader classLoader = TeaVMTool.class.getClassLoader();
@@ -99,7 +101,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return targetDirectory;
}
- @Override
public void setTargetDirectory(File targetDirectory) {
this.targetDirectory = targetDirectory;
}
@@ -116,7 +117,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return minifying;
}
- @Override
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
@@ -125,7 +125,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return incremental;
}
- @Override
public void setIncremental(boolean incremental) {
this.incremental = incremental;
}
@@ -142,7 +141,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return debugInformationGenerated;
}
- @Override
public void setDebugInformationGenerated(boolean debugInformationGenerated) {
this.debugInformationGenerated = debugInformationGenerated;
}
@@ -159,7 +157,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return sourceMapsFileGenerated;
}
- @Override
public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
this.sourceMapsFileGenerated = sourceMapsFileGenerated;
}
@@ -168,18 +165,15 @@ public class TeaVMTool implements BaseTeaVMTool {
return sourceFilesCopied;
}
- @Override
public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied;
}
- @Override
public Properties getProperties() {
return properties;
}
- @Override
- public List getTransformers() {
+ public List getTransformers() {
return transformers;
}
@@ -191,7 +185,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return log;
}
- @Override
public void setLog(TeaVMToolLog log) {
this.log = log;
}
@@ -220,7 +213,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return classLoader;
}
- @Override
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@@ -289,7 +281,6 @@ public class TeaVMTool implements BaseTeaVMTool {
return resources;
}
- @Override
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
sourceFileProviders.add(sourceFileProvider);
}
@@ -377,7 +368,7 @@ public class TeaVMTool implements BaseTeaVMTool {
vm.setOptimizationLevel(optimizationLevel);
vm.installPlugins();
- for (ClassHolderTransformer transformer : transformers) {
+ for (ClassHolderTransformer transformer : resolveTransformers(classLoader)) {
vm.add(transformer);
}
if (mainClass != null) {
@@ -402,10 +393,8 @@ public class TeaVMTool implements BaseTeaVMTool {
log.info("Output file successfully built");
} else if (problemProvider.getSevereProblems().isEmpty()) {
log.info("Output file built with warnings");
- TeaVMProblemRenderer.describeProblems(vm, log);
} else {
log.info("Output file built with errors");
- TeaVMProblemRenderer.describeProblems(vm, log);
}
File outputFile = new File(targetDirectory, outputName);
@@ -507,4 +496,41 @@ public class TeaVMTool implements BaseTeaVMTool {
copier.setLog(log);
copier.copy(new File(targetDirectory, "src"));
}
+
+ private List resolveTransformers(ClassLoader classLoader) {
+ List transformerInstances = new ArrayList<>();
+ if (transformers == null) {
+ return transformerInstances;
+ }
+ for (String transformerName : transformers) {
+ Class> transformerRawType;
+ try {
+ transformerRawType = Class.forName(transformerName, true, classLoader);
+ } catch (ClassNotFoundException e) {
+ log.error("Transformer not found: " + transformerName, e);
+ continue;
+ }
+ if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
+ log.error("Transformer " + transformerName + " is not subtype of "
+ + ClassHolderTransformer.class.getName());
+ continue;
+ }
+ Class extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
+ ClassHolderTransformer.class);
+ Constructor extends ClassHolderTransformer> ctor;
+ try {
+ ctor = transformerType.getConstructor();
+ } catch (NoSuchMethodException e) {
+ log.error("Transformer " + transformerName + " has no default constructor");
+ continue;
+ }
+ try {
+ ClassHolderTransformer transformer = ctor.newInstance();
+ transformerInstances.add(transformer);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+ log.error("Error instantiating transformer " + transformerName, e);
+ }
+ }
+ return transformerInstances;
+ }
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/builder/BuildException.java b/tools/core/src/main/java/org/teavm/tooling/builder/BuildException.java
new file mode 100644
index 000000000..388ad7b6e
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/BuildException.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 Alexey Andreev.
+ *
+ * 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.teavm.tooling.builder;
+
+public class BuildException extends Exception {
+ public BuildException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildResult.java b/tools/core/src/main/java/org/teavm/tooling/builder/BuildResult.java
similarity index 84%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildResult.java
rename to tools/core/src/main/java/org/teavm/tooling/builder/BuildResult.java
index ffca62f2b..f068d66ac 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildResult.java
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/BuildResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,19 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.model;
+package org.teavm.tooling.builder;
import java.util.Collection;
import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.ProblemProvider;
-public interface TeaVMBuildResult {
+public interface BuildResult {
CallGraph getCallGraph();
- boolean isErrorOccurred();
-
- String getStackTrace();
-
ProblemProvider getProblems();
Collection getUsedResources();
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java
similarity index 66%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java
rename to tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java
index 168a666cb..6bfcc1b3d 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,16 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.model;
+package org.teavm.tooling.builder;
import java.util.List;
import java.util.Properties;
+import org.teavm.backend.wasm.render.WasmBinaryVersion;
import org.teavm.tooling.TeaVMTargetType;
+import org.teavm.tooling.TeaVMToolLog;
+import org.teavm.vm.TeaVMOptimizationLevel;
import org.teavm.vm.TeaVMProgressListener;
-public interface TeaVMBuildStrategy {
+public interface BuildStrategy {
void init();
+ void setLog(TeaVMToolLog log);
+
void addSourcesDirectory(String directory);
void addSourcesJar(String jarFile);
@@ -45,7 +50,21 @@ public interface TeaVMBuildStrategy {
void setIncremental(boolean incremental);
+ void setMinifying(boolean minifying);
+
void setProperties(Properties properties);
- TeaVMBuildResult build();
+ void setTransformers(String[] transformers);
+
+ void setOptimizationLevel(TeaVMOptimizationLevel level);
+
+ void setTargetFileName(String targetFileName);
+
+ void setClassesToPreserve(String[] classesToPreserve);
+
+ void setCacheDirectory(String cacheDirectory);
+
+ void setWasmVersion(WasmBinaryVersion wasmVersion);
+
+ BuildResult build() throws BuildException;
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/builder/ClassLoaderFactory.java b/tools/core/src/main/java/org/teavm/tooling/builder/ClassLoaderFactory.java
new file mode 100644
index 000000000..ac62b7d10
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/ClassLoaderFactory.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 Alexey Andreev.
+ *
+ * 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.teavm.tooling.builder;
+
+import java.net.URL;
+
+public interface ClassLoaderFactory {
+ ClassLoader create(URL[] urls, ClassLoader innerClassLoader);
+}
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java
similarity index 67%
rename from tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java
rename to tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java
index 77f4f8a16..63c957a40 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,48 +13,56 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps;
+package org.teavm.tooling.builder;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
-import org.jetbrains.jps.incremental.CompileContext;
-import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.teavm.backend.wasm.render.WasmBinaryVersion;
import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.ProblemProvider;
-import org.teavm.idea.jps.model.TeaVMBuildResult;
-import org.teavm.idea.jps.model.TeaVMBuildStrategy;
-import org.teavm.idea.jps.util.ExceptionUtil;
import org.teavm.tooling.EmptyTeaVMToolLog;
import org.teavm.tooling.TeaVMTargetType;
import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.TeaVMToolLog;
import org.teavm.tooling.sources.DirectorySourceFileProvider;
import org.teavm.tooling.sources.JarSourceFileProvider;
import org.teavm.tooling.sources.SourceFileProvider;
+import org.teavm.vm.TeaVMOptimizationLevel;
import org.teavm.vm.TeaVMProgressListener;
-public class InProcessBuildStrategy implements TeaVMBuildStrategy {
- private final CompileContext context;
+public class InProcessBuildStrategy implements BuildStrategy {
+ private final ClassLoaderFactory classLoaderFactory;
private List classPathEntries = new ArrayList<>();
private TeaVMTargetType targetType;
private String mainClass;
private String targetDirectory;
+ private String targetFileName = "";
+ private boolean incremental;
+ private String cacheDirectory;
+ private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
+ private boolean minifying;
private boolean sourceMapsFileGenerated;
private boolean debugInformationGenerated;
private boolean sourceFilesCopied;
+ private String[] transformers = new String[0];
+ private String[] classesToPreserve = new String[0];
+ private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0x1;
private final List sourceFileProviders = new ArrayList<>();
private TeaVMProgressListener progressListener;
private Properties properties = new Properties();
+ private TeaVMToolLog log = new EmptyTeaVMToolLog();
- public InProcessBuildStrategy(CompileContext context) {
- this.context = context;
+ public InProcessBuildStrategy(ClassLoaderFactory classLoaderFactory) {
+ this.classLoaderFactory = classLoaderFactory;
}
@Override
@@ -115,6 +123,7 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
@Override
public void setIncremental(boolean incremental) {
+ this.incremental = incremental;
}
@Override
@@ -124,20 +133,67 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
}
@Override
- public TeaVMBuildResult build() {
+ public void setLog(TeaVMToolLog log) {
+ this.log = log;
+ }
+
+ @Override
+ public void setMinifying(boolean minifying) {
+ this.minifying = minifying;
+ }
+
+ @Override
+ public void setTransformers(String[] transformers) {
+ this.transformers = transformers.clone();
+ }
+
+ @Override
+ public void setOptimizationLevel(TeaVMOptimizationLevel level) {
+ this.optimizationLevel = level;
+ }
+
+ @Override
+ public void setTargetFileName(String targetFileName) {
+ this.targetFileName = targetFileName;
+ }
+
+ @Override
+ public void setClassesToPreserve(String[] classesToPreserve) {
+ this.classesToPreserve = classesToPreserve.clone();
+ }
+
+ @Override
+ public void setCacheDirectory(String cacheDirectory) {
+ this.cacheDirectory = cacheDirectory;
+ }
+
+ @Override
+ public void setWasmVersion(WasmBinaryVersion wasmVersion) {
+ this.wasmVersion = wasmVersion;
+ }
+
+ @Override
+ public BuildResult build() throws BuildException {
TeaVMTool tool = new TeaVMTool();
tool.setProgressListener(progressListener);
- tool.setLog(new EmptyTeaVMToolLog());
+ tool.setLog(log);
tool.setTargetType(targetType);
tool.setMainClass(mainClass);
tool.setTargetDirectory(new File(targetDirectory));
+ tool.setTargetFileName(targetFileName);
tool.setClassLoader(buildClassLoader());
+ tool.setOptimizationLevel(optimizationLevel);
tool.setSourceMapsFileGenerated(sourceMapsFileGenerated);
tool.setDebugInformationGenerated(debugInformationGenerated);
tool.setSourceFilesCopied(sourceFilesCopied);
- tool.setMinifying(false);
+ tool.setMinifying(minifying);
+ tool.setIncremental(incremental);
+ tool.getTransformers().addAll(Arrays.asList(transformers));
+ tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
+ tool.setCacheDirectory(cacheDirectory != null ? new File(cacheDirectory) : null);
+ tool.setWasmVersion(wasmVersion);
tool.getProperties().putAll(properties);
@@ -145,22 +201,17 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
tool.addSourceFileProvider(fileProvider);
}
- boolean errorOccurred = false;
- String stackTrace = null;
try {
tool.generate();
} catch (TeaVMToolException | RuntimeException | Error e) {
- e.printStackTrace(System.err);
- stackTrace = ExceptionUtil.exceptionToString(e);
- context.processMessage(new CompilerMessage("TeaVM", e));
- errorOccurred = true;
+ throw new BuildException(e);
}
Set generatedFiles = tool.getGeneratedFiles().stream()
.map(File::getAbsolutePath)
.collect(Collectors.toSet());
- return new InProcessBuildResult(tool.getDependencyInfo().getCallGraph(), errorOccurred, stackTrace,
+ return new InProcessBuildResult(tool.getDependencyInfo().getCallGraph(),
tool.getProblemProvider(), tool.getClasses(), tool.getUsedResources(), generatedFiles);
}
@@ -173,26 +224,19 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
}
}).toArray(URL[]::new);
- RenamingClassLoader classLoader = new RenamingClassLoader(urls, TeaVMBuilder.class.getClassLoader());
- classLoader.rename("org/objectweb/asm/", "org/teavm/asm/");
- return classLoader;
+ return classLoaderFactory.create(urls, InProcessBuildStrategy.class.getClassLoader());
}
- static class InProcessBuildResult implements TeaVMBuildResult {
+ static class InProcessBuildResult implements BuildResult {
private CallGraph callGraph;
- private boolean errorOccurred;
- private String stackTrace;
private ProblemProvider problemProvider;
private Collection classes;
private Collection usedResources;
private Collection generatedFiles;
- InProcessBuildResult(CallGraph callGraph, boolean errorOccurred, String stackTrace,
- ProblemProvider problemProvider, Collection classes, Collection usedResources,
- Collection generatedFiles) {
+ InProcessBuildResult(CallGraph callGraph, ProblemProvider problemProvider,
+ Collection classes, Collection usedResources, Collection generatedFiles) {
this.callGraph = callGraph;
- this.errorOccurred = errorOccurred;
- this.stackTrace = stackTrace;
this.problemProvider = problemProvider;
this.classes = classes;
this.usedResources = usedResources;
@@ -204,16 +248,6 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy {
return callGraph;
}
- @Override
- public boolean isErrorOccurred() {
- return errorOccurred;
- }
-
- @Override
- public String getStackTrace() {
- return stackTrace;
- }
-
@Override
public ProblemProvider getProblems() {
return problemProvider;
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java
similarity index 56%
rename from tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java
rename to tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java
index 165211183..207c7ea96 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java
+++ b/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,39 +13,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps;
+package org.teavm.tooling.builder;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
+import org.teavm.backend.wasm.render.WasmBinaryVersion;
import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.Problem;
import org.teavm.diagnostics.ProblemProvider;
-import org.teavm.idea.jps.model.TeaVMBuildResult;
-import org.teavm.idea.jps.model.TeaVMBuildStrategy;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildCallback;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildRequest;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildResponse;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
+import org.teavm.tooling.EmptyTeaVMToolLog;
import org.teavm.tooling.TeaVMTargetType;
+import org.teavm.tooling.TeaVMToolLog;
+import org.teavm.tooling.daemon.RemoteBuildCallback;
+import org.teavm.tooling.daemon.RemoteBuildRequest;
+import org.teavm.tooling.daemon.RemoteBuildResponse;
+import org.teavm.tooling.daemon.RemoteBuildService;
+import org.teavm.vm.TeaVMOptimizationLevel;
import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener;
-public class RemoteBuildStrategy implements TeaVMBuildStrategy {
- private TeaVMRemoteBuildRequest request;
- private TeaVMRemoteBuildService buildService;
+public class RemoteBuildStrategy implements BuildStrategy {
+ private RemoteBuildRequest request;
+ private RemoteBuildService buildService;
private TeaVMProgressListener progressListener;
+ private TeaVMToolLog log = new EmptyTeaVMToolLog();
- public RemoteBuildStrategy(TeaVMRemoteBuildService buildService) {
+ public RemoteBuildStrategy(RemoteBuildService buildService) {
this.buildService = buildService;
}
@Override
public void init() {
- request = new TeaVMRemoteBuildRequest();
+ request = new RemoteBuildRequest();
+ request.optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
+ request.wasmVersion = WasmBinaryVersion.V_0x1;
}
@Override
@@ -110,14 +115,57 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
}
@Override
- public TeaVMBuildResult build() {
- TeaVMRemoteBuildResponse response;
+ public void setLog(TeaVMToolLog log) {
+ this.log = log;
+ }
+
+ @Override
+ public void setMinifying(boolean minifying) {
+ request.minifying = minifying;
+ }
+
+ @Override
+ public void setTransformers(String[] transformers) {
+ request.transformers = transformers.clone();
+ }
+
+ @Override
+ public void setOptimizationLevel(TeaVMOptimizationLevel level) {
+ request.optimizationLevel = level;
+ }
+
+ @Override
+ public void setTargetFileName(String targetFileName) {
+ request.tagetFileName = targetFileName;
+ }
+
+ @Override
+ public void setClassesToPreserve(String[] classesToPreserve) {
+ request.classesToPreserve = classesToPreserve.clone();
+ }
+
+ @Override
+ public void setCacheDirectory(String cacheDirectory) {
+ request.cacheDirectory = cacheDirectory;
+ }
+
+ @Override
+ public void setWasmVersion(WasmBinaryVersion wasmVersion) {
+ request.wasmVersion = wasmVersion;
+ }
+
+ @Override
+ public BuildResult build() throws BuildException {
+ RemoteBuildResponse response;
try {
- response = buildService.build(request, new CallbackImpl(progressListener));
+ response = buildService.build(request, new CallbackImpl(progressListener, log));
} catch (Throwable e) {
- throw new RuntimeException(e);
+ throw new BuildException(e);
}
- return new TeaVMBuildResult() {
+ if (response.exception != null) {
+ throw new BuildException(response.exception);
+ }
+ return new BuildResult() {
private ProblemProvider problems = new ProblemProvider() {
@Override
public List getProblems() {
@@ -135,16 +183,6 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
return response.callGraph;
}
- @Override
- public boolean isErrorOccurred() {
- return response.errorOccurred;
- }
-
- @Override
- public String getStackTrace() {
- return response.stackTrace;
- }
-
@Override
public ProblemProvider getProblems() {
return problems;
@@ -167,22 +205,54 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy {
};
}
- static class CallbackImpl extends UnicastRemoteObject implements TeaVMRemoteBuildCallback {
+ static class CallbackImpl extends UnicastRemoteObject implements RemoteBuildCallback {
private TeaVMProgressListener listener;
+ private TeaVMToolLog log;
- public CallbackImpl(TeaVMProgressListener listener) throws RemoteException {
+ public CallbackImpl(TeaVMProgressListener listener, TeaVMToolLog log) throws RemoteException {
super();
this.listener = listener;
+ this.log = log;
}
@Override
- public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) throws RemoteException {
- return listener.phaseStarted(phase, count);
+ public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
+ return listener != null ? listener.phaseStarted(phase, count) : TeaVMProgressFeedback.CONTINUE;
}
@Override
- public TeaVMProgressFeedback progressReached(int progress) throws RemoteException {
- return listener.progressReached(progress);
+ public TeaVMProgressFeedback progressReached(int progress) {
+ return listener != null ? listener.progressReached(progress) : TeaVMProgressFeedback.CONTINUE;
+ }
+
+ @Override
+ public void errorReported(String message, Throwable e) {
+ log.error(message, e);
+ }
+
+ @Override
+ public void errorReported(String message) {
+ log.error(message);
+ }
+
+ @Override
+ public void warningReported(String message, Throwable e) {
+ log.warning(message, e);
+ }
+
+ @Override
+ public void warningReported(String message) {
+ log.warning(message);
+ }
+
+ @Override
+ public void infoReported(String message, Throwable e) {
+ log.info(message, e);
+ }
+
+ @Override
+ public void infoReported(String message) {
+ log.info(message);
}
}
}
diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java b/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java
similarity index 71%
rename from tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java
index 1feae14e1..223f4eb8a 100644
--- a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,11 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.daemon;
+package org.teavm.tooling.daemon;
-import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManager;
-import com.intellij.openapi.extensions.PluginId;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -34,22 +31,12 @@ import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Random;
-import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildCallback;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildRequest;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildResponse;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
-import org.teavm.idea.jps.util.ExceptionUtil;
-import org.teavm.tooling.EmptyTeaVMToolLog;
import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException;
import org.teavm.tooling.sources.DirectorySourceFileProvider;
@@ -58,15 +45,12 @@ import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener;
-public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemoteBuildService {
+public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildService {
private static final int MIN_PORT = 10000;
private static final int MAX_PORT = 1 << 16;
- private static final Set KOTLIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
- "teavm-plugin.jar", "teavm.jar"));
- private static final String DAEMON_CLASS = TeaVMBuildDaemon.class.getName().replace('.', '/') + ".class";
- private static final int DAEMON_CLASS_DEPTH;
private static final String DAEMON_MESSAGE_PREFIX = "TeaVM daemon port: ";
private static final String INCREMENTAL_PROPERTY = "teavm.daemon.incremental";
+ private static final String DEBUG_PORT_PROPERTY = "teavm.daemon.debug.port";
private boolean incremental;
private int port;
private Registry registry;
@@ -74,17 +58,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
private ClassLoader lastJarClassLoader;
private List lastJarClassPath;
- static {
- int depth = 0;
- for (int i = 0; i < DAEMON_CLASS.length(); ++i) {
- if (DAEMON_CLASS.charAt(i) == '/') {
- depth++;
- }
- }
- DAEMON_CLASS_DEPTH = depth;
- }
-
- TeaVMBuildDaemon(boolean incremental) throws RemoteException {
+ BuildDaemon(boolean incremental) throws RemoteException {
super();
this.incremental = incremental;
Random random = new Random();
@@ -96,7 +70,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
continue;
}
try {
- registry.bind(TeaVMRemoteBuildService.ID, this);
+ registry.bind(RemoteBuildService.ID, this);
} catch (RemoteException | AlreadyBoundException e) {
throw new IllegalStateException("Could not bind remote build assistant service", e);
}
@@ -139,7 +113,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
public static void main(String[] args) throws RemoteException {
boolean incremental = Boolean.parseBoolean(System.getProperty(INCREMENTAL_PROPERTY, "false"));
- TeaVMBuildDaemon daemon = new TeaVMBuildDaemon(incremental);
+ BuildDaemon daemon = new BuildDaemon(incremental);
System.out.println(DAEMON_MESSAGE_PREFIX + daemon.port);
if (daemon.incrementalCache != null) {
System.out.println("Incremental cache set up in " + daemon.incrementalCache);
@@ -147,8 +121,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
}
@Override
- public TeaVMRemoteBuildResponse build(TeaVMRemoteBuildRequest request, TeaVMRemoteBuildCallback callback)
- throws RemoteException {
+ public RemoteBuildResponse build(RemoteBuildRequest request, RemoteBuildCallback callback) {
System.out.println("Build started");
if (!request.incremental && incremental) {
@@ -163,21 +136,34 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
TeaVMTool tool = new TeaVMTool();
tool.setIncremental(incremental && request.incremental);
if (tool.isIncremental()) {
- tool.setCacheDirectory(incrementalCache);
+ tool.setCacheDirectory(request.cacheDirectory != null
+ ? new File(request.cacheDirectory)
+ : incrementalCache);
}
tool.setProgressListener(createProgressListener(callback));
- tool.setLog(new EmptyTeaVMToolLog());
+ tool.setLog(new RemoteBuildLog(callback));
+ if (request.transformers != null) {
+ tool.getTransformers().addAll(Arrays.asList(request.transformers));
+ }
+ if (request.classesToPreserve != null) {
+ tool.getClassesToPreserve().addAll(Arrays.asList(request.classesToPreserve));
+ }
tool.setTargetType(request.targetType);
tool.setMainClass(request.mainClass);
tool.setTargetDirectory(new File(request.targetDirectory));
+ tool.setTargetFileName(request.tagetFileName);
tool.setClassLoader(buildClassLoader(request.classPath, incremental && request.incremental));
tool.setSourceMapsFileGenerated(request.sourceMapsFileGenerated);
tool.setDebugInformationGenerated(request.debugInformationGenerated);
tool.setSourceFilesCopied(request.sourceFilesCopied);
- tool.getProperties().putAll(request.properties);
+ if (request.properties != null) {
+ tool.getProperties().putAll(request.properties);
+ }
- tool.setMinifying(false);
+ tool.setOptimizationLevel(request.optimizationLevel);
+ tool.setMinifying(request.minifying);
+ tool.setWasmVersion(request.wasmVersion);
for (String sourceDirectory : request.sourceDirectories) {
tool.addSourceFileProvider(new DirectorySourceFileProvider(new File(sourceDirectory)));
@@ -186,27 +172,24 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
tool.addSourceFileProvider(new JarSourceFileProvider(new File(sourceJar)));
}
- boolean errorOccurred = false;
- String stackTrace = null;
+ RemoteBuildResponse response = new RemoteBuildResponse();
try {
tool.generate();
System.out.println("Build complete");
} catch (TeaVMToolException | RuntimeException | Error e) {
- stackTrace = ExceptionUtil.exceptionToString(e);
- errorOccurred = true;
+ response.exception = e;
}
- TeaVMRemoteBuildResponse response = new TeaVMRemoteBuildResponse();
- response.errorOccurred = errorOccurred;
- response.stackTrace = stackTrace;
- response.callGraph = tool.getDependencyInfo().getCallGraph();
- response.problems.addAll(tool.getProblemProvider().getProblems());
- response.severeProblems.addAll(tool.getProblemProvider().getSevereProblems());
- response.classes.addAll(tool.getClasses());
- response.usedResources.addAll(tool.getUsedResources());
- response.generatedFiles.addAll(tool.getGeneratedFiles().stream()
- .map(File::getAbsolutePath)
- .collect(Collectors.toSet()));
+ if (response.exception == null) {
+ response.callGraph = tool.getDependencyInfo().getCallGraph();
+ response.problems.addAll(tool.getProblemProvider().getProblems());
+ response.severeProblems.addAll(tool.getProblemProvider().getSevereProblems());
+ response.classes.addAll(tool.getClasses());
+ response.usedResources.addAll(tool.getUsedResources());
+ response.generatedFiles.addAll(tool.getGeneratedFiles().stream()
+ .map(File::getAbsolutePath)
+ .collect(Collectors.toSet()));
+ }
return response;
}
@@ -254,7 +237,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
return new URLClassLoader(urls, jarClassLoader);
}
- private TeaVMProgressListener createProgressListener(TeaVMRemoteBuildCallback callback) {
+ private TeaVMProgressListener createProgressListener(RemoteBuildCallback callback) {
return new TeaVMProgressListener() {
private long lastReportedTime;
@@ -283,18 +266,26 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
};
}
- public static TeaVMDaemonInfo start(boolean incremental, int daemonMemory) throws IOException {
+ public static DaemonInfo start(boolean incremental, int daemonMemory, DaemonLog log,
+ String... classPathEntries) throws IOException {
String javaHome = System.getProperty("java.home");
String javaCommand = javaHome + "/bin/java";
- String classPath = String.join(File.pathSeparator, detectClassPath());
- ProcessBuilder builder = new ProcessBuilder(javaCommand, "-cp", classPath,
+ String classPath = String.join(File.pathSeparator, classPathEntries);
+ List arguments = new ArrayList<>();
+
+ arguments.addAll(Arrays.asList(javaCommand, "-cp", classPath,
"-D" + INCREMENTAL_PROPERTY + "=" + incremental,
- "-Xmx" + daemonMemory + "m",
- TeaVMBuildDaemon.class.getName());
+ "-Xmx" + daemonMemory + "m"));
+
+ String debugPort = System.getProperty(DEBUG_PORT_PROPERTY);
+ if (debugPort != null) {
+ arguments.add("-agentlib:jdwp=transport=dt_socket,quiet=y,server=y,address=" + debugPort + ",suspend=y");
+ }
+
+ arguments.add(BuildDaemon.class.getName());
+
+ ProcessBuilder builder = new ProcessBuilder(arguments.toArray(new String[0]));
Process process = builder.start();
-
- Log log = LogFactory.getLog(TeaVMBuildDaemon.class);
-
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream(),
StandardCharsets.UTF_8));
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream(),
@@ -311,6 +302,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
}
IOUtils.closeQuietly(stderrReader);
IOUtils.closeQuietly(stdoutReader);
+ process.destroy();
throw new IllegalStateException("Could not start daemon. Stderr: " + sb);
}
int port = Integer.parseInt(line.substring(DAEMON_MESSAGE_PREFIX.length()));
@@ -318,7 +310,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
daemonThread(new DaemonProcessOutputWatcher(log, stdoutReader, "stdout", false)).start();
daemonThread(new DaemonProcessOutputWatcher(log, stderrReader, "stderr", true)).start();
- return new TeaVMDaemonInfo(port, process);
+ return new DaemonInfo(port, process);
}
private static Thread daemonThread(Runnable runnable) {
@@ -328,12 +320,12 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
}
static class DaemonProcessOutputWatcher implements Runnable {
- private Log log;
+ private DaemonLog log;
private BufferedReader reader;
private String name;
private boolean isError;
- public DaemonProcessOutputWatcher(Log log, BufferedReader reader, String name, boolean isError) {
+ DaemonProcessOutputWatcher(DaemonLog log, BufferedReader reader, String name, boolean isError) {
this.log = log;
this.reader = reader;
this.name = name;
@@ -359,30 +351,4 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote
}
}
}
-
- private static List detectClassPath() {
- IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.teavm.idea"));
- Set visited = new HashSet<>();
- List classPath = new ArrayList<>();
- findInHierarchy(plugin.getPath(), classPath, visited);
- return classPath;
- }
-
- private static void findInHierarchy(File file, List targetFiles, Set visited) {
- if (!visited.add(file)) {
- return;
- }
- if (file.isFile() && KOTLIN_FILES.contains(file.getName())) {
- targetFiles.add(file.getAbsolutePath());
- } else if (file.getPath().endsWith(DAEMON_CLASS)) {
- for (int i = 0; i <= DAEMON_CLASS_DEPTH; ++i) {
- file = file.getParentFile();
- }
- targetFiles.add(file.getAbsolutePath());
- } else if (file.isDirectory()) {
- for (File childFile : file.listFiles()) {
- findInHierarchy(childFile, targetFiles, visited);
- }
- }
- }
}
diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMDaemonInfo.java b/tools/core/src/main/java/org/teavm/tooling/daemon/DaemonInfo.java
similarity index 84%
rename from tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMDaemonInfo.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/DaemonInfo.java
index 2354f6733..075f39ab9 100644
--- a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMDaemonInfo.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/DaemonInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.daemon;
+package org.teavm.tooling.daemon;
-public class TeaVMDaemonInfo {
+public class DaemonInfo {
private int port;
private Process process;
- TeaVMDaemonInfo(int port, Process process) {
+ DaemonInfo(int port, Process process) {
this.port = port;
this.process = process;
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/daemon/DaemonLog.java b/tools/core/src/main/java/org/teavm/tooling/daemon/DaemonLog.java
new file mode 100644
index 000000000..827153fce
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/DaemonLog.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2018 Alexey Andreev.
+ *
+ * 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.teavm.tooling.daemon;
+
+public interface DaemonLog {
+ void error(String message);
+
+ void error(String message, Throwable e);
+
+ void info(String message);
+}
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildCallback.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildCallback.java
similarity index 61%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildCallback.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildCallback.java
index 9a19b224c..8a1ce0733 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildCallback.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,15 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.remote;
+package org.teavm.tooling.daemon;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
-public interface TeaVMRemoteBuildCallback extends Remote {
+public interface RemoteBuildCallback extends Remote {
TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) throws RemoteException;
TeaVMProgressFeedback progressReached(int progress) throws RemoteException;
+
+ void errorReported(String message, Throwable e) throws RemoteException;
+
+ void errorReported(String message) throws RemoteException;
+
+ void warningReported(String message, Throwable e) throws RemoteException;
+
+ void warningReported(String message) throws RemoteException;
+
+ void infoReported(String message, Throwable e) throws RemoteException;
+
+ void infoReported(String message) throws RemoteException;
}
diff --git a/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildLog.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildLog.java
new file mode 100644
index 000000000..de09afc30
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildLog.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2018 Alexey Andreev.
+ *
+ * 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.teavm.tooling.daemon;
+
+import java.rmi.RemoteException;
+import org.teavm.tooling.TeaVMToolLog;
+
+class RemoteBuildLog implements TeaVMToolLog {
+ private RemoteBuildCallback callback;
+
+ RemoteBuildLog(RemoteBuildCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void info(String text) {
+ try {
+ callback.infoReported(text);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void debug(String text) {
+
+ }
+
+ @Override
+ public void warning(String text) {
+ try {
+ callback.warningReported(text);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void error(String text) {
+ try {
+ callback.errorReported(text);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void info(String text, Throwable e) {
+ try {
+ callback.infoReported(text, e);
+ } catch (RemoteException e2) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void debug(String text, Throwable e) {
+ }
+
+ @Override
+ public void warning(String text, Throwable e) {
+ try {
+ callback.warningReported(text, e);
+ } catch (RemoteException e2) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void error(String text, Throwable e) {
+ try {
+ callback.errorReported(text, e);
+ } catch (RemoteException e2) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java
similarity index 71%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java
index 67f7e86dc..78e4cf865 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,24 +13,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.remote;
+package org.teavm.tooling.daemon;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import org.teavm.backend.wasm.render.WasmBinaryVersion;
import org.teavm.tooling.TeaVMTargetType;
+import org.teavm.vm.TeaVMOptimizationLevel;
-public class TeaVMRemoteBuildRequest implements Serializable {
+public class RemoteBuildRequest implements Serializable {
public final List sourceDirectories = new ArrayList<>();
public final List sourceJarFiles = new ArrayList<>();
public final List classPath = new ArrayList<>();
+ public String[] transformers;
+ public String[] classesToPreserve;
public TeaVMTargetType targetType;
public String mainClass;
public String targetDirectory;
+ public String tagetFileName = "";
public boolean sourceMapsFileGenerated;
public boolean debugInformationGenerated;
public boolean sourceFilesCopied;
public boolean incremental;
+ public String cacheDirectory;
+ public boolean minifying;
public Properties properties;
+ public TeaVMOptimizationLevel optimizationLevel;
+ public WasmBinaryVersion wasmVersion;
}
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildResponse.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildResponse.java
similarity index 85%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildResponse.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildResponse.java
index 6364a5e4b..dc68e2683 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildResponse.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.remote;
+package org.teavm.tooling.daemon;
import java.io.Serializable;
import java.util.ArrayList;
@@ -23,13 +23,12 @@ import java.util.Set;
import org.teavm.callgraph.CallGraph;
import org.teavm.diagnostics.Problem;
-public class TeaVMRemoteBuildResponse implements Serializable {
+public class RemoteBuildResponse implements Serializable {
public CallGraph callGraph;
- public boolean errorOccurred;
public final List problems = new ArrayList<>();
public final List severeProblems = new ArrayList<>();
public final Set usedResources = new HashSet<>();
public final Set classes = new HashSet<>();
public final Set generatedFiles = new HashSet<>();
- public String stackTrace;
+ public Throwable exception;
}
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildService.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildService.java
similarity index 73%
rename from tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildService.java
rename to tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildService.java
index 951991ca3..bb04a3392 100644
--- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildService.java
+++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildService.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,15 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.idea.jps.remote;
+package org.teavm.tooling.daemon;
import java.rmi.Remote;
import java.rmi.RemoteException;
-public interface TeaVMRemoteBuildService extends Remote {
+public interface RemoteBuildService extends Remote {
String REMOTE_PORT = "teavm.daemon.remote-port";
String ID = "TeaVM-Daemon";
- TeaVMRemoteBuildResponse build(TeaVMRemoteBuildRequest request, TeaVMRemoteBuildCallback callback)
- throws RemoteException;
+ RemoteBuildResponse build(RemoteBuildRequest request, RemoteBuildCallback callback) throws RemoteException;
}
diff --git a/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java b/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
index 0e87ee95f..ac7aed340 100644
--- a/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
+++ b/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
@@ -157,9 +157,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
String cacheDir = profile.getCacheDirectory();
tool.setCacheDirectory(!cacheDir.isEmpty() ?
new File(varManager.performStringSubstitution(cacheDir, false)) : null);
- for (ClassHolderTransformer transformer : instantiateTransformers(profile, classLoader)) {
- tool.getTransformers().add(transformer);
- }
+ tool.getTransformers().addAll(Arrays.asList(profile.getTransformers()));
tool.getClassesToPreserve().addAll(profile.getClassesToPreserve());
for (SourceFileProvider provider : sourceProviders) {
tool.addSourceFileProvider(provider);
@@ -540,42 +538,6 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
return projects;
}
- private List instantiateTransformers(TeaVMProfile profile, ClassLoader classLoader)
- throws CoreException{
- List transformerInstances = new ArrayList<>();
- for (String transformerName : profile.getTransformers()) {
- Class> transformerRawType;
- try {
- transformerRawType = Class.forName(transformerName, true, classLoader);
- } catch (ClassNotFoundException e) {
- putConfigMarker("Transformer not found: " + transformerName);
- continue;
- }
- if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
- putConfigMarker("Transformer " + transformerName + " is not a subtype of " +
- ClassHolderTransformer.class.getName());
- continue;
- }
- Class extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
- ClassHolderTransformer.class);
- Constructor extends ClassHolderTransformer> ctor;
- try {
- ctor = transformerType.getConstructor();
- } catch (NoSuchMethodException e) {
- putConfigMarker("Transformer " + transformerName + " has no default constructor");
- continue;
- }
- try {
- ClassHolderTransformer transformer = ctor.newInstance();
- transformerInstances.add(transformer);
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
- putConfigMarker("Error instantiating transformer " + transformerName);
- continue;
- }
- }
- return transformerInstances;
- }
-
private void putConfigMarker(String message) throws CoreException {
IMarker marker = getProject().createMarker(TeaVMEclipsePlugin.CONFIG_MARKER_ID);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/util/DaemonUtil.java b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/util/DaemonUtil.java
new file mode 100644
index 000000000..0b4b41da8
--- /dev/null
+++ b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/util/DaemonUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 Alexey Andreev.
+ *
+ * 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.teavm.idea.jps.util;
+
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManager;
+import com.intellij.openapi.extensions.PluginId;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.teavm.tooling.daemon.BuildDaemon;
+
+public final class DaemonUtil {
+ private static final Set PLUGIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
+ "teavm-plugin.jar", "teavm.jar"));
+ private static final String DAEMON_CLASS = BuildDaemon.class.getName().replace('.', '/') + ".class";
+ private static final int DAEMON_CLASS_DEPTH;
+
+ static {
+ int depth = 0;
+ for (int i = 0; i < DAEMON_CLASS.length(); ++i) {
+ if (DAEMON_CLASS.charAt(i) == '/') {
+ depth++;
+ }
+ }
+ DAEMON_CLASS_DEPTH = depth;
+ }
+
+ private DaemonUtil() {
+ }
+
+ public static List detectClassPath() {
+ IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.teavm.idea"));
+ Set visited = new HashSet<>();
+ List classPath = new ArrayList<>();
+ findInHierarchy(plugin.getPath(), classPath, visited);
+ return classPath;
+ }
+
+ private static void findInHierarchy(File file, List targetFiles, Set visited) {
+ if (!visited.add(file)) {
+ return;
+ }
+ if (file.isFile() && PLUGIN_FILES.contains(file.getName())) {
+ targetFiles.add(file.getAbsolutePath());
+ } else if (file.getPath().endsWith(DAEMON_CLASS)) {
+ for (int i = 0; i <= DAEMON_CLASS_DEPTH; ++i) {
+ file = file.getParentFile();
+ }
+ targetFiles.add(file.getAbsolutePath());
+ } else if (file.isDirectory()) {
+ for (File childFile : file.listFiles()) {
+ findInHierarchy(childFile, targetFiles, visited);
+ }
+ }
+ }
+}
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingClassLoader.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingClassLoader.java
index 484229829..c64162c53 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingClassLoader.java
+++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingVisitor.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingVisitor.java
index b05f11627..5b279f8c3 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingVisitor.java
+++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RenamingVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Alexey Andreev.
+ * Copyright 2018 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java
index d4f76300c..4f6341298 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java
+++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java
@@ -22,6 +22,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -57,8 +58,6 @@ import org.teavm.common.IntegerArray;
import org.teavm.diagnostics.DefaultProblemTextConsumer;
import org.teavm.diagnostics.Problem;
import org.teavm.diagnostics.ProblemProvider;
-import org.teavm.idea.jps.model.TeaVMBuildResult;
-import org.teavm.idea.jps.model.TeaVMBuildStrategy;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
import org.teavm.idea.jps.model.TeaVMProperty;
import org.teavm.idea.jps.remote.TeaVMBuilderAssistant;
@@ -67,6 +66,9 @@ import org.teavm.model.CallLocation;
import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation;
import org.teavm.model.ValueType;
+import org.teavm.tooling.builder.BuildException;
+import org.teavm.tooling.builder.BuildResult;
+import org.teavm.tooling.builder.BuildStrategy;
import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener;
@@ -79,10 +81,10 @@ class TeaVMBuild {
private final TeaVMBuilderAssistant assistant;
private final Map sourceFileCache = new HashMap<>();
private final Map fileLineCache = new HashMap<>();
- private TeaVMBuildStrategy buildStrategy;
+ private BuildStrategy buildStrategy;
private BuildOutputConsumer outputConsumer;
- TeaVMBuild(CompileContext context, TeaVMBuilderAssistant assistant, TeaVMBuildStrategy buildStrategy,
+ TeaVMBuild(CompileContext context, TeaVMBuilderAssistant assistant, BuildStrategy buildStrategy,
BuildOutputConsumer outputConsumer) {
this.context = context;
this.assistant = assistant;
@@ -90,7 +92,7 @@ class TeaVMBuild {
this.outputConsumer = outputConsumer;
}
- boolean perform(JpsModule module, TeaVMBuildTarget target) throws IOException {
+ boolean perform(JpsModule module, TeaVMBuildTarget target) throws IOException, BuildException {
TeaVMStorageProvider storageProvider = new TeaVMStorageProvider(
target.getConfiguration().getTargetType().name());
storage = context.getProjectDescriptor().dataManager.getStorage(target, storageProvider);
@@ -128,24 +130,16 @@ class TeaVMBuild {
}
buildStrategy.setProperties(properties);
- TeaVMBuildResult buildResult = buildStrategy.build();
+ BuildResult buildResult = buildStrategy.build();
- if (!buildResult.isErrorOccurred() && buildResult.getProblems().getSevereProblems().isEmpty()) {
+ if (!buildResult.getProblems().getSevereProblems().isEmpty()) {
updateStorage(buildResult);
}
reportProblems(buildResult.getProblems(), buildResult.getCallGraph());
- if (!buildResult.isErrorOccurred()) {
- for (String fileName : buildResult.getGeneratedFiles()) {
- outputConsumer.registerOutputFile(new File(fileName), Collections.emptyList());
- }
- }
-
- if (buildResult.getStackTrace() != null) {
- context.processMessage(new CompilerMessage("TeaVM", BuildMessage.Kind.ERROR,
- "Compiler crashed:\n" + buildResult.getStackTrace(), "",
- -1, -1, -1, -1, -1));
+ for (String fileName : buildResult.getGeneratedFiles()) {
+ outputConsumer.registerOutputFile(new File(fileName), Collections.emptyList());
}
return true;
@@ -390,7 +384,7 @@ class TeaVMBuild {
private int[] getLineOffsetsCacheMiss(File file) {
IntegerArray lines = new IntegerArray(50);
- try (Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8")) {
+ try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
int offset = 0;
lines.add(0);
@@ -450,10 +444,9 @@ class TeaVMBuild {
return false;
}
- private void updateStorage(TeaVMBuildResult buildResult) {
+ private void updateStorage(BuildResult buildResult) {
Set resources = Stream.concat(buildResult.getClasses().stream()
.map(cls -> cls.replace('.', '/') + ".class"), buildResult.getUsedResources().stream())
- .sorted()
.collect(toSet());
List participatingFiles = resources.stream()
.map(path -> {
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuilder.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuilder.java
index 934255721..93cb72158 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuilder.java
+++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuilder.java
@@ -16,7 +16,6 @@
package org.teavm.idea.jps;
import static org.teavm.idea.jps.remote.TeaVMBuilderAssistant.REMOTE_PORT;
-import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
@@ -27,17 +26,19 @@ import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.incremental.CompileContext;
-import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.incremental.TargetBuilder;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
-import org.teavm.idea.jps.model.TeaVMBuildStrategy;
import org.teavm.idea.jps.remote.TeaVMBuilderAssistant;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
+import org.teavm.tooling.builder.BuildException;
+import org.teavm.tooling.builder.BuildStrategy;
+import org.teavm.tooling.builder.InProcessBuildStrategy;
+import org.teavm.tooling.builder.RemoteBuildStrategy;
+import org.teavm.tooling.daemon.RemoteBuildService;
public class TeaVMBuilder extends TargetBuilder {
private TeaVMBuilderAssistant assistant;
- private TeaVMRemoteBuildService buildService;
+ private RemoteBuildService buildService;
public TeaVMBuilder() {
super(Collections.singletonList(TeaVMBuildTargetType.INSTANCE));
@@ -52,11 +53,11 @@ public class TeaVMBuilder extends TargetBuilder holder,
- @NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) throws ProjectBuildException,
- IOException {
+ @NotNull BuildOutputConsumer outputConsumer, @NotNull CompileContext context) {
if (assistant == null) {
context.processMessage(new CompilerMessage("TeaVM", BuildMessage.Kind.WARNING,
"No TeaVM builder assistant available. Diagnostic messages will be less informative"));
}
- TeaVMBuildStrategy buildStrategy = buildService != null
- ? new RemoteBuildStrategy(buildService)
- : new InProcessBuildStrategy(context);
- TeaVMBuild build = new TeaVMBuild(context, assistant, buildStrategy, outputConsumer);
+ try {
+ BuildStrategy buildStrategy = buildService != null
+ ? new RemoteBuildStrategy(buildService)
+ : createInProcessBuilder();
+ TeaVMBuild build = new TeaVMBuild(context, assistant, buildStrategy, outputConsumer);
- build.perform(target.getModule(), target);
+ build.perform(target.getModule(), target);
+ } catch (BuildException e) {
+ context.processMessage(CompilerMessage.createInternalBuilderError("TeaVM", e.getCause()));
+ } catch (Exception e) {
+ context.processMessage(CompilerMessage.createInternalBuilderError("TeaVM", e));
+ }
+ }
+
+ private BuildStrategy createInProcessBuilder() {
+ return new InProcessBuildStrategy((urls, innerClassLoader) -> {
+ RenamingClassLoader loader = new RenamingClassLoader(urls, innerClassLoader);
+ loader.rename("org/objectweb/asm/", "org/teavm/asm/");
+ return loader;
+ });
}
@NotNull
diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMStorage.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMStorage.java
index f64712a75..8bfa4d536 100644
--- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMStorage.java
+++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMStorage.java
@@ -25,6 +25,7 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.jps.incremental.storage.StorageOwner;
@@ -39,7 +40,7 @@ public class TeaVMStorage implements StorageOwner {
this.file = file;
if (file.exists()) {
participatingFiles = new ArrayList<>();
- try (Reader innerReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
+ try (Reader innerReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(innerReader)) {
while (true) {
String line = reader.readLine();
@@ -82,7 +83,7 @@ public class TeaVMStorage implements StorageOwner {
}
@Override
- public void clean() throws IOException {
+ public void clean() {
file.delete();
participatingFiles = null;
}
@@ -95,7 +96,7 @@ public class TeaVMStorage implements StorageOwner {
file.delete();
}
} else {
- try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
+ try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
BufferedWriter writer = new BufferedWriter(innerWriter)) {
for (Entry participatingFile : participatingFiles) {
writer.append(participatingFile.path + ":" + participatingFile.timestamp);
diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMDaemonComponent.java b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMDaemonComponent.java
index 2e1def345..99373dfbb 100644
--- a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMDaemonComponent.java
+++ b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMDaemonComponent.java
@@ -18,13 +18,17 @@ package org.teavm.idea;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.components.ServiceManager;
import java.io.IOException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
-import org.teavm.idea.daemon.TeaVMBuildDaemon;
-import org.teavm.idea.daemon.TeaVMDaemonInfo;
import org.teavm.idea.jps.model.TeaVMJpsWorkspaceConfiguration;
+import org.teavm.idea.jps.util.DaemonUtil;
+import org.teavm.tooling.daemon.BuildDaemon;
+import org.teavm.tooling.daemon.DaemonInfo;
+import org.teavm.tooling.daemon.DaemonLog;
public class TeaVMDaemonComponent implements ApplicationComponent {
- private TeaVMDaemonInfo daemonInfo;
+ private DaemonInfo daemonInfo;
private boolean incremental;
private int daemonMemory;
@@ -64,7 +68,9 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
public void startDaemon() {
if (daemonInfo == null) {
try {
- daemonInfo = TeaVMBuildDaemon.start(incremental, daemonMemory);
+ Log log = LogFactory.getLog(TeaVMDaemonComponent.class);
+ daemonInfo = BuildDaemon.start(incremental, daemonMemory, new LogWrapper(log),
+ DaemonUtil.detectClassPath().toArray(new String[0]));
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -116,4 +122,27 @@ public class TeaVMDaemonComponent implements ApplicationComponent {
public String getComponentName() {
return "TeaVM daemon";
}
+
+ static class LogWrapper implements DaemonLog {
+ private Log log;
+
+ public LogWrapper(Log log) {
+ this.log = log;
+ }
+
+ @Override
+ public void error(String s) {
+ log.error(s);
+ }
+
+ @Override
+ public void error(String s, Throwable throwable) {
+ log.error(s, throwable);
+ }
+
+ @Override
+ public void info(String s) {
+ log.info(s);
+ }
+ }
}
diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSConfigurator.java b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSConfigurator.java
index 507964634..4ced5634d 100644
--- a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSConfigurator.java
+++ b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSConfigurator.java
@@ -20,7 +20,7 @@ import com.intellij.compiler.server.BuildProcessParametersProvider;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.annotations.NotNull;
-import org.teavm.idea.jps.remote.TeaVMRemoteBuildService;
+import org.teavm.tooling.daemon.RemoteBuildService;
public class TeaVMJPSConfigurator extends BuildProcessParametersProvider {
private TeaVMJPSRemoteService remoteService;
@@ -37,7 +37,7 @@ public class TeaVMJPSConfigurator extends BuildProcessParametersProvider {
List result = new ArrayList<>();
result.add("-D" + REMOTE_PORT + "=" + remoteService.getPort());
if (daemonComponent.isDaemonRunning()) {
- result.add("-D" + TeaVMRemoteBuildService.REMOTE_PORT + "=" + daemonComponent.getDaemonPort());
+ result.add("-D" + RemoteBuildService.REMOTE_PORT + "=" + daemonComponent.getDaemonPort());
}
return result;
}
diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSRemoteService.java b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSRemoteService.java
index 75da5ec14..05a77af02 100644
--- a/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSRemoteService.java
+++ b/tools/idea/plugin/src/main/java/org/teavm/idea/TeaVMJPSRemoteService.java
@@ -99,8 +99,7 @@ public class TeaVMJPSRemoteService extends UnicastRemoteObject implements Applic
}
@Override
- public TeaVMElementLocation getMethodLocation(String className, String methodName, String methodDesc)
- throws RemoteException {
+ public TeaVMElementLocation getMethodLocation(String className, String methodName, String methodDesc) {
TeaVMElementLocation[] resultHolder = new TeaVMElementLocation[1];
ApplicationManager.getApplication().runReadAction(() -> {
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractTeaVMMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractTeaVMMojo.java
deleted file mode 100644
index 3209d1ab1..000000000
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractTeaVMMojo.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright 2015 Alexey Andreev.
- *
- * 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.teavm.maven;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.MavenArtifactRepository;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.plugins.annotations.Component;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.repository.RepositorySystem;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.tooling.BaseTeaVMTool;
-import org.teavm.tooling.sources.SourceFileProvider;
-
-public abstract class AbstractTeaVMMojo extends AbstractMojo {
- @Component
- protected MavenProject project;
-
- @Component
- protected RepositorySystem repositorySystem;
-
- @Parameter(required = true, readonly = true, defaultValue = "${localRepository}")
- protected MavenArtifactRepository localRepository;
-
- @Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}")
- protected List remoteRepositories;
-
- @Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
- protected List pluginArtifacts;
-
- @Parameter(defaultValue = "${project.build.outputDirectory}")
- protected File classFiles;
-
- @Parameter
- protected List compileScopes;
-
- @Parameter
- protected boolean minifying = true;
-
- @Parameter
- protected Properties properties;
-
- @Parameter
- protected boolean debugInformationGenerated;
-
- @Parameter
- protected boolean sourceMapsGenerated;
-
- @Parameter
- protected boolean sourceFilesCopied;
-
- @Parameter
- protected boolean incremental;
-
- @Parameter
- protected String[] transformers;
-
- protected ClassLoader classLoader;
-
- protected abstract File getTargetDirectory();
-
- protected final List instantiateTransformers(ClassLoader classLoader)
- throws MojoExecutionException {
- List transformerInstances = new ArrayList<>();
- if (transformers == null) {
- return transformerInstances;
- }
- for (String transformerName : transformers) {
- Class> transformerRawType;
- try {
- transformerRawType = Class.forName(transformerName, true, classLoader);
- } catch (ClassNotFoundException e) {
- throw new MojoExecutionException("Transformer not found: " + transformerName, e);
- }
- if (!ClassHolderTransformer.class.isAssignableFrom(transformerRawType)) {
- throw new MojoExecutionException("Transformer " + transformerName + " is not subtype of "
- + ClassHolderTransformer.class.getName());
- }
- Class extends ClassHolderTransformer> transformerType = transformerRawType.asSubclass(
- ClassHolderTransformer.class);
- Constructor extends ClassHolderTransformer> ctor;
- try {
- ctor = transformerType.getConstructor();
- } catch (NoSuchMethodException e) {
- throw new MojoExecutionException("Transformer " + transformerName + " has no default constructor");
- }
- try {
- ClassHolderTransformer transformer = ctor.newInstance();
- transformerInstances.add(transformer);
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
- throw new MojoExecutionException("Error instantiating transformer " + transformerName, e);
- }
- }
- return transformerInstances;
- }
-
- protected void setupTool(BaseTeaVMTool tool) throws MojoExecutionException {
- tool.setLog(new MavenTeaVMToolLog(getLog()));
- try {
- ClassLoader classLoader = prepareClassLoader();
- tool.setClassLoader(classLoader);
- tool.setMinifying(minifying);
- tool.setTargetDirectory(getTargetDirectory());
- tool.getTransformers().addAll(instantiateTransformers(classLoader));
- if (sourceFilesCopied) {
- for (SourceFileProvider provider : getSourceFileProviders()) {
- tool.addSourceFileProvider(provider);
- }
- }
- if (properties != null) {
- tool.getProperties().putAll(properties);
- }
- tool.setIncremental(incremental);
- tool.setDebugInformationGenerated(debugInformationGenerated);
- tool.setSourceMapsFileGenerated(sourceMapsGenerated);
- tool.setSourceFilesCopied(sourceFilesCopied);
- } catch (RuntimeException e) {
- throw new MojoExecutionException("Unexpected error occured", e);
- }
- }
-
- protected final ClassLoader prepareClassLoader() throws MojoExecutionException {
- try {
- Log log = getLog();
- log.info("Preparing classpath for JavaScript generation");
- List urls = new ArrayList<>();
- StringBuilder classpath = new StringBuilder();
- for (Artifact artifact : project.getArtifacts()) {
- if (!filterByScope(artifact)) {
- continue;
- }
- File file = artifact.getFile();
- if (classpath.length() > 0) {
- classpath.append(':');
- }
- classpath.append(file.getPath());
- urls.add(file.toURI().toURL());
- }
- if (classpath.length() > 0) {
- classpath.append(':');
- }
- classpath.append(classFiles.getPath());
- urls.add(classFiles.toURI().toURL());
- for (File additionalEntry : getAdditionalClassPath()) {
- classpath.append(':').append(additionalEntry.getPath());
- urls.add(additionalEntry.toURI().toURL());
- }
- log.info("Using the following classpath for JavaScript generation: " + classpath);
- classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]),
- AbstractTeaVMMojo.class.getClassLoader());
- return classLoader;
- } catch (MalformedURLException e) {
- throw new MojoExecutionException("Error gathering classpath information", e);
- }
- }
-
- protected List getAdditionalClassPath() {
- return Collections.emptyList();
- }
-
- protected boolean filterByScope(Artifact artifact) {
- return compileScopes == null ? isSupportedScope(artifact.getScope())
- : compileScopes.contains(artifact.getScope());
- }
-
- protected boolean isSupportedScope(String scope) {
- switch (scope) {
- case Artifact.SCOPE_COMPILE:
- case Artifact.SCOPE_PROVIDED:
- case Artifact.SCOPE_SYSTEM:
- return true;
- default:
- return false;
- }
- }
-
- protected final List getSourceFileProviders() {
- MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
- lookup.setMavenProject(project);
- lookup.setRepositorySystem(repositorySystem);
- lookup.setLocalRepository(localRepository);
- lookup.setRemoteRepositories(remoteRepositories);
- lookup.setPluginDependencies(pluginArtifacts);
- List providers = lookup.resolve();
- addSourceProviders(providers);
- return providers;
- }
-
- protected void addSourceProviders(@SuppressWarnings("unused") List providers) {
- }
-}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java b/tools/maven/plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java
index a9b049a65..8408acf0f 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/MavenSourceFileProviderLookup.java
@@ -26,9 +26,7 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
-import org.teavm.tooling.sources.DirectorySourceFileProvider;
-import org.teavm.tooling.sources.JarSourceFileProvider;
-import org.teavm.tooling.sources.SourceFileProvider;
+import org.teavm.tooling.builder.BuildStrategy;
public class MavenSourceFileProviderLookup {
private MavenProject mavenProject;
@@ -57,7 +55,7 @@ public class MavenSourceFileProviderLookup {
this.pluginDependencies = pluginDependencies;
}
- public List resolve() {
+ public void resolve(BuildStrategy builder) {
List initialArtifacts = new ArrayList<>();
initialArtifacts.addAll(mavenProject.getArtifacts());
if (pluginDependencies != null) {
@@ -74,7 +72,6 @@ public class MavenSourceFileProviderLookup {
}
artifacts.addAll(initialArtifacts);
- List providers = new ArrayList<>();
for (Artifact artifact : artifacts) {
ArtifactResolutionRequest request = new ArtifactResolutionRequest()
.setLocalRepository(localRepository)
@@ -85,16 +82,15 @@ public class MavenSourceFileProviderLookup {
if (resolvedArtifact.getFile() != null) {
File file = resolvedArtifact.getFile();
if (!file.isDirectory()) {
- providers.add(new JarSourceFileProvider(file));
+ builder.addSourcesJar(file.getAbsolutePath());
} else {
- providers.add(new DirectorySourceFileProvider(file));
+ builder.addSourcesDirectory(file.getAbsolutePath());
}
}
}
}
for (String sourceRoot : mavenProject.getCompileSourceRoots()) {
- providers.add(new DirectorySourceFileProvider(new File(sourceRoot)));
+ builder.addSourcesDirectory(new File(sourceRoot).getAbsolutePath());
}
- return providers;
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java
index ddbbadee2..9fde07aba 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java
@@ -16,26 +16,88 @@
package org.teavm.maven;
import java.io.File;
-import java.util.Arrays;
+import java.net.URLClassLoader;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Properties;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.MavenArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
import org.teavm.backend.wasm.render.WasmBinaryVersion;
+import org.teavm.tooling.TeaVMProblemRenderer;
import org.teavm.tooling.TeaVMTargetType;
-import org.teavm.tooling.TeaVMTool;
-import org.teavm.tooling.TeaVMToolException;
-import org.teavm.tooling.sources.DirectorySourceFileProvider;
-import org.teavm.tooling.sources.SourceFileProvider;
+import org.teavm.tooling.builder.BuildException;
+import org.teavm.tooling.builder.BuildResult;
+import org.teavm.tooling.builder.BuildStrategy;
+import org.teavm.tooling.builder.InProcessBuildStrategy;
+import org.teavm.tooling.builder.RemoteBuildStrategy;
+import org.teavm.tooling.daemon.BuildDaemon;
+import org.teavm.tooling.daemon.DaemonInfo;
+import org.teavm.tooling.daemon.DaemonLog;
+import org.teavm.tooling.daemon.RemoteBuildService;
import org.teavm.vm.TeaVMOptimizationLevel;
@Mojo(name = "compile", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME,
defaultPhase = LifecyclePhase.PROCESS_CLASSES)
-public class TeaVMCompileMojo extends AbstractTeaVMMojo {
+public class TeaVMCompileMojo extends AbstractMojo {
+ @Component
+ private MavenProject project;
+
+ @Component
+ private RepositorySystem repositorySystem;
+
+ @Parameter(required = true, readonly = true, defaultValue = "${localRepository}")
+ private MavenArtifactRepository localRepository;
+
+ @Parameter(required = true, readonly = true, defaultValue = "${project.remoteArtifactRepositories}")
+ private List remoteRepositories;
+
+ @Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
+ private List pluginArtifacts;
+
+ @Parameter(defaultValue = "${project.build.outputDirectory}")
+ private File classFiles;
+
+ @Parameter
+ private List compileScopes;
+
+ @Parameter
+ private boolean minifying = true;
+
+ @Parameter
+ private Properties properties;
+
+ @Parameter
+ private boolean debugInformationGenerated;
+
+ @Parameter
+ private boolean sourceMapsGenerated;
+
+ @Parameter
+ private boolean sourceFilesCopied;
+
+ @Parameter
+ private boolean incremental;
+
+ @Parameter
+ private String[] transformers;
+
@Parameter(defaultValue = "${project.build.directory}/javascript")
private File targetDirectory;
@@ -61,48 +123,197 @@ public class TeaVMCompileMojo extends AbstractTeaVMMojo {
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
@Parameter(defaultValue = "${project.build.directory}/teavm-cache")
- protected File cacheDirectory;
-
- private TeaVMTool tool = new TeaVMTool();
+ private File cacheDirectory;
@Parameter
private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0x1;
- @Override
- protected File getTargetDirectory() {
- return targetDirectory;
+ @Parameter(property = "teavm.outOfProcess", defaultValue = "false")
+ private boolean outOfProcess;
+
+ @Parameter(property = "teavm.processMemory", defaultValue = "512")
+ private int processMemory;
+
+ private void setupBuilder(BuildStrategy builder) throws MojoExecutionException {
+ builder.setLog(new MavenTeaVMToolLog(getLog()));
+ try {
+ builder.setClassPathEntries(prepareClassPath());
+ builder.setMinifying(minifying);
+ builder.setTargetDirectory(targetDirectory.getAbsolutePath());
+ if (transformers != null) {
+ builder.setTransformers(transformers);
+ }
+ if (sourceFilesCopied) {
+ getSourceFileProviders(builder);
+ builder.addSourcesDirectory(sourceDirectory.getAbsolutePath());
+ }
+ if (properties != null) {
+ builder.setProperties(properties);
+ }
+ builder.setIncremental(incremental);
+ builder.setDebugInformationGenerated(debugInformationGenerated);
+ builder.setSourceMapsFileGenerated(sourceMapsGenerated);
+ builder.setSourceFilesCopied(sourceFilesCopied);
+ } catch (RuntimeException e) {
+ throw new MojoExecutionException("Unexpected error occurred", e);
+ }
+ }
+
+ private List prepareClassPath() {
+ Log log = getLog();
+ log.info("Preparing classpath for JavaScript generation");
+ List paths = new ArrayList<>();
+ StringBuilder classpath = new StringBuilder();
+ for (Artifact artifact : project.getArtifacts()) {
+ if (!filterByScope(artifact)) {
+ continue;
+ }
+ File file = artifact.getFile();
+ if (classpath.length() > 0) {
+ classpath.append(':');
+ }
+ classpath.append(file.getPath());
+ paths.add(file.getAbsolutePath());
+ }
+ if (classpath.length() > 0) {
+ classpath.append(':');
+ }
+ classpath.append(classFiles.getPath());
+ paths.add(classFiles.getAbsolutePath());
+ log.info("Using the following classpath for JavaScript generation: " + classpath);
+ return paths;
+ }
+
+ private boolean filterByScope(Artifact artifact) {
+ return compileScopes == null ? isSupportedScope(artifact.getScope())
+ : compileScopes.contains(artifact.getScope());
+ }
+
+ protected boolean isSupportedScope(String scope) {
+ switch (scope) {
+ case Artifact.SCOPE_COMPILE:
+ case Artifact.SCOPE_PROVIDED:
+ case Artifact.SCOPE_SYSTEM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void getSourceFileProviders(BuildStrategy builder) {
+ MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
+ lookup.setMavenProject(project);
+ lookup.setRepositorySystem(repositorySystem);
+ lookup.setLocalRepository(localRepository);
+ lookup.setRemoteRepositories(remoteRepositories);
+ lookup.setPluginDependencies(pluginArtifacts);
+ lookup.resolve(builder);
}
@Override
public void execute() throws MojoExecutionException {
- Log log = getLog();
- setupTool(tool);
- tool.setLog(new MavenTeaVMToolLog(log));
- try {
- tool.setMainClass(mainClass);
- if (!targetFileName.isEmpty()) {
- tool.setTargetFileName(targetFileName);
- }
- tool.setOptimizationLevel(optimizationLevel);
- if (classesToPreserve != null) {
- tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
- }
- tool.setCacheDirectory(cacheDirectory);
- tool.setTargetType(targetType);
- tool.setWasmVersion(wasmVersion);
- tool.generate();
- if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
- throw new MojoExecutionException("Build error");
- }
- } catch (RuntimeException e) {
- throw new MojoExecutionException("Unexpected error occured", e);
- } catch (TeaVMToolException e) {
- throw new MojoExecutionException("IO error occured", e);
+ if (outOfProcess) {
+ executeInSeparateProcess();
+ } else {
+ executeWithBuilder(new InProcessBuildStrategy(URLClassLoader::new));
}
}
- @Override
- protected void addSourceProviders(List providers) {
- providers.add(new DirectorySourceFileProvider(sourceDirectory));
+ private void executeInSeparateProcess() throws MojoExecutionException {
+ DaemonInfo daemon;
+ try {
+ daemon = BuildDaemon.start(false, processMemory, new DaemonLogImpl(), createDaemonClassPath());
+ } catch (Throwable e) {
+ throw new MojoExecutionException("Error starting TeaVM process", e);
+ }
+
+ try {
+ RemoteBuildService buildService;
+ try {
+ Registry registry = LocateRegistry.getRegistry(daemon.getPort());
+ buildService = (RemoteBuildService) registry.lookup(RemoteBuildService.ID);
+ } catch (RemoteException | NotBoundException e) {
+ throw new MojoExecutionException("Error connecting TeaVM process", e);
+ }
+
+ RemoteBuildStrategy builder = new RemoteBuildStrategy(buildService);
+ executeWithBuilder(builder);
+ } finally {
+ daemon.getProcess().destroy();
+ }
+ }
+
+ private void executeWithBuilder(BuildStrategy builder) throws MojoExecutionException {
+ builder.init();
+ Log log = getLog();
+ setupBuilder(builder);
+ MavenTeaVMToolLog toolLog = new MavenTeaVMToolLog(log);
+ builder.setLog(toolLog);
+ try {
+ builder.setMainClass(mainClass);
+ if (!targetFileName.isEmpty()) {
+ builder.setTargetFileName(targetFileName);
+ }
+ builder.setOptimizationLevel(optimizationLevel);
+ if (classesToPreserve != null) {
+ builder.setClassesToPreserve(classesToPreserve);
+ }
+ builder.setCacheDirectory(cacheDirectory.getAbsolutePath());
+ builder.setTargetType(targetType);
+ builder.setWasmVersion(wasmVersion);
+ BuildResult result;
+ result = builder.build();
+ TeaVMProblemRenderer.describeProblems(result.getCallGraph(), result.getProblems(), toolLog);
+ if (stopOnErrors && !result.getProblems().getSevereProblems().isEmpty()) {
+ throw new MojoExecutionException("Build error");
+ }
+ } catch (BuildException e) {
+ throw new MojoExecutionException("Unexpected error occurred", e.getCause());
+ } catch (Exception e) {
+ throw new MojoExecutionException("Unexpected error occurred", e);
+ }
+ }
+
+ private String[] createDaemonClassPath() {
+ Artifact toolArtifact = pluginArtifacts.stream()
+ .filter(artifact -> artifact.getGroupId().equals("org.teavm")
+ && artifact.getArtifactId().equals("teavm-tooling"))
+ .findFirst()
+ .orElse(null);
+ if (toolArtifact == null) {
+ return new String[0];
+ }
+
+ ArtifactResolutionResult resolutionResult = repositorySystem.resolve(new ArtifactResolutionRequest()
+ .setLocalRepository(localRepository)
+ .setRemoteRepositories(new ArrayList<>(remoteRepositories))
+ .setResolveTransitively(true)
+ .setResolveRoot(true)
+ .setArtifact(toolArtifact));
+
+ if (!resolutionResult.isSuccess()) {
+ return new String[0];
+ }
+
+ return resolutionResult.getArtifacts().stream()
+ .map(artifact -> artifact.getFile().getAbsolutePath())
+ .toArray(String[]::new);
+ }
+
+ class DaemonLogImpl implements DaemonLog {
+ @Override
+ public void error(String message) {
+ getLog().error(message);
+ }
+
+ @Override
+ public void error(String message, Throwable e) {
+ getLog().error(message, e);
+ }
+
+ @Override
+ public void info(String message) {
+ getLog().info(message);
+ }
}
}