From 434a3dd20798f11cff7b30fbf4751237ddf5af80 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sat, 1 Jul 2017 23:41:21 +0300 Subject: [PATCH] Fix IDEA debugger issues --- .../java/org/teavm/debugging/PropertyMap.java | 2 +- tools/idea/idea-artifacts/dep-pom.xml | 43 ++++++++++++++++ tools/idea/idea-artifacts/pom.xml | 4 +- tools/idea/plugin/pom.xml | 14 ++++++ .../idea/debug/TeaVMBreakpointProvider.java | 23 +++++++++ .../teavm/idea/debug/TeaVMDebugProcess.java | 21 ++++++-- .../teavm/idea/debug/TeaVMExecutionStack.java | 6 ++- .../debug/TeaVMKotlinBreakpointProvider.java | 27 ++++++++++ .../debug/TeaVMLineBreakpointHandler.java | 15 +++--- .../debug/TeaVMScalaBreakpointProvider.java | 27 ++++++++++ .../org/teavm/idea/debug/TeaVMStackFrame.java | 15 ++++++ .../java/org/teavm/idea/debug/TeaVMValue.java | 49 ++++++++++++++++++- .../src/main/resources/META-INF/kotlin.xml | 21 ++++++++ .../src/main/resources/META-INF/maven.xml | 21 ++++++++ .../src/main/resources/META-INF/plugin.xml | 14 ++++-- .../src/main/resources/META-INF/scala.xml | 21 ++++++++ 16 files changed, 300 insertions(+), 23 deletions(-) create mode 100644 tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMBreakpointProvider.java create mode 100644 tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMKotlinBreakpointProvider.java create mode 100644 tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMScalaBreakpointProvider.java create mode 100644 tools/idea/plugin/src/main/resources/META-INF/kotlin.xml create mode 100644 tools/idea/plugin/src/main/resources/META-INF/maven.xml create mode 100644 tools/idea/plugin/src/main/resources/META-INF/scala.xml diff --git a/core/src/main/java/org/teavm/debugging/PropertyMap.java b/core/src/main/java/org/teavm/debugging/PropertyMap.java index 7acacd541..ff66ae0a3 100644 --- a/core/src/main/java/org/teavm/debugging/PropertyMap.java +++ b/core/src/main/java/org/teavm/debugging/PropertyMap.java @@ -74,7 +74,7 @@ class PropertyMap extends AbstractMap { } } Value value = new Value(debugger, jsVar.getValue()); - vars.put(entry.getKey(), new Variable(name, value)); + vars.put(name, new Variable(name, value)); } backingMap.compareAndSet(null, vars); } diff --git a/tools/idea/idea-artifacts/dep-pom.xml b/tools/idea/idea-artifacts/dep-pom.xml index d52e6c7e6..b611795cf 100644 --- a/tools/idea/idea-artifacts/dep-pom.xml +++ b/tools/idea/idea-artifacts/dep-pom.xml @@ -91,6 +91,27 @@ + + maven-antrun-plugin + 1.8 + + + process-resources + + + + + + + + + run + + + + + org.apache.maven.plugins maven-shade-plugin @@ -262,6 +283,28 @@ commons-logging + + kotlin + + install-file + + prepare-package + + dependencies/idea/plugins/Kotlin/lib/kotlin-plugin.jar + kotlin-plugin + + + + scala + + install-file + + prepare-package + + dependencies/Scala/lib/scala-plugin.jar + scala-plugin + + dependencies/maven diff --git a/tools/idea/idea-artifacts/pom.xml b/tools/idea/idea-artifacts/pom.xml index 313d33005..356ee0508 100644 --- a/tools/idea/idea-artifacts/pom.xml +++ b/tools/idea/idea-artifacts/pom.xml @@ -34,9 +34,7 @@ download-dependencies - - dependencies/teavm.jar - + true diff --git a/tools/idea/plugin/pom.xml b/tools/idea/plugin/pom.xml index bb8ba91a6..1b78e5a99 100644 --- a/tools/idea/plugin/pom.xml +++ b/tools/idea/plugin/pom.xml @@ -94,6 +94,20 @@ ${project.version} + + org.teavm.idea + kotlin-plugin + ${idea.version} + provided + + + + org.teavm.idea + scala-plugin + ${idea.version} + provided + + org.teavm teavm-jps-common diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMBreakpointProvider.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMBreakpointProvider.java new file mode 100644 index 000000000..799a45c57 --- /dev/null +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMBreakpointProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright 2017 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.idea.debug; + +import com.intellij.xdebugger.breakpoints.XBreakpointProperties; +import com.intellij.xdebugger.breakpoints.XLineBreakpointType; + +public interface TeaVMBreakpointProvider> { + Class> getBreakpointType(); +} diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMDebugProcess.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMDebugProcess.java index 452725f4c..4407ff06e 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMDebugProcess.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMDebugProcess.java @@ -15,12 +15,17 @@ */ package org.teavm.idea.debug; +import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType; +import com.intellij.openapi.extensions.ExtensionPoint; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Key; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpointHandler; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; +import java.util.ArrayList; +import java.util.List; import org.jetbrains.annotations.NotNull; import org.teavm.chromerdp.ChromeRDPDebugger; import org.teavm.chromerdp.ChromeRDPServer; @@ -33,7 +38,7 @@ public class TeaVMDebugProcess extends XDebugProcess { public static final Key INNER_BREAKPOINT_KEY = new Key<>("TeaVM breakpoint"); private TeaVMDebuggerEditorsProvider editorsProvider; private final Debugger innerDebugger; - private final TeaVMLineBreakpointHandler breakpointHandler; + private final List> breakpointHandlers = new ArrayList<>(); private final int port; private ChromeRDPServer debugServer; @@ -64,7 +69,17 @@ public class TeaVMDebugProcess extends XDebugProcess { } }); - breakpointHandler = new TeaVMLineBreakpointHandler(session.getProject(), innerDebugger); + breakpointHandlers.add(new TeaVMLineBreakpointHandler<>(JavaLineBreakpointType.class, session.getProject(), + innerDebugger)); + + ExtensionPoint> breakpointProvider = Extensions.getArea( + session.getProject()).getExtensionPoint("org.teavm.extensions.breakpointProvider"); + if (breakpointProvider != null) { + for (TeaVMBreakpointProvider provider : breakpointProvider.getExtensions()) { + breakpointHandlers.add(new TeaVMLineBreakpointHandler<>(provider.getBreakpointType(), + session.getProject(), innerDebugger)); + } + } } private Debugger initDebugger() { @@ -121,6 +136,6 @@ public class TeaVMDebugProcess extends XDebugProcess { @NotNull @Override public XBreakpointHandler[] getBreakpointHandlers() { - return new XBreakpointHandler[] { breakpointHandler }; + return breakpointHandlers.toArray(new XBreakpointHandler[0]); } } diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMExecutionStack.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMExecutionStack.java index 1f45ee0a0..3a0d0a5c2 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMExecutionStack.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMExecutionStack.java @@ -22,6 +22,7 @@ import com.intellij.xdebugger.frame.XExecutionStack; import com.intellij.xdebugger.frame.XStackFrame; import java.util.Arrays; import java.util.Objects; +import java.util.stream.Stream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.teavm.debugging.CallFrame; @@ -66,7 +67,10 @@ public class TeaVMExecutionStack extends XExecutionStack { @Nullable VirtualFile findVirtualFile(@NotNull String partialPath) { - return Arrays.stream(rootManager.getContentSourceRoots()) + Stream roots = Stream.concat( + Arrays.stream(rootManager.getContentSourceRoots()), + Arrays.stream(rootManager.orderEntries().getAllSourceRoots())); + return roots .map(sourceRoot -> sourceRoot.findFileByRelativePath(partialPath)) .filter(Objects::nonNull) .findFirst() diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMKotlinBreakpointProvider.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMKotlinBreakpointProvider.java new file mode 100644 index 000000000..fd6dde125 --- /dev/null +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMKotlinBreakpointProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 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.idea.debug; + +import com.intellij.xdebugger.breakpoints.XLineBreakpointType; +import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties; +import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointType; + +public class TeaVMKotlinBreakpointProvider implements TeaVMBreakpointProvider { + @Override + public Class> getBreakpointType() { + return KotlinLineBreakpointType.class; + } +} diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMLineBreakpointHandler.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMLineBreakpointHandler.java index 317644e51..a2a5b7f42 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMLineBreakpointHandler.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMLineBreakpointHandler.java @@ -15,7 +15,6 @@ */ package org.teavm.idea.debug; -import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; @@ -23,31 +22,32 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.xdebugger.breakpoints.XBreakpointHandler; +import com.intellij.xdebugger.breakpoints.XBreakpointType; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties; import org.teavm.debugging.Breakpoint; import org.teavm.debugging.Debugger; -public class TeaVMLineBreakpointHandler extends XBreakpointHandler> { +public class TeaVMLineBreakpointHandler> extends XBreakpointHandler { private Debugger innerDebugger; private VirtualFileManager vfs; private ProjectFileIndex fileIndex; @SuppressWarnings("unchecked") - public TeaVMLineBreakpointHandler(Project project, Debugger innerDebugger) { - super(JavaLineBreakpointType.class); + public TeaVMLineBreakpointHandler(Class> breakpointType, + Project project, Debugger innerDebugger) { + super(breakpointType); this.innerDebugger = innerDebugger; vfs = VirtualFileManager.getInstance(); fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); } @Override - public void registerBreakpoint(@NotNull XLineBreakpoint breakpoint) { + public void registerBreakpoint(@NotNull B breakpoint) { VirtualFile virtualFile = vfs.findFileByUrl(breakpoint.getFileUrl()); if (virtualFile == null) { return; @@ -81,8 +81,7 @@ public class TeaVMLineBreakpointHandler extends XBreakpointHandler breakpoint, - boolean temporary) { + public void unregisterBreakpoint(@NotNull B breakpoint, boolean temporary) { Breakpoint innerBreakpoint = breakpoint.getUserData(TeaVMDebugProcess.INNER_BREAKPOINT_KEY); if (innerBreakpoint != null) { breakpoint.putUserData(TeaVMDebugProcess.INNER_BREAKPOINT_KEY, null); diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMScalaBreakpointProvider.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMScalaBreakpointProvider.java new file mode 100644 index 000000000..6d14db166 --- /dev/null +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMScalaBreakpointProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 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.idea.debug; + +import com.intellij.xdebugger.breakpoints.XLineBreakpointType; +import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties; +import org.jetbrains.plugins.scala.debugger.breakpoints.ScalaLineBreakpointType; + +public class TeaVMScalaBreakpointProvider implements TeaVMBreakpointProvider { + @Override + public Class> getBreakpointType() { + return ScalaLineBreakpointType.class; + } +} diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMStackFrame.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMStackFrame.java index 7396f2755..e10a9ba9b 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMStackFrame.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMStackFrame.java @@ -16,6 +16,7 @@ package org.teavm.idea.debug; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.xdebugger.XDebuggerUtil; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.frame.XCompositeNode; @@ -26,6 +27,8 @@ import org.jetbrains.annotations.Nullable; import org.teavm.debugging.CallFrame; import org.teavm.debugging.Variable; import org.teavm.debugging.information.SourceLocation; +import org.teavm.debugging.javascript.JavaScriptCallFrame; +import org.teavm.debugging.javascript.JavaScriptLocation; class TeaVMStackFrame extends XStackFrame { private TeaVMExecutionStack stack; @@ -50,6 +53,18 @@ class TeaVMStackFrame extends XStackFrame { } line = innerLocation.getLine() - 1; } + if (virtualFile == null) { + JavaScriptCallFrame jsFrame = innerFrame.getOriginalCallFrame(); + if (jsFrame != null) { + JavaScriptLocation jsLocation = jsFrame.getLocation(); + if (jsLocation != null) { + virtualFile = VirtualFileManager.getInstance().findFileByUrl(jsLocation.getScript()); + if (virtualFile != null) { + line = jsLocation.getLine(); + } + } + } + } position = XDebuggerUtil.getInstance().createPosition(virtualFile, line); } return position; diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMValue.java b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMValue.java index 861f266d9..9062d7bae 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMValue.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/debug/TeaVMValue.java @@ -21,6 +21,8 @@ import com.intellij.xdebugger.frame.XNamedValue; import com.intellij.xdebugger.frame.XValueChildrenList; import com.intellij.xdebugger.frame.XValueNode; import com.intellij.xdebugger.frame.XValuePlace; +import java.util.Arrays; +import java.util.Objects; import javax.swing.Icon; import org.jetbrains.annotations.NotNull; import org.teavm.debugging.Value; @@ -39,8 +41,51 @@ public class TeaVMValue extends XNamedValue { @Override public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) { Icon icon = root ? PlatformIcons.VARIABLE_ICON : PlatformIcons.FIELD_ICON; - node.setPresentation(icon, innerValue.getType(), innerValue.getRepresentation(), - !innerValue.getProperties().isEmpty()); + String representation = innerValue.getRepresentation(); + if (representation == null) { + representation = "null"; + } + if (Objects.equals(innerValue.getType(), "java.lang.String")) { + representation = getStringRepresentation(); + } + node.setPresentation(icon, innerValue.getType(), representation, !innerValue.getProperties().isEmpty()); + } + + private String getStringRepresentation() { + Variable charactersProperty = innerValue.getProperties().get("characters"); + if (charactersProperty != null) { + Variable dataProperty = charactersProperty.getValue().getProperties().get("data"); + if (dataProperty != null) { + Value dataValue = dataProperty.getValue(); + int[] indexes = dataValue.getProperties().keySet().stream() + .filter(t -> isDigits(t)) + .mapToInt(Integer::parseInt) + .toArray(); + int maxIndex = Math.min(Arrays.stream(indexes).max().orElse(-1) + 1, 256); + char[] chars = new char[maxIndex]; + for (int i = 0; i < maxIndex; ++i) { + Variable charProperty = dataValue.getProperties().get(Integer.toString(i)); + if (charProperty != null) { + String charRepr = charProperty.getValue().getRepresentation(); + if (isDigits(charRepr)) { + chars[i] = (char) Integer.parseInt(charRepr); + } + } + } + return new String(chars); + } + } + return ""; + } + + private static boolean isDigits(String str) { + for (int i = 0; i < str.length(); ++i) { + char c = str.charAt(i); + if (c < '0' || c > '9') { + return false; + } + } + return true; } @Override diff --git a/tools/idea/plugin/src/main/resources/META-INF/kotlin.xml b/tools/idea/plugin/src/main/resources/META-INF/kotlin.xml new file mode 100644 index 000000000..9c9071c51 --- /dev/null +++ b/tools/idea/plugin/src/main/resources/META-INF/kotlin.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/tools/idea/plugin/src/main/resources/META-INF/maven.xml b/tools/idea/plugin/src/main/resources/META-INF/maven.xml new file mode 100644 index 000000000..745ca4122 --- /dev/null +++ b/tools/idea/plugin/src/main/resources/META-INF/maven.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/tools/idea/plugin/src/main/resources/META-INF/plugin.xml b/tools/idea/plugin/src/main/resources/META-INF/plugin.xml index c20a87731..946e6c838 100644 --- a/tools/idea/plugin/src/main/resources/META-INF/plugin.xml +++ b/tools/idea/plugin/src/main/resources/META-INF/plugin.xml @@ -1,10 +1,13 @@ - + org.teavm.idea TeaVM IDEA plugin ${project.version} TeaVM community - org.jetbrains.idea.maven + com.intellij.modules.java + org.jetbrains.idea.maven + org.jetbrains.kotlin + org.intellij.scala - - - + + + \ No newline at end of file diff --git a/tools/idea/plugin/src/main/resources/META-INF/scala.xml b/tools/idea/plugin/src/main/resources/META-INF/scala.xml new file mode 100644 index 000000000..3838e5ae3 --- /dev/null +++ b/tools/idea/plugin/src/main/resources/META-INF/scala.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file