diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..99a559dad
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,13 @@
+language: java
+jdk:
+ - oraclejdk8
+cache:
+ directories:
+ - $HOME/.m2
+script: >
+ mvn test \
+ -Dteavm.test.skip=false \
+ -Dteavm.test.selenium="http://$SAUCE_USER_NAME:$SAUCE_ACCESS_KEY@ondemand.saucelabs.com:80/wd/hub" \
+ -Dteavm.test.threads=2
+after_script:
+ - rm -rf $HOME/.m2/repository/org/teavm
\ No newline at end of file
diff --git a/README.md b/README.md
index 38ff1e579..c17b93c53 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
TeaVM
=====
+[![Build Status](https://travis-ci.org/konsoletyper/teavm.svg?branch=selenium)](https://travis-ci.org/konsoletyper/teavm)
+
What is TeaVM?
--------------
diff --git a/core/pom.xml b/core/pom.xml
index 798a6b5a8..98b1d0192 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -45,6 +45,11 @@
hppc
0.6.1
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ true
+
TeaVM core
diff --git a/core/src/main/java/org/teavm/model/MethodReference.java b/core/src/main/java/org/teavm/model/MethodReference.java
index a60d8b4ea..d5ed4a70f 100644
--- a/core/src/main/java/org/teavm/model/MethodReference.java
+++ b/core/src/main/java/org/teavm/model/MethodReference.java
@@ -15,6 +15,8 @@
*/
package org.teavm.model;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
@@ -132,6 +134,7 @@ public class MethodReference {
}
@Override
+ @JsonValue
public String toString() {
if (reprCache == null) {
reprCache = className + "." + name + signatureToString();
@@ -139,6 +142,7 @@ public class MethodReference {
return reprCache;
}
+ @JsonCreator
public static MethodReference parse(String string) {
MethodReference reference = parseIfPossible(string);
if (reference == null) {
diff --git a/html4j/pom.xml b/html4j/pom.xml
index bffacb498..4626c9ea4 100644
--- a/html4j/pom.xml
+++ b/html4j/pom.xml
@@ -74,12 +74,11 @@
generate-javascript-tests
- build-test-javascript
+ testCompile
- process-test-classes
false
- ${project.build.directory}/javascript-test
+ ${project.build.directory}/javascript-test
true
true
@@ -87,13 +86,12 @@
generate-javascript-tck
- build-test-javascript
+ testCompile
- process-test-classes
false
true
- ${project.build.directory}/javascript-tck
+ ${project.build.directory}/javascript-tck
org.teavm.html4j.testing.KOTestAdapter
org.teavm.javascript.NullPointerExceptionTransformer
diff --git a/jso/apis/pom.xml b/jso/apis/pom.xml
index fe2ced996..4ff751af4 100644
--- a/jso/apis/pom.xml
+++ b/jso/apis/pom.xml
@@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-jso-apis
diff --git a/jso/core/pom.xml b/jso/core/pom.xml
index 89a011db5..f44fe2475 100644
--- a/jso/core/pom.xml
+++ b/jso/core/pom.xml
@@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-jso
diff --git a/jso/impl/pom.xml b/jso/impl/pom.xml
index f2c9e9bf3..c596a2929 100644
--- a/jso/impl/pom.xml
+++ b/jso/impl/pom.xml
@@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-jso-impl
diff --git a/platform/pom.xml b/platform/pom.xml
index 6299a95bc..d606b308a 100644
--- a/platform/pom.xml
+++ b/platform/pom.xml
@@ -40,11 +40,6 @@
teavm-jso-apis
${project.version}
-
- org.teavm
- teavm-dom
- ${project.version}
-
junit
junit
diff --git a/pom.xml b/pom.xml
index e10fe10f4..21282c232 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,8 @@
1.2
9.2.1.v20140609
1.7.7
- 1.9.3
+ 2.47.2
+ 2.6.2
@@ -81,6 +82,7 @@
html4j
samples
platform
+ tools/core
tools/cli
tools/maven
tools/chrome-rdp
@@ -166,13 +168,26 @@
slf4j-api
${slf4j.version}
-
diff --git a/samples/async/pom.xml b/samples/async/pom.xml
index 001e04006..2ea775d90 100644
--- a/samples/async/pom.xml
+++ b/samples/async/pom.xml
@@ -57,9 +57,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/samples/benchmark/pom.xml b/samples/benchmark/pom.xml
index ed0590921..4b1bfd80a 100644
--- a/samples/benchmark/pom.xml
+++ b/samples/benchmark/pom.xml
@@ -27,13 +27,7 @@
org.teavm
- teavm-jso
- ${project.version}
- provided
-
-
- org.teavm
- teavm-dom
+ teavm-jso-apis
${project.version}
provided
@@ -111,9 +105,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/samples/hello/pom.xml b/samples/hello/pom.xml
index ed8128e63..b07252129 100644
--- a/samples/hello/pom.xml
+++ b/samples/hello/pom.xml
@@ -42,12 +42,6 @@
${project.version}
provided
-
- org.teavm
- teavm-dom
- ${project.version}
- provided
-
javax.servlet
javax.servlet-api
@@ -76,9 +70,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/samples/kotlin/pom.xml b/samples/kotlin/pom.xml
index f9fcc0606..ce44c2989 100644
--- a/samples/kotlin/pom.xml
+++ b/samples/kotlin/pom.xml
@@ -53,7 +53,7 @@
org.teavm
- teavm-dom
+ teavm-jso-apis
${project.version}
provided
@@ -92,9 +92,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/samples/scala/pom.xml b/samples/scala/pom.xml
index e1c2c61a0..f0837e8cc 100644
--- a/samples/scala/pom.xml
+++ b/samples/scala/pom.xml
@@ -67,9 +67,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/samples/storage/pom.xml b/samples/storage/pom.xml
index 70d0cc0bc..4bea360f1 100644
--- a/samples/storage/pom.xml
+++ b/samples/storage/pom.xml
@@ -38,13 +38,7 @@
org.teavm
- teavm-jso
- ${project.version}
- provided
-
-
- org.teavm
- teavm-dom
+ teavm-jso-apis
${project.version}
provided
@@ -78,12 +72,11 @@
web-client
prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
org.teavm.samples.storage.Application
- SEPARATE
false
true
true
diff --git a/samples/video/pom.xml b/samples/video/pom.xml
index 1f64bc021..02867ca12 100644
--- a/samples/video/pom.xml
+++ b/samples/video/pom.xml
@@ -38,13 +38,7 @@
org.teavm
- teavm-jso
- ${project.version}
- provided
-
-
- org.teavm
- teavm-dom
+ teavm-jso-apis
${project.version}
provided
@@ -76,9 +70,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${project.build.directory}/generated/js/teavm
diff --git a/tests/pom.xml b/tests/pom.xml
index f7a6d202d..002d0faef 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -27,6 +27,13 @@
TeaVM tests
Project containing TeaVM tests, as it is impossible to test each module separately
+
+ false
+ 1
+
+ true
+
+
org.teavm
@@ -72,9 +79,8 @@
generate-javascript-tests
- build-test-javascript
+ testCompile
- process-test-classes
false
true
@@ -89,6 +95,17 @@
${teavm.test.incremental}
+
+ run-javascript-tests
+
+ test
+
+
+ ${teavm.test.skip}
+ ${teavm.test.threads}
+ ${teavm.test.selenium}
+
+
diff --git a/tools/chrome-rdp/pom.xml b/tools/chrome-rdp/pom.xml
index cc17209eb..ab0e3875e 100644
--- a/tools/chrome-rdp/pom.xml
+++ b/tools/chrome-rdp/pom.xml
@@ -21,6 +21,7 @@
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-chrome-rdp
diff --git a/tools/cli/pom.xml b/tools/cli/pom.xml
index 7d1e838c8..51557637f 100644
--- a/tools/cli/pom.xml
+++ b/tools/cli/pom.xml
@@ -21,6 +21,7 @@
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-cli
@@ -30,7 +31,7 @@
org.teavm
- teavm-core
+ teavm-tooling
${project.version}
diff --git a/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java b/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
index 32bf89b19..0a2a45328 100644
--- a/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
+++ b/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
@@ -19,11 +19,17 @@ import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
-import org.apache.commons.cli.*;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.testing.TestAdapter;
-import org.teavm.tooling.TeaVMTestTool;
import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.testing.TeaVMTestTool;
/**
*
@@ -84,7 +90,7 @@ public final class TeaVMTestRunner {
}
TeaVMTestTool tool = new TeaVMTestTool();
- tool.setOutputDir(new File(commandLine.getOptionValue("d", ".")));
+ tool.setTargetDirectory(new File(commandLine.getOptionValue("d", ".")));
tool.setMinifying(commandLine.hasOption("m"));
try {
tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t", "1")));
diff --git a/tools/core/pom.xml b/tools/core/pom.xml
new file mode 100644
index 000000000..54c00a376
--- /dev/null
+++ b/tools/core/pom.xml
@@ -0,0 +1,76 @@
+
+
+ 4.0.0
+
+
+ org.teavm
+ teavm
+ 0.4.0-SNAPSHOT
+ ../..
+
+ teavm-tooling
+ bundle
+
+ TeaVM tooling core
+ TeaVM API that helps to create tooling
+
+
+
+ org.teavm
+ teavm-core
+ ${project.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ ../../checkstyle.xml
+ config_loc=${basedir}/../..
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ org.teavm.*
+ teavm-tooling
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java
new file mode 100644
index 000000000..b279ff85b
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/BaseTeaVMTool.java
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+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/core/src/main/java/org/teavm/tooling/ClassAlias.java b/tools/core/src/main/java/org/teavm/tooling/ClassAlias.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/ClassAlias.java
rename to tools/core/src/main/java/org/teavm/tooling/ClassAlias.java
diff --git a/core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java b/tools/core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java
rename to tools/core/src/main/java/org/teavm/tooling/EmptyTeaVMToolLog.java
diff --git a/core/src/main/java/org/teavm/tooling/InstructionLocationReader.java b/tools/core/src/main/java/org/teavm/tooling/InstructionLocationReader.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/InstructionLocationReader.java
rename to tools/core/src/main/java/org/teavm/tooling/InstructionLocationReader.java
diff --git a/core/src/main/java/org/teavm/tooling/MethodAlias.java b/tools/core/src/main/java/org/teavm/tooling/MethodAlias.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/MethodAlias.java
rename to tools/core/src/main/java/org/teavm/tooling/MethodAlias.java
diff --git a/core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java b/tools/core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
rename to tools/core/src/main/java/org/teavm/tooling/RuntimeCopyOperation.java
diff --git a/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
rename to tools/core/src/main/java/org/teavm/tooling/TeaVMProblemRenderer.java
diff --git a/core/src/main/java/org/teavm/tooling/TeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
similarity index 98%
rename from core/src/main/java/org/teavm/tooling/TeaVMTool.java
rename to tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
index ae767fb16..5938e2e83 100644
--- a/core/src/main/java/org/teavm/tooling/TeaVMTool.java
+++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java
@@ -29,6 +29,8 @@ import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.RenderingContext;
import org.teavm.model.*;
import org.teavm.parsing.ClasspathClassHolderSource;
+import org.teavm.tooling.sources.SourceFileProvider;
+import org.teavm.tooling.sources.SourceFilesCopier;
import org.teavm.vm.*;
import org.teavm.vm.spi.AbstractRendererListener;
@@ -36,7 +38,7 @@ import org.teavm.vm.spi.AbstractRendererListener;
*
* @author Alexey Andreev
*/
-public class TeaVMTool {
+public class TeaVMTool implements BaseTeaVMTool {
private File targetDirectory = new File(".");
private String targetFileName = "classes.js";
private boolean minifying = true;
@@ -69,6 +71,7 @@ public class TeaVMTool {
return targetDirectory;
}
+ @Override
public void setTargetDirectory(File targetDirectory) {
this.targetDirectory = targetDirectory;
}
@@ -85,6 +88,7 @@ public class TeaVMTool {
return minifying;
}
+ @Override
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
@@ -93,6 +97,7 @@ public class TeaVMTool {
return incremental;
}
+ @Override
public void setIncremental(boolean incremental) {
this.incremental = incremental;
}
@@ -133,6 +138,7 @@ public class TeaVMTool {
return debugInformationGenerated;
}
+ @Override
public void setDebugInformationGenerated(boolean debugInformationGenerated) {
this.debugInformationGenerated = debugInformationGenerated;
}
@@ -149,6 +155,7 @@ public class TeaVMTool {
return sourceMapsFileGenerated;
}
+ @Override
public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
this.sourceMapsFileGenerated = sourceMapsFileGenerated;
}
@@ -157,14 +164,17 @@ public class TeaVMTool {
return sourceFilesCopied;
}
+ @Override
public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied;
}
+ @Override
public Properties getProperties() {
return properties;
}
+ @Override
public List getTransformers() {
return transformers;
}
@@ -181,6 +191,7 @@ public class TeaVMTool {
return log;
}
+ @Override
public void setLog(TeaVMToolLog log) {
this.log = log;
}
@@ -189,6 +200,7 @@ public class TeaVMTool {
return classLoader;
}
+ @Override
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@@ -245,6 +257,7 @@ public class TeaVMTool {
return resources;
}
+ @Override
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
sourceFileProviders.add(sourceFileProvider);
}
diff --git a/core/src/main/java/org/teavm/tooling/TeaVMToolException.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMToolException.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/TeaVMToolException.java
rename to tools/core/src/main/java/org/teavm/tooling/TeaVMToolException.java
diff --git a/core/src/main/java/org/teavm/tooling/TeaVMToolLog.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
similarity index 100%
rename from core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
rename to tools/core/src/main/java/org/teavm/tooling/TeaVMToolLog.java
diff --git a/core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java b/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java
similarity index 97%
rename from core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java
rename to tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java
index 21841bed8..aaf0e2abc 100644
--- a/core/src/main/java/org/teavm/tooling/DirectorySourceFileProvider.java
+++ b/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.sources;
import java.io.File;
import java.io.FileInputStream;
diff --git a/core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java b/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java
similarity index 98%
rename from core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java
rename to tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java
index 88b747199..07269d76f 100644
--- a/core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java
+++ b/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.sources;
import java.io.File;
import java.io.IOException;
diff --git a/core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java b/tools/core/src/main/java/org/teavm/tooling/sources/ProgramSourceAggregator.java
similarity index 99%
rename from core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java
rename to tools/core/src/main/java/org/teavm/tooling/sources/ProgramSourceAggregator.java
index fd8997642..b9e2170a0 100644
--- a/core/src/main/java/org/teavm/tooling/ProgramSourceAggregator.java
+++ b/tools/core/src/main/java/org/teavm/tooling/sources/ProgramSourceAggregator.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.sources;
import java.util.List;
import java.util.Set;
diff --git a/core/src/main/java/org/teavm/tooling/SourceFileProvider.java b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileProvider.java
similarity index 96%
rename from core/src/main/java/org/teavm/tooling/SourceFileProvider.java
rename to tools/core/src/main/java/org/teavm/tooling/sources/SourceFileProvider.java
index c5567b036..c1dbebd9b 100644
--- a/core/src/main/java/org/teavm/tooling/SourceFileProvider.java
+++ b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileProvider.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.sources;
import java.io.IOException;
import java.io.InputStream;
diff --git a/core/src/main/java/org/teavm/tooling/SourceFilesCopier.java b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFilesCopier.java
similarity index 96%
rename from core/src/main/java/org/teavm/tooling/SourceFilesCopier.java
rename to tools/core/src/main/java/org/teavm/tooling/sources/SourceFilesCopier.java
index f400c20bf..746f38bdf 100644
--- a/core/src/main/java/org/teavm/tooling/SourceFilesCopier.java
+++ b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFilesCopier.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.sources;
import java.io.*;
import java.util.HashSet;
@@ -23,6 +23,8 @@ import org.apache.commons.io.IOUtils;
import org.teavm.model.ClassReader;
import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodReader;
+import org.teavm.tooling.EmptyTeaVMToolLog;
+import org.teavm.tooling.TeaVMToolLog;
/**
*
diff --git a/core/src/main/java/org/teavm/tooling/ExceptionHelper.java b/tools/core/src/main/java/org/teavm/tooling/testing/ExceptionHelper.java
similarity index 95%
rename from core/src/main/java/org/teavm/tooling/ExceptionHelper.java
rename to tools/core/src/main/java/org/teavm/tooling/testing/ExceptionHelper.java
index ac53214c3..1977a6c7b 100644
--- a/core/src/main/java/org/teavm/tooling/ExceptionHelper.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/ExceptionHelper.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.testing;
/**
*
diff --git a/core/src/main/java/org/teavm/tooling/TeaVMTestTool.java b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
similarity index 64%
rename from core/src/main/java/org/teavm/tooling/TeaVMTestTool.java
rename to tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
index a2895b0eb..b65841aa6 100644
--- a/core/src/main/java/org/teavm/tooling/TeaVMTestTool.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestTool.java
@@ -13,10 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.testing;
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.io.IOUtils;
import org.teavm.common.FiniteExecutor;
import org.teavm.common.SimpleFiniteExecutor;
@@ -26,10 +35,26 @@ import org.teavm.debugging.information.DebugInformationBuilder;
import org.teavm.javascript.EmptyRegularMethodNodeCache;
import org.teavm.javascript.InMemoryRegularMethodNodeCache;
import org.teavm.javascript.MethodNodeCache;
-import org.teavm.model.*;
+import org.teavm.model.ClassHolder;
+import org.teavm.model.ClassHolderSource;
+import org.teavm.model.ClassHolderTransformer;
+import org.teavm.model.CopyClassHolderSource;
+import org.teavm.model.InMemoryProgramCache;
+import org.teavm.model.MethodHolder;
+import org.teavm.model.MethodReference;
+import org.teavm.model.PreOptimizingClassHolderSource;
+import org.teavm.model.ProgramCache;
+import org.teavm.model.ValueType;
import org.teavm.parsing.ClasspathClassHolderSource;
import org.teavm.testing.JUnitTestAdapter;
import org.teavm.testing.TestAdapter;
+import org.teavm.tooling.BaseTeaVMTool;
+import org.teavm.tooling.EmptyTeaVMToolLog;
+import org.teavm.tooling.TeaVMProblemRenderer;
+import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.TeaVMToolLog;
+import org.teavm.tooling.sources.SourceFileProvider;
+import org.teavm.tooling.sources.SourceFilesCopier;
import org.teavm.vm.DirectoryBuildTarget;
import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMBuilder;
@@ -38,10 +63,7 @@ import org.teavm.vm.TeaVMBuilder;
*
* @author Alexey Andreev
*/
-public class TeaVMTestTool {
- private Map> groupedMethods = new HashMap<>();
- private Map fileNames = new HashMap<>();
- private List testMethods = new ArrayList<>();
+public class TeaVMTestTool implements BaseTeaVMTool {
private File outputDir = new File(".");
private boolean minifying = true;
private int numThreads = 1;
@@ -54,19 +76,25 @@ public class TeaVMTestTool {
private ClassLoader classLoader = TeaVMTestTool.class.getClassLoader();
private TeaVMToolLog log = new EmptyTeaVMToolLog();
private boolean debugInformationGenerated;
- private boolean sourceMapsGenerated;
+ private boolean sourceMapsFileGenerated;
private boolean sourceFilesCopied;
private boolean incremental;
private List sourceFileProviders = new ArrayList<>();
private MethodNodeCache astCache;
private ProgramCache programCache;
private SourceFilesCopier sourceFilesCopier;
+ private List testPlan = new ArrayList<>();
+ private int fileIndexGenerator;
+ private long startTime;
+ private int testCount;
+ private AtomicInteger testsBuilt = new AtomicInteger();
public File getOutputDir() {
return outputDir;
}
- public void setOutputDir(File outputDir) {
+ @Override
+ public void setTargetDirectory(File outputDir) {
this.outputDir = outputDir;
}
@@ -74,6 +102,7 @@ public class TeaVMTestTool {
return minifying;
}
+ @Override
public void setMinifying(boolean minifying) {
this.minifying = minifying;
}
@@ -94,6 +123,7 @@ public class TeaVMTestTool {
this.adapter = adapter;
}
+ @Override
public List getTransformers() {
return transformers;
}
@@ -102,6 +132,7 @@ public class TeaVMTestTool {
return additionalScripts;
}
+ @Override
public Properties getProperties() {
return properties;
}
@@ -114,6 +145,7 @@ public class TeaVMTestTool {
return classLoader;
}
+ @Override
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@@ -122,6 +154,7 @@ public class TeaVMTestTool {
return log;
}
+ @Override
public void setLog(TeaVMToolLog log) {
this.log = log;
}
@@ -130,6 +163,7 @@ public class TeaVMTestTool {
return incremental;
}
+ @Override
public void setIncremental(boolean incremental) {
this.incremental = incremental;
}
@@ -138,31 +172,36 @@ public class TeaVMTestTool {
return debugInformationGenerated;
}
+ @Override
public void setDebugInformationGenerated(boolean debugInformationGenerated) {
this.debugInformationGenerated = debugInformationGenerated;
}
- public boolean isSourceMapsGenerated() {
- return sourceMapsGenerated;
+ public boolean isSourceMapsFileGenerated() {
+ return sourceMapsFileGenerated;
}
- public void setSourceMapsGenerated(boolean sourceMapsGenerated) {
- this.sourceMapsGenerated = sourceMapsGenerated;
+ @Override
+ public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
+ this.sourceMapsFileGenerated = sourceMapsFileGenerated;
}
public boolean isSourceFilesCopied() {
return sourceFilesCopied;
}
+ @Override
public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied;
}
+ @Override
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
sourceFileProviders.add(sourceFileProvider);
}
- public void generate() throws TeaVMToolException {
+ public TestPlan generate() throws TeaVMToolException {
+ testsBuilt.set(0);
Runnable finalizer = null;
try {
new File(outputDir, "tests").mkdirs();
@@ -184,12 +223,17 @@ public class TeaVMTestTool {
if (incremental) {
classSource = new PreOptimizingClassHolderSource(classSource);
}
+
+ List groups = new ArrayList<>();
for (String testClass : testClasses) {
ClassHolder classHolder = classSource.get(testClass);
if (classHolder == null) {
throw new TeaVMToolException("Could not find class " + testClass);
}
- findTests(classHolder);
+ TestGroup group = findTests(classHolder);
+ if (group != null) {
+ groups.add(group);
+ }
}
includeAdditionalScripts(classLoader);
@@ -198,83 +242,26 @@ public class TeaVMTestTool {
astCache = new InMemoryRegularMethodNodeCache();
programCache = new InMemoryProgramCache();
}
- File allTestsFile = new File(outputDir, "tests/all.js");
- try (Writer allTestsWriter = new OutputStreamWriter(new FileOutputStream(allTestsFile), "UTF-8")) {
- allTestsWriter.write("prepare = function() {\n");
- allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
- boolean first = true;
- for (String testClass : testClasses) {
- Collection methods = groupedMethods.get(testClass);
- if (methods == null) {
- continue;
- }
- if (!first) {
- allTestsWriter.append(",");
- }
- first = false;
- allTestsWriter.append("\n { name : \"").append(testClass).append("\", methods : [");
- boolean firstMethod = true;
- for (MethodReference methodRef : methods) {
- String scriptName = "tests/" + fileNames.size() + ".js";
- fileNames.put(methodRef, scriptName);
- if (!firstMethod) {
- allTestsWriter.append(",");
- }
- firstMethod = false;
- allTestsWriter.append("\n { name : \"" + methodRef.getName() + "\", script : \""
- + scriptName + "\", expected : [");
- MethodHolder methodHolder = classSource.get(testClass).getMethod(
- methodRef.getDescriptor());
- boolean firstException = true;
- for (String exception : adapter.getExpectedExceptions(methodHolder)) {
- if (!firstException) {
- allTestsWriter.append(", ");
- }
- firstException = false;
- allTestsWriter.append("\"" + exception + "\"");
- }
- allTestsWriter.append("], additionalScripts : [");
- for (int i = 0; i < additionalScriptLocalPaths.size(); ++i) {
- if (i > 0) {
- allTestsWriter.append(", ");
- }
- escapeString(additionalScriptLocalPaths.get(i), allTestsWriter);
- }
- allTestsWriter.append("] }");
- }
- allTestsWriter.append("] }");
- }
- allTestsWriter.write("], function() {}); }");
- }
- int methodsGenerated = 0;
- log.info("Generating test files");
- sourceFilesCopier = new SourceFilesCopier(sourceFileProviders);
- sourceFilesCopier.setLog(log);
+ writeMetadata();
+
FiniteExecutor executor = new SimpleFiniteExecutor();
if (numThreads != 1) {
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
- final ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
+ ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
finalizer = () -> threadedExecutor.stop();
executor = threadedExecutor;
}
- for (final MethodReference method : testMethods) {
- final ClassHolderSource builderClassSource = classSource;
- executor.execute(() -> {
- log.debug("Building test for " + method);
- try {
- decompileClassesForTest(classLoader, new CopyClassHolderSource(builderClassSource), method,
- fileNames.get(method));
- } catch (IOException e) {
- log.error("Error generating JavaScript", e);
- }
- });
- ++methodsGenerated;
- }
- executor.complete();
+ startTime = System.currentTimeMillis();
+ int methodsGenerated = writeMethods(executor, classSource);
+
if (sourceFilesCopied) {
sourceFilesCopier.copy(new File(new File(outputDir, "tests"), "src"));
}
- log.info("Test files successfully generated for " + methodsGenerated + " method(s).");
+ long timeSpent = System.currentTimeMillis() - startTime;
+ log.info("Test files successfully generated for " + methodsGenerated + " method(s) in "
+ + (timeSpent / 1000.0) + " seconds.");
+
+ return new TestPlan("res/runtime.js", groups);
} catch (IOException e) {
throw new TeaVMToolException("IO error occured generating JavaScript files", e);
} finally {
@@ -284,6 +271,74 @@ public class TeaVMTestTool {
}
}
+ private void writeMetadata() throws IOException {
+ File allTestsFile = new File(outputDir, "tests/all.js");
+ try (Writer allTestsWriter = new OutputStreamWriter(new FileOutputStream(allTestsFile), "UTF-8")) {
+ allTestsWriter.write("prepare = function() {\n");
+ allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
+ boolean first = true;
+ for (TestClassBuilder testClass : testPlan) {
+ if (!first) {
+ allTestsWriter.append(",");
+ }
+ first = false;
+ allTestsWriter.append("\n { name : \"").append(testClass.getClassName())
+ .append("\", methods : [");
+ boolean firstMethod = true;
+ for (TestMethodBuilder testMethod : testClass.getMethods()) {
+ String scriptName = testMethod.getFileName();
+ if (!firstMethod) {
+ allTestsWriter.append(",");
+ }
+ firstMethod = false;
+ allTestsWriter.append("\n { name : \"" + testMethod.getMethod().getName()
+ + "\", script : \"" + scriptName + "\", expected : [");
+ boolean firstException = true;
+ for (String exception : testMethod.getExpectedExceptions()) {
+ if (!firstException) {
+ allTestsWriter.append(", ");
+ }
+ firstException = false;
+ allTestsWriter.append("\"" + exception + "\"");
+ }
+ allTestsWriter.append("], additionalScripts : [");
+ for (int i = 0; i < additionalScriptLocalPaths.size(); ++i) {
+ if (i > 0) {
+ allTestsWriter.append(", ");
+ }
+ escapeString(additionalScriptLocalPaths.get(i), allTestsWriter);
+ }
+ allTestsWriter.append("] }");
+ }
+ allTestsWriter.append("] }");
+ }
+ allTestsWriter.write("], function() {}); }");
+ }
+ }
+
+ private int writeMethods(FiniteExecutor executor, ClassHolderSource classSource) {
+ int methodsGenerated = 0;
+ log.info("Generating test files");
+ sourceFilesCopier = new SourceFilesCopier(sourceFileProviders);
+ sourceFilesCopier.setLog(log);
+ for (TestClassBuilder testClass : testPlan) {
+ for (TestMethodBuilder testMethod : testClass.getMethods()) {
+ executor.execute(() -> {
+ log.debug("Building test for " + testMethod.getMethod());
+ try {
+ decompileClassesForTest(classLoader, new CopyClassHolderSource(classSource),
+ testMethod);
+ } catch (IOException e) {
+ log.error("Error generating JavaScript", e);
+ }
+ });
+ ++methodsGenerated;
+ }
+ }
+ executor.complete();
+ return methodsGenerated;
+ }
+
private void resourceToFile(String resource, String fileName) throws IOException {
try (InputStream input = TeaVMTestTool.class.getClassLoader().getResourceAsStream(resource)) {
try (OutputStream output = new FileOutputStream(new File(outputDir, fileName))) {
@@ -292,19 +347,34 @@ public class TeaVMTestTool {
}
}
- private void findTests(ClassHolder cls) {
+ private TestGroup findTests(ClassHolder cls) {
+ List cases = new ArrayList<>();
+ TestClassBuilder testClass = new TestClassBuilder(cls.getName());
for (MethodHolder method : cls.getMethods()) {
if (adapter.acceptMethod(method)) {
MethodReference ref = new MethodReference(cls.getName(), method.getDescriptor());
- testMethods.add(ref);
- List group = groupedMethods.get(cls.getName());
- if (group == null) {
- group = new ArrayList<>();
- groupedMethods.put(cls.getName(), group);
+ String fileName = "tests/" + fileIndexGenerator++ + ".js";
+
+ List exceptions = new ArrayList<>();
+ for (String exception : adapter.getExpectedExceptions(method)) {
+ exceptions.add(exception);
}
- group.add(ref);
+
+ TestMethodBuilder testMethod = new TestMethodBuilder(ref, fileName, exceptions);
+ testClass.getMethods().add(testMethod);
+
+ String debugTable = debugInformationGenerated ? testMethod.getFileName() + ".teavmdbg" : null;
+ cases.add(new TestCase(ref.toString(), testMethod.getFileName(), debugTable,
+ testMethod.getExpectedExceptions()));
+ ++testCount;
}
}
+ if (!testClass.getMethods().isEmpty()) {
+ testPlan.add(testClass);
+ return new TestGroup(cls.getName(), cases);
+ } else {
+ return null;
+ }
}
private void includeAdditionalScripts(ClassLoader classLoader) throws TeaVMToolException {
@@ -332,7 +402,8 @@ public class TeaVMTestTool {
}
private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
- MethodReference methodRef, String targetName) throws IOException {
+ TestMethodBuilder testMethod) throws IOException {
+ String targetName = testMethod.getFileName();
TeaVM vm = new TeaVMBuilder()
.setClassLoader(classLoader)
.setClassSource(classSource)
@@ -347,9 +418,11 @@ public class TeaVMTestTool {
for (ClassHolderTransformer transformer : transformers) {
vm.add(transformer);
}
- File file = new File(outputDir, targetName);
- DebugInformationBuilder debugInfoBuilder = sourceMapsGenerated || debugInformationGenerated
+
+ File file = new File(outputDir, testMethod.getFileName());
+ DebugInformationBuilder debugInfoBuilder = sourceMapsFileGenerated || debugInformationGenerated
? new DebugInformationBuilder() : null;
+ MethodReference methodRef = testMethod.getMethod();
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
MethodReference cons = new MethodReference(methodRef.getClassName(), "", ValueType.VOID);
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
@@ -362,7 +435,7 @@ public class TeaVMTestTool {
vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
innerWriter.append("\n");
innerWriter.append("\nJUnitClient.run();");
- if (sourceMapsGenerated) {
+ if (sourceMapsFileGenerated) {
String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map";
innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName);
}
@@ -376,13 +449,16 @@ public class TeaVMTestTool {
}
}
}
- if (sourceMapsGenerated) {
+
+ if (debugInformationGenerated) {
DebugInformation debugInfo = debugInfoBuilder.getDebugInformation();
- try (OutputStream debugInfoOut = new FileOutputStream(new File(outputDir, targetName + ".teavmdbg"))) {
+ File debugTableFile = new File(outputDir, targetName + ".teavmdbg");
+ try (OutputStream debugInfoOut = new FileOutputStream(debugTableFile)) {
debugInfo.write(debugInfoOut);
}
}
- if (sourceMapsGenerated) {
+
+ if (sourceMapsFileGenerated) {
DebugInformation debugInfo = debugInfoBuilder.getDebugInformation();
String sourceMapsFileName = targetName + ".map";
try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream(
@@ -393,6 +469,20 @@ public class TeaVMTestTool {
if (sourceFilesCopied && vm.getWrittenClasses() != null) {
sourceFilesCopier.addClasses(vm.getWrittenClasses());
}
+
+ incrementCounter();
+ }
+
+ private void incrementCounter() {
+ int count = testsBuilt.incrementAndGet();
+ if (count % 10 != 0) {
+ return;
+ }
+
+ long timeSpent = System.currentTimeMillis() - startTime;
+
+ getLog().info(count + " of " + testCount + " tests built in " + (timeSpent / 1000.0) + " seconds ("
+ + String.format("%.2f", (double) count / timeSpent * 1000.0) + " tests per second avg.)");
}
private void escapeString(String string, Writer writer) throws IOException {
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestToolListener.java b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestToolListener.java
new file mode 100644
index 000000000..4460b2575
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TeaVMTestToolListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.testing;
+
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface TeaVMTestToolListener {
+ void testGenerated(TestCase testCase);
+}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java
new file mode 100644
index 000000000..5c0ae9e1b
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestCase.java
@@ -0,0 +1,66 @@
+/*
+ * 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.testing;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TestCase {
+ private String testMethod;
+ private String testScript;
+ private String debugTable;
+ private List expectedExceptions = new ArrayList<>();
+
+ @JsonCreator
+ public TestCase(
+ @JsonProperty("testMethod") String testMethod,
+ @JsonProperty("script") String testScript,
+ @JsonProperty("debugTable") String debugTable,
+ @JsonProperty("expectedExceptions") List expectedExceptions) {
+ this.testMethod = testMethod;
+ this.testScript = testScript;
+ this.debugTable = debugTable;
+ this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions));
+ }
+
+ @JsonGetter
+ public String getTestMethod() {
+ return testMethod;
+ }
+
+ @JsonGetter("script")
+ public String getTestScript() {
+ return testScript;
+ }
+
+ @JsonGetter
+ public String getDebugTable() {
+ return debugTable;
+ }
+
+ @JsonGetter
+ public List getExpectedExceptions() {
+ return expectedExceptions;
+ }
+}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestClassBuilder.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestClassBuilder.java
new file mode 100644
index 000000000..d50e2b264
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestClassBuilder.java
@@ -0,0 +1,40 @@
+/*
+ * 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.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class TestClassBuilder {
+ private String className;
+ private List methods = new ArrayList<>();
+
+ public TestClassBuilder(String className) {
+ this.className = className;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public List getMethods() {
+ return methods;
+ }
+}
diff --git a/core/src/main/java/org/teavm/tooling/TestExceptionDependency.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionDependency.java
similarity index 98%
rename from core/src/main/java/org/teavm/tooling/TestExceptionDependency.java
rename to tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionDependency.java
index 9fa8acd60..e388e80f6 100644
--- a/core/src/main/java/org/teavm/tooling/TestExceptionDependency.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionDependency.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.testing;
import org.teavm.dependency.AbstractDependencyListener;
import org.teavm.dependency.DependencyAgent;
diff --git a/core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionPlugin.java
similarity index 96%
rename from core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java
rename to tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionPlugin.java
index 2ec7136c6..19a2c04a1 100644
--- a/core/src/main/java/org/teavm/tooling/TestExceptionPlugin.java
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestExceptionPlugin.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.tooling;
+package org.teavm.tooling.testing;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestGroup.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestGroup.java
new file mode 100644
index 000000000..4ab9d5cbb
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestGroup.java
@@ -0,0 +1,49 @@
+/*
+ * 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.testing;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TestGroup {
+ private String className;
+ private List testCases;
+
+ @JsonCreator
+ public TestGroup(@JsonProperty("className") String className,
+ @JsonProperty("testCases") List testCases) {
+ this.className = className;
+ this.testCases = Collections.unmodifiableList(new ArrayList<>(testCases));
+ }
+
+ @JsonGetter("className")
+ public String getClassName() {
+ return className;
+ }
+
+ @JsonGetter("testCases")
+ public List getTestCases() {
+ return testCases;
+ }
+}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestMethodBuilder.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestMethodBuilder.java
new file mode 100644
index 000000000..3faa384d7
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestMethodBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * 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.testing;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.teavm.model.MethodReference;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class TestMethodBuilder {
+ private MethodReference method;
+ private String fileName;
+ private List expectedExceptions = new ArrayList<>();
+
+ public TestMethodBuilder(MethodReference method, String fileName, List expectedExceptions) {
+ this.method = method;
+ this.fileName = fileName;
+ this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions));
+ }
+
+ public MethodReference getMethod() {
+ return method;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public List getExpectedExceptions() {
+ return expectedExceptions;
+ }
+}
diff --git a/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java b/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java
new file mode 100644
index 000000000..32ce4b364
--- /dev/null
+++ b/tools/core/src/main/java/org/teavm/tooling/testing/TestPlan.java
@@ -0,0 +1,50 @@
+/*
+ * 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.testing;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TestPlan {
+ private String runtimeScript;
+ private List groups = new ArrayList<>();
+
+ @JsonCreator
+ public TestPlan(
+ @JsonProperty("runtimeScript") String runtimeScript,
+ @JsonProperty("groups") List groups) {
+ this.runtimeScript = runtimeScript;
+ this.groups = Collections.unmodifiableList(new ArrayList<>(groups));
+ }
+
+ @JsonGetter
+ public String getRuntimeScript() {
+ return runtimeScript;
+ }
+
+ @JsonGetter
+ public List getGroups() {
+ return groups;
+ }
+}
diff --git a/core/src/main/resources/org/teavm/tooling/main.html b/tools/core/src/main/resources/org/teavm/tooling/main.html
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/main.html
rename to tools/core/src/main/resources/org/teavm/tooling/main.html
diff --git a/core/src/main/resources/org/teavm/tooling/test/junit.html b/tools/core/src/main/resources/org/teavm/tooling/test/junit.html
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/junit.html
rename to tools/core/src/main/resources/org/teavm/tooling/test/junit.html
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/class_obj.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/class_obj.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/class_obj.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/class_obj.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/control-000-small.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/junit-support.js b/tools/core/src/main/resources/org/teavm/tooling/test/res/junit-support.js
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/junit-support.js
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/junit-support.js
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/junit.css b/tools/core/src/main/resources/org/teavm/tooling/test/res/junit.css
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/junit.css
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/junit.css
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/methpub_obj.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/package_obj.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/package_obj.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/package_obj.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/package_obj.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/tick-small-red.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/tick-small.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/tick-small.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/tick-small.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/tick-small.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/toggle-small-expand.png
diff --git a/core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png b/tools/core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png
similarity index 100%
rename from core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png
rename to tools/core/src/main/resources/org/teavm/tooling/test/res/toggle-small.png
diff --git a/tools/eclipse/core-plugin/META-INF/MANIFEST.MF b/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
index 52513c7cb..b4bee0aa9 100644
--- a/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
@@ -39,6 +39,7 @@ Bundle-ClassPath: .,
lib/slf4j-api-1.7.7.jar,
lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar,
lib/teavm-core-0.4.0-SNAPSHOT.jar,
+ lib/teavm-tooling-0.4.0-SNAPSHOT.jar,
lib/websocket-api-9.2.1.v20140609.jar,
lib/websocket-client-9.2.1.v20140609.jar,
lib/websocket-common-9.2.1.v20140609.jar,
@@ -70,5 +71,6 @@ Export-Package: org.teavm.cache,
org.teavm.resource,
org.teavm.testing,
org.teavm.tooling,
+ org.teavm.tooling.sources,
org.teavm.vm,
org.teavm.vm.spi
diff --git a/tools/eclipse/core-plugin/build.properties b/tools/eclipse/core-plugin/build.properties
index ea8d50c54..95269dd03 100644
--- a/tools/eclipse/core-plugin/build.properties
+++ b/tools/eclipse/core-plugin/build.properties
@@ -36,6 +36,7 @@ bin.includes = META-INF/,\
lib/slf4j-api-1.7.7.jar,\
lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar,\
lib/teavm-core-0.4.0-SNAPSHOT.jar,\
+ lib/teavm-tooling-0.4.0-SNAPSHOT.jar,\
lib/websocket-api-9.2.1.v20140609.jar,\
lib/websocket-client-9.2.1.v20140609.jar,\
lib/websocket-common-9.2.1.v20140609.jar,\
diff --git a/tools/eclipse/core-plugin/dep-pom.xml b/tools/eclipse/core-plugin/dep-pom.xml
index 41fe15f28..52dd1023d 100644
--- a/tools/eclipse/core-plugin/dep-pom.xml
+++ b/tools/eclipse/core-plugin/dep-pom.xml
@@ -79,6 +79,11 @@
teavm-core
${project.version}
+
+ org.teavm
+ teavm-tooling
+ ${project.version}
+
org.teavm
teavm-chrome-rdp
diff --git a/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF b/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
index 062e541a9..1574d6301 100644
--- a/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: TeaVM plugin for m2e
Bundle-SymbolicName: teavm-eclipse-m2e-plugin;singleton:=true
Bundle-Version: 0.4.0.qualifier
Bundle-Vendor: Alexey Andreev
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: teavm-eclipse-plugin;bundle-version="[0.4.0,0.5.0)",
org.eclipse.m2e.core;bundle-version="[1.3,2)",
org.eclipse.core.runtime;bundle-version="[3.8,4.0)",
diff --git a/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml b/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
index 3ca52caff..e2fb85a6e 100644
--- a/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
+++ b/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
@@ -7,7 +7,7 @@
teavm-maven-plugin
0.4.0-SNAPSHOT
- build-javascript
+ compile
diff --git a/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java b/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
index 220d4ed0f..a8ad00c3a 100644
--- a/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
+++ b/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
@@ -33,7 +33,7 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
private static final String TOOL_ID = "teavm-eclipse-m2e-plugin.tool";
private static final String TEAVM_ARTIFACT_ID = "teavm-maven-plugin";
private static final String TEAVM_GROUP_ID = "org.teavm";
- private static final String TEAVM_MAIN_GOAL = "build-javascript";
+ private static final String TEAVM_MAIN_GOAL = "compile";
private int executionIdGenerator;
private Set usedExecutionIds = new HashSet<>();
private IMaven maven;
diff --git a/tools/eclipse/plugin/META-INF/MANIFEST.MF b/tools/eclipse/plugin/META-INF/MANIFEST.MF
index 416ca1e23..4a219dbb4 100644
--- a/tools/eclipse/plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugin/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: TeaVM plugin for Eclipse
Bundle-SymbolicName: teavm-eclipse-plugin;singleton:=true
Bundle-Version: 0.4.0.qualifier
Bundle-Vendor: Alexey Andreev
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Activator: org.teavm.eclipse.TeaVMEclipsePlugin
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.8.0,4.0)",
org.eclipse.debug.core;bundle-version="[3.7.0,4.0)",
@@ -48,5 +48,6 @@ Import-Package: org.teavm.cache,
org.teavm.resource,
org.teavm.testing,
org.teavm.tooling,
+ org.teavm.tooling.sources,
org.teavm.vm,
org.teavm.vm.spi
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 41c2184b7..a09363e27 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
@@ -21,22 +21,62 @@ import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.*;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
-import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.Signature;
import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite;
import org.teavm.diagnostics.Problem;
import org.teavm.diagnostics.ProblemTextConsumer;
-import org.teavm.model.*;
-import org.teavm.tooling.*;
+import org.teavm.model.CallLocation;
+import org.teavm.model.ClassHolderTransformer;
+import org.teavm.model.FieldReference;
+import org.teavm.model.InstructionLocation;
+import org.teavm.model.MethodReference;
+import org.teavm.model.ValueType;
+import org.teavm.tooling.ClassAlias;
+import org.teavm.tooling.RuntimeCopyOperation;
+import org.teavm.tooling.TeaVMTool;
+import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.sources.DirectorySourceFileProvider;
+import org.teavm.tooling.sources.JarSourceFileProvider;
+import org.teavm.tooling.sources.SourceFileProvider;
/**
*
diff --git a/tools/eclipse/pom.xml b/tools/eclipse/pom.xml
index 9d5cccf51..024fdcba6 100644
--- a/tools/eclipse/pom.xml
+++ b/tools/eclipse/pom.xml
@@ -21,6 +21,7 @@
org.teavm
teavm
0.4.0-SNAPSHOT
+ ../..
teavm-eclipse
pom
diff --git a/tools/maven/plugin/pom.xml b/tools/maven/plugin/pom.xml
index 143dd1213..2c7e153df 100644
--- a/tools/maven/plugin/pom.xml
+++ b/tools/maven/plugin/pom.xml
@@ -50,13 +50,30 @@
org.teavm
- teavm-core
+ teavm-tooling
${project.version}
commons-io
commons-io
+
+ org.seleniumhq.selenium
+ selenium-java
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ net.sourceforge.htmlunit
+ htmlunit
+ 2.18
+
junit
junit
@@ -91,6 +108,14 @@
org.apache.maven.plugins
maven-javadoc-plugin
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+ ../../../checkstyle.xml
+ config_loc=${basedir}/../../..
+
+
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractJavascriptMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractJavascriptMojo.java
new file mode 100644
index 000000000..cb43846e3
--- /dev/null
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/AbstractJavascriptMojo.java
@@ -0,0 +1,219 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public abstract class AbstractJavascriptMojo 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 String mainClass;
+
+ @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()]),
+ AbstractJavascriptMojo.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);
+ return lookup.resolve();
+ }
+}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
index f4c43ec6a..511dd0cb1 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptMojo.java
@@ -16,96 +16,42 @@
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.*;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.MavenArtifactRepository;
-import org.apache.maven.plugin.AbstractMojo;
+import java.util.Arrays;
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.model.ClassHolderTransformer;
-import org.teavm.tooling.*;
+import org.teavm.tooling.ClassAlias;
+import org.teavm.tooling.MethodAlias;
+import org.teavm.tooling.RuntimeCopyOperation;
+import org.teavm.tooling.TeaVMTool;
+import org.teavm.tooling.TeaVMToolException;
/**
*
* @author Alexey Andreev
*/
-@Mojo(name = "build-javascript", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
- requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
-public class BuildJavascriptMojo 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;
-
+@Mojo(name = "compile", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
+ requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME,
+ defaultPhase = LifecyclePhase.PROCESS_CLASSES)
+public class BuildJavascriptMojo extends AbstractJavascriptMojo {
@Parameter(defaultValue = "${project.build.directory}/javascript")
private File targetDirectory;
- @Parameter(defaultValue = "${project.build.outputDirectory}")
- private File classFiles;
-
- @Parameter
- private List compileScopes;
-
@Parameter
private String targetFileName = "classes.js";
- @Parameter
- private boolean minifying = true;
-
@Parameter
private String mainClass;
- @Parameter
- private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
-
- @Parameter
- private Properties properties;
-
@Parameter
private boolean mainPageIncluded;
@Parameter
private boolean bytecodeLogging;
- @Parameter
- private boolean debugInformationGenerated;
-
- @Parameter
- private boolean sourceMapsGenerated;
-
- @Parameter
- private boolean sourceFilesCopied;
-
- @Parameter
- private boolean incremental;
-
- @Parameter(defaultValue = "${project.build.directory}/teavm-cache")
- private File cacheDirectory;
-
- @Parameter
- private String[] transformers;
-
@Parameter
private ClassAlias[] classAliases;
@@ -115,144 +61,37 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Parameter
private boolean stopOnErrors = true;
+ @Parameter
+ protected RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
+
+ @Parameter(defaultValue = "${project.build.directory}/teavm-cache")
+ protected File cacheDirectory;
+
private TeaVMTool tool = new TeaVMTool();
- public void setProject(MavenProject project) {
- this.project = project;
- }
-
- public void setTargetDirectory(File targetDirectory) {
- this.targetDirectory = targetDirectory;
- }
-
- public void setTargetFileName(String targetFileName) {
- this.targetFileName = targetFileName;
- }
-
- public void setClassFiles(File classFiles) {
- this.classFiles = classFiles;
- }
-
- public void setMinifying(boolean minifying) {
- this.minifying = minifying;
- }
-
- public void setBytecodeLogging(boolean bytecodeLogging) {
- this.bytecodeLogging = bytecodeLogging;
- }
-
- public void setRuntimeCopy(RuntimeCopyOperation runtimeCopy) {
- this.runtime = runtimeCopy;
- }
-
- public void setMainPageIncluded(boolean mainPageIncluded) {
- this.mainPageIncluded = mainPageIncluded;
- }
-
- public String[] getTransformers() {
- return transformers;
- }
-
- public void setTransformers(String[] transformers) {
- this.transformers = transformers;
- }
-
- public void setProperties(Properties properties) {
- this.properties = properties;
- }
-
- public void setClassAliases(ClassAlias[] classAliases) {
- this.classAliases = classAliases;
- }
-
- public void setMethodAliases(MethodAlias[] methodAliases) {
- this.methodAliases = methodAliases;
- }
-
- public boolean isDebugInformationGenerated() {
- return debugInformationGenerated;
- }
-
- public void setDebugInformationGenerated(boolean debugInformationGenerated) {
- this.debugInformationGenerated = debugInformationGenerated;
- }
-
- public boolean isSourceMapsGenerated() {
- return sourceMapsGenerated;
- }
-
- public void setSourceMapsGenerated(boolean sourceMapsGenerated) {
- this.sourceMapsGenerated = sourceMapsGenerated;
- }
-
- public boolean isSourceFilesCopied() {
- return sourceFilesCopied;
- }
-
- public void setSourceFilesCopied(boolean sourceFilesCopied) {
- this.sourceFilesCopied = sourceFilesCopied;
- }
-
- public boolean isIncremental() {
- return incremental;
- }
-
- public void setIncremental(boolean incremental) {
- this.incremental = incremental;
- }
-
- public void setStopOnErrors(boolean stopOnErrors) {
- this.stopOnErrors = stopOnErrors;
- }
-
- public File getCacheDirectory() {
- return cacheDirectory;
- }
-
- public void setCacheDirectory(File cacheDirectory) {
- this.cacheDirectory = cacheDirectory;
+ @Override
+ protected File getTargetDirectory() {
+ return targetDirectory;
}
@Override
public void execute() throws MojoExecutionException {
Log log = getLog();
+ setupTool(tool);
tool.setLog(new MavenTeaVMToolLog(log));
try {
- ClassLoader classLoader = prepareClassLoader();
- tool.setClassLoader(classLoader);
tool.setBytecodeLogging(bytecodeLogging);
tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded);
- tool.setMinifying(minifying);
tool.setRuntime(runtime);
- tool.setTargetDirectory(targetDirectory);
tool.setTargetFileName(targetFileName);
- tool.getTransformers().addAll(instantiateTransformers(classLoader));
- if (sourceFilesCopied) {
- MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
- lookup.setMavenProject(project);
- lookup.setRepositorySystem(repositorySystem);
- lookup.setLocalRepository(localRepository);
- lookup.setRemoteRepositories(remoteRepositories);
- lookup.setPluginDependencies(pluginArtifacts);
- for (SourceFileProvider provider : lookup.resolve()) {
- tool.addSourceFileProvider(provider);
- }
- }
if (classAliases != null) {
tool.getClassAliases().addAll(Arrays.asList(classAliases));
}
if (methodAliases != null) {
tool.getMethodAliases().addAll(Arrays.asList(methodAliases));
}
- if (properties != null) {
- tool.getProperties().putAll(properties);
- }
tool.setCacheDirectory(cacheDirectory);
- tool.setIncremental(incremental);
- tool.setDebugInformationGenerated(debugInformationGenerated);
- tool.setSourceMapsFileGenerated(sourceMapsGenerated);
- tool.setSourceFilesCopied(sourceFilesCopied);
tool.generate();
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
throw new MojoExecutionException("Build error");
@@ -263,75 +102,4 @@ public class BuildJavascriptMojo extends AbstractMojo {
throw new MojoExecutionException("IO error occured", e);
}
}
-
- private 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;
- }
-
- private ClassLoader prepareClassLoader() throws MojoExecutionException {
- try {
- Log log = getLog();
- log.info("Preparing classpath for JavaScript generation");
- List urls = new ArrayList<>();
- StringBuilder classpath = new StringBuilder();
- Set scopes;
- if (compileScopes == null) {
- scopes = new HashSet<>(Arrays.asList(
- Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM));
- } else {
- scopes = new HashSet<>(compileScopes);
- }
- for (Artifact artifact : project.getArtifacts()) {
- if (!scopes.contains(artifact.getScope())) {
- 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());
- log.info("Using the following classpath for JavaScript generation: " + classpath);
- return new URLClassLoader(urls.toArray(new URL[urls.size()]), BuildJavascriptMojo.class.getClassLoader());
- } catch (MalformedURLException e) {
- throw new MojoExecutionException("Error gathering classpath information", e);
- }
- }
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
index a194b57ad..7b8618570 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
@@ -15,67 +15,50 @@
*/
package org.teavm.maven;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
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.*;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.FilenameUtils;
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.MojoFailureException;
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.model.ClassHolderTransformer;
import org.teavm.testing.JUnitTestAdapter;
import org.teavm.testing.TestAdapter;
-import org.teavm.tooling.SourceFileProvider;
-import org.teavm.tooling.TeaVMTestTool;
import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.testing.TeaVMTestTool;
+import org.teavm.tooling.testing.TestPlan;
/**
*
* @author Alexey Andreev
*/
-@Mojo(name = "build-test-javascript", requiresDependencyResolution = ResolutionScope.TEST,
- requiresDependencyCollection = ResolutionScope.TEST)
-public class BuildJavascriptTestMojo extends AbstractMojo {
+@Mojo(name = "testCompile", requiresDependencyResolution = ResolutionScope.TEST,
+ requiresDependencyCollection = ResolutionScope.TEST,
+ defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES)
+public class BuildJavascriptTestMojo extends AbstractJavascriptMojo {
private static Set testScopes = new HashSet<>(Arrays.asList(
Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME,
Artifact.SCOPE_PROVIDED));
-
- @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.directory}/javascript-test")
- private File outputDir;
-
- @Parameter(defaultValue = "${project.build.outputDirectory}")
- private File classFiles;
+ private File targetDirectory;
@Parameter(defaultValue = "${project.build.testOutputDirectory}")
private File testFiles;
@@ -86,9 +69,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter
private String[] excludeWildcards = new String[0];
- @Parameter
- private boolean minifying = true;
-
@Parameter
private boolean scanDependencies;
@@ -98,153 +78,47 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter
private String adapterClass = JUnitTestAdapter.class.getName();
- @Parameter
- private String[] transformers;
-
@Parameter
private String[] additionalScripts;
- @Parameter
- private Properties properties;
-
- @Parameter
- private boolean incremental;
-
- @Parameter
- private boolean debugInformationGenerated;
-
- @Parameter
- private boolean sourceMapsGenerated;
-
- @Parameter
- private boolean sourceFilesCopied;
-
private TeaVMTestTool tool = new TeaVMTestTool();
- public void setProject(MavenProject project) {
- this.project = project;
- }
-
- public void setOutputDir(File outputDir) {
- this.outputDir = outputDir;
- }
-
- public void setClassFiles(File classFiles) {
- this.classFiles = classFiles;
- }
-
- public void setTestFiles(File testFiles) {
- this.testFiles = testFiles;
- }
-
- public void setMinifying(boolean minifying) {
- this.minifying = minifying;
- }
-
- public void setNumThreads(int numThreads) {
- this.numThreads = numThreads;
- }
-
- public void setAdapterClass(String adapterClass) {
- this.adapterClass = adapterClass;
- }
-
- public void setWildcards(String[] wildcards) {
- this.wildcards = wildcards;
- }
-
- public void setExcludeWildcards(String[] excludeWildcards) {
- this.excludeWildcards = excludeWildcards;
- }
-
- public String[] getTransformers() {
- return transformers;
- }
-
- public void setTransformers(String[] transformers) {
- this.transformers = transformers;
- }
-
- public void setProperties(Properties properties) {
- this.properties = properties;
- }
-
- public void setIncremental(boolean incremental) {
- this.incremental = incremental;
- }
-
- public boolean isDebugInformationGenerated() {
- return debugInformationGenerated;
- }
-
- public void setDebugInformationGenerated(boolean debugInformationGenerated) {
- this.debugInformationGenerated = debugInformationGenerated;
- }
-
- public boolean isSourceMapsGenerated() {
- return sourceMapsGenerated;
- }
-
- public void setSourceMapsGenerated(boolean sourceMapsGenerated) {
- this.sourceMapsGenerated = sourceMapsGenerated;
- }
-
- public boolean isSourceFilesCopied() {
- return sourceFilesCopied;
- }
-
- public void setSourceFilesCopied(boolean sourceFilesCopied) {
- this.sourceFilesCopied = sourceFilesCopied;
- }
-
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- if (System.getProperty("maven.test.skip", "false").equals("true") ||
- System.getProperty("skipTests") != null) {
+ if (System.getProperty("maven.test.skip", "false").equals("true")
+ || System.getProperty("skipTests") != null) {
getLog().info("Tests build skipped as specified by system property");
return;
}
+
+ setupTool(tool);
try {
- final ClassLoader classLoader = prepareClassLoader();
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
- tool.setClassLoader(classLoader);
tool.setAdapter(createAdapter(classLoader));
findTestClasses(classLoader, testFiles, "");
if (scanDependencies) {
findTestsInDependencies(classLoader);
}
- tool.getTransformers().addAll(instantiateTransformers(classLoader));
- tool.setLog(new MavenTeaVMToolLog(getLog()));
- tool.setOutputDir(outputDir);
tool.setNumThreads(numThreads);
- tool.setMinifying(minifying);
- tool.setIncremental(incremental);
- tool.setDebugInformationGenerated(debugInformationGenerated);
- tool.setSourceMapsGenerated(sourceMapsGenerated);
- tool.setSourceFilesCopied(sourceFilesCopied);
- if (sourceFilesCopied) {
- MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
- lookup.setMavenProject(project);
- lookup.setRepositorySystem(repositorySystem);
- lookup.setLocalRepository(localRepository);
- lookup.setRemoteRepositories(remoteRepositories);
- lookup.setPluginDependencies(pluginArtifacts);
- for (SourceFileProvider provider : lookup.resolve()) {
- tool.addSourceFileProvider(provider);
- }
- }
- if (properties != null) {
- tool.getProperties().putAll(properties);
- }
if (additionalScripts != null) {
tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts));
}
- tool.generate();
+ writePlan(tool.generate());
} catch (TeaVMToolException e) {
throw new MojoFailureException("Error occured generating JavaScript files", e);
}
}
+ private void writePlan(TestPlan plan) throws MojoExecutionException {
+ File file = new File(targetDirectory, "plan.json");
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.writeValue(writer, plan);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Error writing test plan", e);
+ }
+ }
+
private TestAdapter createAdapter(ClassLoader classLoader) throws MojoExecutionException {
Class> adapterClsRaw;
try {
@@ -253,8 +127,8 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
throw new MojoExecutionException("Adapter not found: " + adapterClass, e);
}
if (!TestAdapter.class.isAssignableFrom(adapterClsRaw)) {
- throw new MojoExecutionException("Adapter " + adapterClass + " does not implement " +
- TestAdapter.class.getName());
+ throw new MojoExecutionException("Adapter " + adapterClass + " does not implement "
+ + TestAdapter.class.getName());
}
Class extends TestAdapter> adapterCls = adapterClsRaw.asSubclass(TestAdapter.class);
Constructor extends TestAdapter> cons;
@@ -272,38 +146,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
}
- private ClassLoader prepareClassLoader() throws MojoExecutionException {
- try {
- Log log = getLog();
- log.info("Preparing classpath for JavaScript test generation");
- List urls = new ArrayList<>();
- StringBuilder classpath = new StringBuilder();
- for (Artifact artifact : project.getArtifacts()) {
- if (!testScopes.contains(artifact.getScope())) {
- 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(testFiles.getPath());
- urls.add(testFiles.toURI().toURL());
- classpath.append(':').append(classFiles.getPath());
- urls.add(classFiles.toURI().toURL());
- log.info("Using the following classpath for JavaScript test generation: " + classpath);
- return new URLClassLoader(urls.toArray(new URL[urls.size()]),
- BuildJavascriptTestMojo.class.getClassLoader());
- } catch (MalformedURLException e) {
- throw new MojoExecutionException("Error gathering classpath information", e);
- }
- }
-
private void findTestsInDependencies(ClassLoader classLoader) throws MojoExecutionException {
try {
Log log = getLog();
@@ -384,39 +226,18 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
}
+ @Override
+ protected File getTargetDirectory() {
+ return targetDirectory;
+ }
- private 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;
+ @Override
+ protected List getAdditionalClassPath() {
+ return Arrays.asList(testFiles);
+ }
+
+ @Override
+ protected boolean isSupportedScope(String scope) {
+ return testScopes.contains(scope);
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/HtmlUnitRunStrategy.java b/tools/maven/plugin/src/main/java/org/teavm/maven/HtmlUnitRunStrategy.java
new file mode 100644
index 000000000..0b7b24a57
--- /dev/null
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/HtmlUnitRunStrategy.java
@@ -0,0 +1,107 @@
+/*
+ * 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 com.gargoylesoftware.htmlunit.BrowserVersion;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.WebWindow;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import net.sourceforge.htmlunit.corejs.javascript.Function;
+import net.sourceforge.htmlunit.corejs.javascript.NativeJavaObject;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.plugin.logging.Log;
+import org.teavm.tooling.testing.TestCase;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class HtmlUnitRunStrategy implements TestRunStrategy {
+ private File directory;
+
+ public HtmlUnitRunStrategy(File directory) {
+ this.directory = directory;
+ }
+
+ @Override
+ public void beforeThread() {
+ }
+
+ @Override
+ public void afterThread() {
+ }
+
+ @Override
+ public String runTest(Log log, String runtimeScript, TestCase testCase) throws IOException {
+ try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
+ HtmlPage page = webClient.getPage("about:blank");
+ page.executeJavaScript(readFile(new File(directory, runtimeScript)));
+
+ AsyncResult asyncResult = new AsyncResult();
+ Function function = (Function) page.executeJavaScript(readResource("teavm-htmlunit-adapter.js"))
+ .getJavaScriptResult();
+ Object[] args = new Object[] { new NativeJavaObject(function, asyncResult, AsyncResult.class) };
+ page.executeJavaScriptFunctionIfPossible(function, function, args, page);
+
+ page.executeJavaScript(readFile(new File(directory, testCase.getTestScript())));
+ page.cleanUp();
+ for (WebWindow window : webClient.getWebWindows()) {
+ window.getJobManager().removeAllJobs();
+ }
+ return (String) asyncResult.getResult();
+ }
+ }
+
+ private String readFile(File file) throws IOException {
+ try (InputStream input = new FileInputStream(file)) {
+ return IOUtils.toString(input, "UTF-8");
+ }
+ }
+
+ private String readResource(String resourceName) throws IOException {
+ try (InputStream input = BuildJavascriptTestMojo.class.getClassLoader().getResourceAsStream(resourceName)) {
+ if (input == null) {
+ return "";
+ }
+ return IOUtils.toString(input, "UTF-8");
+ }
+ }
+
+ public class AsyncResult {
+ private CountDownLatch latch = new CountDownLatch(1);
+ private Object result;
+
+ public void complete(Object result) {
+ this.result = result;
+ latch.countDown();
+ }
+
+ public Object getResult() {
+ try {
+ latch.await(5, TimeUnit.SECONDS);
+ return result;
+ } catch (InterruptedException e) {
+ return null;
+ }
+ }
+ }
+}
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 42887a97b..3b6242f79 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,9 @@ 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.DirectorySourceFileProvider;
-import org.teavm.tooling.JarSourceFileProvider;
-import org.teavm.tooling.SourceFileProvider;
+import org.teavm.tooling.sources.DirectorySourceFileProvider;
+import org.teavm.tooling.sources.JarSourceFileProvider;
+import org.teavm.tooling.sources.SourceFileProvider;
/**
*
@@ -85,7 +85,12 @@ public class MavenSourceFileProviderLookup {
ArtifactResolutionResult result = repositorySystem.resolve(request);
for (Artifact resolvedArtifact : result.getArtifacts()) {
if (resolvedArtifact.getFile() != null) {
- providers.add(new JarSourceFileProvider(resolvedArtifact.getFile()));
+ File file = resolvedArtifact.getFile();
+ if (!file.isDirectory()) {
+ providers.add(new JarSourceFileProvider(file));
+ } else {
+ providers.add(new DirectorySourceFileProvider(file));
+ }
}
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java b/tools/maven/plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java
index 862f5c605..1208d4a25 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/MavenTeaVMToolLog.java
@@ -1,3 +1,18 @@
+/*
+ * 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 org.apache.maven.plugin.logging.Log;
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
new file mode 100644
index 000000000..2c0b82354
--- /dev/null
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.teavm.tooling.testing.TestPlan;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+@Mojo(name = "test", defaultPhase = LifecyclePhase.TEST)
+public class RunTestsMojo extends AbstractMojo {
+ @Parameter(defaultValue = "${project.build.directory}/javascript-test")
+ private File testDirectory;
+
+ @Parameter(defaultValue = "${project.build.directory}/teavm-test-report.json")
+ private File reportFile;
+
+ @Parameter
+ private String seleniumURL;
+
+ @Parameter
+ private int numThreads = 1;
+
+ @Parameter
+ private boolean skip;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ if (skip) {
+ getLog().info("Tests run skipped as specified by skip property");
+ return;
+ }
+
+ if (System.getProperty("maven.test.skip", "false").equals("true")
+ || System.getProperty("skipTests") != null) {
+ getLog().info("Tests run skipped as specified by system property");
+ return;
+ }
+
+ TestRunner runner = new TestRunner(pickStrategy());
+ runner.setLog(getLog());
+ runner.setNumThreads(numThreads);
+
+ TestPlan plan;
+ ObjectMapper mapper = new ObjectMapper();
+ File file = new File(testDirectory, "plan.json");
+ try (Reader reader = new InputStreamReader(new FileInputStream(file), "UTF-8")) {
+ plan = mapper.readValue(reader, TestPlan.class);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Error reading test plan", e);
+ }
+
+ runner.run(plan);
+ processReport(runner.getReport());
+ }
+
+ private TestRunStrategy pickStrategy() throws MojoFailureException {
+ if (seleniumURL != null) {
+ try {
+ return new SeleniumRunStrategy(new URL(seleniumURL), testDirectory);
+ } catch (MalformedURLException e) {
+ throw new MojoFailureException("Can't parse URL: " + seleniumURL, e);
+ }
+ } else {
+ return new HtmlUnitRunStrategy(testDirectory);
+ }
+ }
+
+ private void processReport(TestReport report) throws MojoExecutionException, MojoFailureException {
+ if (report.getResults().isEmpty()) {
+ getLog().info("No tests ran");
+ return;
+ }
+
+ int failedTests = 0;
+ for (TestResult result : report.getResults()) {
+ if (result.getStatus() != TestStatus.PASSED) {
+ failedTests++;
+ }
+ }
+
+ if (failedTests > 0) {
+ throw new MojoExecutionException(failedTests + " of " + report.getResults().size() + " test(s) failed");
+ } else {
+ getLog().info("All of " + report.getResults().size() + " tests successfully passed");
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(reportFile), "UTF-8")) {
+ mapper.writeValue(writer, report);
+ } catch (IOException e) {
+ throw new MojoFailureException("Error writing test report", e);
+ }
+ }
+}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumRunStrategy.java b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumRunStrategy.java
new file mode 100644
index 000000000..1bb827c43
--- /dev/null
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumRunStrategy.java
@@ -0,0 +1,95 @@
+/*
+ * 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.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.plugin.logging.Log;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebDriverException;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.teavm.tooling.testing.TestCase;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class SeleniumRunStrategy implements TestRunStrategy {
+ private URL url;
+ private File directory;
+ private ThreadLocal webDriver = new ThreadLocal<>();
+
+ public SeleniumRunStrategy(URL url, File directory) {
+ this.url = url;
+ this.directory = directory;
+ }
+
+ @Override
+ public void beforeThread() {
+ RemoteWebDriver driver = new RemoteWebDriver(url, DesiredCapabilities.chrome());
+ webDriver.set(driver);
+ }
+
+ @Override
+ public void afterThread() {
+ webDriver.get().close();
+ webDriver.remove();
+ }
+
+ @Override
+ public String runTest(Log log, String runtimeScript, TestCase testCase) throws IOException {
+ webDriver.get().manage().timeouts().setScriptTimeout(2, TimeUnit.SECONDS);
+ JavascriptExecutor js = (JavascriptExecutor) webDriver.get();
+ try {
+ return (String) js.executeAsyncScript(
+ readResource("teavm-selenium.js"),
+ readFile(new File(directory, runtimeScript)),
+ readFile(new File(directory, testCase.getTestScript())),
+ readResource("teavm-selenium-adapter.js"));
+ } catch (WebDriverException e) {
+ log.error("Error occured running test " + testCase.getTestMethod(), e);
+ @SuppressWarnings("unchecked")
+ List