package jetbrains.mps.debugger.api.ui.breakpoints; /*Generated by MPS */ import jetbrains.mps.debugger.core.breakpoints.BreakpointsUiComponentEx; import jetbrains.mps.debug.api.breakpoints.IBreakpoint; import jetbrains.mps.debug.api.breakpoints.ILocationBreakpoint; import com.intellij.openapi.components.ProjectComponent; import jetbrains.mps.logging.Logger; import org.apache.log4j.LogManager; import jetbrains.mps.project.MPSProject; import jetbrains.mps.debug.api.BreakpointManagerComponent; import jetbrains.mps.debug.api.breakpoints.BreakpointProvidersManager; import jetbrains.mps.debug.api.BreakpointCreatorsManager; import jetbrains.mps.debug.api.SessionChangeListener; import jetbrains.mps.debug.api.DebugSessionManagerComponent; import com.intellij.openapi.fileEditor.FileEditorManager; import org.jetbrains.annotations.NotNull; import com.intellij.openapi.application.ApplicationManager; import java.util.Set; import jetbrains.mps.nodeEditor.EditorComponent; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import java.util.HashSet; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeUtil; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.ide.editor.util.EditorComponentUtil; import java.util.List; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.util.Computable; import java.util.Collections; import jetbrains.mps.openapi.editor.cells.EditorCell; import jetbrains.mps.debug.api.breakpoints.IBreakpointKind; import jetbrains.mps.debug.api.breakpoints.IBreakpointsProvider; import com.intellij.openapi.ui.Messages; import jetbrains.mps.debugger.core.breakpoints.BreakpointIconRenderrerEx; import jetbrains.mps.debugger.core.breakpoints.BreakpointPainterEx; import com.intellij.openapi.project.Project; import org.jdom.Element; import org.jdom.Attribute; import jetbrains.mps.debug.api.breakpoints.IBreakpointListener; import jetbrains.mps.debug.api.AbstractDebugSession; import jetbrains.mps.debug.api.SessionChangeAdapter; public class BreakpointsUiComponent extends BreakpointsUiComponentEx<IBreakpoint, ILocationBreakpoint> implements ProjectComponent { private static final Logger LOG = Logger.wrap(LogManager.getLogger(BreakpointsUiComponent.class)); private static final String BREAKPOINT_ELEMENT = "breakpoint"; private static final String KIND_TAG = "kind"; private final MPSProject myMPSProject; private final BreakpointManagerComponent myBreakpointsManagerComponent; private final BreakpointProvidersManager myProvidersManager; private final BreakpointCreatorsManager myDebugInfoManager; private final BreakpointsUiComponent.MyBreakpointManagerListener myBreakpointManagerListener = new BreakpointsUiComponent.MyBreakpointManagerListener(); private final BreakpointsUiComponent.MyBreakpointListener myBreakpointListener = new BreakpointsUiComponent.MyBreakpointListener(); private final SessionChangeListener myChangeListener = new BreakpointsUiComponent.MySessionChangeAdapter(); private final DebugSessionManagerComponent.DebugSessionListener myDebugSessionListener = new BreakpointsUiComponent.MyDebugSessionAdapter(); public BreakpointsUiComponent(MPSProject project, BreakpointManagerComponent breakpointsManagerComponent, BreakpointCreatorsManager debugInfoManager, BreakpointProvidersManager providersManager, FileEditorManager fileEditorManager) { super(project.getProject(), fileEditorManager); myMPSProject = project; myBreakpointsManagerComponent = breakpointsManagerComponent; myDebugInfoManager = debugInfoManager; myProvidersManager = providersManager; } @NotNull @Override public String getComponentName() { return "Breakpoints Ui Component"; } @Override public void initComponent() { super.init(); ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { myBreakpointsManagerComponent.setBreakpointsIO(new BreakpointsUiComponent.MyBreakpointsIO()); } }); DebugSessionManagerComponent component = myProject.getComponent(DebugSessionManagerComponent.class); component.addDebugSessionListener(myDebugSessionListener); myBreakpointsManagerComponent.addChangeListener(myBreakpointManagerListener); } @Override public void disposeComponent() { myBreakpointsManagerComponent.removeChangeListener(myBreakpointManagerListener); DebugSessionManagerComponent component = myProject.getComponent(DebugSessionManagerComponent.class); component.removeDebugSessionListener(myDebugSessionListener); super.dispose(); } public void editBreakpointProperties(final ILocationBreakpoint breakpoint) { final BreakpointsBrowserDialog breakpointsBrowserDialog = new BreakpointsBrowserDialog(myMPSProject); breakpointsBrowserDialog.show(); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { breakpointsBrowserDialog.selectBreakpoint(breakpoint); } }); } @NotNull @Override protected Set<ILocationBreakpoint> getBreakpointsForComponent(@NotNull final EditorComponent editorComponent) { final Wrappers._T<Set<ILocationBreakpoint>> result = new Wrappers._T<Set<ILocationBreakpoint>>(new HashSet<ILocationBreakpoint>()); final SRepository repository = editorComponent.getEditorContext().getRepository(); repository.getModelAccess().runReadAction(new Runnable() { public void run() { final SNode editedNode = editorComponent.getEditedNode(); if (editedNode == null) { return; } if (!(SNodeUtil.isAccessible(editedNode, repository))) { Set<IBreakpoint> allBreakpoints = myBreakpointsManagerComponent.getAllIBreakpoints(); Set<ILocationBreakpoint> locationBreakpoints = new HashSet<ILocationBreakpoint>(); for (IBreakpoint breakpoint : allBreakpoints) { if (breakpoint instanceof ILocationBreakpoint) { locationBreakpoints.add((ILocationBreakpoint) breakpoint); } } result.value = locationBreakpoints; return; } SNode rootNode = (editedNode.getModel() == null ? null : editedNode.getContainingRoot()); if (rootNode == null) { return; } final Set<ILocationBreakpoint> closeBreakpoints = myBreakpointsManagerComponent.getBreakpoints(rootNode.getReference()); for (ILocationBreakpoint locationBreakpoint : closeBreakpoints) { SNodeReference nodePtr = locationBreakpoint.getLocation().getNodePointer(); SNode node = nodePtr.resolve(repository); if (node != null && EditorComponentUtil.isNodeShownInTheComponent(editorComponent, node)) { result.value.add(locationBreakpoint); } } } }); return result.value; } @NotNull @Override protected List<EditorComponent> getComponentsForBreakpoint(@NotNull final ILocationBreakpoint breakpoint) { // reverse operation to getBreakpointsForComponent return new ModelAccessHelper(myMPSProject.getModelAccess()).runReadAction(new Computable<List<EditorComponent>>() { public List<EditorComponent> compute() { SNode node = breakpoint.getLocation().getNodePointer().resolve(myMPSProject.getRepository()); if (node != null) { return EditorComponentUtil.findComponentForNode(node, myFileEditorManager); } return Collections.emptyList(); } }); } @Override protected EditorCell findDebuggableOrTraceableCell(EditorCell foundCell) { EditorCell cell = findDebuggableCell(foundCell); if (cell == null) { cell = findTraceableCell(foundCell); } if (cell == null) { return null; } return cell; } private EditorCell findDebuggableCell(EditorCell foundCell) { EditorCell cell = foundCell; while (cell != null) { SNode node = cell.getSNode(); if (myDebugInfoManager.isDebuggableNode(node)) { return cell; } cell = cell.getParent(); } return null; } @Override protected void toggleBreakpoint(@NotNull SNode node) { IBreakpoint breakpoint = null; Set<ILocationBreakpoint> mpsBreakpointSet = myBreakpointsManagerComponent.getBreakpoints(node.getContainingRoot().getReference()); for (ILocationBreakpoint mpsBreakpoint : mpsBreakpointSet) { if (mpsBreakpoint.getLocation().getNodePointer().equals(node.getReference())) { breakpoint = mpsBreakpoint; break; } } if (breakpoint != null) { myBreakpointsManagerComponent.removeBreakpoint(breakpoint); } else { ILocationBreakpoint newBreakpoint = myDebugInfoManager.createBreakpoint(node, myProject); if (newBreakpoint != null) { myBreakpointsManagerComponent.addBreakpoint(newBreakpoint); } else if (myDebugInfoManager.isDebuggableNode(node)) { LOG.error("Node is debuggable but created breakpoint is null.", node); } else { LOG.error("Trying to create breakpoint on non-debuggable node.", node); } } } public void createFromUi(IBreakpointKind kind) { IBreakpointsProvider provider = myProvidersManager.getProvider(kind); if (provider == null) { Messages.showErrorDialog(myProject, "Can not create " + kind.getPresentation() + ". Provider was not found.", "Error Creating" + kind.getPresentation()); } else { IBreakpoint breakpoint = provider.createFromUi(kind, myProject); if (breakpoint != null) { myBreakpointsManagerComponent.addBreakpoint(breakpoint); } } } @Override protected BreakpointIconRenderrerEx<ILocationBreakpoint> createRenderrer(ILocationBreakpoint breakpoint, EditorComponent component) { return new BreakpointIconRenderer(breakpoint, component); } @Override protected BreakpointPainterEx<ILocationBreakpoint> createPainter(ILocationBreakpoint breakpoint) { return new BreakpointPainter(breakpoint); } @Override public void projectOpened() { } @Override public void projectClosed() { } public static BreakpointsUiComponent getInstance(Project project) { return project.getComponent(BreakpointsUiComponent.class); } private class MyBreakpointsIO implements BreakpointManagerComponent.IBreakpointsIO { private MyBreakpointsIO() { } @Override public IBreakpoint readBreakpoint(@NotNull Element element) { String kindName = element.getAttributeValue(BreakpointsUiComponent.KIND_TAG); IBreakpointKind kind = myProvidersManager.getKind(kindName); if (kind == null) { return null; } IBreakpointsProvider provider = myProvidersManager.getProvider(kind); if (provider == null) { return null; } IBreakpoint breakpoint = provider.loadFromState((Element) element.getChildren().get(0), kind, myProject); if (breakpoint != null) { breakpoint.addBreakpointListener(myBreakpointListener); } return breakpoint; } @Override public Element writeBreakpoint(@NotNull IBreakpoint breakpoint) { IBreakpointKind kind = breakpoint.getKind(); IBreakpointsProvider provider = myProvidersManager.getProvider(kind); if (provider == null) { return null; } Element element = provider.saveToState(breakpoint); if (element != null) { Element breakpointElement = new Element(BreakpointsUiComponent.BREAKPOINT_ELEMENT); breakpointElement.setAttribute(new Attribute(BreakpointsUiComponent.KIND_TAG, kind.getName())); breakpointElement.addContent(element); return breakpointElement; } return null; } } private class MyBreakpointManagerListener implements BreakpointManagerComponent.IBreakpointManagerListener { private MyBreakpointManagerListener() { } @Override public void breakpointAdded(@NotNull final IBreakpoint breakpoint) { if (breakpoint instanceof ILocationBreakpoint) { addLocationBreakpoint((ILocationBreakpoint) breakpoint); } breakpoint.addBreakpointListener(myBreakpointListener); } @Override public void breakpointRemoved(@NotNull final IBreakpoint breakpoint) { if (breakpoint instanceof ILocationBreakpoint) { removeLocationBreakpoint((ILocationBreakpoint) breakpoint); } breakpoint.removeBreakpointListener(myBreakpointListener); } } private class MyBreakpointListener implements IBreakpointListener { private MyBreakpointListener() { } @Override public void breakpointEnabledStateToggled(final IBreakpoint breakpoint, boolean enabled) { if (breakpoint instanceof ILocationBreakpoint) { for (EditorComponent editorComponent : getComponentsForBreakpoint((ILocationBreakpoint) breakpoint)) { editorComponent.repaintExternalComponent(); } } } } private class MyDebugSessionAdapter extends DebugSessionManagerComponent.DebugSessionAdapter { private MyDebugSessionAdapter() { } @Override public void registered(AbstractDebugSession session) { session.addChangeListener(myChangeListener); } @Override public void detached(AbstractDebugSession session) { session.removeChangeListener(myChangeListener); } } private class MySessionChangeAdapter extends SessionChangeAdapter { private MySessionChangeAdapter() { } @Override public void muted(AbstractDebugSession session) { ApplicationManager.getApplication().invokeLater((new Runnable() { @Override public void run() { for (EditorComponent editorComponent : EditorComponentUtil.getAllEditorComponents(myFileEditorManager, true)) { editorComponent.repaintExternalComponent(); } } })); } } }