diff --git a/teavm-core/src/main/java/org/teavm/codegen/LocationProvider.java b/teavm-core/src/main/java/org/teavm/codegen/LocationProvider.java new file mode 100644 index 000000000..18d5e9db6 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/codegen/LocationProvider.java @@ -0,0 +1,26 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.codegen; + +/** + * + * @author Alexey Andreev + */ +public interface LocationProvider { + int getLine(); + + int getColumn(); +} diff --git a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java index 1ca23eed4..058e3656e 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java +++ b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java @@ -25,14 +25,15 @@ import org.teavm.model.ValueType; * * @author Alexey Andreev */ -public class SourceWriter implements Appendable { +public class SourceWriter implements Appendable, LocationProvider { private Appendable innerWriter; private int indentSize; private NamingStrategy naming; private boolean lineStart; private boolean minified; private int lineWidth; - private int pos; + private int column; + private int line; SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) { this.naming = naming; @@ -64,7 +65,7 @@ public class SourceWriter implements Appendable { if (value == '\n') { newLine(); } else { - pos++; + column++; } return this; } @@ -94,7 +95,7 @@ public class SourceWriter implements Appendable { return; } appendIndent(); - pos += end - start; + column += end - start; innerWriter.append(csq, start, end); } @@ -131,7 +132,7 @@ public class SourceWriter implements Appendable { if (lineStart) { for (int i = 0; i < indentSize; ++i) { innerWriter.append(" "); - pos += 4; + column += 4; } lineStart = false; } @@ -139,25 +140,26 @@ public class SourceWriter implements Appendable { public SourceWriter newLine() throws IOException{ innerWriter.append('\n'); - pos = 0; + column = 0; + ++line; lineStart = true; return this; } public SourceWriter ws() throws IOException { - if (pos >= lineWidth) { + if (column >= lineWidth) { newLine(); } else { if (!minified) { innerWriter.append(' '); - pos++; + column++; } } return this; } public SourceWriter tokenBoundary() throws IOException { - if (pos >= lineWidth) { + if (column >= lineWidth) { newLine(); } return this; @@ -166,7 +168,7 @@ public class SourceWriter implements Appendable { public SourceWriter softNewLine() throws IOException{ if (!minified) { innerWriter.append('\n'); - pos = 0; + column = 0; lineStart = true; } return this; @@ -185,4 +187,14 @@ public class SourceWriter implements Appendable { public NamingStrategy getNaming() { return naming; } + + @Override + public int getColumn() { + return column; + } + + @Override + public int getLine() { + return line; + } } diff --git a/teavm-core/src/main/java/org/teavm/debugging/Breakpoint.java b/teavm-core/src/main/java/org/teavm/debugging/Breakpoint.java new file mode 100644 index 000000000..2be99d3d0 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/Breakpoint.java @@ -0,0 +1,77 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import java.util.List; + +/** + * + * @author Alexey Andreev + */ +public class Breakpoint { + private Debugger debugger; + private List jsBreakpoints; + private String fileName; + private int line; + private boolean enabled = true; + + Breakpoint(Debugger debugger, List jsBreakpoints, String fileName, int line) { + this.debugger = debugger; + this.jsBreakpoints = jsBreakpoints; + this.fileName = fileName; + this.line = line; + for (JavaScriptBreakpoint jsBreakpoint : jsBreakpoints) { + debugger.breakpointMap.put(jsBreakpoint.getId(), this); + } + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + if (this.enabled == enabled) { + return; + } + for (JavaScriptBreakpoint jsBreakpoint : jsBreakpoints) { + jsBreakpoint.setEnabled(enabled); + } + } + + public String getFileName() { + return fileName; + } + + public int getLine() { + return line; + } + + public void destroy() { + for (JavaScriptBreakpoint jsBreakpoint : jsBreakpoints) { + jsBreakpoint.destroy(); + debugger.breakpointMap.remove(jsBreakpoint.getId()); + } + jsBreakpoints.clear(); + } + + public boolean isDestroyed() { + return jsBreakpoints.isEmpty(); + } + + public Debugger getDebugger() { + return debugger; + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/CallFrame.java b/teavm-core/src/main/java/org/teavm/debugging/CallFrame.java new file mode 100644 index 000000000..59d55fc3f --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/CallFrame.java @@ -0,0 +1,32 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public class CallFrame { + private SourceLocation location; + + CallFrame(SourceLocation location) { + this.location = location; + } + + public SourceLocation getLocation() { + return location; + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java new file mode 100644 index 000000000..3d207156b --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java @@ -0,0 +1,82 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import java.util.*; +import org.teavm.model.MethodDescriptor; +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public class DebugInformation { + List fileNames = new ArrayList<>(); + Map fileNameMap = new HashMap<>(); + List classNames = new ArrayList<>(); + Map classNameMap = new HashMap<>(); + List methods = new ArrayList<>(); + Map methodMap = new HashMap<>(); + List fileDescriptions = new ArrayList<>(); + GeneratedLocation[] fileNameKeys; + int[] fileNameValues; + GeneratedLocation[] classKeys; + int[] classValues; + GeneratedLocation[] methodKeys; + int[] methodValues; + GeneratedLocation[] lineNumberKeys; + int[] lineNumberValues; + + public Collection getGeneratedLocations(String fileName, int lineNumber) { + Integer fileIndex = fileNameMap.get(fileName); + if (fileIndex == null) { + return Collections.emptyList(); + } + FileDescription description = fileDescriptions.get(lineNumber); + return lineNumber < description.generatedLocations.length ? + Arrays.asList(description.generatedLocations[lineNumber]) : + Collections.emptyList(); + } + + public SourceLocation getSourceLocation(int line, int column) { + return getSourceLocation(new GeneratedLocation(line, column)); + } + + public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) { + String fileName = componentByKey(fileNameKeys, fileNameValues, fileNames, generatedLocation); + String className = componentByKey(classKeys, classValues, classNames, generatedLocation); + MethodDescriptor method = componentByKey(methodKeys, methodValues, methods, generatedLocation); + int lineNumberIndex = indexByKey(lineNumberKeys, generatedLocation); + int lineNumber = lineNumberIndex >= 0 ? lineNumberValues[lineNumberIndex] : -1; + return new SourceLocation(fileName, lineNumber, new MethodReference(className, method)); + } + + private T componentByKey(GeneratedLocation[] keys, int[] valueIndexes, List values, + GeneratedLocation location) { + int keyIndex = indexByKey(keys, location); + int valueIndex = keyIndex >= 0 ? valueIndexes[keyIndex] : -1; + return valueIndex >= 0 ? values.get(valueIndex) : null; + } + + private int indexByKey(GeneratedLocation[] keys, GeneratedLocation location) { + int index = Arrays.binarySearch(keys, location); + return index >= 0 ? index : -index - 2; + } + + class FileDescription { + GeneratedLocation[][] generatedLocations; + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationBuilder.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationBuilder.java new file mode 100644 index 000000000..c43f18799 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationBuilder.java @@ -0,0 +1,50 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import org.teavm.codegen.LocationProvider; +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public class DebugInformationBuilder implements DebugInformationEmitter { + private LocationProvider locationProvider; + + public LocationProvider getLocationProvider() { + return locationProvider; + } + + public void setLocationProvider(LocationProvider locationProvider) { + this.locationProvider = locationProvider; + } + + @Override + public void emitFile(String fileName) { + + } + + @Override + public void emitMethod(MethodReference method) { + + } + + @Override + public void emitLineNumber(String lineNumber) { + + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationEmitter.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationEmitter.java new file mode 100644 index 000000000..718a48b5d --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationEmitter.java @@ -0,0 +1,30 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public interface DebugInformationEmitter { + void emitFile(String fileName); + + void emitMethod(MethodReference method); + + void emitLineNumber(String lineNumber); +} \ No newline at end of file diff --git a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java new file mode 100644 index 000000000..dbcaf7132 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java @@ -0,0 +1,148 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import java.util.*; + +/** + * + * @author Alexey Andreev + */ +// TODO: variable name handling +// TODO: class fields handling +public class Debugger { + private List listeners = new ArrayList<>(); + private JavaScriptDebugger javaScriptDebugger; + private DebugInformation debugInformation; + private List temporaryJsBreakpoints = new ArrayList<>(); + Map breakpointMap = new HashMap<>(); + private CallFrame[] callStack; + + public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformation debugInformation) { + this.javaScriptDebugger = javaScriptDebugger; + this.debugInformation = debugInformation; + javaScriptDebugger.addListener(javaScriptListener); + } + + public void addListener(DebuggerListener listener) { + listeners.add(listener); + } + + public void removeListener(DebuggerListener listener) { + listeners.remove(listener); + } + + public void suspend() { + javaScriptDebugger.suspend(); + } + + public void resume() { + javaScriptDebugger.resume(); + } + + public void stepInto() { + if (!javaScriptDebugger.isSuspended()) { + return; + } + javaScriptDebugger.stepInto(); + } + + public void stepOut() { + if (!javaScriptDebugger.isSuspended()) { + return; + } + // TODO: lookup all locations that are "out of" the current location and create temporary breakpoints + } + + public void stepOver() { + if (!javaScriptDebugger.isSuspended()) { + return; + } + // TODO: lookup all locations that are "after" the current location and create temporary breakpoints + } + + public void continueToLocation(String fileName, int line) { + if (!javaScriptDebugger.isSuspended()) { + return; + } + Collection locations = debugInformation.getGeneratedLocations(fileName, line); + for (GeneratedLocation location : locations) { + JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(location); + if (jsBreakpoint != null) { + temporaryJsBreakpoints.add(jsBreakpoint); + } + } + javaScriptDebugger.resume(); + } + + public boolean isSuspended() { + return javaScriptDebugger.isSuspended(); + } + + public Breakpoint createBreakpoint(String fileName, int line) { + Collection locations = debugInformation.getGeneratedLocations(fileName, line); + List jsBreakpoints = new ArrayList<>(); + for (GeneratedLocation location : locations) { + JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(location); + if (jsBreakpoint != null) { + jsBreakpoints.add(jsBreakpoint); + } + } + return !jsBreakpoints.isEmpty() ? new Breakpoint(this, jsBreakpoints, fileName, line) : null; + } + + public CallFrame[] getCallStack() { + if (isSuspended()) { + return null; + } + if (callStack == null) { + // TODO: with inlining enabled we can have several JVM methods compiled into one JavaScript function + // so we must consider this case. + List frames = new ArrayList<>(); + boolean wasEmpty = false; + for (JavaScriptCallFrame jsFrame : javaScriptDebugger.getCallStack()) { + SourceLocation loc = debugInformation.getSourceLocation(jsFrame.getLocation()); + boolean empty = loc.getFileName() != null || loc.getMethod() != null || loc.getLine() < 0; + if (!empty || !wasEmpty) { + frames.add(new CallFrame(loc)); + } + wasEmpty = empty; + } + callStack = frames.toArray(new CallFrame[0]); + } + return callStack.clone(); + } + + private JavaScriptDebuggerListener javaScriptListener = new JavaScriptDebuggerListener() { + @Override + public void resumed() { + for (JavaScriptBreakpoint jsBreakpoint : temporaryJsBreakpoints) { + jsBreakpoint.destroy(); + } + temporaryJsBreakpoints.clear(); + for (DebuggerListener listener : listeners) { + listener.resumed(); + } + } + + @Override + public void paused() { + for (DebuggerListener listener : listeners) { + listener.paused(); + } + } + }; +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebuggerListener.java b/teavm-core/src/main/java/org/teavm/debugging/DebuggerListener.java new file mode 100644 index 000000000..fed17ae70 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/DebuggerListener.java @@ -0,0 +1,26 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public interface DebuggerListener { + void resumed(); + + void paused(); +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/DummyDebugInformationEmitter.java b/teavm-core/src/main/java/org/teavm/debugging/DummyDebugInformationEmitter.java new file mode 100644 index 000000000..43c6b20b1 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/DummyDebugInformationEmitter.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import org.teavm.model.MethodReference; + + +/** + * + * @author Alexey Andreev + */ +public class DummyDebugInformationEmitter implements DebugInformationEmitter { + @Override + public void emitFile(String fileName) { + } + + @Override + public void emitMethod(MethodReference method) { + } + + @Override + public void emitLineNumber(String lineNumber) { + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/GeneratedLocation.java b/teavm-core/src/main/java/org/teavm/debugging/GeneratedLocation.java new file mode 100644 index 000000000..250c26b5c --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/GeneratedLocation.java @@ -0,0 +1,47 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public class GeneratedLocation implements Comparable { + private int line; + private int column; + + public GeneratedLocation(int line, int column) { + this.line = line; + this.column = column; + } + + public int getLine() { + return line; + } + + public int getColumn() { + return column; + } + + @Override + public int compareTo(GeneratedLocation o) { + int r = Integer.compare(line, o.line); + if (r == 0) { + r = Integer.compare(column, o.column); + } + return r; + } +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java new file mode 100644 index 000000000..5923c7426 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public interface JavaScriptBreakpoint { + boolean isEnabled(); + + void setEnabled(boolean enabled); + + String getId(); + + String getFileName(); + + GeneratedLocation getLocation(); + + void destroy(); +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java new file mode 100644 index 000000000..21bfcbbed --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public interface JavaScriptCallFrame { + GeneratedLocation getLocation(); +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java new file mode 100644 index 000000000..b8114193a --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java @@ -0,0 +1,46 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public interface JavaScriptDebugger { + void addListener(JavaScriptDebuggerListener listener); + + void removeListener(JavaScriptDebuggerListener listener); + + void suspend(); + + void resume(); + + void stepInto(); + + void stepOut(); + + void stepOver(); + + void continueToLocation(GeneratedLocation location); + + boolean isSuspended(); + + JavaScriptCallFrame[] getCallStack(); + + JavaScriptBreakpoint getCurrentBreakpoint(); + + JavaScriptBreakpoint createBreakpoint(GeneratedLocation location); +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java new file mode 100644 index 000000000..a8b076bba --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java @@ -0,0 +1,26 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +/** + * + * @author Alexey Andreev + */ +public interface JavaScriptDebuggerListener { + void paused(); + + void resumed(); +} diff --git a/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java b/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java new file mode 100644 index 000000000..9be482085 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java @@ -0,0 +1,46 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.debugging; + +import org.teavm.model.MethodReference; + +/** + * + * @author Alexey Andreev + */ +public class SourceLocation { + private String fileName; + private int line; + private MethodReference method; + + public SourceLocation(String fileName, int line, MethodReference method) { + this.fileName = fileName; + this.line = line; + this.method = method; + } + + public String getFileName() { + return fileName; + } + + public int getLine() { + return line; + } + + public MethodReference getMethod() { + return method; + } +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/AssignmentStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/AssignmentStatement.java index 9aa5b965a..49f670f8b 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/AssignmentStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/AssignmentStatement.java @@ -1,12 +1,12 @@ /* * Copyright 2011 Alexey Andreev. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,12 +16,13 @@ package org.teavm.javascript.ast; /** - * + * * @author Alexey Andreev */ public class AssignmentStatement extends Statement { private Expr leftValue; private Expr rightValue; + private NodeLocation location; public Expr getLeftValue() { return leftValue; @@ -39,6 +40,14 @@ public class AssignmentStatement extends Statement { this.rightValue = rightValue; } + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/BreakStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/BreakStatement.java index 0625b840a..d4f77ae8c 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/BreakStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/BreakStatement.java @@ -21,6 +21,7 @@ package org.teavm.javascript.ast; */ public class BreakStatement extends Statement { private IdentifiedStatement target; + private NodeLocation location; public IdentifiedStatement getTarget() { return target; @@ -30,6 +31,14 @@ public class BreakStatement extends Statement { this.target = target; } + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/ContinueStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/ContinueStatement.java index 236d9fd75..e2c3e6636 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/ContinueStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/ContinueStatement.java @@ -21,6 +21,7 @@ package org.teavm.javascript.ast; */ public class ContinueStatement extends Statement { private IdentifiedStatement target; + private NodeLocation location; public IdentifiedStatement getTarget() { return target; @@ -30,6 +31,14 @@ public class ContinueStatement extends Statement { this.target = target; } + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java b/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java index 06f035b77..4e846bd28 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/Expr.java @@ -25,6 +25,8 @@ import org.teavm.model.*; * @author Alexey Andreev */ public abstract class Expr implements Cloneable { + private NodeLocation location; + public abstract void acceptVisitor(ExprVisitor visitor); @Override @@ -148,4 +150,12 @@ public abstract class Expr implements Cloneable { expr.setType(type); return expr; } + + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/NodeLocation.java b/teavm-core/src/main/java/org/teavm/javascript/ast/NodeLocation.java new file mode 100644 index 000000000..cab9f859c --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/NodeLocation.java @@ -0,0 +1,46 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.javascript.ast; + +import org.teavm.model.MethodDescriptor; + +/** + * + * @author Alexey Andreev + */ +public class NodeLocation { + private String className; + private MethodDescriptor method; + private int lineNumber; + + public NodeLocation(String className, MethodDescriptor method, int lineNumber) { + this.className = className; + this.method = method; + this.lineNumber = lineNumber; + } + + public String getClassName() { + return className; + } + + public MethodDescriptor getMethod() { + return method; + } + + public int getLineNumber() { + return lineNumber; + } +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/ReturnStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/ReturnStatement.java index 5d9c43398..02de6557c 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/ReturnStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/ReturnStatement.java @@ -21,6 +21,7 @@ package org.teavm.javascript.ast; */ public class ReturnStatement extends Statement { private Expr result; + private NodeLocation location; public Expr getResult() { return result; @@ -30,6 +31,14 @@ public class ReturnStatement extends Statement { this.result = result; } + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/ThrowStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/ThrowStatement.java index 610db5ead..1e2712dac 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/ThrowStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/ThrowStatement.java @@ -21,6 +21,7 @@ package org.teavm.javascript.ast; */ public class ThrowStatement extends Statement { private Expr exception; + private NodeLocation location; public Expr getException() { return exception; @@ -30,6 +31,14 @@ public class ThrowStatement extends Statement { this.exception = exception; } + public NodeLocation getLocation() { + return location; + } + + public void setLocation(NodeLocation location) { + this.location = location; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/teavm-core/src/main/java/org/teavm/model/Instruction.java b/teavm-core/src/main/java/org/teavm/model/Instruction.java index b63ae11a9..66b006634 100644 --- a/teavm-core/src/main/java/org/teavm/model/Instruction.java +++ b/teavm-core/src/main/java/org/teavm/model/Instruction.java @@ -23,6 +23,7 @@ import org.teavm.model.instructions.InstructionVisitor; */ public abstract class Instruction { private BasicBlock basicBlock; + private InstructionLocation location; void setBasicBlock(BasicBlock basicBlock) { this.basicBlock = basicBlock; @@ -36,5 +37,13 @@ public abstract class Instruction { return basicBlock != null ? basicBlock.getProgram() : null; } + public InstructionLocation getLocation() { + return location; + } + + public void setLocation(InstructionLocation location) { + this.location = location; + } + public abstract void acceptVisitor(InstructionVisitor visitor); } diff --git a/teavm-core/src/main/java/org/teavm/model/InstructionLocation.java b/teavm-core/src/main/java/org/teavm/model/InstructionLocation.java new file mode 100644 index 000000000..6c205fd09 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/InstructionLocation.java @@ -0,0 +1,38 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.model; + +/** + * + * @author Alexey Andreev + */ +public class InstructionLocation { + private String className; + private MethodDescriptor method; + private int lineNumber = -1; + + public String getClassName() { + return className; + } + + public MethodDescriptor getMethod() { + return method; + } + + public int getLineNumber() { + return lineNumber; + } +}