diff --git a/tools/chrome-rdp/pom.xml b/tools/chrome-rdp/pom.xml index bad58b2e5..25cc8589f 100644 --- a/tools/chrome-rdp/pom.xml +++ b/tools/chrome-rdp/pom.xml @@ -54,7 +54,6 @@ com.fasterxml.jackson.core jackson-databind - true diff --git a/tools/chrome-rdp/src/main/js/chrome/contentscript.js b/tools/chrome-rdp/src/main/js/chrome/contentscript.js new file mode 100644 index 000000000..4e5149a5a --- /dev/null +++ b/tools/chrome-rdp/src/main/js/chrome/contentscript.js @@ -0,0 +1,27 @@ +/* + * Copyright 2018 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. + */ + +window.addEventListener("message", function(event) { + if (event.source !== window) { + return; + } + + var data = event.data; + if (typeof data.teavmDebugger !== "undefined") { + chrome.runtime.sendMessage({ command: "debug", port: data.teavmDebugger.port }); + } +}, false); +window.postMessage({ teavmDebuggerRequest: true }, "*"); \ No newline at end of file diff --git a/tools/chrome-rdp/src/main/js/chrome/main.js b/tools/chrome-rdp/src/main/js/chrome/main.js index 1279ba1fa..7209a6969 100644 --- a/tools/chrome-rdp/src/main/js/chrome/main.js +++ b/tools/chrome-rdp/src/main/js/chrome/main.js @@ -1,15 +1,16 @@ debuggerAgentMap = {}; chrome.browserAction.onClicked.addListener(function(tab) { - new DebuggerAgent(tab).attach(); + new DebuggerAgent(tab, 2357).attach(); }); -function DebuggerAgent(tab) { +function DebuggerAgent(tab, port) { this.pendingMessages = []; this.connection = null; this.tab = null; this.debuggee = { tabId : tab.id }; this.attachedToDebugger = false; this.messageBuffer = ""; + this.port = port; debuggerAgentMap[tab.id] = this; } DebuggerAgent.MAX_MESSAGE_SIZE = 65534; @@ -20,12 +21,12 @@ DebuggerAgent.prototype.attach = function() { }.bind(this, this.connectToServer.bind(this))); }; DebuggerAgent.prototype.connectToServer = function() { - this.connection = new WebSocket("ws://localhost:2357/"); + this.connection = new WebSocket("ws://localhost:" + this.port + "/"); this.connection.onmessage = function(event) { var str = event.data; var ctl = str.substring(0, 1); this.messageBuffer += str.substring(1); - if (ctl == '.') { + if (ctl === '.') { this.receiveMessage(JSON.parse(this.messageBuffer)); this.messageBuffer = ""; } @@ -95,4 +96,10 @@ chrome.debugger.onDetach.addListener(function(source) { agent.attachedToDebugger = false; agent.disconnect(); } +}); + +chrome.runtime.onMessage.addListener(function(message, sender, callback) { + if (message.command === "debug") { + new DebuggerAgent(sender.tab, message.port).attach(); + } }); \ No newline at end of file diff --git a/tools/chrome-rdp/src/main/js/chrome/manifest.json b/tools/chrome-rdp/src/main/js/chrome/manifest.json index c9931916d..5972d3972 100644 --- a/tools/chrome-rdp/src/main/js/chrome/manifest.json +++ b/tools/chrome-rdp/src/main/js/chrome/manifest.json @@ -3,9 +3,9 @@ "name": "TeaVM debugger agent", "description": "TeaVM debugger agent, that sends RDP commands over WebSocket", - "version": "0.2", + "version": "0.6.0", - "permissions" : ["debugger", "activeTab", "tabs"], + "permissions" : ["debugger", "activeTab", "tabs", "*://*/*"], "browser_action" : { "default_icon": "teavm-16.png", @@ -14,5 +14,12 @@ "background": { "scripts": ["main.js"] - } + }, + + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*", "file://*/*"], + "js": ["contentscript.js"] + } + ] } \ No newline at end of file diff --git a/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java b/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java index 608bb8895..5c4eee0d9 100644 --- a/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java +++ b/tools/devserver/src/main/java/org/teavm/devserver/CodeServlet.java @@ -79,6 +79,7 @@ public class CodeServlet extends HttpServlet { private boolean indicator; private boolean automaticallyReloaded; private int port; + private int debugPort; private Map> sourceFileCache = new HashMap<>(); @@ -138,6 +139,10 @@ public class CodeServlet extends HttpServlet { this.port = port; } + public void setDebugPort(int debugPort) { + this.debugPort = debugPort; + } + public void setAutomaticallyReloaded(boolean automaticallyReloaded) { this.automaticallyReloaded = automaticallyReloaded; } @@ -450,10 +455,6 @@ public class CodeServlet extends HttpServlet { } private void addIndicator() { - if (!indicator) { - return; - } - String script = getIndicatorScript(false); try (Writer writer = new OutputStreamWriter(buildTarget.appendToResource(fileName), StandardCharsets.UTF_8)) { writer.append("\n"); @@ -472,6 +473,8 @@ public class CodeServlet extends HttpServlet { script = script.replace("BOOT_FLAG", Boolean.toString(boot)); script = script.replace("RELOAD_FLAG", Boolean.toString(automaticallyReloaded)); script = script.replace("FILE_NAME", "http://localhost:" + port + pathToFile + fileName); + script = script.replace("INDICATOR_FLAG", Boolean.toString(indicator)); + script = script.replace("DEBUG_PORT", Integer.toString(debugPort)); return script; } catch (IOException e) { throw new RuntimeException("IO error occurred writing debug information", e); diff --git a/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java b/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java index c7b499f6d..a30a58a6a 100644 --- a/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java +++ b/tools/devserver/src/main/java/org/teavm/devserver/DevServer.java @@ -46,6 +46,7 @@ public class DevServer { private Server server; private int port = 9090; + private int debugPort; public void setMainClass(String mainClass) { this.mainClass = mainClass; @@ -59,6 +60,10 @@ public class DevServer { this.port = port; } + public void setDebugPort(int debugPort) { + this.debugPort = debugPort; + } + public void setPathToFile(String pathToFile) { if (!pathToFile.startsWith("/")) { pathToFile = "/" + pathToFile; @@ -122,6 +127,7 @@ public class DevServer { servlet.setIndicator(indicator); servlet.setAutomaticallyReloaded(reloadedAutomatically); servlet.setPort(port); + servlet.setDebugPort(debugPort); for (DevServerListener listener : listeners) { servlet.addListener(listener); } diff --git a/tools/devserver/src/main/resources/org/teavm/devserver/indicator.js b/tools/devserver/src/main/resources/org/teavm/devserver/indicator.js index 539041f3c..c330209c0 100644 --- a/tools/devserver/src/main/resources/org/teavm/devserver/indicator.js +++ b/tools/devserver/src/main/resources/org/teavm/devserver/indicator.js @@ -16,6 +16,8 @@ (function () { var boot = BOOT_FLAG; var reload = RELOAD_FLAG; + var indicatorVisible = INDICATOR_FLAG; + var debugPort = DEBUG_PORT; function createWebSocket() { var loc = window.location; @@ -121,10 +123,12 @@ document.body.appendChild(indicator.container); } - if (document.body) { - onLoad(); - } else { - window.addEventListener("load", onLoad); + if (indicatorVisible) { + if (document.body) { + onLoad(); + } else { + window.addEventListener("load", onLoad); + } } function startMain() { @@ -164,4 +168,17 @@ if (boot) { indicator.show("File is not ready, about to compile"); } + + if (debugPort > 0) { + function connectDebugAgent(event) { + if (event.source !== window) { + return; + } + var data = event.data; + if (typeof data.teavmDebuggerRequest !== "undefined") { + window.postMessage({teavmDebugger: {port: debugPort}}, "*"); + } + } + window.addEventListener("message", connectDebugAgent); + } })(); \ No newline at end of file diff --git a/tools/idea/idea-artifacts/dep-pom.xml b/tools/idea/idea-artifacts/dep-pom.xml index f564b4289..7ce219eb0 100644 --- a/tools/idea/idea-artifacts/dep-pom.xml +++ b/tools/idea/idea-artifacts/dep-pom.xml @@ -94,7 +94,7 @@ + dest="${basedir}/dependencies/scala.zip" skipexisting="true"/> 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 1abe59711..c9f8ffc9a 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 @@ -16,6 +16,8 @@ package org.teavm.idea.debug; import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.execution.ui.ExecutionConsole; import com.intellij.icons.AllIcons; import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.Extensions; @@ -49,6 +51,7 @@ public class TeaVMDebugProcess extends XDebugProcess { private final int port; private ChromeRDPServer debugServer; ConcurrentMap> breakpointMap = new ConcurrentHashMap<>(); + public ExecutionConsole console; public TeaVMDebugProcess(@NotNull XDebugSession session, int port) { super(session); @@ -188,4 +191,10 @@ public class TeaVMDebugProcess extends XDebugProcess { public XBreakpointHandler[] getBreakpointHandlers() { return breakpointHandlers.toArray(new XBreakpointHandler[0]); } + + @NotNull + @Override + public ExecutionConsole createConsole() { + return console != null ? console : super.createConsole(); + } } diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerConfiguration.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerConfiguration.java index 656ce43ff..e332883b0 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerConfiguration.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerConfiguration.java @@ -26,4 +26,5 @@ public class DevServerConfiguration { public int port; public String pathToFile; public String fileName; + public int debugPort; } diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerRunner.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerRunner.java index ac0ffff1e..fc9c87c23 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerRunner.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/DevServerRunner.java @@ -125,6 +125,9 @@ public class DevServerRunner extends UnicastRemoteObject implements DevServerMan case "-f": server.setFileName(args[++i]); break; + case "-P": + server.setDebugPort(Integer.parseInt(args[++i])); + break; } } server.setClassPath(classPath.toArray(new String[0])); @@ -179,6 +182,11 @@ public class DevServerRunner extends UnicastRemoteObject implements DevServerMan arguments.add(entry); } + if (options.debugPort > 0) { + arguments.add("-P"); + arguments.add(Integer.toString(options.debugPort)); + } + ProcessBuilder builder = new ProcessBuilder(arguments.toArray(new String[0])); Process process = builder.start(); BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream(), diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunState.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunState.java index 2641eec53..b8a4056bf 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunState.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunState.java @@ -21,12 +21,11 @@ import com.intellij.execution.ExecutionResult; import com.intellij.execution.Executor; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.configurations.SearchScopeProvider; +import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.filters.TextConsoleBuilder; import com.intellij.execution.filters.TextConsoleBuilderFactory; -import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; -import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.util.JavaParametersUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -36,24 +35,24 @@ import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; import java.io.IOException; -import java.io.OutputStream; +import java.net.Socket; import java.util.Arrays; import java.util.Objects; +import java.util.Random; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.teavm.idea.DaemonUtil; -import org.teavm.idea.DevServerRunnerListener; import org.teavm.idea.devserver.ui.TeaVMDevServerConsole; public class TeaVMDevServerRunState implements RunProfileState { private final TeaVMDevServerConfiguration configuration; private final TextConsoleBuilder consoleBuilder; + private final Project project; public TeaVMDevServerRunState(@NotNull ExecutionEnvironment environment, @NotNull TeaVMDevServerConfiguration configuration) { this.configuration = configuration; - Project project = environment.getProject(); + project = environment.getProject(); GlobalSearchScope searchScope = SearchScopeProvider.createSearchScope(project, environment.getRunProfile()); consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project, searchScope); } @@ -83,15 +82,44 @@ public class TeaVMDevServerRunState implements RunProfileState { config.mainClass = configuration.getMainClass(); config.maxHeap = configuration.getMaxHeap(); + if (executor.getId().equals(DefaultDebugExecutor.EXECUTOR_ID)) { + config.debugPort = choosePort(); + } + + TeaVMProcessHandler processHandler; + ExecutionResult executionResult; try { TeaVMDevServerConsole console = new TeaVMDevServerConsole(consoleBuilder.getConsole()); - ProcessHandlerImpl processHandler = new ProcessHandlerImpl(config, console); + processHandler = new TeaVMProcessHandler(config, console); console.getUnderlyingConsole().attachToProcess(processHandler); processHandler.start(); - return new DefaultExecutionResult(console, processHandler); + executionResult = new DefaultExecutionResult(console, processHandler); } catch (IOException e) { throw new ExecutionException(e); } + + return executionResult; + } + + private int choosePort() { + Random random = new Random(); + int minPort = 10000; + int maxPort = 1 << 16; + for (int i = 0; i < 20; ++i) { + int port = minPort + random.nextInt(maxPort - minPort); + if (isPortAvailable(port)) { + return port; + } + } + throw new RuntimeException("Could not find available port"); + } + + private boolean isPortAvailable(int port) { + try (Socket ignored = new Socket("localhost", port)) { + return false; + } catch (IOException ignored) { + return true; + } } private String path(VirtualFile file) { @@ -103,63 +131,4 @@ public class TeaVMDevServerRunState implements RunProfileState { } return file.getCanonicalPath(); } - - class ProcessHandlerImpl extends ProcessHandler implements DevServerRunnerListener { - private DevServerConfiguration config; - private TeaVMDevServerConsole console; - private DevServerInfo info; - - ProcessHandlerImpl(DevServerConfiguration config, TeaVMDevServerConsole console) { - this.config = config; - this.console = console; - } - - void start() throws IOException { - info = DevServerRunner.start(DaemonUtil.detectClassPath().toArray(new String[0]), config, this); - console.setServerManager(info.server); - startNotify(); - } - - @Override - protected void destroyProcessImpl() { - info.process.destroy(); - } - - @Override - protected void detachProcessImpl() { - try { - info.server.stop(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public boolean detachIsDefault() { - return true; - } - - @Nullable - @Override - public OutputStream getProcessInput() { - return null; - } - - - @Override - public void error(String text) { - console.getUnderlyingConsole().print(text + System.lineSeparator(), ConsoleViewContentType.ERROR_OUTPUT); - } - - @Override - public void info(String text) { - console.getUnderlyingConsole().print(text + System.lineSeparator(), ConsoleViewContentType.NORMAL_OUTPUT); - } - - @Override - public void stopped(int code) { - console.stop(); - notifyProcessTerminated(code); - } - } } diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunner.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunner.java index 588f8e554..2ed37ea36 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunner.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMDevServerRunner.java @@ -20,11 +20,21 @@ import com.intellij.execution.ExecutionResult; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.configurations.RunnerSettings; +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.GenericProgramRunner; +import com.intellij.execution.runners.RunContentBuilder; +import com.intellij.execution.ui.ExecutionConsole; import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.xdebugger.XDebugProcess; +import com.intellij.xdebugger.XDebugProcessStarter; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebuggerManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.teavm.idea.debug.TeaVMDebugProcess; public class TeaVMDevServerRunner extends GenericProgramRunner { @NotNull @@ -47,6 +57,32 @@ public class TeaVMDevServerRunner extends GenericProgramRunner { return null; } - return null; + RunContentDescriptor runContent = new RunContentBuilder(executionResult, environment).showRunContent(null); + int debugPort = ((TeaVMProcessHandler) executionResult.getProcessHandler()).config.debugPort; + ExecutionConsole console = runContent.getExecutionConsole(); + ProcessHandler processHandler = runContent.getProcessHandler(); + if (debugPort > 0) { + XDebuggerManager debuggerManager = XDebuggerManager.getInstance(environment.getProject()); + XDebugSession debugSession = debuggerManager.startSession(environment, new XDebugProcessStarter() { + @NotNull + @Override + public XDebugProcess start(@NotNull XDebugSession session) { + TeaVMDebugProcess debugProcess = new TeaVMDebugProcess(session, debugPort); + debugProcess.console = console; + return debugProcess; + } + }); + runContent = debugSession.getRunContentDescriptor(); + + ProcessHandler debugProcessHandler = debugSession.getDebugProcess().getProcessHandler(); + debugProcessHandler.addProcessListener(new ProcessAdapter() { + @Override + public void processTerminated(@NotNull ProcessEvent event) { + processHandler.destroyProcess(); + } + }); + } + + return runContent; } } diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMProcessHandler.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMProcessHandler.java new file mode 100644 index 000000000..a82c30410 --- /dev/null +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/TeaVMProcessHandler.java @@ -0,0 +1,85 @@ +/* + * Copyright 2018 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.devserver; + +import com.intellij.execution.process.ProcessHandler; +import com.intellij.execution.ui.ConsoleViewContentType; +import java.io.IOException; +import java.io.OutputStream; +import org.jetbrains.annotations.Nullable; +import org.teavm.idea.DaemonUtil; +import org.teavm.idea.DevServerRunnerListener; +import org.teavm.idea.devserver.ui.TeaVMDevServerConsole; + +class TeaVMProcessHandler extends ProcessHandler implements DevServerRunnerListener { + DevServerConfiguration config; + private TeaVMDevServerConsole console; + private DevServerInfo info; + + TeaVMProcessHandler(DevServerConfiguration config, TeaVMDevServerConsole console) { + this.config = config; + this.console = console; + } + + void start() throws IOException { + info = DevServerRunner.start(DaemonUtil.detectClassPath().toArray(new String[0]), config, this); + console.setServerManager(info.server); + startNotify(); + Runtime.getRuntime().addShutdownHook(new Thread(() -> info.process.destroy())); + } + + @Override + protected void destroyProcessImpl() { + info.process.destroy(); + } + + @Override + protected void detachProcessImpl() { + try { + info.server.stop(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public boolean detachIsDefault() { + return true; + } + + @Nullable + @Override + public OutputStream getProcessInput() { + return null; + } + + + @Override + public void error(String text) { + console.getUnderlyingConsole().print(text + System.lineSeparator(), ConsoleViewContentType.ERROR_OUTPUT); + } + + @Override + public void info(String text) { + console.getUnderlyingConsole().print(text + System.lineSeparator(), ConsoleViewContentType.NORMAL_OUTPUT); + } + + @Override + public void stopped(int code) { + console.stop(); + notifyProcessTerminated(code); + } +} diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/ui/TeaVMDevServerConsole.java b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/ui/TeaVMDevServerConsole.java index 4c03ee508..c9e4665cc 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/ui/TeaVMDevServerConsole.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/devserver/ui/TeaVMDevServerConsole.java @@ -15,8 +15,12 @@ */ package org.teavm.idea.devserver.ui; +import com.intellij.execution.filters.Filter; +import com.intellij.execution.filters.HyperlinkInfo; +import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ConsoleView; -import com.intellij.execution.ui.ExecutionConsole; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.openapi.actionSystem.AnAction; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.rmi.RemoteException; @@ -26,11 +30,13 @@ import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JProgressBar; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.teavm.idea.devserver.DevServerBuildResult; import org.teavm.idea.devserver.DevServerManager; import org.teavm.idea.devserver.DevServerManagerListener; -public class TeaVMDevServerConsole extends JPanel implements ExecutionConsole { +public class TeaVMDevServerConsole extends JPanel implements ConsoleView { private ConsoleView underlyingConsole; private DevServerManager serverManager; private ServerListenerImpl serverListener; @@ -135,6 +141,82 @@ public class TeaVMDevServerConsole extends JPanel implements ExecutionConsole { rebuildButton.setEnabled(false); } + @Override + public void print(@NotNull String s, @NotNull ConsoleViewContentType consoleViewContentType) { + underlyingConsole.print(s, consoleViewContentType); + } + + @Override + public void clear() { + underlyingConsole.clear(); + } + + @Override + public void scrollTo(int i) { + underlyingConsole.scrollTo(i); + } + + @Override + public void attachToProcess(ProcessHandler processHandler) { + underlyingConsole.attachToProcess(processHandler); + } + + @Override + public void setOutputPaused(boolean b) { + underlyingConsole.setOutputPaused(b); + } + + @Override + public boolean isOutputPaused() { + return underlyingConsole.isOutputPaused(); + } + + @Override + public boolean hasDeferredOutput() { + return underlyingConsole.hasDeferredOutput(); + } + + @Override + public void performWhenNoDeferredOutput(@NotNull Runnable runnable) { + underlyingConsole.performWhenNoDeferredOutput(runnable); + } + + @Override + public void setHelpId(@NotNull String s) { + underlyingConsole.setHelpId(s); + } + + @Override + public void addMessageFilter(@NotNull Filter filter) { + underlyingConsole.addMessageFilter(filter); + } + + @Override + public void printHyperlink(@NotNull String s, @Nullable HyperlinkInfo hyperlinkInfo) { + underlyingConsole.printHyperlink(s, hyperlinkInfo); + } + + @Override + public int getContentSize() { + return underlyingConsole.getContentSize(); + } + + @Override + public boolean canPause() { + return underlyingConsole.canPause(); + } + + @NotNull + @Override + public AnAction[] createConsoleActions() { + return underlyingConsole.createConsoleActions(); + } + + @Override + public void allowHeavyFilters() { + underlyingConsole.allowHeavyFilters(); + } + class ServerListenerImpl extends UnicastRemoteObject implements DevServerManagerListener { private NumberFormat percentFormat = NumberFormat.getPercentInstance();