/* * Copyright 2013-2017 Grzegorz Ligas <ligasgr@gmail.com> and other contributors * (see the CONTRIBUTORS file). * * 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.intellij.xquery.debugger; import com.codnos.dbgp.api.Breakpoint; import com.codnos.dbgp.api.DBGpIde; import com.codnos.dbgp.api.DebuggerIde; import com.codnos.dbgp.api.Status; import com.codnos.dbgp.api.SystemInfo; import com.intellij.execution.ExecutionResult; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.openapi.Disposable; import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpointHandler; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XSuspendContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; import static com.codnos.dbgp.api.Breakpoint.aConditionalBreakpoint; import static com.codnos.dbgp.api.Breakpoint.aLineBreakpoint; public class XQueryDebugProcess extends XDebugProcess implements Disposable { private final ExecutionConsole executionConsole; private final DBGpIde dbgpIde; private final ProcessHandler processHandler; private final XBreakpointHandler<?>[] xBreakpointHandlers = new XBreakpointHandler<?>[]{ new XQueryBreakpointHandler(this, XQueryBreakpointType.class), }; private final Map<String, Breakpoint> breakpointLocationToBreakpoint = new HashMap<>(); public XQueryDebugProcess(XDebugSession session, ExecutionResult executionResult, DBGpIde dbgpIde) { super(session); this.dbgpIde = dbgpIde; executionConsole = executionResult.getExecutionConsole(); processHandler = executionResult.getProcessHandler(); } @Override public boolean checkCanInitBreakpoints() { return false; } @Nullable @Override protected ProcessHandler doGetProcessHandler() { return processHandler; } @NotNull @Override public ExecutionConsole createConsole() { return executionConsole; } @NotNull @Override public XBreakpointHandler<?>[] getBreakpointHandlers() { return xBreakpointHandlers; } @NotNull @Override public XDebuggerEditorsProvider getEditorsProvider() { return new XQueryEditorsProvider(); } @Override public void startStepOver(XSuspendContext context) { dbgpIde.stepOver(); } @Override public void startStepInto(XSuspendContext context) { dbgpIde.stepInto(); } @Override public void startStepOut(XSuspendContext context) { dbgpIde.stepOut(); } @Override public void startPausing() { dbgpIde.breakNow(); } @Override public void stop() { } @Override public void resume(XSuspendContext context) { dbgpIde.run(); } @Override public void runToPosition(@NotNull XSourcePosition position, XSuspendContext context) { String fileURL = XQueryBreakpointHandler.getFileUrl(position); int lineNumber = XQueryBreakpointHandler.getActualLineNumber(position.getLine()); dbgpIde.breakpointSet(aLineBreakpoint(fileURL, lineNumber).withTemporary(true).build()); dbgpIde.run(); } public void setBreakpoint(String fileURL, int lineNumber, XExpression conditionExpression) { Breakpoint breakpoint = dbgpIde.breakpointSet(createBreakpoint(fileURL, lineNumber, conditionExpression)); breakpointLocationToBreakpoint.put(locationString(fileURL, lineNumber), breakpoint); } private Breakpoint createBreakpoint(String fileURL, int lineNumber, XExpression conditionExpression) { if (conditionExpression != null) { return aConditionalBreakpoint(fileURL, lineNumber, conditionExpression.getExpression()).build(); } return aLineBreakpoint(fileURL, lineNumber).build(); } @NotNull private String locationString(String fileURL, int lineNumber) { return fileURL + "#" + lineNumber; } public void removeBreakpoint(String fileURL, int lineNumber) { dbgpIde.breakpointRemove(breakpointLocationToBreakpoint.get(locationString(fileURL, lineNumber)).getBreakpointId()); } @Override public void dispose() { } public static class XQueryDebuggerIde implements DebuggerIde { private final XDebugSession session; private final ProcessHandler processHandler; public XQueryDebuggerIde(XDebugSession session, ProcessHandler processHandler) { this.session = session; this.processHandler = processHandler; } @Override public void onConnected(SystemInfo message) { UIUtil.invokeLaterIfNeeded(() -> { session.initBreakpoints(); session.resume(); }); } @Override public void onStatus(Status status, DBGpIde dbgpIde) { if (Status.STOPPED == status) { processHandler.destroyProcess(); } else if (Status.BREAK == status) { UIUtil.invokeLaterIfNeeded(() -> session.positionReached(prepareContext(dbgpIde))); } } private XSuspendContext prepareContext(DBGpIde dbgpIde) { return new XQuerySuspendContext(dbgpIde, session.getProject()); } } }