建模级别的调试

Debugging on Modeling Level

背景: 最近我一直在使用一个名为 eMoflon 的插件,它与 eclipse EMF 一起工作并从模型生成 Java 代码,就像 EMF 一样,但有一些附加功能。软件的静态结构是在 UML class 图的帮助下建模的,其中动态行为(即方法)是用所谓的 Story Drvien Modeling (SDM's) 建模的,这有点类似于 Activity 图,但每个节点都包含代码块(实际上它们包含图转换以模仿特定行为,但这些转换转换为生成的代码块)。

我想开发的是 Debugger,它代表建模级别的调试,即不同于标准的 eclipse jdt Debugger,调试器在断点处停止,然后当我们按下 Stepover 时它继续进行逐行。在我的例子中,我想在我的 SDM 的不同 Nodes 上放置断点,并假设当我的调试器停止在特定的 node 然后当我按下 Stepover,它应该跳转到下一个 Node 如果我要按 StepIn 然后它应该进入那个特定的节点.

伪例子

问题?

我解决这个问题的方法是让 eMoflon 在生成的 Java 代码中注入特定的代码片段(比如 //Stop 语句)。当在代码中遇到 //Stop 语句时,我与 JDT 一起工作的调试器插件应该能够暂停 java 的执行。现在我已经根据 Platform Debug Model 的指导方针实现了一个调试器,但我似乎无法找到让我的插件与 JDT 通信的方法。这甚至可能是我想要做的吗?

有人告诉我 java 代码暂停只能通过 JDT/Debug 完成,如果是这样的话,我可以用标准 JDT/Debug 复制上述行为或扩展 JDT/Debug 我的插件的功能?

如果您已经使用过断点侦听器之类的东西,那么升级到 JDT/Debug 应该不会太难。一个入口点是 class JDIDebugModel,它可以让你创建 Java 断点,或者添加一个 IJavaBreakpointListener,它可以让你很好地控制 Java 时应该发生什么命中断点。

接下来您可能应该看看 package org.eclipse.jdt.debug.core 中的各种抽象,其中许多是 Platform/Debug 类型的特化(例如,IJavaDebugTarget -> IDebugTarget, IJavaThread -> IThread, IJavaValue -> IValue)。例如,您可以从 IJavaObject 获取其类型,它应该是 IJavaClassType.

重要的是要理解所有这些抽象代表目标 JVM 中的元素,调试器通过 JDWP 与之对话(参见许多实现中的 "JDI" 名称前缀 class 在 JDT/Debug 中)。因此,上述概念与 JDT/Core 中的概念没有 直接 联系,但您可以使用以下桥梁从 JDT/Debug 到 JDT/Core:

  • 从当前调试目标
  • 获取启动的ILaunchConfiguration
  • 从启动配置中检索 project name
  • 使用正常的 Eclipse 机制检索 IProject,然后检索 IJavaProject

如果您有一个 IJavaClassType 和一个 IJavaProject,您还可以检索在调试器中看到的元素的 JDT/Core 表示。

以上仅解释了 JDT/Debug 的一些功能及其与 Platform/Debug 和 JDT/Core 的关系。它没有提供实现调试器的完整策略,因此您仍然需要问自己以下问题:

  • 我想在读取生成的 Java classes 后以编程方式创建断点吗?
  • 我是否要生成(虚拟)对预先创建断点的特定知名方法的调用?
  • 当调试器遇到断点时,如何确定当前执行对应的模型元素?

您可能会从我在 debuggers for interpreted DSLs 上的演示幻灯片中获得更多灵感。这些幻灯片附有一个 git 存储库,演示了我在实现该调试器时所采取的步骤。您会发现相似之处(我使用状态图/FSM 作为示例——我也使用 EMF 作为模型等)和差异(我的示例语言是文本而非图形——我对状态图的执行方法是解释而不是代码生成).

在该演示文稿中,您还会发现现有 API 和扩展点很好地支持调试器的许多改编,而对于某些任务,我找不到所需的可扩展性。对于后面的任务,我使用 Object Teams,使 "impossible" 变得简单。