samples/javaastviewer.js

Fri, 05 Jun 2015 12:38:53 +0200

author
mhaupt
date
Fri, 05 Jun 2015 12:38:53 +0200
changeset 1398
2f1b9f4daec1
parent 962
ac62e33a99b0
permissions
-rw-r--r--

8080087: Nashorn $ENV.PWD is originally undefined
Summary: On Windows, the PWD environment variable does not exist and cannot be imported in scripting mode, so it is set explicitly.
Reviewed-by: lagergren, sundar

aoqi@0 1 #// Usage: jjs -fx javaastviewer.js -- <.java files>
aoqi@0 2
aoqi@0 3 /*
aoqi@0 4 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
attila@962 5 *
aoqi@0 6 * Redistribution and use in source and binary forms, with or without
aoqi@0 7 * modification, are permitted provided that the following conditions
aoqi@0 8 * are met:
attila@962 9 *
aoqi@0 10 * - Redistributions of source code must retain the above copyright
aoqi@0 11 * notice, this list of conditions and the following disclaimer.
attila@962 12 *
aoqi@0 13 * - Redistributions in binary form must reproduce the above copyright
aoqi@0 14 * notice, this list of conditions and the following disclaimer in the
aoqi@0 15 * documentation and/or other materials provided with the distribution.
attila@962 16 *
aoqi@0 17 * - Neither the name of Oracle nor the names of its
aoqi@0 18 * contributors may be used to endorse or promote products derived
aoqi@0 19 * from this software without specific prior written permission.
attila@962 20 *
aoqi@0 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
aoqi@0 22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
aoqi@0 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
aoqi@0 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
aoqi@0 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
aoqi@0 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
aoqi@0 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
aoqi@0 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
aoqi@0 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
aoqi@0 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
aoqi@0 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
aoqi@0 32 */
aoqi@0 33
aoqi@0 34 // This example demonstrates Java subclassing by Java.extend
aoqi@0 35 // and javac Compiler and Tree API. This example also uses
aoqi@0 36 // -fx and javafx TreeView to visualize Java AST as TreeView
aoqi@0 37
aoqi@0 38 if (!$OPTIONS._fx || arguments.length == 0) {
aoqi@0 39 print("Usage: jjs -fx javaastviewer.js -- <.java files>");
aoqi@0 40 exit(1);
aoqi@0 41 }
aoqi@0 42
aoqi@0 43 // Java types used
aoqi@0 44 var Enum = Java.type("java.lang.Enum");
aoqi@0 45 var HashSet = Java.type("java.util.HashSet");
aoqi@0 46 var Name = Java.type("javax.lang.model.element.Name");
aoqi@0 47 var List = Java.type("java.util.List");
aoqi@0 48 var Set = Java.type("java.util.Set");
aoqi@0 49 var SimpleTreeVisitor = Java.type("com.sun.source.util.SimpleTreeVisitor");
aoqi@0 50 var StringArray = Java.type("java.lang.String[]");
aoqi@0 51 var ToolProvider = Java.type("javax.tools.ToolProvider");
aoqi@0 52 var Tree = Java.type("com.sun.source.tree.Tree");
aoqi@0 53
aoqi@0 54 function javaASTToScriptObject(args) {
aoqi@0 55 // properties ignored (javac implementation class properties) in AST view.
aoqi@0 56 // may not be exhaustive - any getAbc would become "abc" property or
aoqi@0 57 // public field becomes a property of same name.
aoqi@0 58 var ignoredProps = new HashSet();
attila@962 59 for each (var word in
attila@962 60 ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs',
aoqi@0 61 'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam',
aoqi@0 62 'restype', 'params', 'startPosition', 'thrown',
aoqi@0 63 'tree', 'typarams', 'typetag', 'vartype']) {
aoqi@0 64 ignoredProps.add(word);
aoqi@0 65 }
aoqi@0 66
aoqi@0 67 // get the system compiler tool
aoqi@0 68 var compiler = ToolProvider.systemJavaCompiler;
aoqi@0 69
aoqi@0 70 // get standard file manager
aoqi@0 71 var fileMgr = compiler.getStandardFileManager(null, null, null);
aoqi@0 72
aoqi@0 73 // make a list of compilation unit from command line argument file names
aoqi@0 74 // Using Java.to convert script array (arguments) to a Java String[]
aoqi@0 75 var compUnits = fileMgr.getJavaFileObjects(Java.to(args, StringArray));
aoqi@0 76
aoqi@0 77 // create a new compilation task
aoqi@0 78 var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
aoqi@0 79
aoqi@0 80 // subclass SimpleTreeVisitor - converts Java AST node to
aoqi@0 81 // a simple script object by walking through it
aoqi@0 82 var ConverterVisitor = Java.extend(SimpleTreeVisitor);
aoqi@0 83
aoqi@0 84 var visitor = new ConverterVisitor() {
aoqi@0 85 // convert java AST node to a friendly script object
attila@962 86 // which can be viewed. Every node ends up in defaultAction
aoqi@0 87 // method of SimpleTreeVisitor method.
aoqi@0 88
aoqi@0 89 defaultAction: function (node, p) {
aoqi@0 90 var resultObj = {};
aoqi@0 91 // Nashorn does not iterate properties and methods of Java objects
aoqi@0 92 // But, we can bind properties of any object (including java objects)
aoqi@0 93 // to a script object and iterate it!
aoqi@0 94 var obj = {};
aoqi@0 95 Object.bindProperties(obj, node);
aoqi@0 96
aoqi@0 97 // we don't want every property, method of java object
aoqi@0 98 for (var prop in obj) {
aoqi@0 99 var val = obj[prop];
aoqi@0 100 var type = typeof val;
aoqi@0 101 // ignore 'method' members
aoqi@0 102 if (type == 'function' || type == 'undefined') {
aoqi@0 103 continue;
aoqi@0 104 }
aoqi@0 105
aoqi@0 106 // ignore properties from Javac implementation
aoqi@0 107 // classes - hack by name!!
aoqi@0 108 if (ignoredProps.contains(prop)) {
aoqi@0 109 continue;
aoqi@0 110 }
aoqi@0 111
aoqi@0 112 // subtree - recurse it
aoqi@0 113 if (val instanceof Tree) {
aoqi@0 114 resultObj[prop] = visitor.visit(val, p);
aoqi@0 115 } else if (val instanceof List) {
aoqi@0 116 // List of trees - recurse each and make an array
aoqi@0 117 var len = val.size();
aoqi@0 118 if (len != 0) {
aoqi@0 119 var arr = [];
aoqi@0 120 for (var j = 0; j < len; j++) {
aoqi@0 121 var e = val[j];
aoqi@0 122 if (e instanceof Tree) {
aoqi@0 123 arr.push(visitor.visit(e, p));
aoqi@0 124 }
aoqi@0 125 }
aoqi@0 126 resultObj[prop] = arr;
aoqi@0 127 }
aoqi@0 128 } else if (val instanceof Set) {
aoqi@0 129 // Set - used for modifier flags
aoqi@0 130 // make array
aoqi@0 131 var len = val.size();
aoqi@0 132 if (len != 0) {
aoqi@0 133 var arr = [];
aoqi@0 134 for each (var e in val) {
aoqi@0 135 if (e instanceof Enum || typeof e == 'string') {
aoqi@0 136 arr.push(e.toString());
aoqi@0 137 }
aoqi@0 138 }
aoqi@0 139 resultObj[prop] = arr;
aoqi@0 140 }
aoqi@0 141 } else if (val instanceof Enum || val instanceof Name) {
aoqi@0 142 // make string for any Enum or Name
aoqi@0 143 resultObj[prop] = val.toString();
aoqi@0 144 } else if (type != 'object') {
aoqi@0 145 // primitives 'as is'
aoqi@0 146 resultObj[prop] = val;
aoqi@0 147 }
aoqi@0 148 }
aoqi@0 149 return resultObj;
aoqi@0 150 }
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 // top level object with one property for each compilation unit
aoqi@0 154 var scriptObj = {};
aoqi@0 155 for each (var cu in task.parse()) {
aoqi@0 156 scriptObj[cu.sourceFile.name] = cu.accept(visitor, null);
aoqi@0 157 }
aoqi@0 158
aoqi@0 159 return scriptObj;
aoqi@0 160 }
aoqi@0 161
aoqi@0 162 // JavaFX classes used
aoqi@0 163 var StackPane = Java.type("javafx.scene.layout.StackPane");
aoqi@0 164 var Scene = Java.type("javafx.scene.Scene");
aoqi@0 165 var TreeItem = Java.type("javafx.scene.control.TreeItem");
aoqi@0 166 var TreeView = Java.type("javafx.scene.control.TreeView");
aoqi@0 167
aoqi@0 168 // Create a javafx TreeItem to view a script object
aoqi@0 169 function treeItemForObject(obj, name) {
aoqi@0 170 var item = new TreeItem(name);
aoqi@0 171 for (var prop in obj) {
aoqi@0 172 var node = obj[prop];
aoqi@0 173 if (typeof node == 'object') {
aoqi@0 174 if (node == null) {
aoqi@0 175 // skip nulls
aoqi@0 176 continue;
aoqi@0 177 }
aoqi@0 178 var subitem = treeItemForObject(node, prop);
aoqi@0 179 } else {
aoqi@0 180 var subitem = new TreeItem(prop + ": " + node);
aoqi@0 181 }
aoqi@0 182 item.children.add(subitem);
aoqi@0 183 }
aoqi@0 184
aoqi@0 185 item.expanded = true;
aoqi@0 186 return item;
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 var commandArgs = arguments;
aoqi@0 190
aoqi@0 191 // JavaFX start method
aoqi@0 192 function start(stage) {
aoqi@0 193 var obj = javaASTToScriptObject(commandArgs);
aoqi@0 194 stage.title = "Java AST Viewer"
aoqi@0 195 var rootItem = treeItemForObject(obj, "AST");
aoqi@0 196 rootItem.expanded = true;
aoqi@0 197 var tree = new TreeView(rootItem);
aoqi@0 198 var root = new StackPane();
aoqi@0 199 root.children.add(tree);
aoqi@0 200 stage.scene = new Scene(root, 300, 450);
aoqi@0 201 stage.show();
aoqi@0 202 }

mercurial