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>
<configuration>
<minifying>false</minifying>
<sourceMapsGenerated>true</sourceMapsGenerated>
<sourceFilesCopied>true</sourceFilesCopied>
<properties>
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
</properties>

View File

@ -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<String> 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);

View File

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

View File

@ -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<String, String> 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()) {

View File

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

View File

@ -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<IProject> usedProjects = new HashSet<>();
private static Map<TeaVMProfile, Set<String>> 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<IJavaProject> projectQueue = new ArrayDeque<>();
projectQueue.add(javaProject);
Set<IJavaProject> 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<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 {
private Set<IContainer> containerSet = new HashSet<>();
private List<IContainer> containers = new ArrayList<>();

View File

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