Tuesday, July 24, 2007

Code Advice #15: Name getters properly!

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.


(See intro for a background and caveats on these coding advice blog entries.)




It's been a while since I've posted Java-coding opinions. But I couldn't resist on this one. The tip itself is straightforward:


A getter method's name should not sound like an action method.

Getter methods and setter methods should not have the same name.



I'm speaking from bitter experience since I just fixed a bug where my code had accidentally been calling a getter method, when I thought I was calling a setter method.
The method in question is java.lang.ProcessBuilder#redirectErrorStream. If you're launching a process, and you want to read its output, you may want to redirect its error output to its standard output such that you only have to read the input from a single source (assuming you don't care to distinguish between output and error.)



Well, my code was initializing the ProcessBuilder:


ProcessBuilder pb = new ProcessBuilder(args);
pb.directory(pwd);
pb.redirectErrorStream();



The problem here is that redirectErrorStream() does NOT redirect the error stream! It just returns false to tell me that it's not yet planning to redirect the error stream. The correct way to do this is


ProcessBuilder pb = new ProcessBuilder(args);
pb.directory(pwd);
pb.redirectErrorStream(true);


That's right - the setter and the getter are overloaded! Ewwwww!!!



This is the kind of thing a bug detection tool like findbugs could detect. It already warns if it sees you doing something similar, like calling String.trim() without storing the return value. Unfortunately, it didn't warn me about this case - so I filed a request. But this was a great reminder to run findbugs on my code again, which turned up some other interesting things to look at...


NetBeans Ruby support interview

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.


Roman and Gregg interviewed me in the latest episode of the NetBeans podcast.



Here are the shownotes from Roman's blog:


  • 0:00 Introduction and Tor's podcasting, he's also a podcaster at the Javaposse

  • 2:30 What Tor has worked on at Sun: Java Studio Creator,
    Project Semplice,
    and the Ruby
    tools

  • 5:00 Overview of Ruby features in the
    NetBeans IDE

  • 7:25 Debugging Ruby

  • 9:50 Rails support

  • 10:51 Switching between Ruby implementations

  • 11:49 Implementation of the type inference and code completion logic

  • 17:10 Implementation of refactoring features

  • 18:54 Features Tor wants to implement next

  • 21:33 Community feedback

  • 23:17 Why should Java developers look at Ruby?

  • 26:38 Other Ruby development tools

  • 29:49 A version of NetBeans IDE that just has Ruby support?
    Check out this page on deadlock

  • 32:16 Opportunities for contributors and cool features; check out the
    wiki page.

  • 34:55 Support for other dynamic languages.
    Erlang IDE based
    on Tor's code.




The episode is here, subscription is here.


Wednesday, July 18, 2007

Jump In - The Water's Warm!

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.





My previous blog entry discussed the new Quick Fix feature for Ruby in NetBeans.
Today, I'd like to invite you all to jump in and add your own quick fixes!
Nothing (with some notable exceptions...) could be more fun! Writing a quickfix is easy, fairly self-contained (so it's easy to get started), and the resulting feature has high user visibility and utility. Thus, I think it's a great way to join an open source project and have some fun. Besides, working on tools is extra rewarding since at the end of the day, as a programmer you get to use the stuff you're building in your day-to-day work!



I've written a bunch of "Getting Started" documentation for how to write your own hints. The main starting point is is the How to Write a Hint document, which tells you everything you need to know. Look it over and see if you get inspired! If so, follow these steps:


Even if you don't want to code on the project, I'd love to have your active mailing list participation. Please join the mailinglists (or read it with a newsreader or web interface). Also feel free to edit the wiki pages and add your own quickfix requests.



I hope to see some of you on dev@ruby.netbeans.org soon!



Here are some hint ideas to get you started (a more up to date list is in the hint-howto wiki page):

  • Offer to replace a { } block with a do-end and vice versa (unless it's a single-line block where braces are most common)
  • Look for typos: incorrect spelling of "initialize", or perhaps an assignment to a variable that is close in spelling to another symbol
  • Offer to add parentheses to a code construct where the lack of parentheses results in ambiguity (such as nested method calls without parentheses)
  • Offer to remove parentheses where that's okay (some developers prefer not to use them)
  • Offer non-Railsy deprecations: Use fileutils instead of ftools, cgi instead of cgi-lib, avoid importenv, ... Anything else?
  • Offer to remove unused variables (the left hand side of the assignment, or if the right hand side is known not to
    have side effects, the entire statement)
  • Style warnings: Using method names containing uppercase/camelcase names, or constants containing lowercase characters
    • Camelcase warnings should perhaps not kick in for projects enabled for Java API calls (e.g. with JRuby)
  • Offer to fix various code style violations - see one example style guide,
    here's another, and yet another
  • Split multiple statements on a line into separate lines (I have this for defs and classes but x=y; foo should be splittable.)
  • (JRuby projects) For an unknown class, check the Java index and offer to "import" the Java class into the Ruby name space
  • Tell us your own ideas!


Wednesday, July 11, 2007

Ruby Screenshot of the Week #15: Hints and Quick Fixes!

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.


I've justed checked in support for Ruby hints and quickfixes. Most Java IDE users should be familiar with this, but I'll illustrate with some screenshots:



I've opened a Ruby file - notice the little lightbulb thingy and the underline on one of the lines:






The tooltip for the lightbulb will tell you that you have a block variable which is reusing a local variable. This means that the local variable
will be modified by the block - which is sometimes not intentional. Let's put the caret there and press Alt-Enter (or invoke the "Fix Code..." item from the Source menu)






You can now use the arrow keys to choose among the available fixes, and press Return to apply one.
This will initiate in-place editing of only the local variable references (or only the block variable references, depending on which fix you selected). When you're done you
have a unique block variable that is no longer aliasing or side-effecting the local variable:






(The in-place editing is still a bit buggy because of issue 108889. Hopefully we can get it fixed soon.)



Here's another hint: Rails Deprecations.
This looks for usages of deprecated Rails idioms, and adds little warning signs with a description. Here's an example of how this looks:






In the above code, you're using the @request field, instead of the request or request= attribute methods.
And by the way, if any Rails experts are reading this: The Rails Deprecation document describes
these fields are deprecated, yet the Rails code generator itself spits out code which uses them (specifically, in the controller's functional test). Is there
a good reason for this? For now, the rails deprecation hint skips Rails test files when scanning for this issue.


Here's another Rails deprecation example - using one of the various deprecated methods. The tip also states the suggested replacement:






And finally, here's a line-specific quickfix. It only kicks in to analyze the current line and is suitable for things you wouldn't want splattered all over your file, such as offers to create classes and methods etc. This tip looks for class or method definitions on a single line, and offers to split and reformat them across multiple lines (I think Charlie requested this one). Here's a typical same-line-class put into a rails controller test:






Applying the fix yields the expected result - semicolons removed, newlines placed in the right places and indentation fixed as expected:






You can configure the available hints under options. (The Ruby options are going to be expanded and reorganized shortly). Here's the hints panel which lets you see the available hints, enable/disable them, and configure whether each hint is shown as a warning, an error, or a warning on the cursor-line only.






Notice how the list of hints is kinda short today... That will be the topic of my next blog entry!



P.S. We're after feature freeze so whether this appears on the update center or in the default product remains to be seen, but I'm always an optimist. In any case, it will be easy to access it. For now however it's in the daily builds


Tuesday, July 10, 2007

Progress

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.


I apologize for not blogging in several weeks. A number of factors have contributed; in addition to coming down with a cold, we've had a short vacation, and perhaps most importantly, I've been working on some things that aren't very glamorous to blog about.



In particular, stabilization. I rewrote the way indentation is computed, so it should be working pretty well now. One of my unit tests takes all the Ruby files in the Ruby lib distribution as well as all the Rails files, formats them and verifies that the results look okay. Various bugs have in the past caused the formatting to skew off to the right or left if the IDE didn't properly interpret the code correctly. But it's now handling nearly all 1500 files correctly. (I say nearly because I've had to exclude a couple of files that trigger a lexing bug. Unfortunately, it's a bug outside my area and the responsible engineer is on vacation - that's July for you - but it should hopefully get addressed soon. There are some other bugs in the same situation. Thank you for your patience if you're one of the daily-build-downloaders... Give us a couple of more weeks).



I've also manually inspected the diffs for some of the largest source files - date.rb, resolv.rb etc. - and not only does the new NetBeans formatting avoid mangling the source file - it produces nearly identical results to the manually formatted sources! In both files only 10-15 lines differed, and these mostly because there's no clear agreed upon convention on how far a "hanging indent" should go.



In any case, please give it a try and let me know how it works. Smart-indent (indenting the caret when you press Return) is also using the new algorithm, so writing code like


foo =

and pressing return should now do what you expect - it will indent further in on the next line - and if you type a statement there which completes the assignment and press return, indentation is back out to the top level.



Another area I've been tweaking is handling heredocs properly. This was really challenging. Ruby allows you to write "references" to a String (which you will start defining on the next line) and then continue writing your expression. The expression then continues AFTER the string has been completed. Here's a screenshot which shows this in action:






As you can see, the method call I'm writing starts on the first line, and finishes on the last line; there are three literal strings passed to the function, and two of them are
defined as heredocs (<<).



This is mostly working now (except for some incremental lexing bugs I'll get to later). I also fixed it such that matching tag highlighting (and navigation) works for heredoc markers.



Meanwhile, I haven't only been bug fixing. More on that in my next blog entry, hopefully within the next day or two....



Oh, and one more quick thing: With the latest builds, in your RHTML files, you can now control click on render :partial's, link_to etc. and it will warp to the corresponding files - RHTML partials, controller files, actions, etc.



Here's clicking on a render partial:






Here's clicking on a controller. (Even though the hyperlink only shows the controller part as the link, the Go To Declaration handler is actually looking at the parse tree and finds the :action definition too such that it can jump to the actual action in that controller.





Wednesday, June 20, 2007

Ruby Screenshot of the Week #14: RHTML

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.


Phew - it's been a very busy past couple of weeks. We had feature freeze for NetBeans 6 just a couple of days ago (Friday night at midnight to be exact) so I was focusing all my energy on getting as many things done as possible by the deadline. From here on out, focus will be on stability. I'm starting to work my way through the bug list, and it's looking promising.



The feature I'd like to show this time is a recent addition: Improved RHTML support. In particular, RHTML completion, RHTML goto declaration, and displaying Ruby errors in RHTML files.



Here's RHTML completion (click for full size):








Things to notice here is that first of all, the various methods you might want completion (and more importantly, documentation) for that are coming from ActionView are showing up as expected - link_to, form_tag, and so on. In addition, methods from your Helper class for this controller also show up. There's also an inherited attribute from ActionView here.



Second, note the enhanced display of the rdoc. It turns out lots of Rails documentation have code snippets, and the colorizer (which I
discussed recently) now properly handles language embedding too - RHTML fragments containing Ruby and HTML colors.) Speaking of colors, NetBeans 6 recently got a makeover in the default color scheme. In addition, there are some new color themes available in the options dialog - including the old colors. You can see the new colors in these screenshots.



Go To Declaration is pretty self explanatory - it works the same way that it does in Ruby files; hold the Ctrl-key and click on identifiers and it will warp to the definition for that method, class or variable assignment. Another new feature is displaying source errors in the file. Behind the scenes, NetBeans now models what ERB will do to the file in a Rails server, and maps these errors back to the RHTML source. Thus, if you have an error like the below, you get an error annotation with a tooltip displaying the error:






One thing which is still missing is indentation of the Ruby code in RHTML files. Marek Fukala is working on this for all the embedded languages, and I believe this feature is still going in after the freeze, so look for it in upcoming builds.



Finally, thanks to those of you who have been using the regular builds and providing feedback and bug reports. I apologize for the last couple of weeks - because of the heavy feature focus before the deadline I haven't been very responsive, and the builds have gone through a huge amount of flux. One of the things which is going on is that all the keyboard shortcuts have been changing - the details are outlined here - so if you thought something was broken, perhaps it's just using a different shortcut now. (We're still tweaking this.) Things will get more and more stable from day to day now. Milestone 10 should be out in a couple of weeks.


Tuesday, June 5, 2007

Ruby Screenshot of the Week #13: Refactoring

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.


As of this evening there are two new features in the builds: Find Usages, and Rename. Let's start with Find Usages. Right click on a symbol and choose "Find Usages" (or use the keyboard shortcut). Let's say I search for the usages of the UserMail class in the Mephisto Rails blogging application (click for full size):








This feature also knows about .rhtml and .erb files - it parses the embedded Ruby and analyzes it. Here's an example where I've searched for the usages of a @comments field in a controller - notice the .rhtml matches:






(Sorry, I know these images might be a bit large on some screens; I should have taken the screenshots at a smaller screen resolution than my usual 1680x1050.)



In the Find usages dialog I can also ask NetBeans to find subtypes of the class rather than usages. Here's an example of what I get if I search for subclasses of the ApplicationController class:






Next, Rename refactoring. Let's say that I want to rename the @comments field in my Rails application controller. I right click on it, choose a new name and hit OK. I then click "Preview", and in the bottom window I get a list of refactoring operations, along with diffs for the currently selected item. I can (and should!) walk through the changes with the Up/Down arrows, and I can unselect any changes that I don't like before I click the Refactor button to apply the changes. Click on the image for full size (I'm showing both the dialog and the results window here; in reality you'd first get the dialog, and when you hit Preview it disappears and you see the bottom window.)








Again, notice how the renaming operation includes changes in .rhtml files. The advantage of this approach over a regular Search/Replace editor operation is that by using parse trees, we have a lot more confidence in the matches. The IDE will not confuse a local variable reference to foo with a method named foo. It does however still have difficulties knowing whether symbols and method names that occur in multiple places refer to say the same method, so at this point it errs on the side of optimism and presents them all as potential uses.



WARNING: This feature is definitely preliminary!! Hopefully the bold red warning in both the Rename and Find Usages dialog makes this really clear. The Refactor button will be disabled and Preview required shortly.



However, this feature should be improving rapidly as I get feedback and implement some more things on my todo-list. Find Usages at least should be quite useful as a navigation tool. If you're going to use the Rename feature, please make a backup of your code first!



(This feature requires the very latest builds - try the Ruby IDE from nbextras.org, or for fuller instructions, see the wiki page. Auto updating from M9 isn't working any more because I'm relying on private APIs that have changed incompatibly.)



P.S. A great big thank you to all of you who have tried the NetBeans Ruby support, and especially to those of you who have provided feedback!