diff --git a/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF b/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF
index b12c1d49a..23396ace7 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF
+++ b/teavm-eclipse/teavm-eclipse-plugin/META-INF/MANIFEST.MF
@@ -54,3 +54,4 @@ Bundle-ClassPath: .,
lib/websocket-server-9.2.1.v20140609.jar,
lib/websocket-servlet-9.2.1.v20140609.jar
Export-Package: org.teavm.eclipse.debugger
+Bundle-ActivationPolicy: lazy
diff --git a/teavm-eclipse/teavm-eclipse-plugin/plugin.xml b/teavm-eclipse/teavm-eclipse-plugin/plugin.xml
index ec6c9a8e6..1d25682f8 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/plugin.xml
+++ b/teavm-eclipse/teavm-eclipse-plugin/plugin.xml
@@ -52,9 +52,13 @@
-
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipsePlugin.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipsePlugin.java
index afe47a4ee..06b20a7e4 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipsePlugin.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/TeaVMEclipsePlugin.java
@@ -15,22 +15,20 @@
*/
package org.teavm.eclipse;
-import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
/**
*
* @author Alexey Andreev
*/
-public class TeaVMEclipsePlugin extends Plugin {
+public class TeaVMEclipsePlugin extends AbstractUIPlugin {
public static final String ID = "org.teavm.eclipse";
-
- public static final String NATURE_ID = "org.teavm.eclipse.nature";
-
+ public static final String NATURE_ID = ID + ".nature";
+ public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod";
private static TeaVMEclipsePlugin defaultInstance;
- static {
- }
-
public TeaVMEclipsePlugin() {
defaultInstance = this;
}
@@ -38,4 +36,12 @@ public class TeaVMEclipsePlugin extends Plugin {
public static TeaVMEclipsePlugin getDefault() {
return defaultInstance;
}
+
+ public static IStatus makeError(Throwable e) {
+ return new Status(IStatus.ERROR, ID, "Error occured", e);
+ }
+
+ public static void logError(Throwable e) {
+ getDefault().getLog().log(makeError(e));
+ }
}
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/MainClassSelectionDialog.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/MainClassSelectionDialog.java
new file mode 100644
index 000000000..666b1783b
--- /dev/null
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/MainClassSelectionDialog.java
@@ -0,0 +1,146 @@
+package org.teavm.eclipse.ui;
+
+import static org.teavm.eclipse.TeaVMEclipsePlugin.MAIN_METHOD_DIALOG_ID;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
+import org.teavm.eclipse.TeaVMEclipsePlugin;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class MainClassSelectionDialog extends FilteredItemsSelectionDialog {
+ private IJavaProject javaProject;
+
+ public MainClassSelectionDialog(Shell shell, IJavaProject javaProject) {
+ super(shell, false);
+ this.javaProject = javaProject;
+ setTitle("Searching main class");
+ LabelProvider labelProvider = new LabelProvider() {
+ @Override public String getText(Object element) {
+ return getElementName(element);
+ }
+ };
+ setListLabelProvider(labelProvider);
+ setDetailsLabelProvider(labelProvider);
+ }
+
+ @Override
+ protected Control createExtendedContentArea(Composite parent) {
+ return null;
+ }
+
+ @Override
+ protected ItemsFilter createFilter() {
+ return new ItemsFilter() {
+ @Override public boolean matchItem(Object item) {
+ IType type = (IType)item;
+ return type.getTypeQualifiedName().toLowerCase().contains(getPattern().toLowerCase());
+ }
+ @Override public boolean isConsistentItem(Object item) {
+ return item instanceof IType;
+ }
+ };
+ }
+
+ @Override
+ protected void fillContentProvider(AbstractContentProvider contentProvider, ItemsFilter filter,
+ IProgressMonitor progressMonitor) throws CoreException {
+ IType[] mainTypes = findMainTypes(progressMonitor);
+ for (IType type : mainTypes) {
+ contentProvider.add(type, filter);
+ }
+ }
+
+ @Override
+ protected IDialogSettings getDialogSettings() {
+ IDialogSettings settings = TeaVMEclipsePlugin.getDefault().getDialogSettings();
+ IDialogSettings section = settings.getSection(MAIN_METHOD_DIALOG_ID);
+ if (section == null) {
+ section = settings.addNewSection(MAIN_METHOD_DIALOG_ID);
+ }
+ return section;
+ }
+
+ @Override
+ public String getElementName(Object element) {
+ IType type = (IType)element;
+ return getTypeName(type);
+ }
+
+ private String getTypeName(IType type) {
+ if (type == null) {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder(type.getTypeQualifiedName());
+ if (type.getPackageFragment() != null) {
+ sb.append(" in ").append(type.getPackageFragment().getElementName());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ protected Comparator> getItemsComparator() {
+ return new Comparator() {
+ @Override public int compare(IType o1, IType o2) {
+ return getTypeName(o1).compareTo(getTypeName(o2));
+ }
+ };
+ }
+
+ @Override
+ protected IStatus validateItem(Object item) {
+ return Status.OK_STATUS;
+ }
+
+ private IType[] findMainTypes(IProgressMonitor progressMonitor) {
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] { javaProject },
+ IJavaSearchScope.SOURCES | IJavaSearchScope.REFERENCED_PROJECTS |
+ IJavaSearchScope.APPLICATION_LIBRARIES);
+ SearchPattern pattern = SearchPattern.createPattern("main(String[]) void", IJavaSearchConstants.METHOD,
+ IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
+ SearchParticipant[] participants = new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() };
+ MainClassCollector collector = new MainClassCollector();
+ try {
+ new SearchEngine().search(pattern, participants, scope, collector, progressMonitor);
+ } catch (CoreException e) {
+ logError(e);
+ return new IType[0];
+ }
+ IType[] foundTypes = collector.getTypes().toArray(new IType[collector.getTypes().size()]);
+ return foundTypes;
+ }
+
+ private void logError(Throwable e) {
+ IStatus status = TeaVMEclipsePlugin.makeError(e);
+ TeaVMEclipsePlugin.getDefault().getLog().log(status);
+ ErrorDialog.openError(getShell(), "Error", "Error", status);
+ }
+
+ private static class MainClassCollector extends SearchRequestor {
+ private Set types = new HashSet<>();
+
+ public Set getTypes() {
+ return types;
+ }
+
+ @Override
+ public void acceptSearchMatch(SearchMatch match) throws CoreException {
+ IMethod method = (IMethod)match.getElement();
+ if ((method.getFlags() & Flags.AccStatic) != 0) {
+ types.add(method.getDeclaringType());
+ }
+ }
+ }
+}
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java
index c1ba8eb0a..5dd75c37e 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyPage.java
@@ -1,10 +1,15 @@
package org.teavm.eclipse.ui;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbenchPropertyPage;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PropertyPage;
+import org.teavm.eclipse.TeaVMEclipsePlugin;
/**
*
@@ -16,7 +21,17 @@ public class TeaVMProjectPropertyPage extends PropertyPage implements IWorkbench
@Override
protected Control createContents(Composite parent) {
widget = new TeaVMProjectPropertyWidget(parent);
- widget.load((IProject)getElement().getAdapter(IProject.class));
+ widget.setRunnableContext(PlatformUI.getWorkbench().getProgressService());
+ IProject project = (IProject)getElement().getAdapter(IProject.class);
+ try {
+ if (project.hasNature(JavaCore.NATURE_ID)) {
+ IJavaProject javaProject = JavaCore.create(project);
+ widget.setJavaProject(javaProject);
+ }
+ } catch (CoreException e) {
+ TeaVMEclipsePlugin.logError(e);
+ }
+ widget.load(project);
return widget;
}
diff --git a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyWidget.java b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyWidget.java
index dd71da014..f296e6889 100644
--- a/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyWidget.java
+++ b/teavm-eclipse/teavm-eclipse-plugin/src/main/java/org/teavm/eclipse/ui/TeaVMProjectPropertyWidget.java
@@ -4,16 +4,27 @@ import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
import org.eclipse.jface.dialogs.ErrorDialog;
-import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.service.prefs.BackingStoreException;
import org.teavm.eclipse.TeaVMEclipsePlugin;
/**
@@ -22,6 +33,10 @@ import org.teavm.eclipse.TeaVMEclipsePlugin;
*/
public class TeaVMProjectPropertyWidget extends Composite {
private Button natureButton;
+ private Text mainClassField;
+ private Button mainClassChooseButton;
+ private IJavaProject javaProject;
+ private IRunnableContext runnableContext;
public TeaVMProjectPropertyWidget(Composite parent) {
super(parent, SWT.NONE);
@@ -31,22 +46,84 @@ public class TeaVMProjectPropertyWidget extends Composite {
setLayout(layout);
natureButton = new Button(this, SWT.CHECK);
natureButton.setText("TeaVM build enabled");
+ createOptionsContainer();
+
+ natureButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateEnabled(natureButton.getSelection());
+ }
+ });
+ }
+
+ private void updateEnabled(boolean enabled) {
+ mainClassField.setEnabled(enabled);
+ mainClassChooseButton.setEnabled(enabled);
+ }
+
+ private void createOptionsContainer() {
+ Composite container = new Composite(this, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.verticalSpacing = 6;
+ layout.horizontalSpacing = 6;
+ container.setLayout(layout);
+ createMainClassField(container);
+ }
+
+ private void createMainClassField(Composite container) {
+ Label label = new Label(container, SWT.NONE);
+ label.setText("Main class:");
+ Composite row = new Composite(container, SWT.NONE);
+ RowLayout rowLayout = new RowLayout();
+ row.setLayout(rowLayout);
+ rowLayout.type = SWT.HORIZONTAL;
+ rowLayout.spacing = 3;
+ mainClassField = new Text(row, SWT.SINGLE | SWT.BORDER);
+ RowData rowData = new RowData();
+ rowData.width = 300;
+ mainClassField.setLayoutData(rowData);
+ mainClassChooseButton = new Button(row, SWT.PUSH);
+ mainClassChooseButton.setText("Choose...");
+ mainClassChooseButton.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ chooseMainClass();
+ }
+ });
+ }
+
+ private void chooseMainClass() {
+ MainClassSelectionDialog selectionDialog = new MainClassSelectionDialog(getShell(), javaProject);
+ if (selectionDialog.open() == MainClassSelectionDialog.OK) {
+ Object[] result = selectionDialog.getResult();
+ if (result.length > 0) {
+ IType type = (IType)result[0];
+ mainClassField.setText(type.getFullyQualifiedName());
+ }
+ }
+ }
+
+ public void setJavaProject(IJavaProject javaProject) {
+ this.javaProject = javaProject;
+ }
+
+ public void setRunnableContext(IRunnableContext runnableContext) {
+ this.runnableContext = runnableContext;
}
public void load(IProject project) {
try {
natureButton.setSelection(project.hasNature(TeaVMEclipsePlugin.NATURE_ID));
- } catch (CoreException e) {
+ ProjectScope scope = new ProjectScope(project);
+ IEclipsePreferences preferences = scope.getNode(TeaVMEclipsePlugin.ID);
+ preferences.sync();
+ mainClassField.setText(preferences.get("mainClass", ""));
+ updateEnabled(natureButton.getSelection());
+ } catch (CoreException | BackingStoreException e) {
reportError(e);
}
}
- private void reportError(Throwable e) {
- e.printStackTrace();
- Status status = new Status(Status.ERROR, TeaVMEclipsePlugin.ID, getToolTipText(), e);
- ErrorDialog.openError(getShell(), "Error occured", "Error occured", status);
- }
-
public boolean save(IProject project) {
try {
if (natureButton.getSelection()) {
@@ -58,17 +135,20 @@ public class TeaVMProjectPropertyWidget extends Composite {
removeNature(project);
}
}
+ ProjectScope scope = new ProjectScope(project);
+ IEclipsePreferences preferences = scope.getNode(TeaVMEclipsePlugin.ID);
+ preferences.put("mainClass", mainClassField.getText().trim());
+ preferences.flush();
return true;
- } catch (CoreException e) {
+ } catch (CoreException | BackingStoreException e) {
reportError(e);
return false;
}
}
private void addNature(final IProject project) {
- ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(getShell());
try {
- progressDialog.run(false, true, new IRunnableWithProgress() {
+ runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
@@ -86,24 +166,25 @@ public class TeaVMProjectPropertyWidget extends Composite {
} catch (InterruptedException e) {
reportError(e);
} catch (InvocationTargetException e) {
- reportError(e.getTargetException());
+ return;
}
}
private void removeNature(final IProject project) {
- ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(getShell());
try {
- progressDialog.run(false, true, new IRunnableWithProgress() {
+ runnableContext.run(false, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
- String[] natureIds = project.getDescription().getNatureIds();
+ IProjectDescription projectDescription = project.getDescription();
+ String[] natureIds = projectDescription.getNatureIds();
String[] newNatureIds = new String[natureIds.length - 1];
for (int i = 0; i < natureIds.length; ++i) {
- if (natureIds.equals(TeaVMEclipsePlugin.NATURE_ID)) {
- System.arraycopy(natureIds, 0, newNatureIds, 0, i - 1);
+ if (natureIds[i].equals(TeaVMEclipsePlugin.NATURE_ID)) {
+ System.arraycopy(natureIds, 0, newNatureIds, 0, i);
System.arraycopy(natureIds, i + 1, newNatureIds, i, newNatureIds.length - i);
- project.getDescription().setNatureIds(newNatureIds);
+ projectDescription.setNatureIds(newNatureIds);
+ project.setDescription(projectDescription, monitor);
break;
}
}
@@ -115,7 +196,13 @@ public class TeaVMProjectPropertyWidget extends Composite {
} catch (InterruptedException e) {
reportError(e);
} catch (InvocationTargetException e) {
- reportError(e.getTargetException());
+ return;
}
}
+
+ private void reportError(Throwable e) {
+ IStatus status = TeaVMEclipsePlugin.makeError(e);
+ TeaVMEclipsePlugin.getDefault().getLog().log(status);
+ ErrorDialog.openError(getShell(), "Error occured", "Error occured", status);
+ }
}