问题 以编程方式编辑/修改.java文件? (不是.class文件)


所以,这是一段代码使用 CodeModel 生成java代码:

    JCodeModel cm = new JCodeModel();
    JDefinedClass dc = cm._class("foo.Bar");
    JMethod m = dc.method(0, int.class, "foo"); 
    m.body()._return(JExpr.lit(5));
    File f = new File("C:/target/classes");
    f.mkdirs();
    cm.build(f);

此代码生成.java文件:

package foo;
public class Bar {

       int foo() {
        return  5;
    }
}

但是,我 不要 希望CodeModel为我创建一个新的java文件。我已经有一个.java文件,并希望在其中的方法中添加几行代码。所以,我希望API直接修改java文件/创建它的修改后的副本。有没有办法做到这一点?


3129
2018-02-25 12:19


起源

在java中使用[C#]的部分类将在某种程度上有所帮助...... - Fakrudeen
@Fakrudeen请详细说明。 - Jay
C#允许类定义跨越多个文件。如果更改只是附加的,您可以在另一个文件中定义[生成]它们,而不是修改现有文件。所有这些对你来说都没有意义,因为java没有部分类。这就是我将其添加为评论的原因。 - Fakrudeen


答案:


我知道自原始帖子以来已经有一段时间了,但看起来更容易看到的Java转换库之一

来自 勺子主页

Spoon使您可以转换(见下文)和分析(参见示例)   源代码。 Spoon提供了完整且细粒度的Java元模型   任何程序元素(类,方法,字段,语句,   表达式...)可以被读取和修改。   Spoon作为输入源代码并生成转换后的源代码   准备编译。

更新:Square也创建了 JavaPoet 源代码生成库,流畅的API看起来很简单,可以掌握。


10
2018-01-18 23:23



甚至不记得为什么我问过这个问题:) ..谢谢你回答它 - 我正在回答你的答案! - Jay
JavaPoet可以读入现有的源代码吗?在浏览JavaPoet README.md时,我找不到任何提及它。 - JohnC
@JohnC,对不起,我没有愤怒地使用JavaPoet,但从我可以收集的内容来看,Spoon似乎更符合您的要求。没有理由不将2个库组合起来进行修改和纯生成(即正确工作的正确工具)。 - Big Rich


您真的需要完整解析要修改的代码,以确保将代码插入正确的位置。我认为你最好的选择是利用一个现有的解析工具,允许重写代码,而不是试图手工做一些事情。

Eclipse IDE可以做这样的事情来支持代码重构。这个 文章 可能会有所帮助。


2
2018-02-25 12:30





...我希望API直接修改java文件/创建它的修改后的副本。有没有办法做到这一点?

JavaParser类 是一个API,允许您读取Java文件,修改它们,并以String形式获取结果。

更具体地说,JavaParser解析文件并构建AST(抽象语法树)。然后,您可以使用API​​修改表示源代码的JavaParser AST,并检索AST的String表示形式。

我已经有一个.java文件,并希望在其中的方法中添加几行代码。

下面是使用JavaParser将一行添加到方法体末端并打印结果的示例:

class MyClass {
    public static void someMethod() {
        /* ... */
        // Lines will be added here:
    }

    public static void main(String[] args) {
        String newStatement = "System.out.println(\"Hello world!\");"
        File myClassSourceFile = new File("MyClass.java");
        CompilationUnit cu = JavaParser.parse(myClassSourceFile);
        ClassOrInterfaceDeclaration classDeclaration = cu.getClassByName("MyClass").get();
        MethodDeclaration method = classDeclaration.getMethodsByName().get(0);
        method.getBody().get().addStatement(newStatement);

        // Print out the resulting Java source code.
        System.out.println(cu.toString());
    }
}

CompilationUnit  - 来自JavaParser的javadoc,“这个类代表整个编译单元。每个java文件代表一个编译单元。”

注意:在您的代码中,您将需要使用适当的可选处理替换Option.get()调用。


2
2018-03-15 20:13



如果生成的源代码是原始代码但是进行了本地化修改,那么您的回答并没有告诉我。该问题要求尽可能少的修改,可能是为了防止许多版本控制冲突。 - neves


你想要的是一个 程序转换系统。这是一个解析源文件的工具,可以 应用转换来修改它,重新生成带有修改的源代码。

源到源转换系统接受以下形式的规则:

lhs -> rhs  if cond

在哪里 LHS 和 RHS是语言和语言的有效片段的源模式 条件 检查规则是否可以安全申请。 (考虑“?x /?x - > 1 if?x~ = 0”;您需要条件来验证除法是否有效)。

一个这样的工具是我们的 DMS软件再造工具包。 DMS具有完整的C,C ++,C#,Java,COBOL,Python,PHP和ECMAScript前端解析器(与许多鲜为人知的语言一样)并且可以直接应用这些规则。 DMS还提供符号表构造和控制以及数据流分析,因为它们通常用于定义a 条件 对于复杂的规则。如果需要,您还可以回退到“标准”程序界面来访问树节点并修改AST。


-1
2018-02-26 05:32



@Ira谢谢。然而,我正在考虑使用开源软件,而不是商业软件。 - Jay
好吧,你可以试试TXL txl.ca 或战略 strategoxt.org,这也是具有源到源重写规则的程序转换系统。它们没有,我相信从根本上是程序语言转换的必要条件,是符号表和流程分析工具。我们发现这些对于进行可靠的大规模程序转换是不可或缺的。您可以尝试在OSS工具中自己实现这些,但它需要做很多工作。因人而异。 - Ira Baxter
哇。 7年的答案,直接解决OP的问题,包括提供开源替代方案,当OP在他的评论中明确表示......和 现在 它吸引了什么?我不认为贬低者愿意解释为什么他们贬低了。 - Ira Baxter