/* * Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan * * 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 com.goide.dlv.protocol; import com.google.gson.stream.JsonWriter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jsonProtocol.OutMessage; import org.jetbrains.jsonProtocol.Request; import java.io.IOException; import java.util.List; /** * Please add your requests as a subclasses, otherwise reflection won't work. * * @param <T> type of callback * @see com.goide.dlv.DlvCommandProcessor#getResultType(String) */ public abstract class DlvRequest<T> extends OutMessage implements Request<T> { private static final String PARAMS = "params"; private static final String ID = "id"; private boolean argumentsObjectStarted; private DlvRequest() { try { getWriter().name("method").value(getMethodName()); } catch (IOException e) { throw new RuntimeException(e); } } @NotNull @Override public String getMethodName() { return "RPCServer." + getClass().getSimpleName(); } @Override public final void beginArguments() { if (!argumentsObjectStarted) { argumentsObjectStarted = true; if (needObject()) { try { getWriter().name(PARAMS); getWriter().beginArray(); getWriter().beginObject(); } catch (IOException e) { throw new RuntimeException(e); } } } } protected boolean needObject() { return true; } @Override public final void finalize(int id) { try { if (argumentsObjectStarted) { if (needObject()) { getWriter().endObject(); getWriter().endArray(); } } getWriter().name(ID).value(id); getWriter().endObject(); getWriter().close(); } catch (IOException e) { throw new RuntimeException(e); } } public final static class ClearBreakpoint extends DlvRequest<DlvApi.Breakpoint> { public ClearBreakpoint(int id) { writeSingletonIntArray(PARAMS, id); } @Override protected boolean needObject() { return false; } } public final static class CreateBreakpoint extends DlvRequest<DlvApi.Breakpoint> { public CreateBreakpoint(String path, int line) { writeString("file", path); writeLong("line", line); } } public final static class StacktraceGoroutine extends DlvRequest<List<DlvApi.Location>> { public StacktraceGoroutine() { writeLong("Id", -1); writeLong("Depth", 100); } } private abstract static class Locals<T> extends DlvRequest<T> { Locals(int frameId) { writeLong("GoroutineID", -1); writeLong("Frame", frameId); } } public final static class ListLocalVars extends Locals<List<DlvApi.Variable>> { public ListLocalVars(int frameId) { super(frameId); } } public final static class ListFunctionArgs extends Locals<List<DlvApi.Variable>> { public ListFunctionArgs(int frameId) { super(frameId); } } public final static class Command extends DlvRequest<DlvApi.DebuggerState> { public Command(@Nullable String command) { writeString("Name", command); } } public final static class Detach extends DlvRequest<Integer> { public Detach(boolean kill) { try { beginArguments(); getWriter().name(PARAMS).beginArray().value(kill).endArray(); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected boolean needObject() { return false; } } public final static class EvalSymbol extends DlvRequest<DlvApi.Variable> { public EvalSymbol(@NotNull String symbol, int frameId) { try { getWriter().name(PARAMS).beginArray(); writeScope(frameId, getWriter()) .name("Symbol").value(symbol) .endObject().endArray(); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected boolean needObject() { return false; } } @NotNull private static JsonWriter writeScope(int frameId, @NotNull JsonWriter writer) throws IOException { // todo: ask vladimir how to simplify this return writer.beginObject() .name("Scope").beginObject() .name("GoroutineID").value(-1) .name("Frame").value(frameId).endObject(); } public final static class SetSymbol extends DlvRequest<Object> { public SetSymbol(@NotNull String symbol, @NotNull String value, int frameId) { try { getWriter().name(PARAMS).beginArray(); writeScope(frameId, getWriter()) .name("Symbol").value(symbol) .name("Value").value(value) .endObject().endArray(); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected boolean needObject() { return false; } } }