【问题标题】:How to add a code snippet to method body with JDT/AST如何使用 JDT/AST 向方法主体添加代码片段
【发布时间】:2012-11-27 21:17:43
【问题描述】:

我正在尝试使用 JDT/AST 生成 Java 源代码。我现在有MethodDeclaration 并想将代码 sn-p(来自另一个来源)添加到方法主体。代码 sn-p 可以包含任何 Java 代码,甚至是语法无效的代码。我只是找不到这样做的方法。

对于 JCodeModel,您将使用 JBlock#directStatement(String s) method

有没有办法用 JDT/AST 做到这一点?

【问题讨论】:

  • AST 操作通常要求您拥有语法上有效的树。如果该方法的代码无效,通常情况下,您将没有要插入的有效树并且您将无法执行此操作,或者您可以执行此操作但只能获得一棵无意义的树作为结果。
  • 好吧,那么 JST/AST 似乎不是合适的工具...
  • 为什么要插入无效代码?
  • 我正在实现教育软件,其中 UML 活动图(由学生创建)应该被翻译成 Java 源代码。在图表编辑器中,可以使用任意 Java 代码定义动作节点,这些代码需要按原样出现在生成的代码中。
  • 然后你可以解析代码,如果没有错误就使用它,如果没有错误就将它作为cmets插入。

标签: java code-generation abstract-syntax-tree eclipse-jdt


【解决方案1】:

由于您为应用程序的其余部分提供了格式良好的树,并且您想在特定位置插入格式不正确的文本,因此使用标准的树节点插入机制几乎无法做到这一点。

重要的是您为有效的程序文本生成文本,并在正确的位置插入片段。在某处必须有一段逻辑将 AST 打印为文本。您需要做的是要求将 AST 打印为文本,并在该过程的中间捕获它,在必要的精确点插入您的任意文本。

我们的 DMS 软件再工程工具包在其漂亮的打印机中具有进入/退出打印节点挂钩,以允许这种事情发生。

如果 JDT/AST 中不存在这样的东西,你可以尝试修改它的 prettyprinter 来给你那个钩子。或者,您可以考虑通过添加不属于标准集的另一种树节点类型来修改 JDT/AST,它只包含任意文本但行为类似于方法节点。大概每个节点都控制打印的内容;然后您可以为该树节点定义漂亮打印,以使其输出其文本。

最后一个非常老套的解决方案:在任意文本所在的位置插入一个完全有效的 AST,其中包含具有唯一名称的虚假标识符,例如 ZZZ。然后,将 AST 打印为字符串,并对字符串进行后处理,以将包含唯一名称的虚假树替换为实际的用户文本。

【讨论】:

    【解决方案2】:

    您首先需要将代码 sn-p 解析为 AST。为此,您可以使用ASTParser API。

    可以得到一个编译单元的编译问题(见CompilationUnit.getProblems())。

    modify Java code using JDT 有几种方法。我建议您考虑使用 ASTRewrite API 来修改方法的主体。

    【讨论】:

    • 嗯,我之前查过API参考,但是找不到添加任意代码sn-p的方法。考虑到代码 sn-p 可能包含语法上无效的代码。 (我刚刚将此添加到原始问题中......)
    • 可以解析任意代码sn-p。然后,将生成的 AST 节点插入方法主体的 AST 节点。 Eclipse 解析器在一定程度上容忍语法错误。
    • “在某种程度上”不幸的是还不够。 :(
    • 我添加了我的答案以包括获取编译问题的指针。
    • 它不是关于检索编译问题。提问者想要将包含编译错误的代码添加到 AST。我相信这是不可能使用任何标准的 JDT 操作技术的。
    【解决方案3】:

    您可以使用 ASTParser API 操作 AST - 甚至不必编译输出。

    这是您的案例的示例:

    String textToInsert = "Some text";
    StringLiteral stringLiteral = methodDeclaration.getAST().newStringLiteral();
    rewriter.set(stringLiteral, StringLiteral.ESCAPED_VALUE_PROPERTY, textToInsert, null);
    ListRewrite methodStatements = rewriter.getListRewrite(methodDeclaration.getBody(), Block.STATEMENTS_PROPERTY);
    methodStatements.insertFirst(stringLiteral, null);
    

    结果:

    public void myMethod() {
      Some text
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-24
      • 1970-01-01
      相关资源
      最近更新 更多