有没有办法在gradle中进行源到源的java重构?

时间:2014-01-23 08:54:45

标签: java ant refactoring gradle

我得到了一些自动生成的Java代码。我愿意在编译之前自动重构。它主要是类重命名和包修改。

是否有可用的gradle或ant任务?

6 个答案:

答案 0 :(得分:4)

  

我想得到一些自动生成的java代码   在编译之前自动重构。它主要是类重命名   和包装修改。

[非主题评论:您应该修复生成代码的代码。自动生成代码然后使用其他工具修改它看起来不像是正确的方法。]

Eclipse提供了可以在程序中使用的refactoring API(没有eclipse)。原始工具是JDT(我曾经使用过它),我想新的解决方案是LTK - 没试过。

答案 1 :(得分:3)

你想要的是program transformation system(PTS)。

PTS读取源代码,构建程序表示(通常是抽象语法树或AST),应用转换(通常在“如果你看到这个”中,用替换它< / em>“target langauge”表面“语法”到树中,并且可以从修改的AST重新生成有效的源文本(通常是漂亮的)。示例表面语法可能按字面意思写成如下(语法因系统而异):

    \x ** 2 ==>  \x * \x

通常需要一组由元程序控制的协同工作的转换规则,以实现更复杂的结果。如何编写元程序在PTS中有很大的不同。

您通常必须配置PTS以解析/重新打印所选择的目标语言。 Stratego,TXL和DMS(我的工具)都已经拥有Java解析器/ prettyprinters,并且都有表面语法重写。给定PTS的选择,您将生成源代码,然后使用一组转换和相应的元程序启动运行该工具的过程,以实现所需的特定代码更改。我相信Stratego有一个Java实现,您可以将它集成到您​​的应用程序中,避免单独的过程。

复杂的是,您经常要进行的转换需要名称解析,类型信息或对代码中数据流的某些理解。 Stratego和TXL没有内置此信息,因此您必须通过编写其他转换来按需计算它;这实际上有点难,因为语言语义很复杂。我们的工具DMS已经为Java完成了这些工具,但数据流上有些不完整。

如果您的问题实际上只是名称替换,并且名称在您生成的代码中是唯一的,那么您可能会使用以下转换:

      uniquename1 ==> replacementpath1

e.g。

      foo.bar ==>  baz.bar.foo

(如果这真的足够了,你可能只是替换文本字符串而不是PTS。我的大部分职业生涯都花在发现没有任何事情像我希望的那样简单。)

Eclipse的JDT可能是另一种选择。它当然有一个解析器,但没有表面语法转换,所以它不是真正的PTS)。相反,转换是用Java编码的,通过在树上走来走去并使用JDT API进行更改,所以这有点痛苦。 AFAIK,它提供了对名称信息的访问,但是如果我理解它则不提供表达式类型,并且没有对数据流的特定支持。我理解将它与Eclipse隔离以用作模块并不容易; YMMV。

曾经有一个名为Spoon的独立工具,它提供了Java解析,全名和类型解析,但是在程序树上进行了修改。我不知道是否跟踪过Java的现代方言(例如,1.5及以上的模板)。

答案 2 :(得分:3)

如你所说,你使用“xjc”生成代码,你想要“大多数类重命名和包修改”,也许一些“xjc”选项会做你想要的:

-p <pkg>           :  specifies the target package
-b <file/dir>      :  specify external bindings files (each <file> must have its own -b)
                      If a directory is given, **/*.xjb is searched

使用“-p”可以定义生成的代码应该属于的目标包。有关使用绑定选项,请查看此处以获取更多信息http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html

编辑另一种方法可能是:将生成的文件移动到您想要的目录中,然后使用replace插件替换复制的源文件中的包规范

<plugin>
   <artifactId>maven-resources-plugin</artifactId>
   <executions>
      <execution>
         <id>copy-resources</id>
         <phase>process-resources</phase>
         <goals>
            <goal>copy-resources</goal>
         </goals>
         <configuration>
            <outputDirectory>the.directory.for.the.classes.to.move.to</outputDirectory>
            <resources>
               <resource>
                  <directory>the.directory.of.ajc.classes</directory>
                  ... do here the appropriate settings ...
               </resource>
            </resources>
         </configuration>
      </execution>
   </executions>
</plugin>

<plugin>
    <groupId>com.google.code.maven-replacer-plugin</groupId>
    <artifactId>replacer</artifactId>
    <version>1.5.2</version>
    <executions>
        <execution>
            <phase>process-sources</phase>
            <goals>
                <goal>replace</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <includes>
            <include>**/src/main/gen/**/**.java</include>
        </includes>
        <token>^package the.one.you.want.to.replace</token>
        <value>package you.want.the.classes.to.be</value>
        <regexFlags>
            <regexFlag>MULTILINE</regexFlag>
        </regexFlags>
    </configuration>
</plugin>

答案 3 :(得分:3)

如果您尝试控制 xjc 生成的包名和类名,则可以提供external binding file

你会说:

<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <jxb:bindings schemaLocation="your.xsd" node="/xs:schema">
    <jxb:schemaBindings>
      <jxb:package name="the.package.name.you.want" />
    </jxb:schemaBindings>
  </jxb:bindings>
</jxb:bindings>

对于您想要自定义的每个类名,您将拥有:

<jxb:bindings node="//xs:complexType[@name='UglyTypeName']">
  <jxb:class name="MyNiceClass"/>
</jxb:bindings>

例如,将其保存到bindings.xjb文件中,然后像这样运行 xjc

xjc your.xsd -b bindings.xjb

答案 4 :(得分:1)

有一个名为Spoon的工具。该项目是开源的,使您能够使用源到源的方法转换和分析Java源代码。它提供了一个完整且细粒度的Java元模型,其中任何程序元素(类,方法,字段,语句,表达式......)都可以被访问以供读取和修改。

您可以在其网站上获得有关它的更多信息:http://spoon.gforge.inria.fr/

要使用Gradle运行勺子,可以在项目中插入插件并在其上应用Spoon。要使用它,请克隆此项目(https://github.com/SpoonLabs/spoon-gradle-plugin)并在本地存储库(./gradlew install)上安装插件。之后,您可以将它插入到项目中,如何在插件的文档中解释(https://github.com/SpoonLabs/spoon-gradle-plugin#basic-usage)。

我希望这可以帮助任何对java转换源感兴趣的新开发人员来源! :)

答案 5 :(得分:0)

使用proguard编译后可以执行此操作。 proguard有一个gradle任务。