Search code examples
eclipsedebuggingeclipse-pluginemfeclipse-jdt

Debugging on Modeling Level


Background: Lately I've been working with a Plugin called eMoflon which works with eclipse EMF and generates Java code from Models just like EMF but with some added features. The static structure of the software is modeled with the help of UML class Diagrams where as the dynamic behaviour (that is methods) is modeled with so called Story Drvien Modelling (SDM's) which are kind of similar to Activity Digrams but each node contain chunks of code (Actually they contain Graph transformation to mimick particular behaviour but these transformations translate into chunks of generated code).

enter image description here

What I want to develop is a Debugger which represents debugging on modeling level i.e unlike standard eclipse jdt Debugger where the debugger stops at a breapoint and then when we press Stepover it proceeds line by line. In my case I would like to place breakpoint on different Nodes of my SDM and suppose when My debugger stops at a particular node then when I press Stepover, it should jump to next Node and if I were to press StepIn then it should enter that particular Node.

Pseudo Example enter image description here enter image description here

Question?

My approach in solving this problem is that I can make eMoflon inject particular snippets of code (like say //Stop statement) in the generated Java code. My debugger plugin working along with JDT should be able to suspend the execution of java when //Stop statement is encountered in code. Now I have already implemented a Debugger on the guidelines of Platform Debug Model but I can't seem to find a away for my Plugin to communicate with JDT. Is that that even possible what I am trying to do?

Somebody told me java code suspension can only be done through JDT/Debug, if that is the case then can I replicate the above behaviour with standard JDT/Debug or expand on JDT/Debug functionality with my Plugin?


Solution

  • If you already worked with things like a breakpoint listener, moving up to JDT/Debug shouldn't be too hard. One entry point is class JDIDebugModel, which lets you create Java breakpoints, or add an IJavaBreakpointListener, which lets you nicely control what should happen when a Java breakpoint is hit.

    Next you should probably take a look at the various abstractions in package org.eclipse.jdt.debug.core, many of which are specializations of types from Platform/Debug (e.g., IJavaDebugTarget -> IDebugTarget, IJavaThread -> IThread, IJavaValue -> IValue). From an IJavaObject, you can e.g., obtain its type, which should be an IJavaClassType.

    It is important to understand that all those abstractions represent elements in the target JVM, to which the debugger talks via JDWP (cf. the "JDI" name prefix in many implementation classes in JDT/Debug). So, the above concepts have no direct connection to those in JDT/Core, but you may use the following bridge to go from JDT/Debug to JDT/Core:

    • Get the ILaunchConfiguration of the launch from the current debug target
    • From the launch configuration retrieve the project name.
    • Use normal Eclipse mechanisms to retrieve the IProject and then the IJavaProject

    If you have an IJavaClassType and an IJavaProject you can also retrieve the JDT/Core representations of the elements seen in the debugger.

    The above only explains some capabilities of JDT/Debug and how this relates to Platform/Debug and JDT/Core. It doesn't provide a full strategy for implementing your debugger, so you still need to ask yourself questions like:

    • Do I want to programatically create breakpoints after reading the generated Java classes?
    • Do I want to generate (dummy) calls to specific well-known methods on which a breakpoint has been created beforehand?
    • When the debugger hits a breakpoint, how do I determine the model element that corresponds to the current execution?

    You may get further inspiration from my presentation slides on debuggers for interpreted DSLs. The slides are accompanied by a git repository demonstrating the steps I took while implementing that debugger. You will find similarities (I used statecharts / FSM as my example -- I, too, use EMF for the models etc.) and differences (my example language is textual not graphical -- my execution approach for statecharts is interpretation rather than code generation).

    In that presentation you will also find that many adaptations of the debugger are nicely supported by existing API and extension points, while for some tasks I could not find the desired extensibility. For the latter tasks I use Object Teams, for making the "impossible" simple.