Deep refactoring of tooling libraries

This commit is contained in:
Alexey Andreev 2015-10-09 17:56:38 +03:00
parent 90fec4e219
commit 5522f55c68
66 changed files with 744 additions and 633 deletions

View File

@ -74,12 +74,11 @@
<execution> <execution>
<id>generate-javascript-tests</id> <id>generate-javascript-tests</id>
<goals> <goals>
<goal>build-test-javascript</goal> <goal>testCompile</goal>
</goals> </goals>
<phase>process-test-classes</phase>
<configuration> <configuration>
<minifying>false</minifying> <minifying>false</minifying>
<outputDir>${project.build.directory}/javascript-test</outputDir> <targetDirectory>${project.build.directory}/javascript-test</targetDirectory>
<debugInformationGenerated>true</debugInformationGenerated> <debugInformationGenerated>true</debugInformationGenerated>
<sourceMapsGenerated>true</sourceMapsGenerated> <sourceMapsGenerated>true</sourceMapsGenerated>
</configuration> </configuration>
@ -87,13 +86,12 @@
<execution> <execution>
<id>generate-javascript-tck</id> <id>generate-javascript-tck</id>
<goals> <goals>
<goal>build-test-javascript</goal> <goal>testCompile</goal>
</goals> </goals>
<phase>process-test-classes</phase>
<configuration> <configuration>
<minifying>false</minifying> <minifying>false</minifying>
<scanDependencies>true</scanDependencies> <scanDependencies>true</scanDependencies>
<outputDir>${project.build.directory}/javascript-tck</outputDir> <targetDirectory>${project.build.directory}/javascript-tck</targetDirectory>
<adapterClass>org.teavm.html4j.testing.KOTestAdapter</adapterClass> <adapterClass>org.teavm.html4j.testing.KOTestAdapter</adapterClass>
<transformers> <transformers>
<param>org.teavm.javascript.NullPointerExceptionTransformer</param> <param>org.teavm.javascript.NullPointerExceptionTransformer</param>

View File

@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-jso-apis</artifactId> <artifactId>teavm-jso-apis</artifactId>

View File

@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-jso</artifactId> <artifactId>teavm-jso</artifactId>

View File

@ -21,6 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-jso-impl</artifactId> <artifactId>teavm-jso-impl</artifactId>

12
pom.xml
View File

@ -70,6 +70,7 @@
<jetty.version>9.2.1.v20140609</jetty.version> <jetty.version>9.2.1.v20140609</jetty.version>
<slf4j.version>1.7.7</slf4j.version> <slf4j.version>1.7.7</slf4j.version>
<selenium.version>2.47.2</selenium.version> <selenium.version>2.47.2</selenium.version>
<jackson.version>2.6.2</jackson.version>
</properties> </properties>
<modules> <modules>
@ -81,6 +82,7 @@
<module>html4j</module> <module>html4j</module>
<module>samples</module> <module>samples</module>
<module>platform</module> <module>platform</module>
<module>tools/core</module>
<module>tools/cli</module> <module>tools/cli</module>
<module>tools/maven</module> <module>tools/maven</module>
<module>tools/chrome-rdp</module> <module>tools/chrome-rdp</module>
@ -176,6 +178,16 @@
<artifactId>selenium-remote-driver</artifactId> <artifactId>selenium-remote-driver</artifactId>
<version>${selenium.version}</version> <version>${selenium.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -57,9 +57,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -111,9 +111,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -76,9 +76,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -92,9 +92,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -36,6 +36,8 @@
<module>video</module> <module>video</module>
<module>async</module> <module>async</module>
<module>kotlin</module> <module>kotlin</module>
<!--
<module>scala</module> <module>scala</module>
-->
</modules> </modules>
</project> </project>

View File

@ -67,9 +67,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -78,12 +78,11 @@
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase> <phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>
<mainClass>org.teavm.samples.storage.Application</mainClass> <mainClass>org.teavm.samples.storage.Application</mainClass>
<runtime>SEPARATE</runtime>
<minifying>false</minifying> <minifying>false</minifying>
<debugInformationGenerated>true</debugInformationGenerated> <debugInformationGenerated>true</debugInformationGenerated>
<sourceMapsGenerated>true</sourceMapsGenerated> <sourceMapsGenerated>true</sourceMapsGenerated>

View File

@ -76,9 +76,8 @@
<executions> <executions>
<execution> <execution>
<id>web-client</id> <id>web-client</id>
<phase>prepare-package</phase>
<goals> <goals>
<goal>build-javascript</goal> <goal>compile</goal>
</goals> </goals>
<configuration> <configuration>
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory> <targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>

View File

@ -72,9 +72,8 @@
<execution> <execution>
<id>generate-javascript-tests</id> <id>generate-javascript-tests</id>
<goals> <goals>
<goal>build-test-javascript</goal> <goal>testCompile</goal>
</goals> </goals>
<phase>process-test-classes</phase>
<configuration> <configuration>
<minifying>false</minifying> <minifying>false</minifying>
<scanDependencies>true</scanDependencies> <scanDependencies>true</scanDependencies>

View File

@ -21,6 +21,7 @@
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-cli</artifactId> <artifactId>teavm-cli</artifactId>
@ -30,7 +31,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId> <artifactId>teavm-tooling</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -19,11 +19,17 @@ import java.io.File;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Arrays; 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.model.ClassHolderTransformer;
import org.teavm.testing.TestAdapter; import org.teavm.testing.TestAdapter;
import org.teavm.tooling.TeaVMTestTool;
import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.TeaVMToolException;
import org.teavm.tooling.testing.TeaVMTestTool;
/** /**
* *
@ -84,7 +90,7 @@ public final class TeaVMTestRunner {
} }
TeaVMTestTool tool = new TeaVMTestTool(); TeaVMTestTool tool = new TeaVMTestTool();
tool.setOutputDir(new File(commandLine.getOptionValue("d", "."))); tool.setTargetDirectory(new File(commandLine.getOptionValue("d", ".")));
tool.setMinifying(commandLine.hasOption("m")); tool.setMinifying(commandLine.hasOption("m"));
try { try {
tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t", "1"))); tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t", "1")));

64
tools/core/pom.xml Normal file
View File

@ -0,0 +1,64 @@
<!--
Copyright 2014 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.teavm</groupId>
<artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>teavm-tooling</artifactId>
<name>TeaVM tooling core</name>
<description>TeaVM API that helps to create tooling</description>
<dependencies>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<configLocation>../../checkstyle.xml</configLocation>
<propertyExpansion>config_loc=${basedir}/../..</propertyExpansion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -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<ClassHolderTransformer> getTransformers();
void setLog(TeaVMToolLog log);
void setClassLoader(ClassLoader classLoader);
void addSourceFileProvider(SourceFileProvider sourceFileProvider);
}

View File

@ -29,6 +29,8 @@ import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.RenderingContext; import org.teavm.javascript.RenderingContext;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.parsing.ClasspathClassHolderSource; 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.*;
import org.teavm.vm.spi.AbstractRendererListener; import org.teavm.vm.spi.AbstractRendererListener;
@ -36,7 +38,7 @@ import org.teavm.vm.spi.AbstractRendererListener;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TeaVMTool { public class TeaVMTool implements BaseTeaVMTool {
private File targetDirectory = new File("."); private File targetDirectory = new File(".");
private String targetFileName = "classes.js"; private String targetFileName = "classes.js";
private boolean minifying = true; private boolean minifying = true;
@ -69,6 +71,7 @@ public class TeaVMTool {
return targetDirectory; return targetDirectory;
} }
@Override
public void setTargetDirectory(File targetDirectory) { public void setTargetDirectory(File targetDirectory) {
this.targetDirectory = targetDirectory; this.targetDirectory = targetDirectory;
} }
@ -85,6 +88,7 @@ public class TeaVMTool {
return minifying; return minifying;
} }
@Override
public void setMinifying(boolean minifying) { public void setMinifying(boolean minifying) {
this.minifying = minifying; this.minifying = minifying;
} }
@ -93,6 +97,7 @@ public class TeaVMTool {
return incremental; return incremental;
} }
@Override
public void setIncremental(boolean incremental) { public void setIncremental(boolean incremental) {
this.incremental = incremental; this.incremental = incremental;
} }
@ -133,6 +138,7 @@ public class TeaVMTool {
return debugInformationGenerated; return debugInformationGenerated;
} }
@Override
public void setDebugInformationGenerated(boolean debugInformationGenerated) { public void setDebugInformationGenerated(boolean debugInformationGenerated) {
this.debugInformationGenerated = debugInformationGenerated; this.debugInformationGenerated = debugInformationGenerated;
} }
@ -149,6 +155,7 @@ public class TeaVMTool {
return sourceMapsFileGenerated; return sourceMapsFileGenerated;
} }
@Override
public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) { public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
this.sourceMapsFileGenerated = sourceMapsFileGenerated; this.sourceMapsFileGenerated = sourceMapsFileGenerated;
} }
@ -157,14 +164,17 @@ public class TeaVMTool {
return sourceFilesCopied; return sourceFilesCopied;
} }
@Override
public void setSourceFilesCopied(boolean sourceFilesCopied) { public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied; this.sourceFilesCopied = sourceFilesCopied;
} }
@Override
public Properties getProperties() { public Properties getProperties() {
return properties; return properties;
} }
@Override
public List<ClassHolderTransformer> getTransformers() { public List<ClassHolderTransformer> getTransformers() {
return transformers; return transformers;
} }
@ -181,6 +191,7 @@ public class TeaVMTool {
return log; return log;
} }
@Override
public void setLog(TeaVMToolLog log) { public void setLog(TeaVMToolLog log) {
this.log = log; this.log = log;
} }
@ -189,6 +200,7 @@ public class TeaVMTool {
return classLoader; return classLoader;
} }
@Override
public void setClassLoader(ClassLoader classLoader) { public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
@ -245,6 +257,7 @@ public class TeaVMTool {
return resources; return resources;
} }
@Override
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) { public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
sourceFileProviders.add(sourceFileProvider); sourceFileProviders.add(sourceFileProvider);
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.sources;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.sources;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.sources;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.sources;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.sources;
import java.io.*; import java.io.*;
import java.util.HashSet; import java.util.HashSet;
@ -23,6 +23,8 @@ import org.apache.commons.io.IOUtils;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodReader; import org.teavm.model.MethodReader;
import org.teavm.tooling.EmptyTeaVMToolLog;
import org.teavm.tooling.TeaVMToolLog;
/** /**
* *

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
/** /**
* *

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -25,6 +25,7 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.teavm.common.FiniteExecutor; import org.teavm.common.FiniteExecutor;
import org.teavm.common.SimpleFiniteExecutor; import org.teavm.common.SimpleFiniteExecutor;
@ -47,6 +48,13 @@ import org.teavm.model.ValueType;
import org.teavm.parsing.ClasspathClassHolderSource; import org.teavm.parsing.ClasspathClassHolderSource;
import org.teavm.testing.JUnitTestAdapter; import org.teavm.testing.JUnitTestAdapter;
import org.teavm.testing.TestAdapter; 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.DirectoryBuildTarget;
import org.teavm.vm.TeaVM; import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMBuilder; import org.teavm.vm.TeaVMBuilder;
@ -55,7 +63,7 @@ import org.teavm.vm.TeaVMBuilder;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TeaVMTestTool { public class TeaVMTestTool implements BaseTeaVMTool {
private File outputDir = new File("."); private File outputDir = new File(".");
private boolean minifying = true; private boolean minifying = true;
private int numThreads = 1; private int numThreads = 1;
@ -68,22 +76,25 @@ public class TeaVMTestTool {
private ClassLoader classLoader = TeaVMTestTool.class.getClassLoader(); private ClassLoader classLoader = TeaVMTestTool.class.getClassLoader();
private TeaVMToolLog log = new EmptyTeaVMToolLog(); private TeaVMToolLog log = new EmptyTeaVMToolLog();
private boolean debugInformationGenerated; private boolean debugInformationGenerated;
private boolean sourceMapsGenerated; private boolean sourceMapsFileGenerated;
private boolean sourceFilesCopied; private boolean sourceFilesCopied;
private boolean incremental; private boolean incremental;
private List<SourceFileProvider> sourceFileProviders = new ArrayList<>(); private List<SourceFileProvider> sourceFileProviders = new ArrayList<>();
private MethodNodeCache astCache; private MethodNodeCache astCache;
private ProgramCache programCache; private ProgramCache programCache;
private SourceFilesCopier sourceFilesCopier; private SourceFilesCopier sourceFilesCopier;
private List<TeaVMTestToolListener> listeners = new ArrayList<>(); private List<TestClassBuilder> testPlan = new ArrayList<>();
private List<TeaVMTestClass> testPlan = new ArrayList<>();
private int fileIndexGenerator; private int fileIndexGenerator;
private long startTime;
private int testCount;
private AtomicInteger testsBuilt = new AtomicInteger();
public File getOutputDir() { public File getOutputDir() {
return outputDir; return outputDir;
} }
public void setOutputDir(File outputDir) { @Override
public void setTargetDirectory(File outputDir) {
this.outputDir = outputDir; this.outputDir = outputDir;
} }
@ -91,6 +102,7 @@ public class TeaVMTestTool {
return minifying; return minifying;
} }
@Override
public void setMinifying(boolean minifying) { public void setMinifying(boolean minifying) {
this.minifying = minifying; this.minifying = minifying;
} }
@ -111,6 +123,7 @@ public class TeaVMTestTool {
this.adapter = adapter; this.adapter = adapter;
} }
@Override
public List<ClassHolderTransformer> getTransformers() { public List<ClassHolderTransformer> getTransformers() {
return transformers; return transformers;
} }
@ -119,6 +132,7 @@ public class TeaVMTestTool {
return additionalScripts; return additionalScripts;
} }
@Override
public Properties getProperties() { public Properties getProperties() {
return properties; return properties;
} }
@ -131,6 +145,7 @@ public class TeaVMTestTool {
return classLoader; return classLoader;
} }
@Override
public void setClassLoader(ClassLoader classLoader) { public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
@ -139,6 +154,7 @@ public class TeaVMTestTool {
return log; return log;
} }
@Override
public void setLog(TeaVMToolLog log) { public void setLog(TeaVMToolLog log) {
this.log = log; this.log = log;
} }
@ -147,6 +163,7 @@ public class TeaVMTestTool {
return incremental; return incremental;
} }
@Override
public void setIncremental(boolean incremental) { public void setIncremental(boolean incremental) {
this.incremental = incremental; this.incremental = incremental;
} }
@ -155,31 +172,36 @@ public class TeaVMTestTool {
return debugInformationGenerated; return debugInformationGenerated;
} }
@Override
public void setDebugInformationGenerated(boolean debugInformationGenerated) { public void setDebugInformationGenerated(boolean debugInformationGenerated) {
this.debugInformationGenerated = debugInformationGenerated; this.debugInformationGenerated = debugInformationGenerated;
} }
public boolean isSourceMapsGenerated() { public boolean isSourceMapsFileGenerated() {
return sourceMapsGenerated; return sourceMapsFileGenerated;
} }
public void setSourceMapsGenerated(boolean sourceMapsGenerated) { @Override
this.sourceMapsGenerated = sourceMapsGenerated; public void setSourceMapsFileGenerated(boolean sourceMapsFileGenerated) {
this.sourceMapsFileGenerated = sourceMapsFileGenerated;
} }
public boolean isSourceFilesCopied() { public boolean isSourceFilesCopied() {
return sourceFilesCopied; return sourceFilesCopied;
} }
@Override
public void setSourceFilesCopied(boolean sourceFilesCopied) { public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied; this.sourceFilesCopied = sourceFilesCopied;
} }
@Override
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) { public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
sourceFileProviders.add(sourceFileProvider); sourceFileProviders.add(sourceFileProvider);
} }
public void generate() throws TeaVMToolException { public TestPlan generate() throws TeaVMToolException {
testsBuilt.set(0);
Runnable finalizer = null; Runnable finalizer = null;
try { try {
new File(outputDir, "tests").mkdirs(); new File(outputDir, "tests").mkdirs();
@ -201,12 +223,17 @@ public class TeaVMTestTool {
if (incremental) { if (incremental) {
classSource = new PreOptimizingClassHolderSource(classSource); classSource = new PreOptimizingClassHolderSource(classSource);
} }
List<TestGroup> groups = new ArrayList<>();
for (String testClass : testClasses) { for (String testClass : testClasses) {
ClassHolder classHolder = classSource.get(testClass); ClassHolder classHolder = classSource.get(testClass);
if (classHolder == null) { if (classHolder == null) {
throw new TeaVMToolException("Could not find class " + testClass); throw new TeaVMToolException("Could not find class " + testClass);
} }
findTests(classHolder); TestGroup group = findTests(classHolder);
if (group != null) {
groups.add(group);
}
} }
includeAdditionalScripts(classLoader); includeAdditionalScripts(classLoader);
@ -220,16 +247,21 @@ public class TeaVMTestTool {
FiniteExecutor executor = new SimpleFiniteExecutor(); FiniteExecutor executor = new SimpleFiniteExecutor();
if (numThreads != 1) { if (numThreads != 1) {
int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors(); int threads = numThreads != 0 ? numThreads : Runtime.getRuntime().availableProcessors();
final ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads); ThreadPoolFiniteExecutor threadedExecutor = new ThreadPoolFiniteExecutor(threads);
finalizer = () -> threadedExecutor.stop(); finalizer = () -> threadedExecutor.stop();
executor = threadedExecutor; executor = threadedExecutor;
} }
startTime = System.currentTimeMillis();
int methodsGenerated = writeMethods(executor, classSource); int methodsGenerated = writeMethods(executor, classSource);
if (sourceFilesCopied) { if (sourceFilesCopied) {
sourceFilesCopier.copy(new File(new File(outputDir, "tests"), "src")); 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) { } catch (IOException e) {
throw new TeaVMToolException("IO error occured generating JavaScript files", e); throw new TeaVMToolException("IO error occured generating JavaScript files", e);
} finally { } finally {
@ -245,7 +277,7 @@ public class TeaVMTestTool {
allTestsWriter.write("prepare = function() {\n"); allTestsWriter.write("prepare = function() {\n");
allTestsWriter.write(" return new JUnitServer(document.body).readTests(["); allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
boolean first = true; boolean first = true;
for (TeaVMTestClass testClass : testPlan) { for (TestClassBuilder testClass : testPlan) {
if (!first) { if (!first) {
allTestsWriter.append(","); allTestsWriter.append(",");
} }
@ -253,7 +285,7 @@ public class TeaVMTestTool {
allTestsWriter.append("\n { name : \"").append(testClass.getClassName()) allTestsWriter.append("\n { name : \"").append(testClass.getClassName())
.append("\", methods : ["); .append("\", methods : [");
boolean firstMethod = true; boolean firstMethod = true;
for (TeaVMTestMethod testMethod : testClass.getMethods()) { for (TestMethodBuilder testMethod : testClass.getMethods()) {
String scriptName = testMethod.getFileName(); String scriptName = testMethod.getFileName();
if (!firstMethod) { if (!firstMethod) {
allTestsWriter.append(","); allTestsWriter.append(",");
@ -289,13 +321,12 @@ public class TeaVMTestTool {
log.info("Generating test files"); log.info("Generating test files");
sourceFilesCopier = new SourceFilesCopier(sourceFileProviders); sourceFilesCopier = new SourceFilesCopier(sourceFileProviders);
sourceFilesCopier.setLog(log); sourceFilesCopier.setLog(log);
for (TeaVMTestClass testClass : testPlan) { for (TestClassBuilder testClass : testPlan) {
for (TeaVMTestMethod testMethod : testClass.getMethods()) { for (TestMethodBuilder testMethod : testClass.getMethods()) {
final ClassHolderSource builderClassSource = classSource;
executor.execute(() -> { executor.execute(() -> {
log.debug("Building test for " + testMethod.getMethod()); log.debug("Building test for " + testMethod.getMethod());
try { try {
decompileClassesForTest(classLoader, new CopyClassHolderSource(builderClassSource), decompileClassesForTest(classLoader, new CopyClassHolderSource(classSource),
testMethod); testMethod);
} catch (IOException e) { } catch (IOException e) {
log.error("Error generating JavaScript", e); log.error("Error generating JavaScript", e);
@ -316,8 +347,9 @@ public class TeaVMTestTool {
} }
} }
private void findTests(ClassHolder cls) { private TestGroup findTests(ClassHolder cls) {
TeaVMTestClass testClass = new TeaVMTestClass(cls.getName()); List<TestCase> cases = new ArrayList<>();
TestClassBuilder testClass = new TestClassBuilder(cls.getName());
for (MethodHolder method : cls.getMethods()) { for (MethodHolder method : cls.getMethods()) {
if (adapter.acceptMethod(method)) { if (adapter.acceptMethod(method)) {
MethodReference ref = new MethodReference(cls.getName(), method.getDescriptor()); MethodReference ref = new MethodReference(cls.getName(), method.getDescriptor());
@ -328,12 +360,19 @@ public class TeaVMTestTool {
exceptions.add(exception); exceptions.add(exception);
} }
TeaVMTestMethod testMethod = new TeaVMTestMethod(ref, fileName, exceptions); TestMethodBuilder testMethod = new TestMethodBuilder(ref, fileName, exceptions);
testClass.getMethods().add(testMethod); testClass.getMethods().add(testMethod);
String debugTable = debugInformationGenerated ? testMethod.getFileName() + ".teavmdbg" : null;
cases.add(new TestCase(ref, testMethod.getFileName(), debugTable, testMethod.getExpectedExceptions()));
++testCount;
} }
} }
if (!testClass.getMethods().isEmpty()) { if (!testClass.getMethods().isEmpty()) {
testPlan.add(testClass); testPlan.add(testClass);
return new TestGroup(cls.getName(), cases);
} else {
return null;
} }
} }
@ -362,7 +401,7 @@ public class TeaVMTestTool {
} }
private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource, private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
TeaVMTestMethod testMethod) throws IOException { TestMethodBuilder testMethod) throws IOException {
String targetName = testMethod.getFileName(); String targetName = testMethod.getFileName();
TeaVM vm = new TeaVMBuilder() TeaVM vm = new TeaVMBuilder()
.setClassLoader(classLoader) .setClassLoader(classLoader)
@ -380,7 +419,7 @@ public class TeaVMTestTool {
} }
File file = new File(outputDir, testMethod.getFileName()); File file = new File(outputDir, testMethod.getFileName());
DebugInformationBuilder debugInfoBuilder = sourceMapsGenerated || debugInformationGenerated DebugInformationBuilder debugInfoBuilder = sourceMapsFileGenerated || debugInformationGenerated
? new DebugInformationBuilder() : null; ? new DebugInformationBuilder() : null;
MethodReference methodRef = testMethod.getMethod(); MethodReference methodRef = testMethod.getMethod();
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) { try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(file), "UTF-8")) {
@ -395,7 +434,7 @@ public class TeaVMTestTool {
vm.build(innerWriter, new DirectoryBuildTarget(outputDir)); vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
innerWriter.append("\n"); innerWriter.append("\n");
innerWriter.append("\nJUnitClient.run();"); innerWriter.append("\nJUnitClient.run();");
if (sourceMapsGenerated) { if (sourceMapsFileGenerated) {
String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map"; String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map";
innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName); innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName);
} }
@ -410,16 +449,15 @@ public class TeaVMTestTool {
} }
} }
File debugTableFile = null;
if (debugInformationGenerated) { if (debugInformationGenerated) {
DebugInformation debugInfo = debugInfoBuilder.getDebugInformation(); DebugInformation debugInfo = debugInfoBuilder.getDebugInformation();
debugTableFile = new File(outputDir, targetName + ".teavmdbg"); File debugTableFile = new File(outputDir, targetName + ".teavmdbg");
try (OutputStream debugInfoOut = new FileOutputStream(debugTableFile)) { try (OutputStream debugInfoOut = new FileOutputStream(debugTableFile)) {
debugInfo.write(debugInfoOut); debugInfo.write(debugInfoOut);
} }
} }
if (sourceMapsGenerated) { if (sourceMapsFileGenerated) {
DebugInformation debugInfo = debugInfoBuilder.getDebugInformation(); DebugInformation debugInfo = debugInfoBuilder.getDebugInformation();
String sourceMapsFileName = targetName + ".map"; String sourceMapsFileName = targetName + ".map";
try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream( try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream(
@ -431,11 +469,19 @@ public class TeaVMTestTool {
sourceFilesCopier.addClasses(vm.getWrittenClasses()); sourceFilesCopier.addClasses(vm.getWrittenClasses());
} }
TeaVMTestCase testCase = new TeaVMTestCase(methodRef, new File(outputDir, "res/runtime.js"), incrementCounter();
file, debugTableFile, testMethod.getExpectedExceptions()); }
for (TeaVMTestToolListener listener : listeners) {
listener.testGenerated(testCase); 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 { private void escapeString(String string, Writer writer) throws IOException {
@ -465,12 +511,4 @@ public class TeaVMTestTool {
} }
writer.append('\"'); writer.append('\"');
} }
public void addListener(TeaVMTestToolListener listener) {
listeners.add(listener);
}
public void removeListener(TeaVMTestToolListener listener) {
listeners.remove(listener);
}
} }

View File

@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public interface TeaVMTestToolListener { public interface TeaVMTestToolListener {
void testGenerated(TeaVMTestCase testCase); void testGenerated(TestCase testCase);
} }

View File

@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import java.io.File; 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.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -25,38 +27,40 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TeaVMTestCase { public class TestCase {
private MethodReference testMethod; private MethodReference testMethod;
private File runtimeScript; private String testScript;
private File testScript; private String debugTable;
private File debugTable;
private List<String> expectedExceptions = new ArrayList<>(); private List<String> expectedExceptions = new ArrayList<>();
public TeaVMTestCase(MethodReference testMethod, File runtimeScript, File testScript, File debugTable, @JsonCreator
List<String> expectedExceptions) { public TestCase(
@JsonProperty("testMethod") MethodReference testMethod,
@JsonProperty("script") String testScript,
@JsonProperty("debugTable") String debugTable,
@JsonProperty("expectedExceptions") List<String> expectedExceptions) {
this.testMethod = testMethod; this.testMethod = testMethod;
this.runtimeScript = runtimeScript;
this.testScript = testScript; this.testScript = testScript;
this.debugTable = debugTable; this.debugTable = debugTable;
this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions)); this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions));
} }
@JsonGetter
public MethodReference getTestMethod() { public MethodReference getTestMethod() {
return testMethod; return testMethod;
} }
public File getRuntimeScript() { @JsonGetter("script")
return runtimeScript; public String getTestScript() {
}
public File getTestScript() {
return testScript; return testScript;
} }
public File getDebugTable() { @JsonGetter
public String getDebugTable() {
return debugTable; return debugTable;
} }
@JsonGetter
public List<String> getExpectedExceptions() { public List<String> getExpectedExceptions() {
return expectedExceptions; return expectedExceptions;
} }

View File

@ -13,19 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class TeaVMTestClass { class TestClassBuilder {
private String className; private String className;
private List<TeaVMTestMethod> methods; private List<TestMethodBuilder> methods = new ArrayList<>();
public TeaVMTestClass(String className) { public TestClassBuilder(String className) {
this.className = className; this.className = className;
} }
@ -33,7 +34,7 @@ class TeaVMTestClass {
return className; return className;
} }
public List<TeaVMTestMethod> getMethods() { public List<TestMethodBuilder> getMethods() {
return methods; return methods;
} }
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import org.teavm.dependency.AbstractDependencyListener; import org.teavm.dependency.AbstractDependencyListener;
import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyAgent;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;

View File

@ -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<TestCase> testCases;
@JsonCreator
public TestGroup(@JsonProperty("className") String className,
@JsonProperty("testCases") List<TestCase> testCases) {
this.className = className;
this.testCases = Collections.unmodifiableList(new ArrayList<>(testCases));
}
@JsonGetter("className")
public String getClassName() {
return className;
}
@JsonGetter("testCases")
public List<TestCase> getTestCases() {
return testCases;
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.tooling; package org.teavm.tooling.testing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -24,12 +24,12 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class TeaVMTestMethod { class TestMethodBuilder {
private MethodReference method; private MethodReference method;
private String fileName; private String fileName;
private List<String> expectedExceptions = new ArrayList<>(); private List<String> expectedExceptions = new ArrayList<>();
public TeaVMTestMethod(MethodReference method, String fileName, List<String> expectedExceptions) { public TestMethodBuilder(MethodReference method, String fileName, List<String> expectedExceptions) {
this.method = method; this.method = method;
this.fileName = fileName; this.fileName = fileName;
this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions)); this.expectedExceptions = Collections.unmodifiableList(new ArrayList<>(expectedExceptions));

View File

@ -0,0 +1,47 @@
/*
* 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.JsonProperty;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*
* @author Alexey Andreev
*/
public class TestPlan {
private String runtimeScript;
private List<TestGroup> groups = new ArrayList<>();
@JsonCreator
public TestPlan(
@JsonProperty("runtimeScript") String runtimeScript,
@JsonProperty("groupList") List<TestGroup> groups) {
this.runtimeScript = runtimeScript;
this.groups = Collections.unmodifiableList(new ArrayList<>(groups));
}
public String getRuntimeScript() {
return runtimeScript;
}
public List<TestGroup> getGroups() {
return groups;
}
}

View File

Before

Width:  |  Height:  |  Size: 774 B

After

Width:  |  Height:  |  Size: 774 B

View File

@ -39,6 +39,7 @@ Bundle-ClassPath: .,
lib/slf4j-api-1.7.7.jar, lib/slf4j-api-1.7.7.jar,
lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar, lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar,
lib/teavm-core-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-api-9.2.1.v20140609.jar,
lib/websocket-client-9.2.1.v20140609.jar, lib/websocket-client-9.2.1.v20140609.jar,
lib/websocket-common-9.2.1.v20140609.jar, lib/websocket-common-9.2.1.v20140609.jar,

View File

@ -36,6 +36,7 @@ bin.includes = META-INF/,\
lib/slf4j-api-1.7.7.jar,\ lib/slf4j-api-1.7.7.jar,\
lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar,\ lib/teavm-chrome-rdp-0.4.0-SNAPSHOT.jar,\
lib/teavm-core-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-api-9.2.1.v20140609.jar,\
lib/websocket-client-9.2.1.v20140609.jar,\ lib/websocket-client-9.2.1.v20140609.jar,\
lib/websocket-common-9.2.1.v20140609.jar,\ lib/websocket-common-9.2.1.v20140609.jar,\

View File

@ -79,6 +79,11 @@
<artifactId>teavm-core</artifactId> <artifactId>teavm-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-tooling</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm-chrome-rdp</artifactId> <artifactId>teavm-chrome-rdp</artifactId>

View File

@ -21,6 +21,7 @@
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-eclipse</artifactId> <artifactId>teavm-eclipse</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@ -50,7 +50,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId> <artifactId>teavm-tooling</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
@ -68,7 +68,6 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>2.6.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View File

@ -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<MavenArtifactRepository> remoteRepositories;
@Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
protected List<Artifact> pluginArtifacts;
@Parameter(defaultValue = "${project.build.outputDirectory}")
protected File classFiles;
@Parameter
protected List<String> 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<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
throws MojoExecutionException {
List<ClassHolderTransformer> 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<URL> 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<File> 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<SourceFileProvider> getSourceFileProviders() {
MavenSourceFileProviderLookup lookup = new MavenSourceFileProviderLookup();
lookup.setMavenProject(project);
lookup.setRepositorySystem(repositorySystem);
lookup.setLocalRepository(localRepository);
lookup.setRemoteRepositories(remoteRepositories);
lookup.setPluginDependencies(pluginArtifacts);
return lookup.resolve();
}
}

View File

@ -16,33 +16,16 @@
package org.teavm.maven; package org.teavm.maven;
import java.io.File; 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.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
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.MojoExecutionException;
import org.apache.maven.plugin.logging.Log; 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.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope; 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.ClassAlias; import org.teavm.tooling.ClassAlias;
import org.teavm.tooling.MethodAlias; import org.teavm.tooling.MethodAlias;
import org.teavm.tooling.RuntimeCopyOperation; import org.teavm.tooling.RuntimeCopyOperation;
import org.teavm.tooling.SourceFileProvider;
import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.TeaVMToolException;
@ -50,72 +33,25 @@ import org.teavm.tooling.TeaVMToolException;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Mojo(name = "build-javascript", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, @Mojo(name = "compile", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME,
public class BuildJavascriptMojo extends AbstractMojo { defaultPhase = LifecyclePhase.PROCESS_CLASSES)
@Component public class BuildJavascriptMojo extends AbstractJavascriptMojo {
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<MavenArtifactRepository> remoteRepositories;
@Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
private List<Artifact> pluginArtifacts;
@Parameter(defaultValue = "${project.build.directory}/javascript") @Parameter(defaultValue = "${project.build.directory}/javascript")
private File targetDirectory; private File targetDirectory;
@Parameter(defaultValue = "${project.build.outputDirectory}")
private File classFiles;
@Parameter
private List<String> compileScopes;
@Parameter @Parameter
private String targetFileName = "classes.js"; private String targetFileName = "classes.js";
@Parameter
private boolean minifying = true;
@Parameter @Parameter
private String mainClass; private String mainClass;
@Parameter
private RuntimeCopyOperation runtime = RuntimeCopyOperation.SEPARATE;
@Parameter
private Properties properties;
@Parameter @Parameter
private boolean mainPageIncluded; private boolean mainPageIncluded;
@Parameter @Parameter
private boolean bytecodeLogging; 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 @Parameter
private ClassAlias[] classAliases; private ClassAlias[] classAliases;
@ -125,152 +61,37 @@ public class BuildJavascriptMojo extends AbstractMojo {
@Parameter @Parameter
private boolean stopOnErrors = true; 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(); private TeaVMTool tool = new TeaVMTool();
public void setProject(MavenProject project) { @Override
this.project = project; protected File getTargetDirectory() {
} return targetDirectory;
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 void setCompileScopes(List<String> compileScopes) {
this.compileScopes = compileScopes;
}
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
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 @Override
public void execute() throws MojoExecutionException { public void execute() throws MojoExecutionException {
Log log = getLog(); Log log = getLog();
setupTool(tool);
tool.setLog(new MavenTeaVMToolLog(log)); tool.setLog(new MavenTeaVMToolLog(log));
try { try {
ClassLoader classLoader = prepareClassLoader();
tool.setClassLoader(classLoader);
tool.setBytecodeLogging(bytecodeLogging); tool.setBytecodeLogging(bytecodeLogging);
tool.setMainClass(mainClass); tool.setMainClass(mainClass);
tool.setMainPageIncluded(mainPageIncluded); tool.setMainPageIncluded(mainPageIncluded);
tool.setMinifying(minifying);
tool.setRuntime(runtime); tool.setRuntime(runtime);
tool.setTargetDirectory(targetDirectory);
tool.setTargetFileName(targetFileName); 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) { if (classAliases != null) {
tool.getClassAliases().addAll(Arrays.asList(classAliases)); tool.getClassAliases().addAll(Arrays.asList(classAliases));
} }
if (methodAliases != null) { if (methodAliases != null) {
tool.getMethodAliases().addAll(Arrays.asList(methodAliases)); tool.getMethodAliases().addAll(Arrays.asList(methodAliases));
} }
if (properties != null) {
tool.getProperties().putAll(properties);
}
tool.setCacheDirectory(cacheDirectory); tool.setCacheDirectory(cacheDirectory);
tool.setIncremental(incremental);
tool.setDebugInformationGenerated(debugInformationGenerated);
tool.setSourceMapsFileGenerated(sourceMapsGenerated);
tool.setSourceFilesCopied(sourceFilesCopied);
tool.generate(); tool.generate();
if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) { if (stopOnErrors && !tool.getProblemProvider().getSevereProblems().isEmpty()) {
throw new MojoExecutionException("Build error"); throw new MojoExecutionException("Build error");
@ -281,75 +102,4 @@ public class BuildJavascriptMojo extends AbstractMojo {
throw new MojoExecutionException("IO error occured", e); throw new MojoExecutionException("IO error occured", e);
} }
} }
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader)
throws MojoExecutionException {
List<ClassHolderTransformer> 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<URL> urls = new ArrayList<>();
StringBuilder classpath = new StringBuilder();
Set<String> 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);
}
}
} }

View File

@ -21,8 +21,6 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
@ -33,55 +31,31 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.apache.maven.artifact.Artifact; 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.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log; 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.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope; 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.JUnitTestAdapter;
import org.teavm.testing.TestAdapter; import org.teavm.testing.TestAdapter;
import org.teavm.tooling.SourceFileProvider;
import org.teavm.tooling.TeaVMTestTool;
import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.TeaVMToolException;
import org.teavm.tooling.testing.TeaVMTestTool;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Mojo(name = "build-test-javascript", requiresDependencyResolution = ResolutionScope.TEST, @Mojo(name = "testCompile", requiresDependencyResolution = ResolutionScope.TEST,
requiresDependencyCollection = ResolutionScope.TEST) requiresDependencyCollection = ResolutionScope.TEST,
public class BuildJavascriptTestMojo extends AbstractMojo { defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES)
public class BuildJavascriptTestMojo extends AbstractJavascriptMojo {
private static Set<String> testScopes = new HashSet<>(Arrays.asList( private static Set<String> testScopes = new HashSet<>(Arrays.asList(
Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME,
Artifact.SCOPE_PROVIDED)); 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<MavenArtifactRepository> remoteRepositories;
@Parameter(readonly = true, defaultValue = "${plugin.artifacts}")
private List<Artifact> pluginArtifacts;
@Parameter(defaultValue = "${project.build.directory}/javascript-test") @Parameter(defaultValue = "${project.build.directory}/javascript-test")
private File outputDir; private File targetDirectory;
@Parameter(defaultValue = "${project.build.outputDirectory}")
private File classFiles;
@Parameter(defaultValue = "${project.build.testOutputDirectory}") @Parameter(defaultValue = "${project.build.testOutputDirectory}")
private File testFiles; private File testFiles;
@ -92,9 +66,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter @Parameter
private String[] excludeWildcards = new String[0]; private String[] excludeWildcards = new String[0];
@Parameter
private boolean minifying = true;
@Parameter @Parameter
private boolean scanDependencies; private boolean scanDependencies;
@ -104,9 +75,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter @Parameter
private String adapterClass = JUnitTestAdapter.class.getName(); private String adapterClass = JUnitTestAdapter.class.getName();
@Parameter
private String[] transformers;
@Parameter @Parameter
private String[] additionalScripts; private String[] additionalScripts;
@ -116,15 +84,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
@Parameter @Parameter
private boolean incremental; private boolean incremental;
@Parameter
private boolean debugInformationGenerated;
@Parameter
private boolean sourceMapsGenerated;
@Parameter
private boolean sourceFilesCopied;
@Parameter @Parameter
private URL seleniumURL; private URL seleniumURL;
@ -132,86 +91,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
private TeaVMTestTool tool = new TeaVMTestTool(); 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;
}
public void setSeleniumURL(URL seleniumURL) {
this.seleniumURL = seleniumURL;
}
@Override @Override
public void execute() throws MojoExecutionException, MojoFailureException { public void execute() throws MojoExecutionException, MojoFailureException {
if (System.getProperty("maven.test.skip", "false").equals("true") || if (System.getProperty("maven.test.skip", "false").equals("true") ||
@ -220,54 +99,21 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
return; return;
} }
seleniumRunner = new SeleniumTestRunner(); setupTool(tool);
seleniumRunner.setUrl(seleniumURL);
seleniumRunner.setLog(getLog());
seleniumRunner.detectSelenium();
try { try {
final ClassLoader classLoader = prepareClassLoader();
getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'"); getLog().info("Searching for tests in the directory `" + testFiles.getAbsolutePath() + "'");
tool.setClassLoader(classLoader);
tool.setAdapter(createAdapter(classLoader)); tool.setAdapter(createAdapter(classLoader));
findTestClasses(classLoader, testFiles, ""); findTestClasses(classLoader, testFiles, "");
if (scanDependencies) { if (scanDependencies) {
findTestsInDependencies(classLoader); findTestsInDependencies(classLoader);
} }
tool.getTransformers().addAll(instantiateTransformers(classLoader));
tool.setLog(new MavenTeaVMToolLog(getLog()));
tool.setOutputDir(outputDir);
tool.setNumThreads(numThreads); 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) { if (additionalScripts != null) {
tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts)); tool.getAdditionalScripts().addAll(Arrays.asList(additionalScripts));
} }
tool.addListener(testCase -> seleniumRunner.run(testCase));
tool.generate(); tool.generate();
seleniumRunner.stopSelenium();
seleniumRunner.waitForSelenium();
processReport(seleniumRunner.getReport());
} catch (TeaVMToolException e) { } catch (TeaVMToolException e) {
throw new MojoFailureException("Error occured generating JavaScript files", e); throw new MojoFailureException("Error occured generating JavaScript files", e);
} finally {
seleniumRunner.stopSelenium();
} }
} }
@ -318,38 +164,6 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
} }
} }
private ClassLoader prepareClassLoader() throws MojoExecutionException {
try {
Log log = getLog();
log.info("Preparing classpath for JavaScript test generation");
List<URL> 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 { private void findTestsInDependencies(ClassLoader classLoader) throws MojoExecutionException {
try { try {
Log log = getLog(); Log log = getLog();
@ -430,40 +244,18 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
} }
} }
@Override
private List<ClassHolderTransformer> instantiateTransformers(ClassLoader classLoader) protected File getTargetDirectory() {
throws MojoExecutionException { return targetDirectory;
List<ClassHolderTransformer> 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<File> getAdditionalClassPath() {
return Arrays.asList(testFiles);
}
@Override
protected boolean isSupportedScope(String scope) {
return testScopes.contains(scope);
}
} }

View File

@ -26,9 +26,9 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem; import org.apache.maven.repository.RepositorySystem;
import org.teavm.tooling.DirectorySourceFileProvider; import org.teavm.tooling.sources.DirectorySourceFileProvider;
import org.teavm.tooling.JarSourceFileProvider; import org.teavm.tooling.sources.JarSourceFileProvider;
import org.teavm.tooling.SourceFileProvider; import org.teavm.tooling.sources.SourceFileProvider;
/** /**
* *

View File

@ -0,0 +1,31 @@
/*
* 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 org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
/**
*
* @author Alexey Andreev
*/
@Mojo(name = "run-tests", defaultPhase = LifecyclePhase.TEST)
public class RunTestsMojo {
@Parameter(defaultValue = "${project.build.directory}/javascript-tests")
private File targetDirectory;
}

View File

@ -35,7 +35,9 @@ import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriver;
import org.teavm.tooling.TeaVMTestCase; import org.teavm.tooling.testing.TestCase;
import org.teavm.tooling.testing.TestGroup;
import org.teavm.tooling.testing.TestPlan;
/** /**
* *
@ -43,13 +45,15 @@ import org.teavm.tooling.TeaVMTestCase;
*/ */
public class SeleniumTestRunner { public class SeleniumTestRunner {
private URL url; private URL url;
private WebDriver webDriver; private int numThreads = 1;
private ThreadLocal<WebDriver> webDriver = new ThreadLocal<>();
private BlockingQueue<Runnable> seleniumTaskQueue = new LinkedBlockingQueue<>(); private BlockingQueue<Runnable> seleniumTaskQueue = new LinkedBlockingQueue<>();
private CountDownLatch latch = new CountDownLatch(1); private CountDownLatch latch = new CountDownLatch(1);
private volatile boolean seleniumStopped = false; private volatile boolean seleniumStopped = false;
private Log log; private Log log;
private List<TestResult> report = new CopyOnWriteArrayList<>(); private List<TestResult> report = new CopyOnWriteArrayList<>();
private ThreadLocal<List<TestResult>> localReport = new ThreadLocal<>(); private ThreadLocal<List<TestResult>> localReport = new ThreadLocal<>();
private File directory = new File(".");
public URL getUrl() { public URL getUrl() {
return url; return url;
@ -63,28 +67,55 @@ public class SeleniumTestRunner {
this.log = log; this.log = log;
} }
public void detectSelenium() { public File getDirectory() {
if (url == null) { return directory;
return; }
}
ChromeDriver driver = new ChromeDriver(); public void setDirectory(File directory) {
webDriver = driver; this.directory = directory;
new Thread(() -> { }
localReport.set(new ArrayList<>());
while (!seleniumStopped) { public int getNumThreads() {
Runnable task; return numThreads;
try { }
task = seleniumTaskQueue.poll(1, TimeUnit.SECONDS);
} catch (InterruptedException e) { public void setNumThreads(int numThreads) {
break; this.numThreads = numThreads;
} }
if (task != null) {
task.run(); public void run(TestPlan testPlan) {
} initSelenium();
for (TestGroup group : testPlan.getGroups()) {
for (TestCase testCase : group.getTestCases()) {
run(testPlan.getRuntimeScript(), testCase);
} }
report.addAll(localReport.get()); }
localReport.remove(); stopSelenium();
}).start(); waitForCompletion();
}
private void initSelenium() {
for (int i = 0; i < numThreads; ++i) {
new Thread(() -> {
ChromeDriver driver = new ChromeDriver();
webDriver.set(driver);
localReport.set(new ArrayList<>());
while (!seleniumStopped) {
Runnable task;
try {
task = seleniumTaskQueue.poll(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
break;
}
if (task != null) {
task.run();
}
}
report.addAll(localReport.get());
localReport.remove();
webDriver.remove();
}).start();
}
} }
private void addSeleniumTask(Runnable runnable) { private void addSeleniumTask(Runnable runnable) {
@ -93,14 +124,14 @@ public class SeleniumTestRunner {
} }
} }
public void stopSelenium() { private void stopSelenium() {
addSeleniumTask(() -> { addSeleniumTask(() -> {
seleniumStopped = true; seleniumStopped = true;
latch.countDown(); latch.countDown();
}); });
} }
public void waitForSelenium() { private void waitForCompletion() {
try { try {
latch.await(); latch.await();
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -108,21 +139,18 @@ public class SeleniumTestRunner {
} }
} }
public void run(TeaVMTestCase testCase) { private void run(String runtimeScript, TestCase testCase) {
addSeleniumTask(() -> runImpl(testCase)); addSeleniumTask(() -> runImpl(runtimeScript, testCase));
} }
private void runImpl(TeaVMTestCase testCase) { private void runImpl(String runtimeScript, TestCase testCase) {
if (webDriver == null) { webDriver.get().manage().timeouts().setScriptTimeout(2, TimeUnit.SECONDS);
return;
}
webDriver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS);
JavascriptExecutor js = (JavascriptExecutor) webDriver; JavascriptExecutor js = (JavascriptExecutor) webDriver;
try { try {
String result = (String) js.executeAsyncScript( String result = (String) js.executeAsyncScript(
readResource("teavm-selenium.js"), readResource("teavm-selenium.js"),
readFile(testCase.getRuntimeScript()), readFile(new File(directory, runtimeScript)),
readFile(testCase.getTestScript()), readFile(new File(directory, testCase.getTestScript())),
readResource("teavm-selenium-adapter.js")); readResource("teavm-selenium-adapter.js"));
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
ObjectNode resultObject = (ObjectNode) mapper.readTree(result); ObjectNode resultObject = (ObjectNode) mapper.readTree(result);

View File

@ -21,6 +21,7 @@
<groupId>org.teavm</groupId> <groupId>org.teavm</groupId>
<artifactId>teavm</artifactId> <artifactId>teavm</artifactId>
<version>0.4.0-SNAPSHOT</version> <version>0.4.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent> </parent>
<artifactId>teavm-maven</artifactId> <artifactId>teavm-maven</artifactId>