mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add IDEA run configuration that runs dev server
This commit is contained in:
parent
bab0cd59a6
commit
d7d4dc1571
|
@ -1,9 +1,11 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="IDEA" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
|
<configuration default="false" name="IDEA" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType">
|
||||||
<module name="teavm-idea" />
|
<module name="teavm-idea" />
|
||||||
<option name="VM_PARAMETERS" value="-Xmx1024m -Xms256m -ea" />
|
<option name="VM_PARAMETERS" value="-Xmx1024m -Xms256m -ea" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<predefined_log_file id="idea.log" enabled="true" />
|
<predefined_log_file enabled="true" id="idea.log" />
|
||||||
<method />
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
|
@ -80,6 +80,11 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
|
@ -135,6 +140,15 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>html/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
@ -151,7 +165,7 @@
|
||||||
</includes>
|
</includes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
<relocations>
|
<relocations>
|
||||||
<relocation>cd
|
<relocation>
|
||||||
<pattern>org.objectweb.asm</pattern>
|
<pattern>org.objectweb.asm</pattern>
|
||||||
<shadedPattern>org.teavm.asm</shadedPattern>
|
<shadedPattern>org.teavm.asm</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
|
|
11
core/pom.xml
11
core/pom.xml
|
@ -107,10 +107,19 @@
|
||||||
<artifactSet>
|
<artifactSet>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>junit:junit</exclude>
|
<exclude>junit:junit</exclude>
|
||||||
<exclude>org:teavm:*</exclude>
|
<exclude>org.teavm:teavm-interop</exclude>
|
||||||
|
<exclude>org.teavm:teavm-metaprogramming-api</exclude>
|
||||||
<exclude>com.fasterxml.jackson.core:jackson-annotations</exclude>
|
<exclude>com.fasterxml.jackson.core:jackson-annotations</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/module-info.class</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
<relocations>
|
<relocations>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>org.objectweb.asm</pattern>
|
<pattern>org.objectweb.asm</pattern>
|
||||||
|
|
|
@ -79,6 +79,13 @@ public class InMemoryMethodNodeCache implements MethodNodeCache {
|
||||||
newAsyncItems.clear();
|
newAsyncItems.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
cache.clear();
|
||||||
|
newItems.clear();
|
||||||
|
asyncCache.clear();
|
||||||
|
newAsyncItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
static final class RegularItem {
|
static final class RegularItem {
|
||||||
final RegularMethodNode node;
|
final RegularMethodNode node;
|
||||||
final String[] dependencies;
|
final String[] dependencies;
|
||||||
|
|
|
@ -59,6 +59,11 @@ public class InMemoryProgramCache implements ProgramCache {
|
||||||
newItems.clear();
|
newItems.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
cache.clear();
|
||||||
|
newItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
static final class Item {
|
static final class Item {
|
||||||
final Program program;
|
final Program program;
|
||||||
final String[] dependencies;
|
final String[] dependencies;
|
||||||
|
|
|
@ -62,4 +62,9 @@ public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheSt
|
||||||
cache.keySet().removeAll(classes);
|
cache.keySet().removeAll(classes);
|
||||||
freshClasses.removeAll(classes);
|
freshClasses.removeAll(classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
cache.clear();
|
||||||
|
freshClasses.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
dependencyAnalyzer.setAsyncSupported(target.isAsyncSupported());
|
dependencyAnalyzer.setAsyncSupported(target.isAsyncSupported());
|
||||||
dependencyAnalyzer.setInterruptor(() -> {
|
dependencyAnalyzer.setInterruptor(() -> {
|
||||||
int progress = lastKnownClasses > 0 ? dependencyAnalyzer.getReachableClasses().size() : 0;
|
int progress = lastKnownClasses > 0 ? dependencyAnalyzer.getReachableClasses().size() : 0;
|
||||||
return progressListener.progressReached(progress) == TeaVMProgressFeedback.CONTINUE;
|
cancelled |= progressListener.progressReached(progress) != TeaVMProgressFeedback.CONTINUE;
|
||||||
|
return !cancelled;
|
||||||
});
|
});
|
||||||
target.contributeDependencies(dependencyAnalyzer);
|
target.contributeDependencies(dependencyAnalyzer);
|
||||||
dependencyAnalyzer.processDependencies();
|
dependencyAnalyzer.processDependencies();
|
||||||
|
|
|
@ -34,17 +34,6 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
|
|
@ -43,17 +43,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
|
|
@ -38,17 +38,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||||
|
|
|
@ -57,17 +57,6 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
|
@ -46,6 +46,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ow2.asm</groupId>
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
@ -82,17 +83,6 @@
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>test-jar</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
|
10
pom.xml
10
pom.xml
|
@ -197,11 +197,6 @@
|
||||||
<artifactId>rhino</artifactId>
|
<artifactId>rhino</artifactId>
|
||||||
<version>${rhino.version}</version>
|
<version>${rhino.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.1.1</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
@ -286,6 +281,11 @@
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>3.0.2</version>
|
<version>3.0.2</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
|
|
|
@ -86,7 +86,7 @@ public final class BenchmarkStarter {
|
||||||
private static void render() {
|
private static void render() {
|
||||||
CanvasRenderingContext2D context = (CanvasRenderingContext2D) canvas.getContext("2d");
|
CanvasRenderingContext2D context = (CanvasRenderingContext2D) canvas.getContext("2d");
|
||||||
context.setFillStyle("white");
|
context.setFillStyle("white");
|
||||||
context.setStrokeStyle("grey");
|
context.setStrokeStyle("red");
|
||||||
context.fillRect(0, 0, 600, 600);
|
context.fillRect(0, 0, 600, 600);
|
||||||
context.save();
|
context.save();
|
||||||
context.translate(0, 600);
|
context.translate(0, 600);
|
||||||
|
|
|
@ -48,13 +48,6 @@
|
||||||
<artifactId>teavm-jso-apis</artifactId>
|
<artifactId>teavm-jso-apis</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-jso-apis</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<classifier>tests</classifier>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.teavm</groupId>
|
<groupId>org.teavm</groupId>
|
||||||
<artifactId>teavm-metaprogramming-impl</artifactId>
|
<artifactId>teavm-metaprogramming-impl</artifactId>
|
||||||
|
|
|
@ -110,18 +110,6 @@
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifest>
|
|
||||||
<mainClass>org.teavm.cli.TeaVMRunner</mainClass>
|
|
||||||
</manifest>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
@ -134,7 +122,16 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>org.teavm.cli.TeaVMRunner</mainClass>
|
||||||
|
</transformer>
|
||||||
</transformers>
|
</transformers>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.apache.commons</pattern>
|
||||||
|
<shadedPattern>org.teavm.apachecommons</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -114,7 +114,7 @@ public final class TeaVMDevServerRunner {
|
||||||
|
|
||||||
devServer.setIndicator(commandLine.hasOption("indicator"));
|
devServer.setIndicator(commandLine.hasOption("indicator"));
|
||||||
devServer.setReloadedAutomatically(commandLine.hasOption("auto-reload"));
|
devServer.setReloadedAutomatically(commandLine.hasOption("auto-reload"));
|
||||||
devServer.setVerbose(commandLine.hasOption('v'));
|
devServer.setLog(new ConsoleTeaVMToolLog(commandLine.hasOption('v')));
|
||||||
if (commandLine.hasOption("port")) {
|
if (commandLine.hasOption("port")) {
|
||||||
try {
|
try {
|
||||||
devServer.setPort(Integer.parseInt(commandLine.getOptionValue("port")));
|
devServer.setPort(Integer.parseInt(commandLine.getOptionValue("port")));
|
||||||
|
|
|
@ -15,11 +15,18 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.tooling;
|
package org.teavm.tooling;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ProgramReader;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.instructions.AbstractInstructionReader;
|
import org.teavm.model.instructions.AbstractInstructionReader;
|
||||||
|
import org.teavm.vm.TeaVM;
|
||||||
|
|
||||||
class InstructionLocationReader extends AbstractInstructionReader {
|
public class InstructionLocationReader extends AbstractInstructionReader {
|
||||||
private Set<String> resources;
|
private Set<String> resources;
|
||||||
|
|
||||||
public InstructionLocationReader(Set<String> resources) {
|
public InstructionLocationReader(Set<String> resources) {
|
||||||
|
@ -32,4 +39,32 @@ class InstructionLocationReader extends AbstractInstructionReader {
|
||||||
resources.add(location.getFileName());
|
resources.add(location.getFileName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<String> extractUsedResources(TeaVM vm) {
|
||||||
|
Set<String> resources = new LinkedHashSet<>();
|
||||||
|
ClassReaderSource classSource = vm.getDependencyClassSource();
|
||||||
|
InstructionLocationReader reader = new InstructionLocationReader(resources);
|
||||||
|
for (MethodReference methodRef : vm.getMethods()) {
|
||||||
|
ClassReader cls = classSource.get(methodRef.getClassName());
|
||||||
|
if (cls == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||||
|
if (method == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramReader program = method.getProgram();
|
||||||
|
if (program == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
program.basicBlockAt(i).readAllInstructions(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,11 +52,7 @@ import org.teavm.diagnostics.ProblemProvider;
|
||||||
import org.teavm.model.ClassHolderSource;
|
import org.teavm.model.ClassHolderSource;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
import org.teavm.model.MethodReader;
|
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
import org.teavm.model.PreOptimizingClassHolderSource;
|
import org.teavm.model.PreOptimizingClassHolderSource;
|
||||||
import org.teavm.model.ProgramReader;
|
|
||||||
import org.teavm.parsing.ClasspathClassHolderSource;
|
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||||
import org.teavm.tooling.sources.SourceFileProvider;
|
import org.teavm.tooling.sources.SourceFileProvider;
|
||||||
import org.teavm.tooling.sources.SourceFilesCopier;
|
import org.teavm.tooling.sources.SourceFilesCopier;
|
||||||
|
@ -268,31 +264,7 @@ public class TeaVMTool {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> resources = new HashSet<>();
|
return InstructionLocationReader.extractUsedResources(vm);
|
||||||
ClassReaderSource classSource = vm.getDependencyClassSource();
|
|
||||||
InstructionLocationReader reader = new InstructionLocationReader(resources);
|
|
||||||
for (MethodReference methodRef : vm.getMethods()) {
|
|
||||||
ClassReader cls = classSource.get(methodRef.getClassName());
|
|
||||||
if (cls == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
|
||||||
if (method == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgramReader program = method.getProgram();
|
|
||||||
if (program == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
|
||||||
program.basicBlockAt(i).readAllInstructions(reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resources;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
|
public void addSourceFileProvider(SourceFileProvider sourceFileProvider) {
|
||||||
|
|
|
@ -66,24 +66,6 @@
|
||||||
<artifactId>teavm-tooling</artifactId>
|
<artifactId>teavm-tooling</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-classlib</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-metaprogramming-impl</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-jso-impl</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
|
|
@ -96,8 +96,12 @@ public class CodeServlet extends HttpServlet {
|
||||||
|
|
||||||
private final Set<CodeWsEndpoint> wsEndpoints = new LinkedHashSet<>();
|
private final Set<CodeWsEndpoint> wsEndpoints = new LinkedHashSet<>();
|
||||||
private final Object statusLock = new Object();
|
private final Object statusLock = new Object();
|
||||||
|
private volatile boolean cancelRequested;
|
||||||
private boolean compiling;
|
private boolean compiling;
|
||||||
private double progress;
|
private double progress;
|
||||||
|
private boolean waiting;
|
||||||
|
private Thread buildThread;
|
||||||
|
private List<DevServerListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
public CodeServlet(String mainClass, String[] classPath) {
|
public CodeServlet(String mainClass, String[] classPath) {
|
||||||
this.mainClass = mainClass;
|
this.mainClass = mainClass;
|
||||||
|
@ -160,6 +164,37 @@ public class CodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addListener(DevServerListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidateCache() {
|
||||||
|
synchronized (statusLock) {
|
||||||
|
if (compiling) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
astCache.invalidate();
|
||||||
|
programCache.invalidate();
|
||||||
|
classSource.invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildProject() {
|
||||||
|
synchronized (statusLock) {
|
||||||
|
if (waiting) {
|
||||||
|
buildThread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelBuild() {
|
||||||
|
synchronized (statusLock) {
|
||||||
|
if (compiling) {
|
||||||
|
cancelRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String path = req.getPathInfo();
|
String path = req.getPathInfo();
|
||||||
|
@ -206,15 +241,20 @@ public class CodeServlet extends HttpServlet {
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
stopped = true;
|
stopped = true;
|
||||||
|
synchronized (statusLock) {
|
||||||
|
if (waiting) {
|
||||||
|
buildThread.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws ServletException {
|
public void init() throws ServletException {
|
||||||
super.init();
|
super.init();
|
||||||
Thread thread = new Thread(this::runTeaVM);
|
Thread thread = new Thread(this::runTeaVM);
|
||||||
thread.setDaemon(true);
|
|
||||||
thread.setName("TeaVM compiler");
|
thread.setName("TeaVM compiler");
|
||||||
thread.start();
|
thread.start();
|
||||||
|
buildThread = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean serveSourceFile(String fileName, HttpServletResponse resp) throws IOException {
|
private boolean serveSourceFile(String fileName, HttpServletResponse resp) throws IOException {
|
||||||
|
@ -306,12 +346,20 @@ public class CodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
synchronized (statusLock) {
|
||||||
|
waiting = true;
|
||||||
|
}
|
||||||
watcher.waitForChange(750);
|
watcher.waitForChange(750);
|
||||||
} catch (InterruptedException e) {
|
synchronized (statusLock) {
|
||||||
log.info("Build thread interrupted");
|
waiting = false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
log.info("Changes detected. Recompiling.");
|
log.info("Changes detected. Recompiling.");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
if (stopped) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log.info("Build triggered by user");
|
||||||
|
}
|
||||||
|
|
||||||
List<String> staleClasses = getChangedClasses(watcher.grabChangedFiles());
|
List<String> staleClasses = getChangedClasses(watcher.grabChangedFiles());
|
||||||
if (staleClasses.size() > 15) {
|
if (staleClasses.size() > 15) {
|
||||||
|
@ -325,6 +373,7 @@ public class CodeServlet extends HttpServlet {
|
||||||
|
|
||||||
classSource.evict(staleClasses);
|
classSource.evict(staleClasses);
|
||||||
}
|
}
|
||||||
|
log.info("Build process stopped");
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
log.error("Compile server crashed", e);
|
log.error("Compile server crashed", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -359,6 +408,9 @@ public class CodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildOnce() {
|
private void buildOnce() {
|
||||||
|
fireBuildStarted();
|
||||||
|
reportProgress(0);
|
||||||
|
|
||||||
DebugInformationBuilder debugInformationBuilder = new DebugInformationBuilder();
|
DebugInformationBuilder debugInformationBuilder = new DebugInformationBuilder();
|
||||||
ClassLoader classLoader = initClassLoader();
|
ClassLoader classLoader = initClassLoader();
|
||||||
classSource.setUnderlyingSource(new PreOptimizingClassHolderSource(
|
classSource.setUnderlyingSource(new PreOptimizingClassHolderSource(
|
||||||
|
@ -390,7 +442,6 @@ public class CodeServlet extends HttpServlet {
|
||||||
log.info("Starting build");
|
log.info("Starting build");
|
||||||
progressListener.last = 0;
|
progressListener.last = 0;
|
||||||
progressListener.lastTime = System.currentTimeMillis();
|
progressListener.lastTime = System.currentTimeMillis();
|
||||||
reportProgress(0);
|
|
||||||
vm.build(buildTarget, fileName);
|
vm.build(buildTarget, fileName);
|
||||||
addIndicator();
|
addIndicator();
|
||||||
generateDebug(debugInformationBuilder);
|
generateDebug(debugInformationBuilder);
|
||||||
|
@ -450,6 +501,7 @@ public class CodeServlet extends HttpServlet {
|
||||||
private void postBuild(TeaVM vm, long startTime) {
|
private void postBuild(TeaVM vm, long startTime) {
|
||||||
if (!vm.wasCancelled()) {
|
if (!vm.wasCancelled()) {
|
||||||
log.info("Recompiled stale methods: " + programCache.getPendingItemsCount());
|
log.info("Recompiled stale methods: " + programCache.getPendingItemsCount());
|
||||||
|
fireBuildComplete(vm);
|
||||||
if (vm.getProblemProvider().getSevereProblems().isEmpty()) {
|
if (vm.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||||
log.info("Build complete successfully");
|
log.info("Build complete successfully");
|
||||||
saveNewResult();
|
saveNewResult();
|
||||||
|
@ -466,11 +518,13 @@ public class CodeServlet extends HttpServlet {
|
||||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||||
} else {
|
} else {
|
||||||
log.info("Build cancelled");
|
log.info("Build cancelled");
|
||||||
|
fireBuildCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
astCache.discard();
|
astCache.discard();
|
||||||
programCache.discard();
|
programCache.discard();
|
||||||
buildTarget.clear();
|
buildTarget.clear();
|
||||||
|
cancelRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printStats(TeaVM vm, long startTime) {
|
private void printStats(TeaVM vm, long startTime) {
|
||||||
|
@ -553,6 +607,10 @@ public class CodeServlet extends HttpServlet {
|
||||||
for (CodeWsEndpoint endpoint : endpoints) {
|
for (CodeWsEndpoint endpoint : endpoints) {
|
||||||
endpoint.progress(progress);
|
endpoint.progress(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (DevServerListener listener : listeners) {
|
||||||
|
listener.compilationProgress(progress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportCompilationComplete(boolean success) {
|
private void reportCompilationComplete(boolean success) {
|
||||||
|
@ -573,6 +631,25 @@ public class CodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fireBuildStarted() {
|
||||||
|
for (DevServerListener listener : listeners) {
|
||||||
|
listener.compilationStarted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireBuildCancelled() {
|
||||||
|
for (DevServerListener listener : listeners) {
|
||||||
|
listener.compilationCancelled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireBuildComplete(TeaVM vm) {
|
||||||
|
CodeServletBuildResult result = new CodeServletBuildResult(vm, new ArrayList<>(buildTarget.getNames()));
|
||||||
|
for (DevServerListener listener : listeners) {
|
||||||
|
listener.compilationComplete(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final ProgressListenerImpl progressListener = new ProgressListenerImpl();
|
private final ProgressListenerImpl progressListener = new ProgressListenerImpl();
|
||||||
|
|
||||||
class ProgressListenerImpl implements TeaVMProgressListener {
|
class ProgressListenerImpl implements TeaVMProgressListener {
|
||||||
|
@ -622,6 +699,11 @@ public class CodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TeaVMProgressFeedback getResult() {
|
private TeaVMProgressFeedback getResult() {
|
||||||
|
if (cancelRequested) {
|
||||||
|
log.info("Trying to cancel compilation due to user request");
|
||||||
|
return TeaVMProgressFeedback.CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
log.info("Trying to cancel compilation due to server stopping");
|
log.info("Trying to cancel compilation due to server stopping");
|
||||||
return TeaVMProgressFeedback.CANCEL;
|
return TeaVMProgressFeedback.CANCEL;
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.devserver;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.callgraph.CallGraph;
|
||||||
|
import org.teavm.diagnostics.ProblemProvider;
|
||||||
|
import org.teavm.tooling.InstructionLocationReader;
|
||||||
|
import org.teavm.tooling.builder.BuildResult;
|
||||||
|
import org.teavm.vm.TeaVM;
|
||||||
|
|
||||||
|
class CodeServletBuildResult implements BuildResult {
|
||||||
|
private TeaVM vm;
|
||||||
|
private List<String> generatedFiles;
|
||||||
|
private Collection<String> usedResources;
|
||||||
|
|
||||||
|
public CodeServletBuildResult(TeaVM vm, List<String> generatedFiles) {
|
||||||
|
this.vm = vm;
|
||||||
|
this.generatedFiles = generatedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CallGraph getCallGraph() {
|
||||||
|
return vm.getDependencyInfo().getCallGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProblemProvider getProblems() {
|
||||||
|
return vm.getProblemProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getUsedResources() {
|
||||||
|
if (usedResources == null) {
|
||||||
|
usedResources = InstructionLocationReader.extractUsedResources(vm);
|
||||||
|
}
|
||||||
|
return usedResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getClasses() {
|
||||||
|
return vm.getClasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getGeneratedFiles() {
|
||||||
|
return generatedFiles;
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,6 @@ import org.eclipse.jetty.server.ServerConnector;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||||
import org.teavm.tooling.ConsoleTeaVMToolLog;
|
|
||||||
import org.teavm.tooling.TeaVMToolLog;
|
import org.teavm.tooling.TeaVMToolLog;
|
||||||
|
|
||||||
public class DevServer {
|
public class DevServer {
|
||||||
|
@ -41,8 +40,9 @@ public class DevServer {
|
||||||
private List<String> sourcePath = new ArrayList<>();
|
private List<String> sourcePath = new ArrayList<>();
|
||||||
private boolean indicator;
|
private boolean indicator;
|
||||||
private boolean reloadedAutomatically;
|
private boolean reloadedAutomatically;
|
||||||
private boolean verbose;
|
|
||||||
private TeaVMToolLog log;
|
private TeaVMToolLog log;
|
||||||
|
private CodeServlet servlet;
|
||||||
|
private List<DevServerListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
private Server server;
|
private Server server;
|
||||||
private int port = 9090;
|
private int port = 9090;
|
||||||
|
@ -85,16 +85,27 @@ public class DevServer {
|
||||||
this.reloadedAutomatically = reloadedAutomatically;
|
this.reloadedAutomatically = reloadedAutomatically;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVerbose(boolean verbose) {
|
|
||||||
this.verbose = verbose;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getSourcePath() {
|
public List<String> getSourcePath() {
|
||||||
return sourcePath;
|
return sourcePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void invalidateCache() {
|
||||||
|
servlet.invalidateCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildProject() {
|
||||||
|
servlet.buildProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelBuild() {
|
||||||
|
servlet.cancelBuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(DevServerListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
log = new ConsoleTeaVMToolLog(verbose);
|
|
||||||
server = new Server();
|
server = new Server();
|
||||||
ServerConnector connector = new ServerConnector(server);
|
ServerConnector connector = new ServerConnector(server);
|
||||||
connector.setPort(port);
|
connector.setPort(port);
|
||||||
|
@ -103,7 +114,7 @@ public class DevServer {
|
||||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
context.setContextPath("/");
|
context.setContextPath("/");
|
||||||
server.setHandler(context);
|
server.setHandler(context);
|
||||||
CodeServlet servlet = new CodeServlet(mainClass, classPath);
|
servlet = new CodeServlet(mainClass, classPath);
|
||||||
servlet.setFileName(fileName);
|
servlet.setFileName(fileName);
|
||||||
servlet.setPathToFile(pathToFile);
|
servlet.setPathToFile(pathToFile);
|
||||||
servlet.setLog(log);
|
servlet.setLog(log);
|
||||||
|
@ -111,6 +122,9 @@ public class DevServer {
|
||||||
servlet.setIndicator(indicator);
|
servlet.setIndicator(indicator);
|
||||||
servlet.setAutomaticallyReloaded(reloadedAutomatically);
|
servlet.setAutomaticallyReloaded(reloadedAutomatically);
|
||||||
servlet.setPort(port);
|
servlet.setPort(port);
|
||||||
|
for (DevServerListener listener : listeners) {
|
||||||
|
servlet.addListener(listener);
|
||||||
|
}
|
||||||
context.addServlet(new ServletHolder(servlet), "/*");
|
context.addServlet(new ServletHolder(servlet), "/*");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -129,6 +143,8 @@ public class DevServer {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
server = null;
|
||||||
|
servlet = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DevServerEndpointConfig implements ServerEndpointConfig {
|
private class DevServerEndpointConfig implements ServerEndpointConfig {
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.devserver;
|
||||||
|
|
||||||
|
import org.teavm.tooling.builder.BuildResult;
|
||||||
|
|
||||||
|
public interface DevServerListener {
|
||||||
|
void compilationStarted();
|
||||||
|
|
||||||
|
void compilationProgress(double progress);
|
||||||
|
|
||||||
|
void compilationComplete(BuildResult result);
|
||||||
|
|
||||||
|
void compilationCancelled();
|
||||||
|
}
|
|
@ -44,23 +44,21 @@
|
||||||
<groupId>org.teavm</groupId>
|
<groupId>org.teavm</groupId>
|
||||||
<artifactId>teavm-tooling</artifactId>
|
<artifactId>teavm-tooling</artifactId>
|
||||||
<version>${teavm.version}</version>
|
<version>${teavm.version}</version>
|
||||||
<exclusions>
|
</dependency>
|
||||||
<exclusion>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.teavm</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>teavm-devserver</artifactId>
|
||||||
</exclusion>
|
<version>${teavm.version}</version>
|
||||||
</exclusions>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.teavm</groupId>
|
||||||
|
<artifactId>teavm-classlib</artifactId>
|
||||||
|
<version>${teavm.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.teavm</groupId>
|
<groupId>org.teavm</groupId>
|
||||||
<artifactId>teavm-chrome-rdp</artifactId>
|
<artifactId>teavm-chrome-rdp</artifactId>
|
||||||
<version>${teavm.version}</version>
|
<version>${teavm.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -125,6 +123,36 @@
|
||||||
</atrifactSet>
|
</atrifactSet>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<outputFile>dependencies/teavm.jar</outputFile>
|
<outputFile>dependencies/teavm.jar</outputFile>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.google.gson</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.gson</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.jcraft.jzlib</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.jzlib</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.eclipse.jetty</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.jetty</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.joda.time</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.jodatime</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.objectweb.asm</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.jetty.asm</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.slf4j</pattern>
|
||||||
|
<shadedPattern>org.teavm.shade.slf4j</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.apache.commons</pattern>
|
||||||
|
<shadedPattern>org.teavm.apachecommons</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
|
@ -24,13 +24,16 @@ import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.teavm.idea.devserver.DevServerRunner;
|
||||||
import org.teavm.tooling.daemon.BuildDaemon;
|
import org.teavm.tooling.daemon.BuildDaemon;
|
||||||
|
|
||||||
public final class DaemonUtil {
|
public final class DaemonUtil {
|
||||||
private static final Set<String> PLUGIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
|
private static final Set<String> PLUGIN_FILES = new HashSet<>(Arrays.asList("teavm-jps-common.jar",
|
||||||
"teavm-plugin.jar", "teavm.jar"));
|
"teavm-plugin.jar", "teavm.jar"));
|
||||||
private static final String DAEMON_CLASS = BuildDaemon.class.getName().replace('.', '/') + ".class";
|
private static final String DAEMON_CLASS = BuildDaemon.class.getName().replace('.', '/') + ".class";
|
||||||
|
private static final String DEV_SERVER_CLASS = DevServerRunner.class.getName().replace('.', '/') + ".class";
|
||||||
private static final int DAEMON_CLASS_DEPTH;
|
private static final int DAEMON_CLASS_DEPTH;
|
||||||
|
private static final int DEV_SERVER_CLASS_DEPTH;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
@ -40,6 +43,14 @@ public final class DaemonUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DAEMON_CLASS_DEPTH = depth;
|
DAEMON_CLASS_DEPTH = depth;
|
||||||
|
|
||||||
|
depth = 0;
|
||||||
|
for (int i = 0; i < DEV_SERVER_CLASS.length(); ++i) {
|
||||||
|
if (DEV_SERVER_CLASS.charAt(i) == '/') {
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEV_SERVER_CLASS_DEPTH = depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DaemonUtil() {
|
private DaemonUtil() {
|
||||||
|
@ -64,6 +75,11 @@ public final class DaemonUtil {
|
||||||
file = file.getParentFile();
|
file = file.getParentFile();
|
||||||
}
|
}
|
||||||
targetFiles.add(file.getAbsolutePath());
|
targetFiles.add(file.getAbsolutePath());
|
||||||
|
} else if (file.getPath().endsWith(DEV_SERVER_CLASS)) {
|
||||||
|
for (int i = 0; i <= DEV_SERVER_CLASS_DEPTH; ++i) {
|
||||||
|
file = file.getParentFile();
|
||||||
|
}
|
||||||
|
targetFiles.add(file.getAbsolutePath());
|
||||||
} else if (file.isDirectory()) {
|
} else if (file.isDirectory()) {
|
||||||
for (File childFile : file.listFiles()) {
|
for (File childFile : file.listFiles()) {
|
||||||
findInHierarchy(childFile, targetFiles, visited);
|
findInHierarchy(childFile, targetFiles, visited);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea;
|
||||||
|
|
||||||
|
public interface DevServerRunnerListener {
|
||||||
|
void error(String text);
|
||||||
|
|
||||||
|
void info(String text);
|
||||||
|
|
||||||
|
void stopped(int code);
|
||||||
|
}
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.idea.debug;
|
package org.teavm.idea.debug;
|
||||||
|
|
||||||
import com.intellij.execution.ExecutionException;
|
|
||||||
import com.intellij.execution.Executor;
|
import com.intellij.execution.Executor;
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory;
|
import com.intellij.execution.configurations.ConfigurationFactory;
|
||||||
import com.intellij.execution.configurations.LocatableConfigurationBase;
|
import com.intellij.execution.configurations.LocatableConfigurationBase;
|
||||||
|
@ -45,8 +44,7 @@ public class TeaVMDebugConfiguration extends LocatableConfigurationBase
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws
|
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
|
||||||
ExecutionException {
|
|
||||||
return new TeaVMRunState(environment, port);
|
return new TeaVMRunState(environment, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.callgraph.CallGraph;
|
||||||
|
import org.teavm.diagnostics.Problem;
|
||||||
|
|
||||||
|
public class DevServerBuildResult implements Serializable {
|
||||||
|
public CallGraph callGraph;
|
||||||
|
public final List<Problem> problems = new ArrayList<>();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
public class DevServerConfiguration {
|
||||||
|
public String javaHome;
|
||||||
|
public int maxHeap;
|
||||||
|
public String mainClass;
|
||||||
|
public String[] classPath;
|
||||||
|
public String[] sourcePath;
|
||||||
|
public boolean indicator;
|
||||||
|
public boolean autoReload;
|
||||||
|
public int port;
|
||||||
|
public String pathToFile;
|
||||||
|
public String fileName;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
public class DevServerInfo {
|
||||||
|
public final int port;
|
||||||
|
public final DevServerManager server;
|
||||||
|
public final Process process;
|
||||||
|
|
||||||
|
DevServerInfo(int port, DevServerManager server, Process process) {
|
||||||
|
this.port = port;
|
||||||
|
this.server = server;
|
||||||
|
this.process = process;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import java.rmi.Remote;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
|
||||||
|
public interface DevServerManager extends Remote {
|
||||||
|
String ID = "TeaVM-BuildServer";
|
||||||
|
|
||||||
|
void stop() throws RemoteException;
|
||||||
|
|
||||||
|
void invalidateCache() throws RemoteException;
|
||||||
|
|
||||||
|
void buildProject() throws RemoteException;
|
||||||
|
|
||||||
|
void cancelBuild() throws RemoteException;
|
||||||
|
|
||||||
|
void addListener(DevServerManagerListener listener) throws RemoteException;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import java.rmi.Remote;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
|
||||||
|
public interface DevServerManagerListener extends Remote {
|
||||||
|
void compilationStarted() throws RemoteException;
|
||||||
|
|
||||||
|
void compilationProgress(double progress) throws RemoteException;
|
||||||
|
|
||||||
|
void compilationComplete(DevServerBuildResult result) throws RemoteException;
|
||||||
|
|
||||||
|
void compilationCancelled() throws RemoteException;
|
||||||
|
}
|
|
@ -0,0 +1,308 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.rmi.AlreadyBoundException;
|
||||||
|
import java.rmi.NoSuchObjectException;
|
||||||
|
import java.rmi.NotBoundException;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.rmi.registry.LocateRegistry;
|
||||||
|
import java.rmi.registry.Registry;
|
||||||
|
import java.rmi.server.UnicastRemoteObject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import org.teavm.devserver.DevServer;
|
||||||
|
import org.teavm.devserver.DevServerListener;
|
||||||
|
import org.teavm.idea.DevServerRunnerListener;
|
||||||
|
import org.teavm.tooling.ConsoleTeaVMToolLog;
|
||||||
|
import org.teavm.tooling.builder.BuildResult;
|
||||||
|
|
||||||
|
public class DevServerRunner extends UnicastRemoteObject implements DevServerManager {
|
||||||
|
private static final int MIN_PORT = 10000;
|
||||||
|
private static final int MAX_PORT = 1 << 16;
|
||||||
|
private static final String PORT_MESSAGE_PREFIX = "Build server port: ";
|
||||||
|
private static final String DEBUG_PORT_PROPERTY = "teavm.server.debug.port";
|
||||||
|
private int port;
|
||||||
|
private Registry registry;
|
||||||
|
private DevServer server;
|
||||||
|
private List<DevServerManagerListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
|
private DevServerRunner(DevServer server) throws RemoteException {
|
||||||
|
super();
|
||||||
|
Random random = new Random();
|
||||||
|
for (int i = 0; i < 20; ++i) {
|
||||||
|
port = random.nextInt(MAX_PORT - MIN_PORT) + MIN_PORT;
|
||||||
|
try {
|
||||||
|
registry = LocateRegistry.createRegistry(port);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
registry.bind(ID, this);
|
||||||
|
} catch (RemoteException | AlreadyBoundException e) {
|
||||||
|
throw new IllegalStateException("Could not bind remote service", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.server = server;
|
||||||
|
server.addListener(devServerListener);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Could not create RMI registry");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCache() {
|
||||||
|
server.invalidateCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildProject() {
|
||||||
|
server.buildProject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelBuild() {
|
||||||
|
server.cancelBuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(DevServerManagerListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
DevServer server = new DevServer();
|
||||||
|
server.setLog(new ConsoleTeaVMToolLog(true));
|
||||||
|
server.setMainClass(args[0]);
|
||||||
|
List<String> classPath = new ArrayList<>();
|
||||||
|
for (int i = 1; i < args.length; ++i) {
|
||||||
|
switch (args[i]) {
|
||||||
|
case "-c":
|
||||||
|
classPath.add(args[++i]);
|
||||||
|
break;
|
||||||
|
case "-s":
|
||||||
|
server.getSourcePath().add(args[++i]);
|
||||||
|
break;
|
||||||
|
case "-i":
|
||||||
|
server.setIndicator(true);
|
||||||
|
break;
|
||||||
|
case "-a":
|
||||||
|
server.setReloadedAutomatically(true);
|
||||||
|
break;
|
||||||
|
case "-p":
|
||||||
|
server.setPort(Integer.parseInt(args[++i]));
|
||||||
|
break;
|
||||||
|
case "-d":
|
||||||
|
server.setPathToFile(args[++i]);
|
||||||
|
break;
|
||||||
|
case "-f":
|
||||||
|
server.setFileName(args[++i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.setClassPath(classPath.toArray(new String[0]));
|
||||||
|
|
||||||
|
DevServerRunner daemon = new DevServerRunner(server);
|
||||||
|
System.out.println(PORT_MESSAGE_PREFIX + daemon.port);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
daemon.registry.unbind(ID);
|
||||||
|
UnicastRemoteObject.unexportObject(daemon, true);
|
||||||
|
} catch (NoSuchObjectException e) {
|
||||||
|
throw new IllegalStateException("Could not shutdown RMI registry", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DevServerInfo start(String[] classPathEntries, DevServerConfiguration options,
|
||||||
|
DevServerRunnerListener listener) throws IOException {
|
||||||
|
String javaCommand = options.javaHome + "/bin/java";
|
||||||
|
String classPath = String.join(File.pathSeparator, classPathEntries);
|
||||||
|
List<String> arguments = new ArrayList<>();
|
||||||
|
|
||||||
|
arguments.addAll(Arrays.asList(javaCommand, "-cp", classPath, "-Xmx" + options.maxHeap + "m"));
|
||||||
|
|
||||||
|
String debugPort = System.getProperty(DEBUG_PORT_PROPERTY);
|
||||||
|
if (debugPort != null) {
|
||||||
|
arguments.add("-agentlib:jdwp=transport=dt_socket,quiet=y,server=y,address=" + debugPort + ",suspend=y");
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.add(DevServerRunner.class.getName());
|
||||||
|
arguments.add(options.mainClass);
|
||||||
|
|
||||||
|
if (options.indicator) {
|
||||||
|
arguments.add("-i");
|
||||||
|
}
|
||||||
|
if (options.autoReload) {
|
||||||
|
arguments.add("-a");
|
||||||
|
}
|
||||||
|
arguments.add("-d");
|
||||||
|
arguments.add(options.pathToFile);
|
||||||
|
arguments.add("-f");
|
||||||
|
arguments.add(options.fileName);
|
||||||
|
arguments.add("-p");
|
||||||
|
arguments.add(Integer.toString(options.port));
|
||||||
|
|
||||||
|
for (String entry : options.classPath) {
|
||||||
|
arguments.add("-c");
|
||||||
|
arguments.add(entry);
|
||||||
|
}
|
||||||
|
for (String entry : options.sourcePath) {
|
||||||
|
arguments.add("-s");
|
||||||
|
arguments.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBuilder builder = new ProcessBuilder(arguments.toArray(new String[0]));
|
||||||
|
Process process = builder.start();
|
||||||
|
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream(),
|
||||||
|
StandardCharsets.UTF_8));
|
||||||
|
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream(),
|
||||||
|
StandardCharsets.UTF_8));
|
||||||
|
String line = stdoutReader.readLine();
|
||||||
|
if (line == null || !line.startsWith(PORT_MESSAGE_PREFIX)) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (true) {
|
||||||
|
line = stderrReader.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.append(line).append('\n');
|
||||||
|
}
|
||||||
|
stderrReader.close();
|
||||||
|
stdoutReader.close();
|
||||||
|
process.destroy();
|
||||||
|
throw new IllegalStateException("Could not start daemon. Stderr: " + sb);
|
||||||
|
}
|
||||||
|
int port = Integer.parseInt(line.substring(PORT_MESSAGE_PREFIX.length()));
|
||||||
|
|
||||||
|
daemonThread("TeaVM devserver stdout", new ProcessOutputWatcher(stdoutReader, listener::info)).start();
|
||||||
|
daemonThread("TeaVM devserver stderr", new ProcessOutputWatcher(stderrReader, listener::error)).start();
|
||||||
|
daemonThread("TeaVM devserver monitor", () -> {
|
||||||
|
int exitCode;
|
||||||
|
try {
|
||||||
|
exitCode = process.waitFor();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listener.stopped(exitCode);
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
DevServerManager service;
|
||||||
|
try {
|
||||||
|
Registry registry = LocateRegistry.getRegistry(port);
|
||||||
|
service = (DevServerManager) registry.lookup(ID);
|
||||||
|
} catch (RemoteException | NotBoundException e) {
|
||||||
|
throw new RuntimeException("Error connecting TeaVM process", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DevServerInfo(port, service, process);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Thread daemonThread(String name, Runnable runnable) {
|
||||||
|
Thread thread = new Thread(runnable);
|
||||||
|
thread.setName(name);
|
||||||
|
thread.setDaemon(true);
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ProcessOutputWatcher implements Runnable {
|
||||||
|
private BufferedReader reader;
|
||||||
|
private Consumer<String> consumer;
|
||||||
|
|
||||||
|
ProcessOutputWatcher(BufferedReader reader, Consumer<String> consumer) {
|
||||||
|
this.reader = reader;
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
consumer.accept(line);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final DevServerListener devServerListener = new DevServerListener() {
|
||||||
|
@Override
|
||||||
|
public void compilationStarted() {
|
||||||
|
for (DevServerManagerListener listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.compilationStarted();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void compilationProgress(double v) {
|
||||||
|
for (DevServerManagerListener listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.compilationProgress(v);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void compilationComplete(BuildResult buildResult) {
|
||||||
|
DevServerBuildResult result = new DevServerBuildResult();
|
||||||
|
result.callGraph = buildResult.getCallGraph();
|
||||||
|
result.problems.addAll(buildResult.getProblems().getProblems());
|
||||||
|
for (DevServerManagerListener listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.compilationComplete(result);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void compilationCancelled() {
|
||||||
|
for (DevServerManagerListener listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.compilationCancelled();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import com.intellij.execution.Executor;
|
||||||
|
import com.intellij.execution.configurations.ConfigurationFactory;
|
||||||
|
import com.intellij.execution.configurations.ModuleBasedConfiguration;
|
||||||
|
import com.intellij.execution.configurations.RunConfiguration;
|
||||||
|
import com.intellij.execution.configurations.RunConfigurationModule;
|
||||||
|
import com.intellij.execution.configurations.RunProfileState;
|
||||||
|
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||||
|
import com.intellij.facet.FacetManager;
|
||||||
|
import com.intellij.openapi.module.Module;
|
||||||
|
import com.intellij.openapi.module.ModuleManager;
|
||||||
|
import com.intellij.openapi.options.SettingsEditor;
|
||||||
|
import com.intellij.openapi.util.InvalidDataException;
|
||||||
|
import com.intellij.openapi.util.WriteExternalException;
|
||||||
|
import com.intellij.util.xmlb.XmlSerializer;
|
||||||
|
import com.intellij.util.xmlb.annotations.Property;
|
||||||
|
import com.intellij.util.xmlb.annotations.Tag;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import org.jdom.Element;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.teavm.idea.TeaVMFacetType;
|
||||||
|
import org.teavm.idea.devserver.ui.TeaVMDevServerSettingsEditor;
|
||||||
|
|
||||||
|
public class TeaVMDevServerConfiguration
|
||||||
|
extends ModuleBasedConfiguration<RunConfigurationModule> {
|
||||||
|
private String mainClass = "";
|
||||||
|
private String jdkPath;
|
||||||
|
private int port = 9090;
|
||||||
|
private String pathToFile = "";
|
||||||
|
private String fileName = "classes.js";
|
||||||
|
private boolean indicator = true;
|
||||||
|
private boolean automaticallyReloaded;
|
||||||
|
private int maxHeap = 1024;
|
||||||
|
|
||||||
|
public TeaVMDevServerConfiguration(
|
||||||
|
@NotNull RunConfigurationModule configurationModule,
|
||||||
|
@NotNull ConfigurationFactory factory) {
|
||||||
|
super("TeaVM dev server", configurationModule, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Module> getValidModules() {
|
||||||
|
Module[] modules = ModuleManager.getInstance(getProject()).getModules();
|
||||||
|
List<Module> validModules = new ArrayList<>();
|
||||||
|
for (Module module : modules) {
|
||||||
|
FacetManager facetManager = FacetManager.getInstance(module);
|
||||||
|
if (facetManager.getFacetByType(TeaVMFacetType.TYPE_ID) != null) {
|
||||||
|
validModules.add(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return validModules;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readExternal(@NotNull Element element) throws InvalidDataException {
|
||||||
|
super.readExternal(element);
|
||||||
|
|
||||||
|
Element child = element.getChild("teavm");
|
||||||
|
if (child != null) {
|
||||||
|
XmlSerializer.deserializeInto(this, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeExternal(@NotNull Element element) throws WriteExternalException {
|
||||||
|
super.writeExternal(element);
|
||||||
|
|
||||||
|
Element child = element.getChild("teavm");
|
||||||
|
if (child == null) {
|
||||||
|
child = new Element("teavm");
|
||||||
|
element.addContent(child);
|
||||||
|
}
|
||||||
|
XmlSerializer.serializeInto(this, child, (accessor, bean) ->
|
||||||
|
!accessor.getName().equals("isAllowRunningInParallel"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
|
||||||
|
return new TeaVMDevServerSettingsEditor(getProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
|
||||||
|
return new TeaVMDevServerRunState(environment, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public String getMainClass() {
|
||||||
|
return mainClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMainClass(String mainClass) {
|
||||||
|
this.mainClass = mainClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public String getJdkPath() {
|
||||||
|
return jdkPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJdkPath(String jdkPath) {
|
||||||
|
this.jdkPath = jdkPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public String getPathToFile() {
|
||||||
|
return pathToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathToFile(String pathToFile) {
|
||||||
|
this.pathToFile = pathToFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public boolean isIndicator() {
|
||||||
|
return indicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndicator(boolean indicator) {
|
||||||
|
this.indicator = indicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public boolean isAutomaticallyReloaded() {
|
||||||
|
return automaticallyReloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomaticallyReloaded(boolean automaticallyReloaded) {
|
||||||
|
this.automaticallyReloaded = automaticallyReloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Property
|
||||||
|
@Tag
|
||||||
|
public int getMaxHeap() {
|
||||||
|
return maxHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxHeap(int maxHeap) {
|
||||||
|
this.maxHeap = maxHeap;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import com.intellij.execution.configurations.ConfigurationFactory;
|
||||||
|
import com.intellij.execution.configurations.ConfigurationTypeBase;
|
||||||
|
import com.intellij.execution.configurations.RunConfiguration;
|
||||||
|
import com.intellij.execution.configurations.RunConfigurationModule;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.IconLoader;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class TeaVMDevServerConfigurationType extends ConfigurationTypeBase {
|
||||||
|
public TeaVMDevServerConfigurationType() {
|
||||||
|
super("TeaVMDevServerConfiguration", "TeaVM development server", "TeaVM development server"
|
||||||
|
+ "agent", IconLoader.getIcon("/teavm-16.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ConfigurationFactory factory = new ConfigurationFactory(this) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public RunConfiguration createTemplateConfiguration(@NotNull Project project) {
|
||||||
|
return new TeaVMDevServerConfiguration(new RunConfigurationModule(project), this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigurationFactory[] getConfigurationFactories() {
|
||||||
|
return new ConfigurationFactory[] { factory };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import com.intellij.execution.DefaultExecutionResult;
|
||||||
|
import com.intellij.execution.ExecutionException;
|
||||||
|
import com.intellij.execution.ExecutionResult;
|
||||||
|
import com.intellij.execution.Executor;
|
||||||
|
import com.intellij.execution.configurations.RunProfileState;
|
||||||
|
import com.intellij.execution.configurations.SearchScopeProvider;
|
||||||
|
import com.intellij.execution.filters.TextConsoleBuilder;
|
||||||
|
import com.intellij.execution.filters.TextConsoleBuilderFactory;
|
||||||
|
import com.intellij.execution.process.ProcessHandler;
|
||||||
|
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||||
|
import com.intellij.execution.runners.ProgramRunner;
|
||||||
|
import com.intellij.execution.ui.ConsoleView;
|
||||||
|
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||||
|
import com.intellij.execution.util.JavaParametersUtil;
|
||||||
|
import com.intellij.openapi.module.Module;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk;
|
||||||
|
import com.intellij.openapi.roots.OrderEnumerator;
|
||||||
|
import com.intellij.openapi.vfs.JarFileSystem;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.teavm.idea.DaemonUtil;
|
||||||
|
import org.teavm.idea.DevServerRunnerListener;
|
||||||
|
|
||||||
|
public class TeaVMDevServerRunState implements RunProfileState {
|
||||||
|
private final TeaVMDevServerConfiguration configuration;
|
||||||
|
private final TextConsoleBuilder consoleBuilder;
|
||||||
|
|
||||||
|
public TeaVMDevServerRunState(@NotNull ExecutionEnvironment environment,
|
||||||
|
@NotNull TeaVMDevServerConfiguration configuration) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
|
||||||
|
Project project = environment.getProject();
|
||||||
|
GlobalSearchScope searchScope = SearchScopeProvider.createSearchScope(project, environment.getRunProfile());
|
||||||
|
consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project, searchScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
|
||||||
|
DevServerConfiguration config = new DevServerConfiguration();
|
||||||
|
Module module = configuration.getConfigurationModule().getModule();
|
||||||
|
|
||||||
|
Sdk moduleSdk = JavaParametersUtil.createModuleJdk(module, true, configuration.getJdkPath());
|
||||||
|
config.javaHome = moduleSdk.getHomePath();
|
||||||
|
OrderEnumerator enumerator = OrderEnumerator.orderEntries(module).withoutSdk().recursively();
|
||||||
|
config.classPath = Arrays.stream(enumerator.getClassesRoots())
|
||||||
|
.map(this::path)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
config.sourcePath = Arrays.stream(enumerator.getSourceRoots())
|
||||||
|
.map(this::path)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
config.pathToFile = configuration.getPathToFile();
|
||||||
|
config.fileName = configuration.getFileName();
|
||||||
|
config.port = configuration.getPort();
|
||||||
|
config.indicator = configuration.isIndicator();
|
||||||
|
config.autoReload = configuration.isAutomaticallyReloaded();
|
||||||
|
config.mainClass = configuration.getMainClass();
|
||||||
|
config.maxHeap = configuration.getMaxHeap();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ConsoleView console = consoleBuilder.getConsole();
|
||||||
|
ProcessHandlerImpl processHandler = new ProcessHandlerImpl(config, console);
|
||||||
|
console.attachToProcess(processHandler);
|
||||||
|
processHandler.start();
|
||||||
|
return new DefaultExecutionResult(console, processHandler);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String path(VirtualFile file) {
|
||||||
|
while (file.getFileSystem() instanceof JarFileSystem) {
|
||||||
|
file = ((JarFileSystem) file.getFileSystem()).getLocalByEntry(file);
|
||||||
|
if (file == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file.getCanonicalPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProcessHandlerImpl extends ProcessHandler implements DevServerRunnerListener {
|
||||||
|
private DevServerConfiguration config;
|
||||||
|
private ConsoleView console;
|
||||||
|
private DevServerInfo info;
|
||||||
|
|
||||||
|
ProcessHandlerImpl(DevServerConfiguration config, ConsoleView console) {
|
||||||
|
this.config = config;
|
||||||
|
this.console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() throws IOException {
|
||||||
|
info = DevServerRunner.start(DaemonUtil.detectClassPath().toArray(new String[0]), config, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void destroyProcessImpl() {
|
||||||
|
info.process.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void detachProcessImpl() {
|
||||||
|
try {
|
||||||
|
info.server.stop();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean detachIsDefault() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public OutputStream getProcessInput() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(String text) {
|
||||||
|
console.print(text + System.lineSeparator(), ConsoleViewContentType.ERROR_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void info(String text) {
|
||||||
|
console.print(text + System.lineSeparator(), ConsoleViewContentType.NORMAL_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopped(int code) {
|
||||||
|
notifyProcessTerminated(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver;
|
||||||
|
|
||||||
|
import com.intellij.execution.ExecutionException;
|
||||||
|
import com.intellij.execution.ExecutionResult;
|
||||||
|
import com.intellij.execution.configurations.RunProfile;
|
||||||
|
import com.intellij.execution.configurations.RunProfileState;
|
||||||
|
import com.intellij.execution.configurations.RunnerSettings;
|
||||||
|
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||||
|
import com.intellij.execution.runners.GenericProgramRunner;
|
||||||
|
import com.intellij.execution.ui.RunContentDescriptor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class TeaVMDevServerRunner extends GenericProgramRunner<RunnerSettings> {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getRunnerId() {
|
||||||
|
return "TeaVMDevServerRunner";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
|
||||||
|
return profile instanceof TeaVMDevServerConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected RunContentDescriptor doExecute(@NotNull RunProfileState state,
|
||||||
|
@NotNull ExecutionEnvironment environment) throws ExecutionException {
|
||||||
|
ExecutionResult executionResult = state.execute(environment.getExecutor(), environment.getRunner());
|
||||||
|
if (executionResult == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver.ui;
|
||||||
|
|
||||||
|
import com.intellij.openapi.options.SettingsEditor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.teavm.idea.devserver.TeaVMDevServerConfiguration;
|
||||||
|
|
||||||
|
public class TeaVMDevServerSettingsEditor extends SettingsEditor<TeaVMDevServerConfiguration> {
|
||||||
|
private final Project project;
|
||||||
|
private TeaVMDevServerSettingsPanel panel;
|
||||||
|
|
||||||
|
public TeaVMDevServerSettingsEditor(Project project) {
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void resetEditorFrom(@NotNull TeaVMDevServerConfiguration s) {
|
||||||
|
if (panel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.load(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyEditorTo(@NotNull TeaVMDevServerConfiguration s) {
|
||||||
|
if (panel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.save(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void disposeEditor() {
|
||||||
|
if (panel != null) {
|
||||||
|
panel = null;
|
||||||
|
}
|
||||||
|
super.disposeEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected JComponent createEditor() {
|
||||||
|
if (panel == null) {
|
||||||
|
panel = new TeaVMDevServerSettingsPanel(project);
|
||||||
|
}
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.idea.devserver.ui;
|
||||||
|
|
||||||
|
import com.intellij.application.options.ModuleDescriptionsComboBox;
|
||||||
|
import com.intellij.execution.configurations.ConfigurationUtil;
|
||||||
|
import com.intellij.execution.ui.ConfigurationModuleSelector;
|
||||||
|
import com.intellij.execution.ui.DefaultJreSelector;
|
||||||
|
import com.intellij.execution.ui.JrePathEditor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.psi.JavaCodeFragment;
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.util.PsiMethodUtil;
|
||||||
|
import com.intellij.ui.EditorTextFieldWithBrowseButton;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import org.teavm.idea.devserver.TeaVMDevServerConfiguration;
|
||||||
|
|
||||||
|
public class TeaVMDevServerSettingsPanel extends JPanel {
|
||||||
|
private final JrePathEditor jrePathEditor;
|
||||||
|
|
||||||
|
private final ModuleDescriptionsComboBox moduleField;
|
||||||
|
private final ConfigurationModuleSelector moduleSelector;
|
||||||
|
|
||||||
|
private EditorTextFieldWithBrowseButton mainClassField;
|
||||||
|
|
||||||
|
private JFormattedTextField portField;
|
||||||
|
private JTextField pathToFileField;
|
||||||
|
private JTextField fileNameField;
|
||||||
|
private JCheckBox indicatorField;
|
||||||
|
private JCheckBox autoReloadField;
|
||||||
|
private JFormattedTextField maxHeapField;
|
||||||
|
|
||||||
|
public TeaVMDevServerSettingsPanel(Project project) {
|
||||||
|
moduleField = new ModuleDescriptionsComboBox();
|
||||||
|
moduleSelector = new ConfigurationModuleSelector(project, moduleField);
|
||||||
|
|
||||||
|
JavaCodeFragment.VisibilityChecker visibilityChecker = (declaration, place) -> {
|
||||||
|
if (declaration instanceof PsiClass) {
|
||||||
|
PsiClass cls = (PsiClass) declaration;
|
||||||
|
if (ConfigurationUtil.MAIN_CLASS.value(cls) && PsiMethodUtil.findMainMethod(cls) != null
|
||||||
|
|| place.getParent() != null && moduleSelector.findClass(cls.getQualifiedName()) != null) {
|
||||||
|
return JavaCodeFragment.VisibilityChecker.Visibility.VISIBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JavaCodeFragment.VisibilityChecker.Visibility.NOT_VISIBLE;
|
||||||
|
};
|
||||||
|
mainClassField = new EditorTextFieldWithBrowseButton(project, true, visibilityChecker);
|
||||||
|
mainClassField.setButtonEnabled(true);
|
||||||
|
|
||||||
|
jrePathEditor = new JrePathEditor(DefaultJreSelector.fromSourceRootsDependencies(moduleField, mainClassField));
|
||||||
|
|
||||||
|
portField = new JFormattedTextField(new DecimalFormat("#0"));
|
||||||
|
fileNameField = new JTextField();
|
||||||
|
pathToFileField = new JTextField();
|
||||||
|
indicatorField = new JCheckBox("Display indicator on a web page:");
|
||||||
|
autoReloadField = new JCheckBox("Reload page automatically:");
|
||||||
|
maxHeapField = new JFormattedTextField(new DecimalFormat("#0"));
|
||||||
|
|
||||||
|
initLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initLayout() {
|
||||||
|
setLayout(new GridBagLayout());
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
GridBagConstraints labelConstraints = new GridBagConstraints();
|
||||||
|
labelConstraints.insets.right = 5;
|
||||||
|
labelConstraints.anchor = GridBagConstraints.LINE_START;
|
||||||
|
|
||||||
|
GridBagConstraints constraints = new GridBagConstraints();
|
||||||
|
constraints.gridwidth = GridBagConstraints.REMAINDER;
|
||||||
|
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
constraints.weightx = 1;
|
||||||
|
constraints.insets.top = 4;
|
||||||
|
constraints.insets.bottom = 4;
|
||||||
|
|
||||||
|
add(new JLabel("Main class:"), labelConstraints);
|
||||||
|
add(mainClassField, constraints);
|
||||||
|
|
||||||
|
add(new JLabel("Use classpath of module:"), labelConstraints);
|
||||||
|
add(moduleField, constraints);
|
||||||
|
|
||||||
|
add(jrePathEditor, constraints);
|
||||||
|
|
||||||
|
add(new JLabel("Port:"), labelConstraints);
|
||||||
|
add(portField, constraints);
|
||||||
|
|
||||||
|
add(new JLabel("File name:"), labelConstraints);
|
||||||
|
add(fileNameField, constraints);
|
||||||
|
|
||||||
|
add(new JLabel("Path to file:"), labelConstraints);
|
||||||
|
add(pathToFileField, constraints);
|
||||||
|
|
||||||
|
add(indicatorField, constraints);
|
||||||
|
add(autoReloadField, constraints);
|
||||||
|
|
||||||
|
add(new JLabel("Server heap limit:"), labelConstraints);
|
||||||
|
add(maxHeapField, constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(TeaVMDevServerConfiguration configuration) {
|
||||||
|
mainClassField.setText(configuration.getMainClass());
|
||||||
|
moduleSelector.reset(configuration);
|
||||||
|
jrePathEditor.setPathOrName(configuration.getJdkPath(), false);
|
||||||
|
fileNameField.setText(configuration.getFileName());
|
||||||
|
pathToFileField.setText(configuration.getPathToFile());
|
||||||
|
indicatorField.setSelected(configuration.isIndicator());
|
||||||
|
autoReloadField.setSelected(configuration.isAutomaticallyReloaded());
|
||||||
|
maxHeapField.setText(Integer.toString(configuration.getMaxHeap()));
|
||||||
|
portField.setText(Integer.toString(configuration.getPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(TeaVMDevServerConfiguration configuration) {
|
||||||
|
configuration.setMainClass(mainClassField.getText());
|
||||||
|
moduleSelector.applyTo(configuration);
|
||||||
|
configuration.setJdkPath(jrePathEditor.getJrePathOrName());
|
||||||
|
configuration.setFileName(fileNameField.getText());
|
||||||
|
configuration.setPathToFile(pathToFileField.getText());
|
||||||
|
configuration.setIndicator(indicatorField.isSelected());
|
||||||
|
configuration.setAutomaticallyReloaded(autoReloadField.isSelected());
|
||||||
|
configuration.setMaxHeap(Integer.parseInt(maxHeapField.getText()));
|
||||||
|
configuration.setPort(Integer.parseInt(portField.getText()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,6 +110,9 @@ public class TeaVMMavenImporter extends MavenImporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
TeaVMJpsConfiguration configuration = facet.getConfiguration().getState();
|
TeaVMJpsConfiguration configuration = facet.getConfiguration().getState();
|
||||||
|
if (justCreated) {
|
||||||
|
configuration.setSkipped(true);
|
||||||
|
}
|
||||||
|
|
||||||
for (Element child : source.getChildren()) {
|
for (Element child : source.getChildren()) {
|
||||||
switch (child.getName()) {
|
switch (child.getName()) {
|
||||||
|
|
|
@ -17,7 +17,6 @@ package org.teavm.idea.ui;
|
||||||
|
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module;
|
||||||
import com.intellij.openapi.options.Configurable;
|
import com.intellij.openapi.options.Configurable;
|
||||||
import com.intellij.openapi.options.ConfigurationException;
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import org.jetbrains.annotations.Nls;
|
import org.jetbrains.annotations.Nls;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -60,7 +59,7 @@ public class TeaVMConfigurable implements Configurable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply() throws ConfigurationException {
|
public void apply() {
|
||||||
panel.save(configuration);
|
panel.save(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ package org.teavm.idea.ui;
|
||||||
|
|
||||||
import com.intellij.facet.ui.FacetEditorTab;
|
import com.intellij.facet.ui.FacetEditorTab;
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module;
|
||||||
import com.intellij.openapi.options.ConfigurationException;
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import org.jetbrains.annotations.Nls;
|
import org.jetbrains.annotations.Nls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -48,7 +47,7 @@ public class TeaVMFacetEditorTab extends FacetEditorTab {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply() throws ConfigurationException {
|
public void apply() {
|
||||||
configurable.apply();
|
configurable.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
<configurationType implementation="org.teavm.idea.debug.TeaVMDebugConfigurationType"/>
|
<configurationType implementation="org.teavm.idea.debug.TeaVMDebugConfigurationType"/>
|
||||||
<programRunner implementation="org.teavm.idea.debug.TeaVMDebugRunner"/>
|
<programRunner implementation="org.teavm.idea.debug.TeaVMDebugRunner"/>
|
||||||
|
|
||||||
|
<configurationType implementation="org.teavm.idea.devserver.TeaVMDevServerConfigurationType"/>
|
||||||
|
<programRunner implementation="org.teavm.idea.devserver.TeaVMDevServerRunner"/>
|
||||||
|
|
||||||
<applicationConfigurable instance="org.teavm.idea.ui.TeaVMSettingsEditorTab"
|
<applicationConfigurable instance="org.teavm.idea.ui.TeaVMSettingsEditorTab"
|
||||||
id="project.teavm.settings"
|
id="project.teavm.settings"
|
||||||
displayName="TeaVM compiler"
|
displayName="TeaVM compiler"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user