1 #// Usage: jjs -scripting -fx nashornastviewer.js -- <scriptfile>
   2 
   3 /*
   4  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  *   - Redistributions of source code must retain the above copyright
  11  *     notice, this list of conditions and the following disclaimer.
  12  *
  13  *   - Redistributions in binary form must reproduce the above copyright
  14  *     notice, this list of conditions and the following disclaimer in the
  15  *     documentation and/or other materials provided with the distribution.
  16  *
  17  *   - Neither the name of Oracle nor the names of its
  18  *     contributors may be used to endorse or promote products derived
  19  *     from this software without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  22  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 # NOTE: This script requires JDK 9 build to run
  35 
  36 if (!$OPTIONS._fx) {
  37     print("Usage: jjs -scripting -fx nashornastviewer.js -- <.js file>");
  38     exit(1);
  39 }
  40 
  41 // Using JavaFX from Nashorn. See also:
  42 // http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html
  43 
  44 // This example shows AST of a script file as a JavaFX
  45 // tree view in a window. If no file is specified, AST of
  46 // this script file is shown. This script demonstrates
  47 // Nashorn Parser API too - http://openjdk.java.net/jeps/236
  48 
  49 // JavaFX classes used
  50 var StackPane = Java.type("javafx.scene.layout.StackPane");
  51 var Scene     = Java.type("javafx.scene.Scene");
  52 var TreeItem  = Java.type("javafx.scene.control.TreeItem");
  53 var TreeView  = Java.type("javafx.scene.control.TreeView");
  54 
  55 // Java classes used
  56 var Enum = Java.type("java.lang.Enum");
  57 var File = Java.type("java.io.File");
  58 var List = Java.type("java.util.List");
  59 var Parser = Java.type("jdk.nashorn.api.tree.Parser");
  60 var Tree = Java.type("jdk.nashorn.api.tree.Tree");
  61 
  62 // Create a javafx TreeItem to view a AST node
  63 function treeItemForASTNode(ast, name) {
  64     var item = new TreeItem(name);
  65     // make an iteratable script object from a Tree
  66     ast = Object.bindProperties({}, ast);
  67     for (var prop in ast) {
  68        var node = ast[prop];
  69        var type = typeof node;
  70  
  71        if (node == null || type == "function") {
  72            // skip nulls and Java methods
  73            continue;
  74        }
  75 
  76        var subitem = null;
  77        if (node instanceof Tree) {
  78            subitem = treeItemForASTNode(node, prop);
  79        } else if (node instanceof List) {
  80            var len = node.size();
  81            subitem = new TreeItem(prop);
  82            for (var i = 0; i < len; i++) {
  83                var li = treeItemForASTNode(node.get(i), String(i));
  84                subitem.children.add(li); 
  85            }
  86        } else if (node instanceof Enum || type != 'object') {
  87            subitem = new TreeItem(prop + ": " + node);
  88        }
  89 
  90        if (subitem) {
  91            item.children.add(subitem);
  92        }
  93     }
  94     return item;
  95 }
  96 
  97 // do we have a script file passed? if not, use current script
  98 var sourceName = arguments.length == 0? __FILE__ : arguments[0];
  99 
 100 var parser = Parser.create("-scripting");
 101 // parse script to get CompilationUnitTree of it
 102 var ast = parser.parse(new File(sourceName), null);
 103 
 104 // JavaFX start method
 105 function start(stage) {
 106     stage.title = "AST Viewer";
 107     var rootItem = treeItemForASTNode(ast, sourceName);
 108     var tree = new TreeView(rootItem);
 109     var root = new StackPane();
 110     root.children.add(tree);
 111     stage.scene = new Scene(root, 300, 450);
 112     stage.show();
 113 }