Simple Custom Refactoring in IntelliJ
Asked Answered
F

1

17

This question is a follow-up for this.

Say I have some class Foo.

class Foo {
    protected String x = "x";

    public String getX() {
        return x;
    }
}

I have a program that uses Foo and violates LoD (Law of Demeter).

class Bar {
    protected Foo foo;

    public Bar() {
        this.foo = new Foo();
    }

    public Foo getFoo() {
        return foo;
    }
}

public static void main(String [] args) {
    Bar bar = new Bar();
    String x = bar.getFoo().getX(); 
}

I can refactor this code to use LoD in two steps.

  1. m bar.getFoo().getX() -> getFooX(bar) (extract to method, also find and replace occurrences)
  2. F6 getFooX(bar) -> bar.getFooX() (move to instance method, also find and replace occurences)

The program that uses Bar no longer violates LoD.

class Bar {
    protected Foo foo;

    public Bar() {
        this.foo = new Foo();
    }

    public Foo getFoo() {
        return foo;
    }

    public String getFooX() {
        return foo.getX();
    }
}

public static void main(String [] args) {
    Bar bar = new Bar();
    String x = bar.getFooX();
}

I am wondering if there is a way to make a custom refactoring method in IntelliJ that would consolidate these two steps into one.

EDIT I got a reply from JetBrains with a link to a pre-existing feature request. Please vote on it if you find this useful!

Hello Michael,

Seems we have similar request in YouTrack: https://youtrack.jetbrains.com/issue/IDEA-122400. Feel free to vote for it and leave comments.

Best regards, Yaroslav Bedrov JetBrains

EDIT There is at least a way to inspect for Law of Demeter issues. screenshot

Here is a gist that contains an inspection profile that will just look for LoD violations. You can import it into IntelliJ.

Fanchie answered 3/7, 2015 at 20:32 Comment(3)
I'm wondering if it's possible to accomplish in one step with current IDEA version (v14), I didn't find any appropriate single command. It might be a good idea to submit a feature request if this function is really missing.Nicotiana
@Nicotiana I's currently being reviewed. The link doesn't look active yet, but it should be here: intellij-support.jetbrains.com/hc/en-us/requests/66429Fanchie
@Nicotiana See my edit, and checkout youtrack.jetbrains.com/issue/IDEA-122400Fanchie
U
3

After adding the getFooX() method to Bar, I would use Edit > Find > Replace Structurally with the following expressions:

Search template:

$instance$.getFoo().getX()

Replacement template:

$instance$.getFooX()

It does the job perfectly. Maybe you can add some constraints to $instance$ variable to narrow the search but that would only be useful if you had multiple classess with that method name.

Undermost answered 16/11, 2015 at 16:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.