Further attempt to make eclipse plugin working

This commit is contained in:
konsoletyper 2014-07-31 15:56:12 +04:00
parent 4b43cbce55
commit 92ba9afee6
17 changed files with 698 additions and 37 deletions

View File

@ -24,6 +24,8 @@
</parent>
<artifactId>teavm-chrome-rdp</artifactId>
<packaging>bundle</packaging>
<name>TeaVM debugging backend for Google Chrome RDP</name>
<description>TeaVM debugging backend for Google Chrome RDP</description>

View File

@ -1,11 +0,0 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: TeaVM eclipse support
Bundle-SymbolicName: teavm-eclipse;singleton:=true
Bundle-Version: 0.2.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.eclipse.debug.core;bundle-version="3.8.0",
org.eclipse.debug.ui;bundle-version="3.9.0",
org.eclipse.core.runtime;bundle-version="3.9.0",
org.eclipse.swt;bundle-version="3.102.0",
org.eclipse.jdt.debug;bundle-version="3.8.0"

View File

@ -1,4 +0,0 @@
source.. = src/main/java/
output.. = target/
bin.includes = META-INF/,\
.

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin id="org.teavm.eclipse" name="TeaVM plugin" version="1.0">
</plugin>

60
teavm-eclipse/pom.xml Normal file
View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.teavm</groupId>
<artifactId>teavm</artifactId>
<version>0.2-SNAPSHOT</version>
</parent>
<artifactId>teavm-eclipse</artifactId>
<packaging>bundle</packaging>
<repositories>
<repository>
<id>swt-repo</id>
<url>https://swt-repo.googlecode.com/svn/repo/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.teavm</groupId>
<artifactId>teavm-chrome-rdp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.core</groupId>
<artifactId>runtime</artifactId>
<version>3.9.100-v20131218-1515</version>
</dependency>
<dependency>
<groupId>org.eclipse.swt</groupId>
<artifactId>org.eclipse.swt.win32.win32.x86</artifactId>
<version>4.2.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>org.teavm.eclipse.*</Export-Package>
<Bundle-SymbolicName>teavm-eclipse</Bundle-SymbolicName>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,19 @@
package org.teavm.eclipse;
import org.eclipse.core.runtime.Plugin;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMEclipsePlugin extends Plugin {
private static TeaVMEclipsePlugin defaultInstance;
public TeaVMEclipsePlugin() {
defaultInstance = this;
}
public static TeaVMEclipsePlugin getDefault() {
return defaultInstance;
}
}

View File

@ -0,0 +1,72 @@
package org.teavm.eclipse.debugger;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
@SuppressWarnings("rawtypes")
public class TeaVMDebugProcess implements IProcess {
private Map<String, String> attributes = new HashMap<>();
private ILaunch launch;
private TeaVMStreamsProxy streamsProxy = new TeaVMStreamsProxy();
public TeaVMDebugProcess(ILaunch launch) {
this.launch = launch;
}
@Override
public Object getAdapter(Class arg0) {
return null;
}
@Override
public boolean canTerminate() {
return false;
}
@Override
public boolean isTerminated() {
return false;
}
@Override
public void terminate() throws DebugException {
}
@Override
public String getAttribute(String attr) {
return attributes.get(attr);
}
@Override
public int getExitValue() throws DebugException {
return 0;
}
@Override
public String getLabel() {
return "TeaVM debug process";
}
@Override
public ILaunch getLaunch() {
return launch;
}
@Override
public IStreamsProxy getStreamsProxy() {
return streamsProxy;
}
@Override
public void setAttribute(String attr, String value) {
attributes.put(attr, value);
}
}

View File

@ -1,6 +1,10 @@
package org.teavm.eclipse.debugger;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
@ -8,11 +12,9 @@ import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.teavm.chromerdp.ChromeRDPServer;
import org.teavm.debugging.Breakpoint;
import org.teavm.debugging.Debugger;
@ -24,15 +26,19 @@ import org.teavm.debugging.DebuggerListener;
*/
@SuppressWarnings("rawtypes")
public class TeaVMDebugTarget implements IDebugTarget {
private ILaunch launch;
private Debugger teavmDebugger;
ILaunch launch;
Debugger teavmDebugger;
private ChromeRDPServer server;
private boolean terminated;
private TeaVMDebugProcess process;
Map<IBreakpoint, Breakpoint> breakpointMap = new HashMap<>();
Map<Breakpoint, IBreakpoint> breakpointBackMap = new HashMap<>();
public TeaVMDebugTarget(ILaunch launch, Debugger teavmDebugger, ChromeRDPServer server) {
this.launch = launch;
this.teavmDebugger = teavmDebugger;
this.server = server;
this.process = new TeaVMDebugProcess(launch);
teavmDebugger.addListener(new DebuggerListener() {
@Override
public void resumed() {
@ -50,7 +56,11 @@ public class TeaVMDebugTarget implements IDebugTarget {
}
@Override
public void breakpointStatusChanged(Breakpoint breakpoint) {
public void breakpointStatusChanged(Breakpoint teavmBreakpoint) {
IBreakpoint breakpoint = breakpointBackMap.get(teavmBreakpoint);
if (breakpoint != null) {
fireEvent(new DebugEvent(breakpoint, DebugEvent.CHANGE));
}
}
@Override
@ -87,25 +97,35 @@ public class TeaVMDebugTarget implements IDebugTarget {
@Override
public void breakpointAdded(IBreakpoint breakpoint) {
if (!(breakpoint instanceof ILineBreakpoint)) {
return;
}
IJavaLineBreakpoint lineBreakpoint = (IJavaLineBreakpoint)breakpoint;
try {
lineBreakpoint.setRegistered(true);
String fileName = lineBreakpoint.getTypeName().replace('.', '/') + ".java";
teavmDebugger.createBreakpoint(fileName, lineBreakpoint.getLineNumber());
breakpoint.setRegistered(true);
int line = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, 1);
String fileName = getRelativePath(breakpoint.getMarker().getResource());
teavmDebugger.createBreakpoint(fileName, line);
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
private String getRelativePath(IResource resource) {
if ((resource.getType() & IResource.PROJECT) != 0 ||
(resource.getType() & IResource.VIRTUAL) != 0) {
return "";
}
return getRelativePath(resource.getParent()) + "/" + resource.getName();
}
@Override
public void breakpointChanged(IBreakpoint arg0, IMarkerDelta arg1) {
}
@Override
public void breakpointRemoved(IBreakpoint arg0, IMarkerDelta arg1) {
public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta markerDelta) {
Breakpoint teavmBreakpoint = breakpointMap.remove(breakpoint);
if (teavmBreakpoint != null) {
teavmBreakpoint.destroy();
breakpointBackMap.remove(teavmBreakpoint);
}
}
@Override
@ -155,7 +175,7 @@ public class TeaVMDebugTarget implements IDebugTarget {
@Override
public String getModelIdentifier() {
return "";
return "org.teavm.eclipse.debugger";
}
@Override
@ -179,7 +199,7 @@ public class TeaVMDebugTarget implements IDebugTarget {
@Override
public IProcess getProcess() {
return null;
return process;
}
@Override
@ -189,11 +209,16 @@ public class TeaVMDebugTarget implements IDebugTarget {
@Override
public boolean hasThreads() throws DebugException {
return false;
return true;
}
@Override
public boolean supportsBreakpoint(IBreakpoint breakpoint) {
return breakpoint instanceof IJavaLineBreakpoint;
try {
return breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER) != null;
} catch (CoreException e) {
// TODO: Log this exception
return false;
}
}
}

View File

@ -0,0 +1,15 @@
package org.teavm.eclipse.debugger;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMSourceLookupDirector extends AbstractSourceLookupDirector {
@Override
public void initializeParticipants() {
addParticipants(new ISourceLookupParticipant[] { new TeaVMSourceLookupParticipant() });
}
}

View File

@ -0,0 +1,21 @@
package org.teavm.eclipse.debugger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
import org.teavm.debugging.SourceLocation;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMSourceLookupParticipant extends AbstractSourceLookupParticipant {
@Override
public String getSourceName(Object object) throws CoreException {
if (object instanceof TeaVMStackFrame) {
TeaVMStackFrame stackFrame = (TeaVMStackFrame)object;
SourceLocation location = stackFrame.callFrame.getLocation();
return location != null ? location.getFileName() : null;
}
return null;
}
}

View File

@ -0,0 +1,158 @@
package org.teavm.eclipse.debugger;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import org.teavm.debugging.CallFrame;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMStackFrame implements IStackFrame {
private TeaVMThread thread;
CallFrame callFrame;
public TeaVMStackFrame(TeaVMThread thread, CallFrame callFrame) {
this.thread = thread;
this.callFrame = callFrame;
}
@Override
public boolean canTerminate() {
return false;
}
@Override
public boolean isTerminated() {
return false;
}
@Override
public void terminate() throws DebugException {
}
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class type) {
return null;
}
@Override
public boolean canStepInto() {
return false;
}
@Override
public boolean canStepOver() {
return false;
}
@Override
public boolean canStepReturn() {
return false;
}
@Override
public boolean isStepping() {
return false;
}
@Override
public void stepInto() throws DebugException {
}
@Override
public void stepOver() throws DebugException {
}
@Override
public void stepReturn() throws DebugException {
}
@Override
public boolean canResume() {
return false;
}
@Override
public boolean canSuspend() {
return false;
}
@Override
public boolean isSuspended() {
return false;
}
@Override
public void resume() throws DebugException {
}
@Override
public void suspend() throws DebugException {
}
@Override
public IDebugTarget getDebugTarget() {
return thread.getDebugTarget();
}
@Override
public ILaunch getLaunch() {
return thread.getLaunch();
}
@Override
public String getModelIdentifier() {
return thread.getModelIdentifier();
}
@Override
public int getCharEnd() throws DebugException {
return -1;
}
@Override
public int getCharStart() throws DebugException {
return -1;
}
@Override
public int getLineNumber() throws DebugException {
return callFrame.getLocation() != null ? callFrame.getLocation().getLine() : -1;
}
@Override
public String getName() throws DebugException {
return callFrame.getLocation() != null ? callFrame.getLocation().getFileName() : "unknown";
}
@Override
public IRegisterGroup[] getRegisterGroups() throws DebugException {
return null;
}
@Override
public IThread getThread() {
return thread;
}
@Override
public IVariable[] getVariables() throws DebugException {
return new IVariable[0];
}
@Override
public boolean hasRegisterGroups() throws DebugException {
return false;
}
@Override
public boolean hasVariables() throws DebugException {
return true;
}
}

View File

@ -0,0 +1,23 @@
package org.teavm.eclipse.debugger;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IStreamMonitor;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMStreamMonitor implements IStreamMonitor {
@Override
public void addListener(IStreamListener listener) {
}
@Override
public String getContents() {
return "";
}
@Override
public void removeListener(IStreamListener arg0) {
}
}

View File

@ -0,0 +1,26 @@
package org.teavm.eclipse.debugger;
import java.io.IOException;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
// TODO: implement interaction with browser console
public class TeaVMStreamsProxy implements IStreamsProxy {
@Override
public IStreamMonitor getErrorStreamMonitor() {
return new TeaVMStreamMonitor();
}
@Override
public IStreamMonitor getOutputStreamMonitor() {
return new TeaVMStreamMonitor();
}
@Override
public void write(String text) throws IOException {
}
}

View File

@ -0,0 +1,146 @@
package org.teavm.eclipse.debugger;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.teavm.debugging.Debugger;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMThread implements IThread {
private Debugger teavmDebugger;
private TeaVMDebugTarget debugTarget;
public TeaVMThread(TeaVMDebugTarget debugTarget) {
this.debugTarget = debugTarget;
this.teavmDebugger = debugTarget.teavmDebugger;
}
@Override
public boolean canTerminate() {
return false;
}
@Override
public boolean isTerminated() {
return false;
}
@Override
public void terminate() throws DebugException {
}
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class type) {
return null;
}
@Override
public boolean canResume() {
return false;
}
@Override
public boolean canSuspend() {
return false;
}
@Override
public boolean isSuspended() {
return teavmDebugger.isSuspended();
}
@Override
public void resume() throws DebugException {
}
@Override
public void suspend() throws DebugException {
}
@Override
public boolean canStepInto() {
return true;
}
@Override
public boolean canStepOver() {
return true;
}
@Override
public boolean canStepReturn() {
return true;
}
@Override
public boolean isStepping() {
return false;
}
@Override
public void stepInto() throws DebugException {
teavmDebugger.stepInto();
}
@Override
public void stepOver() throws DebugException {
teavmDebugger.stepOver();
}
@Override
public void stepReturn() throws DebugException {
teavmDebugger.stepOut();
}
@Override
public IDebugTarget getDebugTarget() {
return debugTarget;
}
@Override
public ILaunch getLaunch() {
return debugTarget.launch;
}
@Override
public String getModelIdentifier() {
return debugTarget.getModelIdentifier();
}
@Override
public IBreakpoint[] getBreakpoints() {
return debugTarget.breakpointMap.keySet().toArray(new IBreakpoint[0]);
}
@Override
public String getName() throws DebugException {
return "main";
}
@Override
public int getPriority() throws DebugException {
return 0;
}
@Override
public IStackFrame[] getStackFrames() throws DebugException {
return null;
}
@Override
public IStackFrame getTopStackFrame() throws DebugException {
return null;
}
@Override
public boolean hasStackFrames() throws DebugException {
return true;
}
}

View File

@ -0,0 +1,68 @@
package org.teavm.eclipse.debugger.ui;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMTab extends AbstractLaunchConfigurationTab {
private Text portField;
@Override
public void createControl(Composite container) {
Composite root = new Composite(container, SWT.NONE);
GridLayout layout = new GridLayout();
layout.verticalSpacing = 6;
layout.numColumns = 2;
root.setLayout(layout);
Label portLabel = new Label(root, SWT.NONE);
portLabel.setText("&Port");
portLabel.setLayoutData(new GridData(GridData.BEGINNING));
portField = new Text(root, SWT.SINGLE | SWT.BORDER);
portField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
portField.addModifyListener(new ModifyListener() {
@Override public void modifyText(ModifyEvent event) {
updateLaunchConfigurationDialog();
}
});
}
@Override
public String getName() {
return null;
}
@Override
public void initializeFrom(ILaunchConfiguration configuration) {
try {
int attr = configuration.getAttribute("teavm-debugger-port", 2357);
portField.setText(String.valueOf(attr));
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
@Override
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute("teavm-debugger-port", Integer.parseInt(portField.getText()));
}
@Override
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute("teavm-debugger-port", 2357);
}
}

View File

@ -0,0 +1,18 @@
package org.teavm.eclipse.debugger.ui;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
import org.eclipse.debug.ui.CommonTab;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TeaVMTabGroup extends AbstractLaunchConfigurationTabGroup {
@Override
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
setTabs(new ILaunchConfigurationTab[] { new TeaVMTab(), new SourceLookupTab(), new CommonTab() });
}
}

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin id="org.teavm.eclipse" version="0.2" name="TeaVM plugin" class="org.teavm.eclipse.TeaVMEclipsePlugin">
<extension point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
sourceLocatorId="org.teavm.eclipse.debugger.sourceLookup"
name="TeaVM remote"
delegate="org.teavm.eclipse.debugger.TeaVMLaunchConfigurationDelegate"
modes="debug"
id="org.teavm.eclipse.debugger.launchConfig">
</launchConfigurationType>
</extension>
<extension point="org.eclipse.debug.core.sourceLocators">
<sourceLocator
name="TeaVM Source Lookup Director"
class="org.teavm.eclipse.debugger.TeaVMSourceLookupDirector"
id="org.teavm.eclipse.debugger.sourceLookup">
</sourceLocator>
</extension>
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
type="org.teavm.eclipse.debugger.launchConfig"
description="Debug TeaVM program"
class="org.teavm.eclipse.debugger.ui.TeaVMTabGroup"
id="org.teavm.eclipse.debugger.ui.tabs">
</launchConfigurationTabGroup>
</extension>
</plugin>