Auto generify non-generic interface implementation
Asked Answered
S

5

18

I have interface

public interface ObjectBuilder<E> {  
   E buildObject();
}

Also, the project has a lot of classes that implement non-generic version of the interface.

class MyClassBuilder implements ObjectBuilder {
    public MyClass buildObject() {/**/}
}

Is it possible to auto convert all of these classes, so that they have implemented a generic version of the interface?

auto refactoring to this:

class MyClassBuilder implements ObjectBuilder<MyClass> {
    public MyClass buildObject() {/**/}
}

Is there a built-in or plug-in Intellij IDEA? Or in other IDE?

Schiffman answered 7/11, 2012 at 11:56 Comment(4)
I can't imagine there's anything so specific (although feel free to prove me wrong!) and I suspect a search/replace is perhaps the way to goFeltie
There's nothing in IntelliJ; it is picked up by the "raw use of paramaterized class" inspection, but that has no quick fix option.Quirt
Just tried with your files in Eclipse.. Didn't work either :-)Bugaboo
@Schiffman How many classes are we talking about? Dozens? Hundreds?Conceive
G
6

What I would do: search for implements ObjectBuilder and automatically replace all occurences with something that doesn't compile, like

implements ObjectBuilder<FIXME>

Then try to compile, and manually fix all breaks. That would probably be quicker than trying to use a more advanced method...

Grievance answered 18/12, 2012 at 14:22 Comment(2)
it would break existing, properly interface implementationSchiffman
Just search for regexp "implements\s+ObjectBuilder\s*{". Eclipse can do that (Ctrl+H, File tab, replace button is at the bottom).Corallite
F
3

You can use Structural Search and Replace feature. It is only available in Ultimate edition though.

Frighten answered 7/11, 2012 at 13:17 Comment(0)
S
2

NetBeans offers a feature called Inspect and Transform, which allows you to write custom inspections and transformations, of the form:

<source-pattern> :: <conditions>
=> <target-pattern> :: <conditions>
;;

For example:

$f.toURL() :: $f instanceof java.io.File
=> $f.toURI().toURL()
;;

You can find more examples of such transformations in a blog post.

Similarly, IntelliJ supports custom code transformation rules through a feature called Structural Search and Replace. Using this feature of IntelliJ, you can make transformations like the following:

class $TestCase$ extends TestCase {
  $MyClassContent$
}
=>
class $TestCase$ extends OurHomeGrownTestCase {
  $MyClassContent$
}

However, I'm not sure if the above rule languages are expressive enough to support your desired transformation. If they cannot express your transformation, you can always resort to the refactoring API of an IDE to automate your custom transformation, e.g.:

Selfappointed answered 20/12, 2012 at 16:12 Comment(0)
R
1

You would probably be interested Program Transformation Systems.

Such tools allow you to state changes to code in terms of source code patterns: "if you see this, then replace it by that". (This is kind of like a programmable "structural search and replace" mentioned in another answer). The stronger tools in this category provide information about types ("symbol tables") and make that available to control the transformations (you surely need that because you are only interested in applying changes to entities related to a specific interface.)

Such tools also allow metaprogramming, to sequence the application of such transformations. With these two ideas, one can implement tools to carry out "massive" changes such as the kind you contemplate.

Rainstorm answered 18/12, 2012 at 14:15 Comment(0)
E
1

Is it possible to auto convert all of these classes, so that they have implemented a generic version of the interface?

Yes it is possible, for appropriate definition of "auto" :)

Is there a built-in or plug-in Intellij IDEA? Or in other IDE?

The transformation you are looking for is quite complex:

for each class (interface) that implements ObjectBuilder (not ObjectBuilder<.*>) 
  if the class declares/defines the method buildObject with return type X 
  then 
    modify the class to implement ObjectBuilder<X> instead of ObjectBuilder. 

You can probably write a plug-in to do this, but I suspect there is no exiting plugin that has a scripting language expressive enough to describe this.

On the other hand, a hard-coded script does not seem difficult at all. I don't have any experience with IntelliJ IDEA but I can see how this can be done even using simple search/replace in Emnacs Lisp.

Elidaelidad answered 21/12, 2012 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.