有没有一种方法可以仅应用重构脚本的副作用?

10
我有一个库,它被更改以引入工厂方法来替换构造函数(原因目前并不重要,在当前情况下,这主要是为了改进类型推断)。
假设有适用于该库的Eclipse重构脚本(因此我基本上拥有一个良好的计算机可读的描述),那么是否有某种方法可以将该脚本应用于仅使用该库的项目(即它只引用编译版本的库)?
例如,我从这个简单的类开始:
public class MyContainer<T> {
    private final T content;

    public MyContainer(final T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }
}

现在我介绍一个工厂(不将构造函数设为私有,但这并不是现在要讨论的问题),该工厂方法如下:
public static <T> MyContainer<T> holding(T content) {
    return new MyContainer<T>(content);
}

当我现在导出一个迁移脚本时,它看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<session version="1.0">
<refactoring comment="Introduce factory &apos;holding&apos; in &apos;scratch.MyContainer&apos; for constructor &apos;scratch.MyContainer.MyContainer()&apos;&#x0A;- Original project: &apos;scratch&apos;&#x0A;- Original element: &apos;scratch.MyContainer.MyContainer()&apos;&#x0A;- Factory name: &apos;holding&apos;&#x0A;- Owner class: &apos;scratch.MyContainer&apos;"
             description="Introduce factory for &apos;MyContainer&apos;"
             element1="/src&lt;scratch{MyContainer.java[MyContainer"
             flags="589830" id="org.eclipse.jdt.ui.introduce.factory"
             input="/src&lt;scratch{MyContainer.java"
             name="holding" project="scratch" protect="false"
             selection="89 0" version="1.0"/>
</session>

应该 包含足够的信息,可以将重构应用到引用了类(通过 jar 文件的 当前 版本)的另一个项目中。

但是尝试应用重构时会出现以下错误:

重构 "Introduce Factory" (org.eclipse.jdt.ui.introduce.factory) 无法执行,因为它的输入 "scratch.MyContainer.java" 不存在。

请注意,它 明确地 提到了 .java,因此它正在寻找源文件,并且不能仅对二进制类型应用重构。

注意: 我不想修改二进制库。我只想将原始构造函数的 调用者 转换为调用工厂方法。

注意2: 在我的特定情况下,搜索和替换无法解决问题。原因是我有 两个 构造函数,一个接受 Object,另一个接受 String。它们应映射到两个 不同的 工厂方法,因此我需要搜索和替换函数还要查看参数的类型信息。

注意3: 即使手动指定“用这个构造函数的实例化替换对象 X 的调用为对此方法的调用”也会受到赞赏。

更新: 在 Eclipse bugzilla 上有一个关于 添加替换调用重构的bugzilla入口。 如果“调用”包括通过给定构造函数实例化对象,那么该功能的实现可能能够解决我的问题。不幸的是,它在过去几年中没有任何活动(尽管它计划用于 3.2 版本)。


有趣的是,搜索和替换为什么行不通呢?签名是否已经发生了变化,以至于您无法编写一个(不那么)简单的字符串操作脚本来提取参数并将其传递给工厂? - user545680
@Bringer128:在我的情况下,我有两个构造函数:一个接受Object,另一个接受String。它们将映射到两个不同的工厂方法(为了更好的可读性)。因此,在我的搜索和替换功能中,我需要类型信息。 - Joachim Sauer
我能想到的唯一办法就是使用IntroduceFactoryRefactoring.java作为指南,自己制作重构插件。 - user545680
2个回答

1

这不是仅对调用者应用重构的方法,但它可能会帮你解决问题。

能否向您的项目中添加一个假的MyContainer.java文件,该文件具有与库中相同的签名,应用您的重构,然后丢弃该java文件?您甚至可以使用反编译源代码,尽管您可能需要自己进行泛型化。


1
这是我目前正在做的事情(虽然我手动重新执行重构,而不是应用脚本),但这绝对不完美。从长远来看,我想建立一个重构脚本库,随着新版本的发布而一起提供,告诉用户“应用这些脚本,您的代码移植到新版本的工作完成了一半以上”。 - Joachim Sauer
你们打算发布库的源代码吗?看起来你们对定义MyContainer的项目应用了重构。当我在一个使用该jar的项目中尝试引入工厂时,我的Eclipse版本(Build id: 20100218-1602)会显示当构造函数在二进制类中时不支持引入工厂 - Miserable Variable
@Hermal:在我的例子中,我没有发布工厂的源代码,所以情况更糟糕。但是即使你会发布源代码,也不希望用户需要该源代码。特别是因为重构无法应用于当前源代码版本(因为它会引入一个已经存在的方法)。 - Joachim Sauer
我想说Eclipse重构完全不支持这个——引入工厂似乎是添加工厂方法,调用点的更改似乎是由第一个重构引起的次要重构。然而,这是一个有趣的问题,我认为我最近在Go中读到过一个工具,可以对调用点进行更改,以正确使用API的新版本。 - Miserable Variable

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接