4

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

不存在这样的东西,那么我将编写一个脚本。

4

6 回答 6

1

如果您使用 eclipse 或其他功能强大的 IDE,您可能已经内置支持这样做。请参阅我无法删除使用 Eclipse 重构的方法?一种方法来实现你想要的。

于 2011-10-21T12:58:21.050 回答
1

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

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

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

于 2011-10-21T13:09:09.777 回答
0

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

http://beautyj.berlios.de/

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

但是,不知道您的案例是否如此简单以至于脚本会比学习如何使用这样的程序更好。尽管出于其他目的将它放入您的工具链中可能也是值得的。

于 2011-10-21T12:04:43.853 回答
0

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

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

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

于 2011-10-21T17:34:03.610 回答
0

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

例如,这个库(用于 ecilipse 和 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 
  ...
于 2021-07-22T03:21:03.060 回答
-1

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

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

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

感谢大家的投入,以后可能会适用。

于 2011-10-22T23:36:51.227 回答