14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.tools.jjs;
27
28 import java.io.BufferedReader;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.io.PrintWriter;
34 import java.util.prefs.Preferences;
35 import jdk.nashorn.internal.objects.Global;
36 import jdk.nashorn.internal.runtime.Context;
37 import jdk.nashorn.internal.runtime.ErrorManager;
38 import jdk.nashorn.internal.runtime.JSType;
39 import jdk.nashorn.internal.runtime.ScriptEnvironment;
40 import jdk.nashorn.internal.runtime.ScriptRuntime;
41 import jdk.nashorn.tools.Shell;
42 import jdk.internal.jline.console.UserInterruptException;
43
44 /**
45 * Interactive command line Shell for Nashorn.
46 */
47 public final class Main extends Shell {
48 private Main() {}
49
50 static final Preferences PREFS = Preferences.userRoot().node("tool/jjs");
51
52 /**
53 * Main entry point with the default input, output and error streams.
54 *
55 * @param args The command line arguments
56 */
57 public static void main(final String[] args) {
58 try {
59 final int exitCode = main(System.in, System.out, System.err, args);
60 if (exitCode != SUCCESS) {
61 System.exit(exitCode);
79 *
80 * @throws IOException if there's a problem setting up the streams
81 */
82 public static int main(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
83 return new Main().run(in, out, err, args);
84 }
85
86 /**
87 * read-eval-print loop for Nashorn shell.
88 *
89 * @param context the nashorn context
90 * @param global global scope object to use
91 * @return return code
92 */
93 protected int readEvalPrint(final Context context, final Global global) {
94 final ScriptEnvironment env = context.getEnv();
95 final String prompt = bundle.getString("shell.prompt");
96 final PrintWriter err = context.getErr();
97 final Global oldGlobal = Context.getGlobal();
98 final boolean globalChanged = (oldGlobal != global);
99
100 try (final Console in = new Console(System.in, System.out, PREFS)) {
101 if (globalChanged) {
102 Context.setGlobal(global);
103 }
104
105 global.addShellBuiltins();
106
107 while (true) {
108 String source = "";
109 try {
110 source = in.readLine(prompt);
111 } catch (final IOException ioe) {
112 err.println(ioe.toString());
113 if (env._dump_on_error) {
114 ioe.printStackTrace(err);
115 }
116 return IO_ERROR;
117 } catch (final UserInterruptException ex) {
118 break;
119 }
120
129 }
130 } catch (final Exception e) {
131 err.println(e);
132 if (env._dump_on_error) {
133 e.printStackTrace(err);
134 }
135 }
136 }
137 } catch (final Exception e) {
138 err.println(e);
139 if (env._dump_on_error) {
140 e.printStackTrace(err);
141 }
142 } finally {
143 if (globalChanged) {
144 Context.setGlobal(oldGlobal);
145 }
146 }
147
148 return SUCCESS;
149 }
150 }
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.tools.jjs;
27
28 import java.io.BufferedReader;
29 import java.io.InputStream;
30 import java.io.InputStreamReader;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.io.PrintWriter;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.prefs.Preferences;
37 import jdk.nashorn.api.tree.AssignmentTree;
38 import jdk.nashorn.api.tree.BinaryTree;
39 import jdk.nashorn.api.tree.CompilationUnitTree;
40 import jdk.nashorn.api.tree.CompoundAssignmentTree;
41 import jdk.nashorn.api.tree.ConditionalExpressionTree;
42 import jdk.nashorn.api.tree.ExpressionTree;
43 import jdk.nashorn.api.tree.ExpressionStatementTree;
44 import jdk.nashorn.api.tree.InstanceOfTree;
45 import jdk.nashorn.api.tree.MemberSelectTree;
46 import jdk.nashorn.api.tree.SimpleTreeVisitorES5_1;
47 import jdk.nashorn.api.tree.Tree;
48 import jdk.nashorn.api.tree.UnaryTree;
49 import jdk.nashorn.api.tree.Parser;
50 import jdk.nashorn.api.scripting.NashornException;
51 import jdk.nashorn.internal.objects.Global;
52 import jdk.nashorn.internal.runtime.Context;
53 import jdk.nashorn.internal.runtime.ErrorManager;
54 import jdk.nashorn.internal.runtime.JSType;
55 import jdk.nashorn.internal.runtime.ScriptEnvironment;
56 import jdk.nashorn.internal.runtime.ScriptObject;
57 import jdk.nashorn.internal.runtime.ScriptRuntime;
58 import jdk.nashorn.tools.Shell;
59 import jdk.internal.jline.console.completer.Completer;
60 import jdk.internal.jline.console.UserInterruptException;
61
62 /**
63 * Interactive command line Shell for Nashorn.
64 */
65 public final class Main extends Shell {
66 private Main() {}
67
68 static final Preferences PREFS = Preferences.userRoot().node("tool/jjs");
69
70 /**
71 * Main entry point with the default input, output and error streams.
72 *
73 * @param args The command line arguments
74 */
75 public static void main(final String[] args) {
76 try {
77 final int exitCode = main(System.in, System.out, System.err, args);
78 if (exitCode != SUCCESS) {
79 System.exit(exitCode);
97 *
98 * @throws IOException if there's a problem setting up the streams
99 */
100 public static int main(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
101 return new Main().run(in, out, err, args);
102 }
103
104 /**
105 * read-eval-print loop for Nashorn shell.
106 *
107 * @param context the nashorn context
108 * @param global global scope object to use
109 * @return return code
110 */
111 protected int readEvalPrint(final Context context, final Global global) {
112 final ScriptEnvironment env = context.getEnv();
113 final String prompt = bundle.getString("shell.prompt");
114 final PrintWriter err = context.getErr();
115 final Global oldGlobal = Context.getGlobal();
116 final boolean globalChanged = (oldGlobal != global);
117 final Parser parser = Parser.create();
118
119 // simple source "tab completer" for nashorn
120 final Completer completer = new Completer() {
121 @Override
122 public int complete(String test, int cursor, List<CharSequence> result) {
123 // check that cursor is at the end of test string. Do not complete in the middle!
124 if (cursor != test.length()) {
125 return cursor;
126 }
127
128 // if it has a ".", then assume it is a member selection expression
129 final int idx = test.lastIndexOf('.');
130 if (idx == -1) {
131 return cursor;
132 }
133
134 // stuff before the last "."
135 final String exprBeforeDot = test.substring(0, idx);
136
137 // Make sure that completed code will have a member expression! Adding ".x" as a
138 // random property/field name selected to make it possible to be a proper member select
139 final ExpressionTree topExpr = getTopLevelExpression(parser, exprBeforeDot + ".x");
140 if (topExpr == null) {
141 // did not parse to be a top level expression, no suggestions!
142 return cursor;
143 }
144
145
146 // Find 'right most' member select expression's start position
147 final int startPosition = (int) getStartOfMemberSelect(topExpr);
148 if (startPosition == -1) {
149 // not a member expression that we can handle for completion
150 return cursor;
151 }
152
153 // The part of the right most member select expression before the "."
154 final String objExpr = test.substring(startPosition, idx);
155
156 // try to evaluate the object expression part as a script
157 Object obj = null;
158 try {
159 obj = context.eval(global, objExpr, global, "<suggestions>");
160 } catch (Exception ignored) {
161 // throw the exception - this is during tab-completion
162 }
163
164 if (obj != null && obj != ScriptRuntime.UNDEFINED) {
165 // where is the last dot? Is there a partial property name specified?
166 final String prefix = test.substring(idx + 1);
167 if (prefix.isEmpty()) {
168 // no user specified "prefix". List all properties of the object
169 result.addAll(PropertiesHelper.getProperties(obj));
170 return cursor;
171 } else {
172 // list of properties matching the user specified prefix
173 result.addAll(PropertiesHelper.getProperties(obj, prefix));
174 return idx + 1;
175 }
176 }
177
178 return cursor;
179 }
180 };
181
182 try (final Console in = new Console(System.in, System.out, PREFS, completer)) {
183 if (globalChanged) {
184 Context.setGlobal(global);
185 }
186
187 global.addShellBuiltins();
188
189 while (true) {
190 String source = "";
191 try {
192 source = in.readLine(prompt);
193 } catch (final IOException ioe) {
194 err.println(ioe.toString());
195 if (env._dump_on_error) {
196 ioe.printStackTrace(err);
197 }
198 return IO_ERROR;
199 } catch (final UserInterruptException ex) {
200 break;
201 }
202
211 }
212 } catch (final Exception e) {
213 err.println(e);
214 if (env._dump_on_error) {
215 e.printStackTrace(err);
216 }
217 }
218 }
219 } catch (final Exception e) {
220 err.println(e);
221 if (env._dump_on_error) {
222 e.printStackTrace(err);
223 }
224 } finally {
225 if (globalChanged) {
226 Context.setGlobal(oldGlobal);
227 }
228 }
229
230 return SUCCESS;
231 }
232
233 // returns ExpressionTree if the given code parses to a top level expression.
234 // Or else returns null.
235 private ExpressionTree getTopLevelExpression(final Parser parser, final String code) {
236 try {
237 final CompilationUnitTree cut = parser.parse("<code>", code, null);
238 final List<? extends Tree> stats = cut.getSourceElements();
239 if (stats.size() == 1) {
240 final Tree stat = stats.get(0);
241 if (stat instanceof ExpressionStatementTree) {
242 return ((ExpressionStatementTree)stat).getExpression();
243 }
244 }
245 } catch (final NashornException ignored) {
246 // ignore any parser error. This is for completion anyway!
247 // And user will get that error later when the expression is evaluated.
248 }
249
250 return null;
251 }
252
253
254 private long getStartOfMemberSelect(final ExpressionTree expr) {
255 if (expr instanceof MemberSelectTree) {
256 return ((MemberSelectTree)expr).getStartPosition();
257 }
258
259 final Tree rightMostExpr = expr.accept(new SimpleTreeVisitorES5_1<Tree, Void>() {
260 @Override
261 public Tree visitAssignment(final AssignmentTree at, final Void v) {
262 return at.getExpression();
263 }
264
265 @Override
266 public Tree visitCompoundAssignment(final CompoundAssignmentTree cat, final Void v) {
267 return cat.getExpression();
268 }
269
270 @Override
271 public Tree visitConditionalExpression(final ConditionalExpressionTree cet, final Void v) {
272 return cet.getFalseExpression();
273 }
274
275 @Override
276 public Tree visitBinary(final BinaryTree bt, final Void v) {
277 return bt.getRightOperand();
278 }
279
280 @Override
281 public Tree visitInstanceOf(final InstanceOfTree it, final Void v) {
282 return it.getType();
283 }
284
285 @Override
286 public Tree visitUnary(final UnaryTree ut, final Void v) {
287 return ut.getExpression();
288 }
289 }, null);
290
291 return (rightMostExpr instanceof MemberSelectTree)?
292 rightMostExpr.getStartPosition() : -1L;
293 }
294 }
|