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 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;