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
36if (!$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
50var StackPane = Java.type("javafx.scene.layout.StackPane");
51var Scene     = Java.type("javafx.scene.Scene");
52var TreeItem  = Java.type("javafx.scene.control.TreeItem");
53var TreeView  = Java.type("javafx.scene.control.TreeView");
54
55// Java classes used
56var Enum = Java.type("java.lang.Enum");
57var File = Java.type("java.io.File");
58var List = Java.type("java.util.List");
59var Parser = Java.type("jdk.nashorn.api.tree.Parser");
60var Tree = Java.type("jdk.nashorn.api.tree.Tree");
61
62// Create a javafx TreeItem to view a AST node
63function 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
98var sourceName = arguments.length == 0? __FILE__ : arguments[0];
99
100var parser = Parser.create("-scripting");
101// parse script to get CompilationUnitTree of it
102var ast = parser.parse(new File(sourceName), null);
103
104// JavaFX start method
105function 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}
114