Code Folding via NetBeans, JJTree, and PowerJava

Once you have a ParserResult, as described yesterday, you also need to have access to some kind of AST node, i.e., not only tokens. Tokens let you distinguish between individual characters in a document, but that's not enough if you want to create code folding for your editor. Below you see code folding for PowerJava, which is an extension to Java 1.5 for role programming. It has about 8 special keywords, which in my editor are shown in orange, as can be seen for two of them below:

The first code fold, i.e., the initial code fold, is created automatically for you if you use the CSL API. However, the other code fold you see above was created via code in the related StructureScanner:

class PowerJavaStructureScanner implements StructureScanner {

    public static final String CODE_FOLDS = "codeblocks";
    public List<? extends StructureItem> scan(ParserResult pr) {
        return new ArrayList<StructureItem>();

    public Map<String, List<OffsetRange>> folds(ParserResult pr) {
        HashMap<String, List<OffsetRange>> folds = new HashMap<String, List<OffsetRange>>();
        PowerJavaParserResult pjpr = (PowerJavaParserResult) pr;
        Document document = pr.getSnapshot().getSource().getDocument(false);
        try {
            ASTCompilationUnit cu = pjpr.getASTCompilationUnit();
            Node[] children = cu.getChildren();
            for (int i = 0; i < children.length; i++) {
                Node node = children[i];
                if (node instanceof ASTTypeDeclaration) {
                    ASTTypeDeclaration asttd = (ASTTypeDeclaration) node;
                    Token jjtGetFirstToken = asttd.jjtGetFirstToken();
                    Token jjtGetLastToken = asttd.jjtGetLastToken();
                    int start = NbDocument.findLineOffset((StyledDocument) document, 
                            jjtGetFirstToken.beginLine - 1) + jjtGetFirstToken.beginColumn - 1;
                    int end = NbDocument.findLineOffset((StyledDocument) document, 
                            jjtGetLastToken.endLine - 1) + jjtGetLastToken.endColumn;
                    String type = CODE_FOLDS;
                    OffsetRange range = new OffsetRange(start, end);
                    List<OffsetRange> fold = folds.get(type);
                    if (fold == null) {
                        fold = new ArrayList<OffsetRange>();
                    folds.put(type, fold);
        } catch (org.netbeans.modules.parsing.spi.ParseException ex) {
        return folds;

    public Configuration getConfiguration() {
        return new Configuration(false, false);


The above implies that you have higher level objects, such as ASTCompilationUnit. You can get those via JJTree, but only if you have defined a related JJT file, in addition to your JJ file. And that's why I am using PowerJava as an example, as can be seen above, because the nice people who created PowerJava have all the relevant source code available. I simply had to run javacc on their Java1.5.jjt file, and then I had everything I needed. I then integrated their lexer into the NetBeans lexer infrastructure, which enabled me to create the syntax coloring you see above. Then I used the generated parser as shown above, i.e., I can now obtain meaningful information via the generated parser so that code folds can be created.


Unfortunately you cannot decide the text that appears when the section is collapsed

Posted by Enrico Scantamburlo on January 10, 2013 at 12:23 PM PST #

Hi there

I've been following your recepe on to make a module plugin for a scripting language I like. However, it seems I suddenly cannot access javax.swing.text classes from within the module, and I cannot figure out what dependencies to define... !

Casting snapshot->source->document to javax.swing.text.StyledDocument is a bit fo class traversing, and I get a BadLocationError, which is also in the swing package, so I get a huge exception that I cannot control.

Is this well known? What might I have done wrong? Do you have any tips for me to try out?

Otherwise, thanks for a super blog!

Posted by guest on April 14, 2013 at 05:41 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« June 2016