Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to apply a refactoring script just for its side-effects?

I've got a library that was changed to introduce a factory method to replace a constructor (the reasons aren't important right now, in the current case it was for improved type inference mostly).

Assuming that there is an Eclipse refactoring script for it (so I pretty much have a nice computer-readable description of the change), is there some way to apply that script to a project that only uses that library (i.e. it only has a reference to a compiled version of the library)?

For example, I start with this simple class:

public class MyContainer<T> {
    private final T content;

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

    public T getContent() {
        return content;
    }
}

Now I introduce a factory (without making the constructor private, but that isn't really relevant right now), the factory method looks like this:

public static <T> MyContainer<T> holding(T content) {
    return new MyContainer<T>(content);
}

When I now export a migration script it looks like this:

<?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>

This should hold enough information to apply the refactoring to another project that references (a current version) of the class via a jar file.

But trying to apply the refactoring gives me this error:

The refatoring 'Introduce Factory' (org.eclipse.jdt.ui.introduce.factory) cannot be performed, since its input 'scratch.MyContainer.java' does not exist.

Note that it explicitly mentions .java, so it's looking for a source file and isn't content with applying the refactoring to the binary type.

Note: I don't want to patch the binary library. I just want the callers of the original constructor to be converted to calling the factory method instead.

Note 2: Search-and-replace won't help in my specific case. The reason is that I have two constructors, one taking an Object and the other takes a String. They should be mapped on two different factory methods, so I'd need the search-and-replace function to look at the type information of the argument as well.

Note 3: even a way to manually specify "replace instantiations of object X with this constructor with calls to this method instead" would be appreciated.

Update: There is a bugzilla entry on the Eclipse bugzilla that is about adding a replace invocation refactoring. An implementation of that feature might be able to solve my problem, if "invocation" includes object instantiation via a given constructor. Unfortunately it saw no activity in the last few years (although it was planned for 3.2).

like image 513
Joachim Sauer Avatar asked Sep 27 '11 09:09

Joachim Sauer


2 Answers

This is not a way to apply refactoring to callers only but it may get you past your problem.

Would it be possible to add to your project a fake MyContainer.java file that has the same signatures as that in the library, apply your refactoring and then discard the java file? You could even use decompiled soure, though you might have to generify it yourself.

like image 171
Miserable Variable Avatar answered Nov 13 '22 09:11

Miserable Variable


I think you will have to write your own refactoring plugin. The tests for org.eclipse.jdt.ui.tests.refactoring are an interesting place to start.

Some interesting reads on the topic:

  • http://www.eclipse.org/articles/article.php?file=Article-Unleashing-the-Power-of-Refactoring/index.html
  • http://www.eclipse.org/articles/Article-LTK/ltk.html
like image 26
Savino Sguera Avatar answered Nov 13 '22 10:11

Savino Sguera