Search This Blog

Loading...

Saturday, May 15, 2010

IDEA candy - Live code formatting

Table of contents




Foreword



I'm continuing the theme of describing IDEA features new to me and going to talk about various live code formatting facilities provided out of the box.



Horizontal code block move



It's possible to perform horizontal move of code located at current line (selected multiline code) to the standard indentation value (defined via 'Settings -> Code Style -> General -> Indent'). Move to right is performed via pressing 'Tab'; move to left via 'Shift + Tab'.

Example: consider the following class:


public class FormattingTest {
public void test(int[] data) {
if (data[0] > 0 && data[1] < 10
&& data[2] > 4 && data[2] < 6
&& data[3] > 18 && data[3] < 20)
{
System.out.println("crazy condition is satisfied");
}
}
}


Suppose you want last line at 'if' condition section to have additional indent. Put cursor to it and press 'Tab'. Result:


public class FormattingTest {
public void test(int[] data) {
if (data[0] > 0 && data[1] < 10
&& data[2] > 4 && data[2] < 6
&& data[3] > 18 && data[3] < 20)
{
System.out.println("crazy condition is satisfied");
}
}
}


Suppose you want to have the second and the third lines of 'if' condition to have one more additional indent. Select them and press 'Tab' again:



Result:


public class FormattingTest {
public void test(int[] data) {
if (data[0] > 0 && data[1] < 10
&& data[2] > 4 && data[2] < 6
&& data[3] > 18 && data[3] < 20)
{
System.out.println("crazy condition is satisfied");
}
}
}


You can perform line(s) code move to left via pressing 'Shit + Tab' instead of 'Tab'.

'Indent Lines' action



Let's continue with our example - it's 'if' condition clause contains two lines that are indented too far to the right now. We'd like to fix indentation in accordance with current formatting settings (i.e. make both lines to have single indent to the first 'if' line). There are two ways to go - the first one is to reformat the code via 'Reformat Action' ('Ctrl + Alt + L'). This is rather ubiqutious approach known to most of IDEA users. It's drawback is in its power - it can introduce/remove line breaks in accordance with current formatting options and we may don't want that.

However, there is a dedicated action that just fixes indentation for selected code (active line). Select target code to indent:



Press 'Ctrl + Alt + I' now - 'Indent Lines' action. Result:


public class FormattingTest {
public void test(int[] data) {
if (data[0] > 0 && data[1] < 10
&& data[2] > 4 && data[2] < 6
&& data[3] > 18 && data[3] < 20)
{
System.out.println("crazy condition is satisfied");
}
}
}


'Join Lines' action



We can notice that we don't need line breaks at out 'if' condition. IDEA allows to automatically collapse multiple lines to the single one.

Example: select target lines to collapse (join):



Invoke 'Join Lines' action ('Ctrl + Shift + J'). Result:


public class FormattingTest {
public void test(int[] data) {
if (data[0] > 0 && data[1] < 10 && data[2] > 4 && data[2] < 6 && data[3] > 18 && data[3] < 20) {
System.out.println("crazy condition is satisfied");
}
}
}


Note that 'Join Lines' action is rather smart - it correctly handles string literals:

Before:



After 'Join Lines' is called for selection:


public class FormattingTest {
public void test(int[] data) {
foo("xxxxxyyyyzzzz");
}

private void foo(String s) {
}
}


Also it manages variable declaration and assignment:

Before:



After 'Join Lines':


public class FormattingTest {
public void test() {
int i = 12;
}
}


Also 'Join Lines' tries to collapse multiple statements to the single one:

Before:



After 'Join Lines':


public class FormattingTest {
public void test(int i) {
int j = i * 14 + 3;
System.out.println(j);
}
}


Also there is feature request for smart processing of StringBuilder and StringBuffers - IDEA-54209.

'Unwrap' action



Last but not least cool action is 'Unwrap'. It simplifies the process of wrapping blocks removal. Consider the following example:


import java.util.concurrent.Callable;

public class FormattingTest {
public void test(Callable<Object> task) {
try {
task.call();
} catch (Exception e) {
e.printStackTrace();
}
}
}


Here method 'foo()' doesn't declare any checked exceptions but calls Callable.call() that declares Throwable. We wrapped the call into try/catch block initially but decide to throw the Throwable to the upper stack now.

We do the following then:

Remove unnecessary try/catch - move caret inside 'try' block and invoke 'Unwrap' action ('Ctrl + Shift + Del'):



Result:


import java.util.concurrent.Callable;

public class FormattingTest {
public void test(Callable<Object> task) {
task.call();
}
}


Then we can add 'throws Throwable' to the method signature using 'Add Exception to Method Signature' quickfix - put the caret to the problem call ('task.call()') and press 'Alt + Enter':



Result:


import java.util.concurrent.Callable;

public class FormattingTest {
public void test(Callable<Object> task) throws Exception {
task.call();
}
}


Develop with pleasure! :)

0 comments:

Post a Comment