diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml
index 6fee604f8..04f1af794 100644
--- a/teavm-classlib/pom.xml
+++ b/teavm-classlib/pom.xml
@@ -85,6 +85,8 @@
process-test-classes
false
+ true
+ true
en, en_US, en_GB, ru, ru_RU
diff --git a/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java b/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java
index 4610d40a5..88b747199 100644
--- a/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java
+++ b/teavm-core/src/main/java/org/teavm/tooling/JarSourceFileProvider.java
@@ -18,6 +18,9 @@ package org.teavm.tooling;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -28,6 +31,7 @@ import java.util.zip.ZipFile;
public class JarSourceFileProvider implements SourceFileProvider {
private File file;
private ZipFile zipFile;
+ private Set sourceFiles = new HashSet<>();
public JarSourceFileProvider(File file) {
this.file = file;
@@ -36,6 +40,10 @@ public class JarSourceFileProvider implements SourceFileProvider {
@Override
public void open() throws IOException {
zipFile = new ZipFile(file);
+ for (Enumeration extends ZipEntry> enumeration = zipFile.entries(); enumeration.hasMoreElements();) {
+ ZipEntry entry = enumeration.nextElement();
+ sourceFiles.add(entry.getName());
+ }
}
@Override
@@ -45,12 +53,13 @@ public class JarSourceFileProvider implements SourceFileProvider {
}
ZipFile zipFile = this.zipFile;
this.zipFile = null;
+ sourceFiles.clear();
zipFile.close();
}
@Override
public InputStream openSourceFile(String fullPath) throws IOException {
- if (zipFile == null) {
+ if (zipFile == null || !sourceFiles.contains(fullPath)) {
return null;
}
ZipEntry entry = zipFile.getEntry(fullPath);
diff --git a/teavm-eclipse/teavm-eclipse-m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java b/teavm-eclipse/teavm-eclipse-m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
index 38e5f9481..49d9c9df2 100644
--- a/teavm-eclipse/teavm-eclipse-m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
+++ b/teavm-eclipse/teavm-eclipse-m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
@@ -93,7 +93,7 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
private void configureProfile(MojoExecution execution, TeaVMProfile profile, IProgressMonitor monitor)
throws CoreException {
- monitor.beginTask("Configuring profile " + profile.getName(), 110);
+ monitor.beginTask("Configuring profile " + profile.getName(), 120);
String buildDir = getProjectBuildDirectory();
String mainClass = maven.getMojoParameterValue(mavenSession, execution, "mainClass", String.class);
@@ -131,6 +131,11 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
profile.setSourceMapsGenerated(sourceMaps != null ? sourceMaps : false);
monitor.worked(10);
+ Boolean sourceFiles = maven.getMojoParameterValue(mavenSession, execution, "sourceFilesCopied",
+ Boolean.class);
+ profile.setSourceFilesCopied(sourceFiles != null ? sourceFiles : false);
+ monitor.worked(10);
+
Boolean incremental = maven.getMojoParameterValue(mavenSession, execution, "incremental", Boolean.class);
profile.setIncremental(incremental != null ? incremental : false);
monitor.worked(10);
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java
index f06e005e8..b9537bdab 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/PreferencesBasedTeaVMProjectSettings.java
@@ -40,6 +40,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
public static final String CACHE_DIRECTORY = "cacheDirectory";
public static final String SOURCE_MAPS = "sourceMaps";
public static final String DEBUG_INFORMATION = "debugInformation";
+ public static final String COPY_SOURCES = "copySources";
public static final String PROPERTIES = "properties";
public static final String CLASSES = "classes";
public static final String TRANSFORMERS = "transformers";
@@ -160,6 +161,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
private String cacheDirectory;
private boolean sourceMapsGenerated;
private boolean debugInformationGenerated;
+ private boolean sourceFilesCopied;
private Properties properties = new Properties();
private String[] transformers = new String[0];
private Map classAliases = new HashMap<>();
@@ -281,6 +283,16 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
this.debugInformationGenerated = debugInformationGenerated;
}
+ @Override
+ public boolean isSourceFilesCopied() {
+ return sourceFilesCopied;
+ }
+
+ @Override
+ public void setSourceFilesCopied(boolean sourceFilesCopied) {
+ this.sourceFilesCopied = sourceFilesCopied;
+ }
+
@Override
public Properties getProperties() {
Properties copy = new Properties();
@@ -336,6 +348,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
cacheDirectory = preferences.get(CACHE_DIRECTORY, "");
sourceMapsGenerated = preferences.getBoolean(SOURCE_MAPS, true);
debugInformationGenerated = preferences.getBoolean(DEBUG_INFORMATION, true);
+ sourceFilesCopied = preferences.getBoolean(COPY_SOURCES, true);
Preferences propertiesPrefs = preferences.node(PROPERTIES);
propertiesPrefs.sync();
properties = new Properties();
@@ -365,6 +378,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
preferences.put(CACHE_DIRECTORY, cacheDirectory);
preferences.putBoolean(SOURCE_MAPS, sourceMapsGenerated);
preferences.putBoolean(DEBUG_INFORMATION, debugInformationGenerated);
+ preferences.putBoolean(COPY_SOURCES, sourceFilesCopied);
Preferences propertiesPrefs = preferences.node(PROPERTIES);
propertiesPrefs.clear();
for (Object key : properties.keySet()) {
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java
index 532238cee..506597ec4 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProfile.java
@@ -67,6 +67,10 @@ public interface TeaVMProfile {
void setDebugInformationGenerated(boolean debugInformationGenerated);
+ boolean isSourceFilesCopied();
+
+ void setSourceFilesCopied(boolean sourceFilesCopied);
+
Properties getProperties();
void setProperties(Properties properties);
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
index 1ebe41e8a..650662b1a 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
@@ -23,7 +23,10 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IClasspathEntry;
@@ -34,10 +37,7 @@ import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
-import org.teavm.tooling.ClassAlias;
-import org.teavm.tooling.RuntimeCopyOperation;
-import org.teavm.tooling.TeaVMTool;
-import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.*;
/**
*
@@ -48,6 +48,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
private URL[] classPath;
private IContainer[] sourceContainers;
private IContainer[] classFileContainers;
+ private SourceFileProvider[] sourceProviders;
private Set usedProjects = new HashSet<>();
private static Map> profileClasses = new WeakHashMap<>();
@@ -98,6 +99,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
tool.setClassLoader(classLoader);
tool.setDebugInformationGenerated(profile.isDebugInformationGenerated());
tool.setSourceMapsFileGenerated(profile.isSourceMapsGenerated());
+ tool.setSourceFilesCopied(profile.isSourceFilesCopied());
String targetDir = profile.getTargetDirectory();
tool.setTargetDirectory(new File(varManager.performStringSubstitution(targetDir, false)));
tool.setTargetFileName(profile.getTargetFileName());
@@ -118,6 +120,9 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
classAlias.setAlias(entry.getValue());
tool.getClassAliases().add(classAlias);
}
+ for (SourceFileProvider provider : sourceProviders) {
+ tool.addSourceFileProvider(provider);
+ }
tool.setProgressListener(new TeaVMEclipseProgressListener(this, monitor, TICKS_PER_PROFILE));
try {
monitor.beginTask("Running TeaVM", 10000);
@@ -167,7 +172,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
}
for (IProject project : getRelatedProjects()) {
IResourceDelta delta = getDelta(project);
- if (shouldBuild(classes, delta)) {
+ if (delta != null && shouldBuild(classes, delta)) {
return true;
}
}
@@ -405,6 +410,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
private void prepareClassPath() throws CoreException {
classPath = new URL[0];
sourceContainers = new IContainer[0];
+ sourceProviders = new SourceFileProvider[0];
IProject project = getProject();
if (!project.hasNature(JavaCore.NATURE_ID)) {
return;
@@ -413,6 +419,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
PathCollector collector = new PathCollector();
SourcePathCollector srcCollector = new SourcePathCollector();
SourcePathCollector binCollector = new SourcePathCollector();
+ SourceFileCollector sourceFileCollector = new SourceFileCollector();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
try {
if (javaProject.getOutputLocation() != null) {
@@ -423,53 +430,70 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
} catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e);
}
- IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
- for (IClasspathEntry entry : entries) {
- switch (entry.getEntryKind()) {
- case IClasspathEntry.CPE_LIBRARY:
- try {
- collector.addPath(entry.getPath());
- } catch (MalformedURLException e) {
- TeaVMEclipsePlugin.logError(e);
- }
- break;
- case IClasspathEntry.CPE_SOURCE:
- if (entry.getOutputLocation() != null) {
+ Queue projectQueue = new ArrayDeque<>();
+ projectQueue.add(javaProject);
+ Set visitedProjects = new HashSet<>();
+ while (!projectQueue.isEmpty()) {
+ javaProject = projectQueue.remove();
+ if (!visitedProjects.add(javaProject)) {
+ continue;
+ }
+ IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
+ for (IClasspathEntry entry : entries) {
+ switch (entry.getEntryKind()) {
+ case IClasspathEntry.CPE_LIBRARY:
try {
- collector.addPath(workspaceRoot.findMember(entry.getOutputLocation()).getLocation());
+ collector.addPath(entry.getPath());
} catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e);
}
- }
- IContainer srcContainer = (IContainer)workspaceRoot.findMember(entry.getPath());
- if (srcContainer != null && srcContainer.getProject() == project) {
- srcCollector.addContainer(srcContainer);
- }
- break;
- case IClasspathEntry.CPE_PROJECT: {
- IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath());
- IProject depProject = resource.getProject();
- if (!depProject.hasNature(JavaCore.NATURE_ID)) {
+ if (entry.getSourceAttachmentPath() != null) {
+ sourceFileCollector.addFile(entry.getSourceAttachmentPath());
+ }
+ break;
+ case IClasspathEntry.CPE_SOURCE:
+ if (entry.getOutputLocation() != null) {
+ try {
+ collector.addPath(workspaceRoot.findMember(entry.getOutputLocation()).getLocation());
+ } catch (MalformedURLException e) {
+ TeaVMEclipsePlugin.logError(e);
+ }
+ }
+ IContainer srcContainer = (IContainer)workspaceRoot.findMember(entry.getPath());
+ if (srcContainer != null) {
+ if (srcContainer.getProject() == project) {
+ srcCollector.addContainer(srcContainer);
+ }
+ sourceFileCollector.addFile(srcContainer.getLocation());
+ }
+ break;
+ case IClasspathEntry.CPE_PROJECT: {
+ IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath());
+ IProject depProject = resource.getProject();
+ if (!depProject.hasNature(JavaCore.NATURE_ID)) {
+ break;
+ }
+ IJavaProject depJavaProject = JavaCore.create(depProject);
+ if (depJavaProject.getOutputLocation() != null) {
+ try {
+ IContainer container = (IContainer)workspaceRoot.findMember(
+ depJavaProject.getOutputLocation());
+ collector.addPath(container.getLocation());
+ binCollector.addContainer(container);
+ } catch (MalformedURLException e) {
+ TeaVMEclipsePlugin.logError(e);
+ }
+ }
+ projectQueue.add(depJavaProject);
break;
}
- IJavaProject depJavaProject = JavaCore.create(depProject);
- if (depJavaProject.getOutputLocation() != null) {
- try {
- IContainer container = (IContainer)workspaceRoot.findMember(
- depJavaProject.getOutputLocation());
- collector.addPath(container.getLocation());
- binCollector.addContainer(container);
- } catch (MalformedURLException e) {
- TeaVMEclipsePlugin.logError(e);
- }
- }
- break;
}
}
}
classPath = collector.getUrls();
sourceContainers = srcCollector.getContainers();
classFileContainers = binCollector.getContainers();
+ sourceProviders = sourceFileCollector.getProviders();
}
static class PathCollector {
@@ -497,6 +521,30 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
}
}
+ static class SourceFileCollector {
+ private Set files = new HashSet<>();
+ private List providers = new ArrayList<>();
+
+ public void addFile(IPath path) {
+ if (!files.add(path.toString())) {
+ return;
+ }
+ File file = path.toFile();
+ if (!file.exists()) {
+ return;
+ }
+ if (file.isDirectory()) {
+ providers.add(new DirectorySourceFileProvider(file));
+ } else {
+ providers.add(new JarSourceFileProvider(file));
+ }
+ }
+
+ public SourceFileProvider[] getProviders() {
+ return providers.toArray(new SourceFileProvider[providers.size()]);
+ }
+ }
+
static class SourcePathCollector {
private Set containerSet = new HashSet<>();
private List containers = new ArrayList<>();
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java
index dedd6dbba..4cfcfeab9 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProfileDialog.java
@@ -69,6 +69,7 @@ public class TeaVMProfileDialog extends Dialog {
private Button cacheDirectoryFileSystemButton;
private Button debugInformationButton;
private Button sourceMapsButton;
+ private Button sourceFilesCopiedButton;
private TableViewer propertiesTableViewer;
private Button addPropertyButton;
private Button deletePropertyButton;
@@ -173,6 +174,7 @@ public class TeaVMProfileDialog extends Dialog {
Group group = createGroup(parent, "Debug settings", 1, false);
createDebugInformationField(group);
createSourceMapsField(group);
+ createSourceFilesCopiedField(group);
}
private void createPropertiesGroup(Composite parent) {
@@ -521,6 +523,11 @@ public class TeaVMProfileDialog extends Dialog {
sourceMapsButton.setText("Generate source maps");
}
+ private void createSourceFilesCopiedField(Composite container) {
+ sourceFilesCopiedButton = new Button(container, SWT.CHECK);
+ sourceFilesCopiedButton.setText("Copy source files");
+ }
+
public void setProject(IProject project) throws CoreException {
if (project.hasNature(JavaCore.NATURE_ID)) {
this.javaProject = JavaCore.create(project);
@@ -668,6 +675,7 @@ public class TeaVMProfileDialog extends Dialog {
cacheDirectoryField.setText(profile.getCacheDirectory());
debugInformationButton.setSelection(profile.isDebugInformationGenerated());
sourceMapsButton.setSelection(profile.isSourceMapsGenerated());
+ sourceFilesCopiedButton.setSelection(profile.isSourceFilesCopied());
propertyList.clear();
Properties properties = profile.getProperties();
for (Object key : properties.keySet()) {
@@ -708,6 +716,7 @@ public class TeaVMProfileDialog extends Dialog {
profile.setCacheDirectory(cacheDirectoryField.getText());
profile.setDebugInformationGenerated(debugInformationButton.getSelection());
profile.setSourceMapsGenerated(sourceMapsButton.getSelection());
+ profile.setSourceFilesCopied(sourceFilesCopiedButton.getSelection());
Properties properties = new Properties();
for (Object item : propertyList) {
KeyValue property = (KeyValue)item;