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.
bar.getFoo().getX()
-> getFooX(bar)
(extract to method, also find and replace occurrences)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.
Here is a gist that contains an inspection profile that will just look for LoD violations. You can import it into IntelliJ.
Invoke refactoringSelect an item to refactor. You can select a file/folder in the Project tool window or expression/symbol in the editor. Press Ctrl+Alt+Shift+T to open a list of refactorings that can be selected. Alternatively, you can use a keyboard shortcut for a specific refactoring.
Go to Settings/Preferences | Editor | Code Style, select your programming language, and open the Wrapping and Braces tab. In the Keep when reformatting section, select the formatting rules which you want to ignore and deselect those which should be applied. Reformat your code ( Ctrl+Alt+L ).
IntelliJ IDEA suggests to import single classes by default. You can change the settings to import entire packages instead. In the Settings/Preferences dialog ( Ctrl+Alt+S ), select Editor | Code Style | Java | Imports. Clear the Use single class import checkbox, and apply the changes.
Examples are: adding, removing, and introducing new parameters, replacing the parameter with the explicit method and method call, parameterize method, making a separate query from modifier, preserve the whole object, remove setting method, etc.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With