Tuesday, March 30, 2010

IDE tip: AST-based Selection

WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.

AST-based selection is a feature which lets you select the surrounding "block", based not on syntactic clues (such as braces and parentheses, as is offered by practically all editors), but based on the parse tree created by the compiler (or the "AST", for abstract syntax tree).

In NetBeans, there are two complementary actions to deal with AST selection: Select Surrounding and its reverse. They have other names which I can never remember, but the keybindings are as follows:

Select surrounding block

  • Mac: Ctrl-Shift-. (period)
  • Windows/Linux/Solaris/Others: Alt-Shift-.


  • Mac: Ctrl-Shift-, (comma)
  • Windows/Linux/Solaris/Others: Alt-Shift-,

On my U.S. keyboard, the comma and period keys are marked with "<" and ">" for the shift key which is somewhat reminiscent of blocks.

These two actions cooperate and are stateful: they remember the original caret location such that you can "go back".
Here's how it works. You want to select something surrounding the caret, say the whole method. In that case you just
hit the surrounding action. With your fingers holding ctrl and shift you hit dot -- once, twice, bam bam bam. If you do it
quickly you might "overshoot" and go one too far and select say the whole class instead of just the method. If so just press
comma and voila, it goes back one step down the selection hierarchy you just came up.

This makes this a very quick way to select code blocks -- no more need to grab the mouse and try to hit exactly the selection
boundaries between characters.

Here's an example of where this comes in useful. I sometimes remove long expressions from method call arguments by pulling it
out as a separate variable. Here's my call, and I want to extract the whole Math.min expression.
First I move the caret anywhere within that expression:

Then I press Alt-Shift-. (or Ctrl-Shift-. on Mac):

One more time:

Let's pretend I was doing it quickly and hit it one extra time:

That's too far, so I press comma (with the modifier keys still pressed):

In practice (and with practice) this is done very quickly, faster than I can
accurately hit both ends of the expression with a mouse drag. And to finish
out the example, let me show a couple of more things related to the task.
Notice how there's a light bulb in the left hand side margin of the editor.
That tells me there are associated quick fixes. I press Alt Enter,
and the quick fix dialog is shown:

I choose "Introduce Variable" and press Return. This gives
a dialog where I can choose the variable name (and whether to replace all occurrences
when applicable). It suggests "min" since that's the function
name of the expression we're extracting.

Just press Return to apply the refactoring, and we've pulled out the argument

I just pressed return and got the default name. Then I realize that this may
not be a great name. What is that last parameter again? I can place the caret
somewhere within the last argument and press Cmd-P (or Ctrl+P
on other platforms) to get NetBeans to "Show Method Parameters".

Let's rename it to length instead. Press Ctrl-R (all platforms) to
apply rename refactoring, which (because this is a local or private variable)
will have "instant rename" applied where your edits are applied immediately
for every keystroke:

Just type the new name - notice that all the boxed expressions are edited synchronously.

Using AST-based selection to identify code blocks to extract as variables or methods
is useful, but it can be used in other ways as well. Let's say I want to add
a second validation step to this function. First I select the code block using
AST selection:

NetBeans has a keyboard command for duplicating the current line: Ctrl-Shift-Down
(and on Mac, it's Cmd-Shift-Down.) Note that when you have a selection, this
duplicates the entire selection. So all we have to do now is apply the duplicate command
and we've got a second if clause we can just tweak to whatever it is it needs to do.

AST based selection should be available in nearly all editor types in NetBeans.
In Ruby, JavaScript, Python, etc it also handles documentation
blocks well - so if you apply select surrounding in say a Ruby comment, it will first select
the current line, then the whole documentation block, then outwards in the AST hierarchy.

Hope you find this helpful. If there are Eclipse or IntelliJ readers who know corresponding
keybindings in Eclipse, feel free to leave a comment so others can find it easily.

No comments:

Post a Comment