package jetbrains.mps.debug.api.breakpoints; /*Generated by MPS */ import jetbrains.mps.textgen.trace.NodeTraceInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SNodeReference; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.textgen.trace.TraceInfoCache; import org.jetbrains.annotations.Nullable; import jetbrains.mps.textgen.trace.TraceablePositionInfo; import org.jetbrains.mps.openapi.model.SModelReference; /** * Connects node breakpoint with target code location using generation trace information. * Given debug info may disappear between debug sessions, location may become invalid. It's up to specific breakpoint to update the location. * XXX Seems reasonable to have persistence-friendly abstraction for location (i.e. smth we persist regardless of actual node/trace info availability) * Now it's SNodeReference, while this class serves both to identify location and perform logic around it. Perhaps, shall strip this class down to * persistence stuff (i.e. SNodeReference), and move target code association code elsewhere? * * NOTE, with all the attempts to improve it, it's bad design anyway. Location API shall not expose implementation details like TraceablePositionInfo at all. */ public class BreakpointLocation { private final NodeTraceInfo myTargetCodeLocation; public BreakpointLocation(@NotNull SNodeReference nodePointer) { myTargetCodeLocation = new NodeTraceInfo(nodePointer); } public BreakpointLocation(@NotNull SNode node) { assert node.getModel() != null : "Tracing doesn't make sense for free-floating nodes"; myTargetCodeLocation = new NodeTraceInfo(node, TraceInfoCache.getInstance().get(node.getModel())); } @NotNull public SNodeReference getNodePointer() { return myTargetCodeLocation.getNode(); } @Nullable public TraceablePositionInfo getTargetCodePosition() { return myTargetCodeLocation.getPosition(); } @Nullable public String getTargetUnitName() { return myTargetCodeLocation.getUnitName(); } /** * * @deprecated meaningless and unused */ @Deprecated public boolean isValid() { return getTargetCodePosition() != null; } public int getLineIndexInFile() { TraceablePositionInfo pos = getTargetCodePosition(); return (pos == null ? -1 : pos.getStartLine() + 1); } @Nullable public String getFileName() { return myTargetCodeLocation.getFileName(); } public String getPresentation() { SNodeReference nodePointer = myTargetCodeLocation.getNode(); return String.format("%s/%s", nodePointer.getModelReference().getModelName(), nodePointer.getNodeId()); } public SModelReference getModelReference() { return myTargetCodeLocation.getNode().getModelReference(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || this.getClass() != o.getClass()) { return false; } SNodeReference nodePointer = myTargetCodeLocation.getNode(); return nodePointer.equals(((BreakpointLocation) o).myTargetCodeLocation.getNode()); } @Override public int hashCode() { return myTargetCodeLocation.getNode().hashCode(); } }