【问题标题】:How to automatically remove methods in java code如何自动删除java代码中的方法
【发布时间】:2011-12-12 12:21:02
【问题描述】:

我需要在一个大型 java 项目中删除一些方法,我想知道是否有工具可以帮助我这样做。我基本上会指定一个签名和一个源文件夹,其中所有匹配的方法都将被删除。

如果不存在,那我就写个脚本吧。

【问题讨论】:

  • 您如何期望您的脚本不会破坏它正在更改的所有代码?有人会假设调用此方法的代码这样做是有原因的,或者它只是一种不再需要的副作用方法?
  • 这些方法是否覆盖了您删除的某些方法?
  • 更多信息:我们希望通过删除包中不适用的主要方法来进行一些清理。它们只是为了进行一些非正式的测试而编写的。
  • 要删除多少个方法?

标签: java program-transformation


【解决方案1】:

您可以使用 Java 中的某些东西来批量修改您的 Java 项目。诀窍是使用自定义注释处理器。使用注释处理器,您几乎可以修改所有内容。

例如,this library ( for ecilipse and IDEA ) 将一些 String 字段成员修改为 /**multiline*/ 文档。

研究库让我也有能力修改方法体。

今天,我想去掉android支持库中一些不需要的方法(用作可编辑的本地模块)。我可以手动删除它们,但之后很难保持更新。

因此,我决定编写另一个注释处理器,允许您删除一些类成员,而不是使用脚本或手动修改代码。

对于IDEA来说,概念验证代码非常简单:

// the custom annotation 
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface StripMethods {
    boolean strip() default true;
    String key() default "";
}
// processing the custom annotation 

@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
    Set<? extends Element> fields = roundEnv.getElementsAnnotatedWith(StripMethods.class);
    for (Element field : fields) {
        StripMethods annotation = field.getAnnotation(StripMethods.class);
        ElementKind KIND = field.getKind();
        if(KIND == ElementKind.CLASS) {
            // the class declaration
            JCTree.JCClassDecl laDcl = (JCTree.JCClassDecl) elementUtils.getTree(field);
            // the definition tree list
            ArrayList<JCTree> defs = new ArrayList<>(laDcl.defs);
            // remove the second member which in this case is a string field 
            defs.remove(2);
            // finally modify the class definition
            laDcl.defs = List.from(defs);
        }
    }
}
@StripMethods
public class Test {
    // the first member is the default constructor
    static {
    }
    
    static final int FieldToRemove = 0;
        
    @Test
    public void test() {
        int variableToRemove = FieldToRemove; 
    }
}

成员删除导致的结果错误:

Test.java:10: error: cannot find symbol
        int variableToRemove = FieldToRemove;
                               ^
  symbol:   variable FieldToRemove
  location: class Test

还有很长的路要走。完成后我会发布代码。


完成。见https://github.com/KnIfER/Metaline

示例用法,从 androidx/appcompat 中移除 NightMode:

  @StripMethods(key="Night")
  public class AppCompatActivity
  ...
  @StripMethods(key="Night")
  public abstract class AppCompatDelegate
  ...
  @StripMethods(key="Night")
  class AppCompatDelegateImpl 
  ...

【讨论】:

    【解决方案2】:

    我寻找快速解决方案但没有找到任何解决方案,我使用了不同的工具来实现:

    1. grep 查找所有包含我想要的主要方法的文件 删除
    2. 在这些文件中查找/替换以将这些方法设为私有
    3. Eclipse 清理只有一条规则:删除未使用的 私有方法

    它完成了这项工作,但会产生轻微的副作用,即删除其他未使用的私有方法。在该项目的上下文中这没什么大不了的,因为几乎所有文件都是以前通过保存操作删除未使用的私有方法保存的。

    感谢大家的意见,以后可能会适用。

    【讨论】:

      【解决方案3】:

      我们的DMS Software Reengineering Toolkit 及其Java Front End 可用于此目的。

      DMS 解析语言(使用其前端,在本例中为 Java)、构建 AST 和符号表,并提供基于自定义分析操作 AST 的工具。在这种情况下,OP想要提供一个方法签名(可能带有一个应该解释它的上下文,因为否则签名中使用的类型可能不会被定义),在符号表中查找该签名,找到声明点( this 在符号表中)作为 AST 节点,然后应用重写规则,将声明替换为空声明。

      他可能希望对找到的方法执行的分析是它是否被使用。我们在符号表中也有这些信息。

      【讨论】:

        【解决方案4】:

        您在谈论“源转换”,而 Google 发现了 BeautyJ for Java 的存在:

        http://beautyj.berlios.de/

        “BeautyJ 可以将 Java 源代码转换为 XML 并返回。BeautyJ 引入了 XJava 格式,该格式将类或接口及其成员与相关的源代码和 Javadoc cmets 一起存储在单个 XML 文件中。BeautyJ 开辟了广阔的通过其 Sourclet API 或通过将 Java 源代码转换为 XML 并允许任何外部转换(例如通过应用 XSLT)来自动构建 Java 源代码的可能性范围。”

        不知道您的情况是否如此简单,以至于编写一个脚本比费力学习如何使用这样的程序要好。尽管出于其他目的将其放入您的工具链中可能也是值得的。

        【讨论】:

          【解决方案5】:

          如果您使用 eclipse 或其他功能强大的 IDE,您可能已经内置支持这样做。 请参阅I can't delete a method using eclipse refactoring?,了解实现您想要的方法。

          【讨论】:

            【解决方案6】:

            今天,有几种方法可以实现这一目标。例如,您可以告诉 Eclipse 编译器为您提供 AST(请参阅my blog for an example)。您可以导航 AST 以查找方法并删除节点以更改源。

            这使得保持代码有效变得容易。使用 Eclipse 代码格式化程序,您可以在之后清理格式化。

            MoDisCo 这样的项目通过分析整个项目并为您提供搜索整个项目的方法更进一步。我刚刚发现 MoDisCo 的文档对于初学者来说并不是很有帮助。

            【讨论】:

              猜你喜欢
              • 2010-10-04
              • 2021-09-11
              • 1970-01-01
              • 2011-05-08
              • 2016-08-02
              • 2020-05-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多