Add support of copying source files into Eclipse:

https://github.com/konsoletyper/teavm/issues/13
This commit is contained in:
Alexey Andreev 2014-09-27 19:23:05 +04:00
parent 6c05ec589a
commit 9d12bffc1b
7 changed files with 134 additions and 43 deletions

View File

@ -85,6 +85,8 @@
<phase>process-test-classes</phase> <phase>process-test-classes</phase>
<configuration> <configuration>
<minifying>false</minifying> <minifying>false</minifying>
<sourceMapsGenerated>true</sourceMapsGenerated>
<sourceFilesCopied>true</sourceFilesCopied>
<properties> <properties>
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available> <java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
</properties> </properties>

View File

@ -18,6 +18,9 @@ package org.teavm.tooling;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; 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.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@ -28,6 +31,7 @@ import java.util.zip.ZipFile;
public class JarSourceFileProvider implements SourceFileProvider { public class JarSourceFileProvider implements SourceFileProvider {
private File file; private File file;
private ZipFile zipFile; private ZipFile zipFile;
private Set<String> sourceFiles = new HashSet<>();
public JarSourceFileProvider(File file) { public JarSourceFileProvider(File file) {
this.file = file; this.file = file;
@ -36,6 +40,10 @@ public class JarSourceFileProvider implements SourceFileProvider {
@Override @Override
public void open() throws IOException { public void open() throws IOException {
zipFile = new ZipFile(file); zipFile = new ZipFile(file);
for (Enumeration<? extends ZipEntry> enumeration = zipFile.entries(); enumeration.hasMoreElements();) {
ZipEntry entry = enumeration.nextElement();
sourceFiles.add(entry.getName());
}
} }
@Override @Override
@ -45,12 +53,13 @@ public class JarSourceFileProvider implements SourceFileProvider {
} }
ZipFile zipFile = this.zipFile; ZipFile zipFile = this.zipFile;
this.zipFile = null; this.zipFile = null;
sourceFiles.clear();
zipFile.close(); zipFile.close();
} }
@Override @Override
public InputStream openSourceFile(String fullPath) throws IOException { public InputStream openSourceFile(String fullPath) throws IOException {
if (zipFile == null) { if (zipFile == null || !sourceFiles.contains(fullPath)) {
return null; return null;
} }
ZipEntry entry = zipFile.getEntry(fullPath); ZipEntry entry = zipFile.getEntry(fullPath);

View File

@ -93,7 +93,7 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
private void configureProfile(MojoExecution execution, TeaVMProfile profile, IProgressMonitor monitor) private void configureProfile(MojoExecution execution, TeaVMProfile profile, IProgressMonitor monitor)
throws CoreException { throws CoreException {
monitor.beginTask("Configuring profile " + profile.getName(), 110); monitor.beginTask("Configuring profile " + profile.getName(), 120);
String buildDir = getProjectBuildDirectory(); String buildDir = getProjectBuildDirectory();
String mainClass = maven.getMojoParameterValue(mavenSession, execution, "mainClass", String.class); String mainClass = maven.getMojoParameterValue(mavenSession, execution, "mainClass", String.class);
@ -131,6 +131,11 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
profile.setSourceMapsGenerated(sourceMaps != null ? sourceMaps : false); profile.setSourceMapsGenerated(sourceMaps != null ? sourceMaps : false);
monitor.worked(10); 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); Boolean incremental = maven.getMojoParameterValue(mavenSession, execution, "incremental", Boolean.class);
profile.setIncremental(incremental != null ? incremental : false); profile.setIncremental(incremental != null ? incremental : false);
monitor.worked(10); monitor.worked(10);

View File

@ -40,6 +40,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
public static final String CACHE_DIRECTORY = "cacheDirectory"; public static final String CACHE_DIRECTORY = "cacheDirectory";
public static final String SOURCE_MAPS = "sourceMaps"; public static final String SOURCE_MAPS = "sourceMaps";
public static final String DEBUG_INFORMATION = "debugInformation"; public static final String DEBUG_INFORMATION = "debugInformation";
public static final String COPY_SOURCES = "copySources";
public static final String PROPERTIES = "properties"; public static final String PROPERTIES = "properties";
public static final String CLASSES = "classes"; public static final String CLASSES = "classes";
public static final String TRANSFORMERS = "transformers"; public static final String TRANSFORMERS = "transformers";
@ -160,6 +161,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
private String cacheDirectory; private String cacheDirectory;
private boolean sourceMapsGenerated; private boolean sourceMapsGenerated;
private boolean debugInformationGenerated; private boolean debugInformationGenerated;
private boolean sourceFilesCopied;
private Properties properties = new Properties(); private Properties properties = new Properties();
private String[] transformers = new String[0]; private String[] transformers = new String[0];
private Map<String, String> classAliases = new HashMap<>(); private Map<String, String> classAliases = new HashMap<>();
@ -281,6 +283,16 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
this.debugInformationGenerated = debugInformationGenerated; this.debugInformationGenerated = debugInformationGenerated;
} }
@Override
public boolean isSourceFilesCopied() {
return sourceFilesCopied;
}
@Override
public void setSourceFilesCopied(boolean sourceFilesCopied) {
this.sourceFilesCopied = sourceFilesCopied;
}
@Override @Override
public Properties getProperties() { public Properties getProperties() {
Properties copy = new Properties(); Properties copy = new Properties();
@ -336,6 +348,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
cacheDirectory = preferences.get(CACHE_DIRECTORY, ""); cacheDirectory = preferences.get(CACHE_DIRECTORY, "");
sourceMapsGenerated = preferences.getBoolean(SOURCE_MAPS, true); sourceMapsGenerated = preferences.getBoolean(SOURCE_MAPS, true);
debugInformationGenerated = preferences.getBoolean(DEBUG_INFORMATION, true); debugInformationGenerated = preferences.getBoolean(DEBUG_INFORMATION, true);
sourceFilesCopied = preferences.getBoolean(COPY_SOURCES, true);
Preferences propertiesPrefs = preferences.node(PROPERTIES); Preferences propertiesPrefs = preferences.node(PROPERTIES);
propertiesPrefs.sync(); propertiesPrefs.sync();
properties = new Properties(); properties = new Properties();
@ -365,6 +378,7 @@ public class PreferencesBasedTeaVMProjectSettings implements TeaVMProjectSetting
preferences.put(CACHE_DIRECTORY, cacheDirectory); preferences.put(CACHE_DIRECTORY, cacheDirectory);
preferences.putBoolean(SOURCE_MAPS, sourceMapsGenerated); preferences.putBoolean(SOURCE_MAPS, sourceMapsGenerated);
preferences.putBoolean(DEBUG_INFORMATION, debugInformationGenerated); preferences.putBoolean(DEBUG_INFORMATION, debugInformationGenerated);
preferences.putBoolean(COPY_SOURCES, sourceFilesCopied);
Preferences propertiesPrefs = preferences.node(PROPERTIES); Preferences propertiesPrefs = preferences.node(PROPERTIES);
propertiesPrefs.clear(); propertiesPrefs.clear();
for (Object key : properties.keySet()) { for (Object key : properties.keySet()) {

View File

@ -67,6 +67,10 @@ public interface TeaVMProfile {
void setDebugInformationGenerated(boolean debugInformationGenerated); void setDebugInformationGenerated(boolean debugInformationGenerated);
boolean isSourceFilesCopied();
void setSourceFilesCopied(boolean sourceFilesCopied);
Properties getProperties(); Properties getProperties();
void setProperties(Properties properties); void setProperties(Properties properties);

View File

@ -23,7 +23,10 @@ import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.*; import java.util.*;
import org.eclipse.core.resources.*; 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.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IClasspathEntry;
@ -34,10 +37,7 @@ import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.InstructionLocation; import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.tooling.ClassAlias; import org.teavm.tooling.*;
import org.teavm.tooling.RuntimeCopyOperation;
import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException;
/** /**
* *
@ -48,6 +48,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
private URL[] classPath; private URL[] classPath;
private IContainer[] sourceContainers; private IContainer[] sourceContainers;
private IContainer[] classFileContainers; private IContainer[] classFileContainers;
private SourceFileProvider[] sourceProviders;
private Set<IProject> usedProjects = new HashSet<>(); private Set<IProject> usedProjects = new HashSet<>();
private static Map<TeaVMProfile, Set<String>> profileClasses = new WeakHashMap<>(); private static Map<TeaVMProfile, Set<String>> profileClasses = new WeakHashMap<>();
@ -98,6 +99,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
tool.setClassLoader(classLoader); tool.setClassLoader(classLoader);
tool.setDebugInformationGenerated(profile.isDebugInformationGenerated()); tool.setDebugInformationGenerated(profile.isDebugInformationGenerated());
tool.setSourceMapsFileGenerated(profile.isSourceMapsGenerated()); tool.setSourceMapsFileGenerated(profile.isSourceMapsGenerated());
tool.setSourceFilesCopied(profile.isSourceFilesCopied());
String targetDir = profile.getTargetDirectory(); String targetDir = profile.getTargetDirectory();
tool.setTargetDirectory(new File(varManager.performStringSubstitution(targetDir, false))); tool.setTargetDirectory(new File(varManager.performStringSubstitution(targetDir, false)));
tool.setTargetFileName(profile.getTargetFileName()); tool.setTargetFileName(profile.getTargetFileName());
@ -118,6 +120,9 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
classAlias.setAlias(entry.getValue()); classAlias.setAlias(entry.getValue());
tool.getClassAliases().add(classAlias); tool.getClassAliases().add(classAlias);
} }
for (SourceFileProvider provider : sourceProviders) {
tool.addSourceFileProvider(provider);
}
tool.setProgressListener(new TeaVMEclipseProgressListener(this, monitor, TICKS_PER_PROFILE)); tool.setProgressListener(new TeaVMEclipseProgressListener(this, monitor, TICKS_PER_PROFILE));
try { try {
monitor.beginTask("Running TeaVM", 10000); monitor.beginTask("Running TeaVM", 10000);
@ -167,7 +172,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
} }
for (IProject project : getRelatedProjects()) { for (IProject project : getRelatedProjects()) {
IResourceDelta delta = getDelta(project); IResourceDelta delta = getDelta(project);
if (shouldBuild(classes, delta)) { if (delta != null && shouldBuild(classes, delta)) {
return true; return true;
} }
} }
@ -405,6 +410,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
private void prepareClassPath() throws CoreException { private void prepareClassPath() throws CoreException {
classPath = new URL[0]; classPath = new URL[0];
sourceContainers = new IContainer[0]; sourceContainers = new IContainer[0];
sourceProviders = new SourceFileProvider[0];
IProject project = getProject(); IProject project = getProject();
if (!project.hasNature(JavaCore.NATURE_ID)) { if (!project.hasNature(JavaCore.NATURE_ID)) {
return; return;
@ -413,6 +419,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
PathCollector collector = new PathCollector(); PathCollector collector = new PathCollector();
SourcePathCollector srcCollector = new SourcePathCollector(); SourcePathCollector srcCollector = new SourcePathCollector();
SourcePathCollector binCollector = new SourcePathCollector(); SourcePathCollector binCollector = new SourcePathCollector();
SourceFileCollector sourceFileCollector = new SourceFileCollector();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot(); IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
try { try {
if (javaProject.getOutputLocation() != null) { if (javaProject.getOutputLocation() != null) {
@ -423,53 +430,70 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true); Queue<IJavaProject> projectQueue = new ArrayDeque<>();
for (IClasspathEntry entry : entries) { projectQueue.add(javaProject);
switch (entry.getEntryKind()) { Set<IJavaProject> visitedProjects = new HashSet<>();
case IClasspathEntry.CPE_LIBRARY: while (!projectQueue.isEmpty()) {
try { javaProject = projectQueue.remove();
collector.addPath(entry.getPath()); if (!visitedProjects.add(javaProject)) {
} catch (MalformedURLException e) { continue;
TeaVMEclipsePlugin.logError(e); }
} IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
break; for (IClasspathEntry entry : entries) {
case IClasspathEntry.CPE_SOURCE: switch (entry.getEntryKind()) {
if (entry.getOutputLocation() != null) { case IClasspathEntry.CPE_LIBRARY:
try { try {
collector.addPath(workspaceRoot.findMember(entry.getOutputLocation()).getLocation()); collector.addPath(entry.getPath());
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
} if (entry.getSourceAttachmentPath() != null) {
IContainer srcContainer = (IContainer)workspaceRoot.findMember(entry.getPath()); sourceFileCollector.addFile(entry.getSourceAttachmentPath());
if (srcContainer != null && srcContainer.getProject() == project) { }
srcCollector.addContainer(srcContainer); break;
} case IClasspathEntry.CPE_SOURCE:
break; if (entry.getOutputLocation() != null) {
case IClasspathEntry.CPE_PROJECT: { try {
IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath()); collector.addPath(workspaceRoot.findMember(entry.getOutputLocation()).getLocation());
IProject depProject = resource.getProject(); } catch (MalformedURLException e) {
if (!depProject.hasNature(JavaCore.NATURE_ID)) { 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; 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(); classPath = collector.getUrls();
sourceContainers = srcCollector.getContainers(); sourceContainers = srcCollector.getContainers();
classFileContainers = binCollector.getContainers(); classFileContainers = binCollector.getContainers();
sourceProviders = sourceFileCollector.getProviders();
} }
static class PathCollector { static class PathCollector {
@ -497,6 +521,30 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
} }
} }
static class SourceFileCollector {
private Set<String> files = new HashSet<>();
private List<SourceFileProvider> 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 { static class SourcePathCollector {
private Set<IContainer> containerSet = new HashSet<>(); private Set<IContainer> containerSet = new HashSet<>();
private List<IContainer> containers = new ArrayList<>(); private List<IContainer> containers = new ArrayList<>();

View File

@ -69,6 +69,7 @@ public class TeaVMProfileDialog extends Dialog {
private Button cacheDirectoryFileSystemButton; private Button cacheDirectoryFileSystemButton;
private Button debugInformationButton; private Button debugInformationButton;
private Button sourceMapsButton; private Button sourceMapsButton;
private Button sourceFilesCopiedButton;
private TableViewer propertiesTableViewer; private TableViewer propertiesTableViewer;
private Button addPropertyButton; private Button addPropertyButton;
private Button deletePropertyButton; private Button deletePropertyButton;
@ -173,6 +174,7 @@ public class TeaVMProfileDialog extends Dialog {
Group group = createGroup(parent, "Debug settings", 1, false); Group group = createGroup(parent, "Debug settings", 1, false);
createDebugInformationField(group); createDebugInformationField(group);
createSourceMapsField(group); createSourceMapsField(group);
createSourceFilesCopiedField(group);
} }
private void createPropertiesGroup(Composite parent) { private void createPropertiesGroup(Composite parent) {
@ -521,6 +523,11 @@ public class TeaVMProfileDialog extends Dialog {
sourceMapsButton.setText("Generate source maps"); 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 { public void setProject(IProject project) throws CoreException {
if (project.hasNature(JavaCore.NATURE_ID)) { if (project.hasNature(JavaCore.NATURE_ID)) {
this.javaProject = JavaCore.create(project); this.javaProject = JavaCore.create(project);
@ -668,6 +675,7 @@ public class TeaVMProfileDialog extends Dialog {
cacheDirectoryField.setText(profile.getCacheDirectory()); cacheDirectoryField.setText(profile.getCacheDirectory());
debugInformationButton.setSelection(profile.isDebugInformationGenerated()); debugInformationButton.setSelection(profile.isDebugInformationGenerated());
sourceMapsButton.setSelection(profile.isSourceMapsGenerated()); sourceMapsButton.setSelection(profile.isSourceMapsGenerated());
sourceFilesCopiedButton.setSelection(profile.isSourceFilesCopied());
propertyList.clear(); propertyList.clear();
Properties properties = profile.getProperties(); Properties properties = profile.getProperties();
for (Object key : properties.keySet()) { for (Object key : properties.keySet()) {
@ -708,6 +716,7 @@ public class TeaVMProfileDialog extends Dialog {
profile.setCacheDirectory(cacheDirectoryField.getText()); profile.setCacheDirectory(cacheDirectoryField.getText());
profile.setDebugInformationGenerated(debugInformationButton.getSelection()); profile.setDebugInformationGenerated(debugInformationButton.getSelection());
profile.setSourceMapsGenerated(sourceMapsButton.getSelection()); profile.setSourceMapsGenerated(sourceMapsButton.getSelection());
profile.setSourceFilesCopied(sourceFilesCopiedButton.getSelection());
Properties properties = new Properties(); Properties properties = new Properties();
for (Object item : propertyList) { for (Object item : propertyList) {
KeyValue property = (KeyValue)item; KeyValue property = (KeyValue)item;