Tuesday, October 9, 2012

NetBeans 7.3 Beta is More Than Easel: Hints and FXML Code Completion

NetBeans 7.3, which is now available in Beta, is already probably best known for its Project Easel features. However, in this post I look at some new features outside of Project Easel that I am happy to see now available in NetBeans.

New Hint: null Dereference

I'm a big fan of NetBeans's hints supports as proven by my blog posts on Seven Indispensable NetBeans Java Hints, Seven NetBeans Hints for Modernizing Java Code, Creating a NetBeans 7.1 Custom Hint, NetBeans 7.2 beta: Faster and More Helpful, and NetBeans 7.1's Unused Assignment and Dead Branch Hints. NetBeans 7.3 introduces another useful hint with the "null Dereference" hint.

The "null dereference" hint warns the developer when variables that might be null in certain cases are being dereferenced. This is shown in the next screen snapshot.

Before looking at another example of this hint in action, I want to first point out the new code editor Breadcrumbs feature. On the bottom of the above image, there are three greater-than inequality signs (> following the three respective labels "SevenThree", "processNullValue", and "if (valueStr != null). These correspond to places in the code where the highlighted variable is used (class it is used in, method it is used in, and conditional within method it is used in). Clicking on any of the greater-than signs expands possibilities of where that variable is next used. This is a handy feature for following code flow for a certain variable within static code.

Returning to the NetBeans "null deference hint," another way to demonstrate that new hint in code is via use of the NetBeans @org.netbeans.api.annotations.common.NullAllowed annotation. Applying this annotation to a parameter of the example method shown earlier leads to the hint being displayed. As a side note, this NetBeans annotation has the feel of the annotations discussed in relation to the Checker Framework in the JavaOne 2012 presentation "Build Your Own Type System for Fun and Profit."

New Suggestion: Invert If Hint

There are times when it is helpful to invert a conditional, such as to improve readability of the code. NetBeans 7.3 provides this with the "Invert If" suggestion. This is demonstrated in the folowing three screen snapshots.

JavaFX FXML Code Completion

One of the features I missed most when working with JavaFX in NetBeans was the inability to enjoy code completion when using FXML. FXML does not have a defined grammar that facilitates any generic XML parser helping with code completion, but fortunately NetBeans 7.3 adds FXML completion to its repertoire (addressing NetBeans Bug 204741).

The next screen snapshot shows the FXML raw editor code completion in action. In this case, an "import" tag is recommended. Note that because I have SceneBuilder installed with my installation of NetBeans, simply clicking on an FXML file always brings that file up in SceneBuilder. To edit this file in XML directly as shown in the next screen snapshot, I right-clicked on the file's name in the Project browser and then selected the "Edit" option.

This version of NetBeans is still in beta and this FXML code completion seems a little buggy. I kept seeing the following exception message when trying to edit an existing FXML file:

The following is a portion of the stack trace logged in the reference log file:

WARNING [org.netbeans.modules.editor.bracesmatching.MasterMatcher]: Origin offsets out of range, origin = [366, 371], caretOffset = 382, lookahead = 2, searching forward. Offending BracesMatcher: org.netbeans.modules.xml.text.bracematch.XMLBraceMatcher@1e084dc
SEVERE [org.openide.util.Exceptions]
java.lang.NullPointerException
 at org.netbeans.modules.javafx2.editor.completion.impl.PropertyCompleter.complete(PropertyCompleter.java:191)
 at org.netbeans.modules.javafx2.editor.FXMLCompletion2$Q$Task.run(FXMLCompletion2.java:207)
 at org.netbeans.modules.parsing.impl.TaskProcessor.callUserTask(TaskProcessor.java:583)
 at org.netbeans.modules.parsing.api.ParserManager$MimeTaskAction.run(ParserManager.java:377)
 at org.netbeans.modules.parsing.api.ParserManager$MimeTaskAction.run(ParserManager.java:360)
 at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:200)
 at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:197)
 at org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager.priorityIO(FileChangedManager.java:176)
 at org.netbeans.modules.masterfs.providers.ProvidedExtensions.priorityIO(ProvidedExtensions.java:360)
 at org.netbeans.modules.parsing.impl.Utilities.runPriorityIO(Utilities.java:72)
 at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:197)
Caused: org.netbeans.modules.parsing.spi.ParseException
 at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:205)
 at org.netbeans.modules.parsing.api.ParserManager.parse(ParserManager.java:331)
 at org.netbeans.modules.javafx2.editor.FXMLCompletion2$Q$Task.run(FXMLCompletion2.java:182)
 at org.netbeans.modules.parsing.impl.TaskProcessor.callUserTask(TaskProcessor.java:583)
 at org.netbeans.modules.parsing.api.ParserManager$UserTaskAction.run(ParserManager.java:150)
 at org.netbeans.modules.parsing.api.ParserManager$UserTaskAction.run(ParserManager.java:134)
 at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:200)
 at org.netbeans.modules.parsing.impl.TaskProcessor$2.call(TaskProcessor.java:197)
 at org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager.priorityIO(FileChangedManager.java:176)
 at org.netbeans.modules.masterfs.providers.ProvidedExtensions.priorityIO(ProvidedExtensions.java:360)
 at org.netbeans.modules.parsing.impl.Utilities.runPriorityIO(Utilities.java:72)
 at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:197)
Caused: org.netbeans.modules.parsing.spi.ParseException
 at org.netbeans.modules.parsing.impl.TaskProcessor.runUserTask(TaskProcessor.java:205)
 at org.netbeans.modules.parsing.api.ParserManager.parse(ParserManager.java:102)
[catch] at org.netbeans.modules.javafx2.editor.FXMLCompletion2$Q.query(FXMLCompletion2.java:129)
 at org.netbeans.spi.editor.completion.support.AsyncCompletionTask.run(AsyncCompletionTask.java:223)
 at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1454)
 at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2036)
SEVERE [org.openide.util.RequestProcessor]: Error in RequestProcessor org.netbeans.spi.editor.completion.support.AsyncCompletionTask
java.lang.AssertionError: AsyncCompletionTask: query=org.netbeans.modules.javafx2.editor.FXMLCompletion2$Q@163ab6b: query.query(): Result set not finished by resultSet.finish()
 at org.netbeans.spi.editor.completion.support.AsyncCompletionTask.run(AsyncCompletionTask.java:225)
 at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1454)
 at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2036)
Caused: org.openide.util.RequestProcessor$FastItem: task failed due to

Although NetBeans 7.3 is still in beta, I am enjoying using it and finding most things to work as I'd expect. A downside of using beta versions is the inevitable problems, but these have not been too big of a deal so far. I look forward to the production release of NetBeans 7.3.

No comments: