Add a minimal TeaVM builder that simply works

This commit is contained in:
konsoletyper 2014-09-15 12:13:27 +04:00
parent 80899af284
commit d9ea3764f8
19 changed files with 287 additions and 46 deletions

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.dependency; package org.teavm.dependency;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
/** /**
@ -25,6 +26,7 @@ public class DependencyStack {
public static final DependencyStack ROOT = new DependencyStack(); public static final DependencyStack ROOT = new DependencyStack();
private MethodReference method; private MethodReference method;
private DependencyStack cause; private DependencyStack cause;
private InstructionLocation location;
private DependencyStack() { private DependencyStack() {
} }
@ -33,11 +35,20 @@ public class DependencyStack {
this(method, ROOT); this(method, ROOT);
} }
public DependencyStack(MethodReference method, InstructionLocation location) {
this(method, location, ROOT);
}
public DependencyStack(MethodReference method, DependencyStack cause) { public DependencyStack(MethodReference method, DependencyStack cause) {
this(method, null, cause);
}
public DependencyStack(MethodReference method, InstructionLocation location, DependencyStack cause) {
if (method == null || cause == null) { if (method == null || cause == null) {
throw new IllegalArgumentException("Arguments must not be null"); throw new IllegalArgumentException("Arguments must not be null");
} }
this.method = method; this.method = method;
this.location = location;
this.cause = cause; this.cause = cause;
} }
@ -49,6 +60,10 @@ public class DependencyStack {
return cause; return cause;
} }
public InstructionLocation getLocation() {
return location;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -254,8 +254,6 @@ public class TeaVMTestTool {
fileNames.get(method)); fileNames.get(method));
} catch (IOException e) { } catch (IOException e) {
log.error("Error generating JavaScript", e); log.error("Error generating JavaScript", e);
} catch (InterruptedException e) {
log.error("Error generating JavaScript", e);
} }
} }
}); });
@ -320,7 +318,7 @@ public class TeaVMTestTool {
} }
private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource, private void decompileClassesForTest(ClassLoader classLoader, ClassHolderSource classSource,
MethodReference methodRef, String targetName) throws IOException, InterruptedException { MethodReference methodRef, String targetName) throws IOException {
TeaVM vm = new TeaVMBuilder() TeaVM vm = new TeaVMBuilder()
.setClassLoader(classLoader) .setClassLoader(classLoader)
.setClassSource(classSource) .setClassSource(classSource)

View File

@ -59,6 +59,8 @@ public class TeaVMTool {
private DiskRegularMethodNodeCache astCache; private DiskRegularMethodNodeCache astCache;
private FileSymbolTable symbolTable; private FileSymbolTable symbolTable;
private FileSymbolTable fileTable; private FileSymbolTable fileTable;
private boolean cancelled;
private TeaVMProgressListener progressListener;
public File getTargetDirectory() { public File getTargetDirectory() {
return targetDirectory; return targetDirectory;
@ -180,8 +182,17 @@ public class TeaVMTool {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
public void generate() throws TeaVMToolException, InterruptedException { public void setProgressListener(TeaVMProgressListener progressListener) {
this.progressListener = progressListener;
}
public boolean wasCancelled() {
return cancelled;
}
public void generate() throws TeaVMToolException {
try { try {
cancelled = false;
log.info("Building JavaScript file"); log.info("Building JavaScript file");
TeaVMBuilder vmBuilder = new TeaVMBuilder(); TeaVMBuilder vmBuilder = new TeaVMBuilder();
if (incremental) { if (incremental) {
@ -205,6 +216,9 @@ public class TeaVMTool {
vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader)); vmBuilder.setClassLoader(classLoader).setClassSource(new ClasspathClassHolderSource(classLoader));
} }
TeaVM vm = vmBuilder.build(); TeaVM vm = vmBuilder.build();
if (progressListener != null) {
vm.setProgressListener(progressListener);
}
vm.setMinifying(minifying); vm.setMinifying(minifying);
vm.setBytecodeLogging(bytecodeLogging); vm.setBytecodeLogging(bytecodeLogging);
vm.setProperties(properties); vm.setProperties(properties);
@ -221,8 +235,7 @@ public class TeaVMTool {
vm.add(transformer); vm.add(transformer);
} }
if (mainClass != null) { if (mainClass != null) {
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", ValueType.arrayOf( MethodDescriptor mainMethodDesc = new MethodDescriptor("main", String[].class, void.class);
ValueType.object("java.lang.String")), ValueType.VOID);
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc)) vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
.withValue(1, "java.lang.String"); .withValue(1, "java.lang.String");
} }
@ -253,6 +266,11 @@ public class TeaVMTool {
vm.add(runtimeInjector); vm.add(runtimeInjector);
} }
vm.build(writer, new DirectoryBuildTarget(targetDirectory)); vm.build(writer, new DirectoryBuildTarget(targetDirectory));
if (vm.wasCancelled()) {
log.info("Build cancelled");
cancelled = true;
return;
}
vm.checkForMissingItems(); vm.checkForMissingItems();
log.info("JavaScript file successfully built"); log.info("JavaScript file successfully built");
if (debugInformationGenerated) { if (debugInformationGenerated) {

View File

@ -83,14 +83,19 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
private RegularMethodNodeCache astCache = new EmptyRegularMethodNodeCache(); private RegularMethodNodeCache astCache = new EmptyRegularMethodNodeCache();
private boolean incremental; private boolean incremental;
private TeaVMProgressListener progressListener; private TeaVMProgressListener progressListener;
private boolean cancelled;
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) { TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
this.classSource = classSource; this.classSource = classSource;
this.classLoader = classLoader; this.classLoader = classLoader;
dependencyChecker = new DependencyChecker(this.classSource, classLoader, this); dependencyChecker = new DependencyChecker(this.classSource, classLoader, this);
progressListener = new TeaVMProgressListener() { progressListener = new TeaVMProgressListener() {
@Override public void progressReached(int progress) throws InterruptedException { } @Override public TeaVMProgressFeedback progressReached(int progress) {
@Override public void phaseStarted(TeaVMPhase phase, int count) throws InterruptedException { } return TeaVMProgressFeedback.CONTINUE;
}
@Override public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
return TeaVMProgressFeedback.CONTINUE;
}
}; };
} }
@ -201,6 +206,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
this.progressListener = progressListener; this.progressListener = progressListener;
} }
public boolean wasCancelled() {
return cancelled;
}
/** /**
* <p>Adds an entry point. TeaVM guarantees, that all methods that are required by the entry point * <p>Adds an entry point. TeaVM guarantees, that all methods that are required by the entry point
* will be available at run-time in browser. Also you need to specify for each parameter of entry point * will be available at run-time in browser. Also you need to specify for each parameter of entry point
@ -323,9 +332,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* @param target where to generate additional resources. Can be null, but if there are * @param target where to generate additional resources. Can be null, but if there are
* plugins or inteceptors that generate additional resources, the build process will fail. * plugins or inteceptors that generate additional resources, the build process will fail.
*/ */
public void build(Appendable writer, BuildTarget target) throws RenderingException, InterruptedException { public void build(Appendable writer, BuildTarget target) throws RenderingException {
// Check dependencies // Check dependencies
progressListener.phaseStarted(TeaVMPhase.DEPENDENCY_CHECKING, 1); reportPhase(TeaVMPhase.DEPENDENCY_CHECKING, 1);
if (wasCancelled()) {
return;
}
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider(); AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
dependencyChecker.linkMethod(new MethodReference("java.lang.Class", "createNew", dependencyChecker.linkMethod(new MethodReference("java.lang.Class", "createNew",
ValueType.object("java.lang.Class")), DependencyStack.ROOT).use(); ValueType.object("java.lang.Class")), DependencyStack.ROOT).use();
@ -343,26 +355,38 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
dependencyChecker.linkMethod(new MethodReference("java.lang.Object", new MethodDescriptor("clone", dependencyChecker.linkMethod(new MethodReference("java.lang.Object", new MethodDescriptor("clone",
ValueType.object("java.lang.Object"))), DependencyStack.ROOT).use(); ValueType.object("java.lang.Object"))), DependencyStack.ROOT).use();
dependencyChecker.processDependencies(); dependencyChecker.processDependencies();
progressListener.progressReached(1); reportProgress(1);
if (hasMissingItems()) { if (wasCancelled() || hasMissingItems()) {
return; return;
} }
// Link // Link
progressListener.phaseStarted(TeaVMPhase.LINKING, 1); reportPhase(TeaVMPhase.LINKING, 1);
if (wasCancelled()) {
return;
}
Linker linker = new Linker(); Linker linker = new Linker();
ListableClassHolderSource classSet = linker.link(dependencyChecker); ListableClassHolderSource classSet = linker.link(dependencyChecker);
progressListener.progressReached(1); reportProgress(1);
if (wasCancelled()) {
return;
}
// Optimize and allocate registers // Optimize and allocate registers
if (!incremental) { if (!incremental) {
devirtualize(classSet, dependencyChecker); devirtualize(classSet, dependencyChecker);
if (wasCancelled()) {
return;
}
} }
List<ClassNode> clsNodes = modelToAst(classSet); List<ClassNode> clsNodes = modelToAst(classSet);
// Render // Render
progressListener.phaseStarted(TeaVMPhase.RENDERING, classSet.getClassNames().size()); reportPhase(TeaVMPhase.RENDERING, classSet.getClassNames().size());
if (wasCancelled()) {
return;
}
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource()); DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, dependencyChecker.getClassSource());
naming.setMinifying(minifying); naming.setMinifying(minifying);
SourceWriterBuilder builder = new SourceWriterBuilder(naming); SourceWriterBuilder builder = new SourceWriterBuilder(naming);
@ -378,7 +402,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
emitCFG(debugEmitter, method.getProgram()); emitCFG(debugEmitter, method.getProgram());
} }
} }
progressListener.progressReached(++classIndex); reportProgress(++classIndex);
if (wasCancelled()) {
return;
}
} }
renderer.setDebugEmitter(debugEmitter); renderer.setDebugEmitter(debugEmitter);
} }
@ -418,6 +445,18 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
} }
private void reportPhase(TeaVMPhase phase, int progressLimit) {
if (progressListener.phaseStarted(phase, progressLimit) == TeaVMProgressFeedback.CANCEL) {
cancelled = true;
}
}
private void reportProgress(int progress) {
if (progressListener.progressReached(progress) == TeaVMProgressFeedback.CANCEL) {
cancelled = true;
}
}
private void emitCFG(DebugInformationEmitter emitter, Program program) { private void emitCFG(DebugInformationEmitter emitter, Program program) {
Map<InstructionLocation, InstructionLocation[]> cfg = ProgramUtils.getLocationCFG(program); Map<InstructionLocation, InstructionLocation[]> cfg = ProgramUtils.getLocationCFG(program);
for (Map.Entry<InstructionLocation, InstructionLocation[]> entry : cfg.entrySet()) { for (Map.Entry<InstructionLocation, InstructionLocation[]> entry : cfg.entrySet()) {
@ -437,9 +476,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
return new SourceLocation(location.getFileName(), location.getLine()); return new SourceLocation(location.getFileName(), location.getLine());
} }
private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) {
throws InterruptedException { reportPhase(TeaVMPhase.DEVIRTUALIZATION, classes.getClassNames().size());
progressListener.phaseStarted(TeaVMPhase.DEVIRTUALIZATION, classes.getClassNames().size()); if (wasCancelled()) {
return;
}
final Devirtualization devirtualization = new Devirtualization(dependency, classes); final Devirtualization devirtualization = new Devirtualization(dependency, classes);
int index = 0; int index = 0;
for (String className : classes.getClassNames()) { for (String className : classes.getClassNames()) {
@ -449,11 +490,14 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
devirtualization.apply(method); devirtualization.apply(method);
} }
} }
progressListener.progressReached(++index); reportProgress(++index);
if (wasCancelled()) {
return;
}
} }
} }
private List<ClassNode> modelToAst(ListableClassHolderSource classes) throws InterruptedException { private List<ClassNode> modelToAst(ListableClassHolderSource classes) {
progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size()); progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size());
Decompiler decompiler = new Decompiler(classes, classLoader); Decompiler decompiler = new Decompiler(classes, classLoader);
decompiler.setRegularMethodCache(incremental ? astCache : null); decompiler.setRegularMethodCache(incremental ? astCache : null);
@ -606,7 +650,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
} }
public void build(File dir, String fileName) throws RenderingException, InterruptedException { public void build(File dir, String fileName) throws RenderingException {
try (Writer writer = new OutputStreamWriter(new FileOutputStream(new File(dir, fileName)), "UTF-8")) { try (Writer writer = new OutputStreamWriter(new FileOutputStream(new File(dir, fileName)), "UTF-8")) {
build(writer, new DirectoryBuildTarget(dir)); build(writer, new DirectoryBuildTarget(dir));
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {

View File

@ -0,0 +1,25 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.vm;
/**
*
* @author Alexey Andreev
*/
public enum TeaVMProgressFeedback {
CONTINUE,
CANCEL
}

View File

@ -20,7 +20,7 @@ package org.teavm.vm;
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public interface TeaVMProgressListener { public interface TeaVMProgressListener {
void phaseStarted(TeaVMPhase phase, int count) throws InterruptedException; TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count);
void progressReached(int progress) throws InterruptedException; TeaVMProgressFeedback progressReached(int progress);
} }

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src/main/java"/> <classpathentry kind="src" path="src/main/java"/>
<classpathentry exported="true" kind="lib" path="lib/gson-2.2.4.jar"/>
<classpathentry exported="true" kind="lib" path="lib/teavm-classlib-0.2-SNAPSHOT.jar"/>
<classpathentry exported="true" kind="lib" path="lib/teavm-platform-0.2-SNAPSHOT.jar"/>
<classpathentry exported="true" kind="lib" path="lib/asm-5.0.1.jar"/> <classpathentry exported="true" kind="lib" path="lib/asm-5.0.1.jar"/>
<classpathentry exported="true" kind="lib" path="lib/asm-commons-5.0.1.jar"/> <classpathentry exported="true" kind="lib" path="lib/asm-commons-5.0.1.jar"/>
<classpathentry exported="true" kind="lib" path="lib/asm-debug-all-4.2.jar"/> <classpathentry exported="true" kind="lib" path="lib/asm-debug-all-4.2.jar"/>

View File

@ -53,6 +53,9 @@ Bundle-ClassPath: .,
lib/websocket-client-9.2.1.v20140609.jar, lib/websocket-client-9.2.1.v20140609.jar,
lib/websocket-common-9.2.1.v20140609.jar, lib/websocket-common-9.2.1.v20140609.jar,
lib/websocket-server-9.2.1.v20140609.jar, lib/websocket-server-9.2.1.v20140609.jar,
lib/websocket-servlet-9.2.1.v20140609.jar lib/websocket-servlet-9.2.1.v20140609.jar,
lib/gson-2.2.4.jar,
lib/teavm-classlib-0.2-SNAPSHOT.jar,
lib/teavm-platform-0.2-SNAPSHOT.jar
Export-Package: org.teavm.eclipse.debugger Export-Package: org.teavm.eclipse.debugger
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy

View File

@ -37,7 +37,10 @@ bin.includes = plugin.xml,\
lib/websocket-client-9.2.1.v20140609.jar,\ lib/websocket-client-9.2.1.v20140609.jar,\
lib/websocket-common-9.2.1.v20140609.jar,\ lib/websocket-common-9.2.1.v20140609.jar,\
lib/websocket-server-9.2.1.v20140609.jar,\ lib/websocket-server-9.2.1.v20140609.jar,\
lib/websocket-servlet-9.2.1.v20140609.jar lib/websocket-servlet-9.2.1.v20140609.jar,\
lib/gson-2.2.4.jar,\
lib/teavm-classlib-0.2-SNAPSHOT.jar,\
lib/teavm-platform-0.2-SNAPSHOT.jar
jars.compile.order = . jars.compile.order = .
jars.extra.classpath = logback.xml,\ jars.extra.classpath = logback.xml,\
lib/asm-5.0.1.jar,\ lib/asm-5.0.1.jar,\
@ -72,4 +75,7 @@ jars.extra.classpath = logback.xml,\
lib/websocket-client-9.2.1.v20140609.jar,\ lib/websocket-client-9.2.1.v20140609.jar,\
lib/websocket-common-9.2.1.v20140609.jar,\ lib/websocket-common-9.2.1.v20140609.jar,\
lib/websocket-server-9.2.1.v20140609.jar,\ lib/websocket-server-9.2.1.v20140609.jar,\
lib/websocket-servlet-9.2.1.v20140609.jar lib/websocket-servlet-9.2.1.v20140609.jar,\
lib/gson-2.2.4.jar,\
lib/teavm-classlib-0.2-SNAPSHOT.jar,\
lib/teavm-platform-0.2-SNAPSHOT.jar

View File

@ -50,6 +50,7 @@
<runtime> <runtime>
<run class="org.teavm.eclipse.TeaVMProjectNature"/> <run class="org.teavm.eclipse.TeaVMProjectNature"/>
</runtime> </runtime>
<builder id="org.teavm.eclipse.builder"/>
</extension> </extension>
<extension point="org.eclipse.ui.propertyPages"> <extension point="org.eclipse.ui.propertyPages">
<page id="org.teavm.eclipse.projectProperties" name="TeaVM" class="org.teavm.eclipse.ui.TeaVMProjectPropertyPage"> <page id="org.teavm.eclipse.projectProperties" name="TeaVM" class="org.teavm.eclipse.ui.TeaVMProjectPropertyPage">
@ -61,4 +62,9 @@
</enabledWhen> </enabledWhen>
</page> </page>
</extension> </extension>
<extension point="org.eclipse.core.resources.builders" id="builder" name="TeaVM builder">
<builder hasNature="true">
<run class="org.teavm.eclipse.TeaVMBuilder"/>
</builder>
</extension>
</plugin> </plugin>

View File

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

View File

@ -4,14 +4,10 @@ import java.io.File;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.*;
import java.util.List; import org.eclipse.core.resources.*;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IClasspathEntry;
@ -19,6 +15,7 @@ import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaCore;
import org.teavm.tooling.RuntimeCopyOperation; import org.teavm.tooling.RuntimeCopyOperation;
import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException;
/** /**
* *
@ -39,7 +36,12 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
tool.setRuntime(RuntimeCopyOperation.SEPARATE); tool.setRuntime(RuntimeCopyOperation.SEPARATE);
tool.setMinifying(false); tool.setMinifying(false);
tool.setMainClass(projectSettings.getMainClass()); tool.setMainClass(projectSettings.getMainClass());
tool.setProgressListener(new TeaVMEclipseProgressListener(monitor));
try {
tool.generate();
} catch (TeaVMToolException e) {
throw new CoreException(TeaVMEclipsePlugin.makeError(e));
}
return null; return null;
} }
@ -57,9 +59,10 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
return new URL[0]; return new URL[0];
} }
IJavaProject javaProject = JavaCore.create(project); IJavaProject javaProject = JavaCore.create(project);
List<URL> urls = new ArrayList<>(); PathCollector collector = new PathCollector();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
try { try {
urls.add(javaProject.getOutputLocation().toFile().toURI().toURL()); collector.addPath(workspaceRoot.findMember(javaProject.getOutputLocation()).getLocation());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
@ -68,7 +71,7 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
switch (entry.getEntryKind()) { switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY: case IClasspathEntry.CPE_LIBRARY:
try { try {
urls.add(entry.getPath().toFile().toURI().toURL()); collector.addPath(entry.getPath());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
@ -76,7 +79,7 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
case IClasspathEntry.CPE_SOURCE: case IClasspathEntry.CPE_SOURCE:
if (entry.getOutputLocation() != null) { if (entry.getOutputLocation() != null) {
try { try {
urls.add(entry.getOutputLocation().toFile().toURI().toURL()); collector.addPath(workspaceRoot.findMember(entry.getOutputLocation()).getLocation());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
@ -91,7 +94,8 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
IJavaProject depJavaProject = JavaCore.create(depProject); IJavaProject depJavaProject = JavaCore.create(depProject);
if (depJavaProject.getOutputLocation() != null) { if (depJavaProject.getOutputLocation() != null) {
try { try {
urls.add(depJavaProject.getOutputLocation().toFile().toURI().toURL()); collector.addPath(workspaceRoot.findMember(depJavaProject.getOutputLocation())
.getLocation());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
@ -100,6 +104,31 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
} }
} }
} }
return urls.toArray(new URL[urls.size()]); return collector.getUrls();
}
static class PathCollector {
private Set<URL> urlSet = new HashSet<>();
private List<URL> urls = new ArrayList<>();
public void addPath(IPath path) throws MalformedURLException {
File file = path.toFile();
if (!file.exists()) {
return;
}
if (file.isDirectory()) {
file = new File(file.getAbsolutePath() + "/");
} else {
file = new File(file.getAbsolutePath());
}
URL url = file.toURI().toURL();
if (urlSet.add(url)) {
urls.add(url);
}
}
public URL[] getUrls() {
return urls.toArray(new URL[urls.size()]);
}
} }
} }

View File

@ -36,6 +36,7 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
public class TeaVMEclipsePlugin extends AbstractUIPlugin { public class TeaVMEclipsePlugin extends AbstractUIPlugin {
public static final String ID = "org.teavm.eclipse"; public static final String ID = "org.teavm.eclipse";
public static final String NATURE_ID = ID + ".nature"; public static final String NATURE_ID = ID + ".nature";
public static final String BUILDER_ID = ID + ".builder";
public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod"; public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod";
private static TeaVMEclipsePlugin defaultInstance; private static TeaVMEclipsePlugin defaultInstance;
private ConcurrentMap<IProject, TeaVMProjectSettings> settingsMap = new ConcurrentHashMap<>(); private ConcurrentMap<IProject, TeaVMProjectSettings> settingsMap = new ConcurrentHashMap<>();

View File

@ -0,0 +1,48 @@
package org.teavm.eclipse;
import org.eclipse.core.runtime.IProgressMonitor;
import org.teavm.vm.TeaVMPhase;
import org.teavm.vm.TeaVMProgressFeedback;
import org.teavm.vm.TeaVMProgressListener;
/**
*
* @author Alexey Andreev
*/
public class TeaVMEclipseProgressListener implements TeaVMProgressListener {
private IProgressMonitor progressMonitor;
public TeaVMEclipseProgressListener(IProgressMonitor progressMonitor) {
this.progressMonitor = progressMonitor;
}
@Override
public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) {
String taskName = "Building";
switch (phase) {
case DECOMPILATION:
taskName = "Decompiling";
break;
case DEPENDENCY_CHECKING:
taskName = "Dependency checking";
break;
case DEVIRTUALIZATION:
taskName = "Applying devirtualization";
break;
case LINKING:
taskName = "Linking";
break;
case RENDERING:
taskName = "Rendering";
break;
}
progressMonitor.beginTask(taskName, count);
return progressMonitor.isCanceled() ? TeaVMProgressFeedback.CANCEL : TeaVMProgressFeedback.CONTINUE;
}
@Override
public TeaVMProgressFeedback progressReached(int progress) {
progressMonitor.worked(progress);
return progressMonitor.isCanceled() ? TeaVMProgressFeedback.CANCEL : TeaVMProgressFeedback.CONTINUE;
}
}

View File

@ -1,8 +1,12 @@
package org.teavm.eclipse; package org.teavm.eclipse;
import java.util.Arrays;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
/** /**
* *
@ -11,12 +15,50 @@ import org.eclipse.core.runtime.CoreException;
public class TeaVMProjectNature implements IProjectNature { public class TeaVMProjectNature implements IProjectNature {
private IProject project; private IProject project;
private boolean hasBuilder() throws CoreException {
IProjectDescription description = project.getDescription();
ICommand[] buildCommands = description.getBuildSpec();
for (ICommand command : buildCommands) {
if (command.getBuilderName().equals(TeaVMEclipsePlugin.BUILDER_ID)) {
return true;
}
}
return false;
}
@Override @Override
public void configure() throws CoreException { public void configure() throws CoreException {
if (!hasBuilder()) {
IProjectDescription description = project.getDescription();
ICommand[] buildCommands = description.getBuildSpec();
buildCommands = Arrays.copyOf(buildCommands, buildCommands.length + 1);
ICommand teaVMCommand = description.newCommand();
teaVMCommand.setBuilderName(TeaVMEclipsePlugin.BUILDER_ID);
buildCommands[buildCommands.length - 1] = teaVMCommand;
description.setBuildSpec(buildCommands);
project.setDescription(description, new NullProgressMonitor());
}
} }
@Override @Override
public void deconfigure() throws CoreException { public void deconfigure() throws CoreException {
if (hasBuilder()) {
IProjectDescription description = project.getDescription();
ICommand[] buildCommands = description.getBuildSpec();
int index = -1;
for (int i = 0; i < buildCommands.length; ++i) {
ICommand command = buildCommands[i];
if (command.getBuilderName().equals(TeaVMEclipsePlugin.BUILDER_ID)) {
index = i;
break;
}
}
ICommand[] newBuildCommands = new ICommand[buildCommands.length - 1];
System.arraycopy(buildCommands, 0, newBuildCommands, 0, index);
System.arraycopy(buildCommands, index + 1, newBuildCommands, index, newBuildCommands.length - index);
description.setBuildSpec(newBuildCommands);
project.setDescription(description, new NullProgressMonitor());
}
} }
@Override @Override

View File

@ -63,7 +63,7 @@ public class TeaVMSourcePathComputerDelegate implements ISourcePathComputerDeleg
case IClasspathEntry.CPE_CONTAINER: case IClasspathEntry.CPE_CONTAINER:
sourceContainers.add(new ClasspathContainerSourceContainer(entry.getPath())); sourceContainers.add(new ClasspathContainerSourceContainer(entry.getPath()));
break; break;
case IClasspathEntry.CPE_LIBRARY:; case IClasspathEntry.CPE_LIBRARY:
sourceContainers.add(new ExternalArchiveSourceContainer(entry.getPath().toString(), true)); sourceContainers.add(new ExternalArchiveSourceContainer(entry.getPath().toString(), true));
if (entry.getSourceAttachmentPath() != null) { if (entry.getSourceAttachmentPath() != null) {
System.out.println(entry.getSourceAttachmentPath()); System.out.println(entry.getSourceAttachmentPath());

View File

@ -26,7 +26,7 @@ public class MainClassSelectionDialog extends FilteredItemsSelectionDialog {
public MainClassSelectionDialog(Shell shell, IJavaProject javaProject) { public MainClassSelectionDialog(Shell shell, IJavaProject javaProject) {
super(shell, false); super(shell, false);
this.javaProject = javaProject; this.javaProject = javaProject;
setTitle("Searching main class"); setTitle("Selecting main class");
LabelProvider labelProvider = new LabelProvider() { LabelProvider labelProvider = new LabelProvider() {
@Override public String getText(Object element) { @Override public String getText(Object element) {
return getElementName(element); return getElementName(element);

View File

@ -167,7 +167,7 @@ public class TeaVMProjectPropertyWidget extends Composite {
private void chooseFileSystemTargetDirectory() { private void chooseFileSystemTargetDirectory() {
String filePath = targetDirectoryField.getText(); String filePath = targetDirectoryField.getText();
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); DirectoryDialog dialog = new DirectoryDialog(getShell());
filePath = dialog.open(); filePath = dialog.open();
if (filePath != null) { if (filePath != null) {
targetDirectoryField.setText(filePath); targetDirectoryField.setText(filePath);

View File

@ -214,8 +214,6 @@ public class BuildJavascriptMojo extends AbstractMojo {
throw new MojoExecutionException("Unexpected error occured", e); throw new MojoExecutionException("Unexpected error occured", e);
} catch (TeaVMToolException e) { } catch (TeaVMToolException e) {
throw new MojoExecutionException("IO error occured", e); throw new MojoExecutionException("IO error occured", e);
} catch (InterruptedException e) {
throw new MojoExecutionException("Build was interrupted", e);
} }
} }