< prev index next >

src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/NashornCompleter.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  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.PrintWriter;
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 import java.util.regex.Pattern;


  32 import jdk.internal.jline.console.completer.Completer;
  33 import jdk.internal.jline.console.UserInterruptException;
  34 import jdk.nashorn.api.tree.AssignmentTree;
  35 import jdk.nashorn.api.tree.BinaryTree;
  36 import jdk.nashorn.api.tree.CompilationUnitTree;
  37 import jdk.nashorn.api.tree.CompoundAssignmentTree;
  38 import jdk.nashorn.api.tree.ConditionalExpressionTree;
  39 import jdk.nashorn.api.tree.ExpressionTree;
  40 import jdk.nashorn.api.tree.ExpressionStatementTree;
  41 import jdk.nashorn.api.tree.FunctionCallTree;
  42 import jdk.nashorn.api.tree.IdentifierTree;
  43 import jdk.nashorn.api.tree.InstanceOfTree;
  44 import jdk.nashorn.api.tree.MemberSelectTree;
  45 import jdk.nashorn.api.tree.NewTree;
  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.tools.PartialParser;
  52 import jdk.nashorn.internal.objects.NativeSyntaxError;
  53 import jdk.nashorn.internal.objects.Global;
  54 import jdk.nashorn.internal.runtime.ECMAException;
  55 import jdk.nashorn.internal.runtime.Context;
  56 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  57 import jdk.nashorn.internal.runtime.ScriptRuntime;
  58 
  59 /**
  60  * A simple source completer for nashorn. Handles code completion for
  61  * expressions as well as handles incomplete single line code.
  62  */
  63 final class NashornCompleter implements Completer {
  64     private final Context context;
  65     private final Global global;
  66     private final ScriptEnvironment env;
  67     private final PartialParser partialParser;
  68     private final PropertiesHelper propsHelper;
  69     private final Parser parser;

  70 
  71     NashornCompleter(final Context context, final Global global,
  72             final PartialParser partialParser, final PropertiesHelper propsHelper) {
  73         this.context = context;
  74         this.global = global;
  75         this.env = context.getEnv();
  76         this.partialParser = partialParser;
  77         this.propsHelper = propsHelper;
  78         this.parser = createParser(env);
  79     }
  80 
  81 
  82     /**
  83      * Is this a ECMAScript SyntaxError thrown for parse issue at the given line and column?
  84      *
  85      * @param exp Throwable to check
  86      * @param line line number to check
  87      * @param column column number to check
  88      *
  89      * @return true if the given Throwable is a ECMAScript SyntaxError at given line, column


 165                     continue;
 166                 } else {
 167                     // print anything else and bail out!
 168                     err.println(pexp);
 169                     if (env._dump_on_error) {
 170                         pexp.printStackTrace(err);
 171                     }
 172                     return null;
 173                 }
 174             }
 175 
 176             // We have complete parseable code!
 177             return buf.toString();
 178         }
 179     }
 180 
 181     // Pattern to match a unfinished member selection expression. object part and "."
 182     // but property name missing pattern.
 183     private static final Pattern SELECT_PROP_MISSING = Pattern.compile(".*\\.\\s*");
 184 



 185     @Override
 186     public int complete(final String test, final int cursor, final List<CharSequence> result) {
 187         // check that cursor is at the end of test string. Do not complete in the middle!
 188         if (cursor != test.length()) {
 189             return cursor;
 190         }
 191 
 192         // get the start of the last expression embedded in the given code
 193         // using the partial parsing support - so that we can complete expressions
 194         // inside statements, function call argument lists, array index etc.
 195         final int exprStart = partialParser.getLastExpressionStart(context, test);
 196         if (exprStart == -1) {
 197             return cursor;
 198         }
 199 
 200 
 201         // extract the last expression string
 202         final String exprStr = test.substring(exprStart);
 203 
 204         // do we have an incomplete member selection expression that misses property name?
 205         final boolean endsWithDot = SELECT_PROP_MISSING.matcher(exprStr).matches();
 206 
 207         // If this is an incomplete member selection, then it is not legal code.
 208         // Make it legal by adding a random property name "x" to it.
 209         final String completeExpr = endsWithDot? exprStr + "x" : exprStr;
 210 
 211         final ExpressionTree topExpr = getTopLevelExpression(parser, completeExpr);
 212         if (topExpr == null) {

















 213             // did not parse to be a top level expression, no suggestions!
 214             return cursor;
 215         }
 216 
 217 
 218         // Find 'right most' expression of the top level expression
 219         final Tree rightMostExpr = getRightMostExpression(topExpr);
 220         if (rightMostExpr instanceof MemberSelectTree) {
 221             return completeMemberSelect(exprStr, cursor, result, (MemberSelectTree)rightMostExpr, endsWithDot);
 222         } else if (rightMostExpr instanceof IdentifierTree) {
 223             return completeIdentifier(exprStr, cursor, result, (IdentifierTree)rightMostExpr);
 224         } else {
 225             // expression that we cannot handle for completion
 226             return cursor;
 227         }
 228     }
 229 
 230     // Internals only below this point
 231 
 232     // fill properties of the incomplete member expression




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  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.File;
  29 import java.io.PrintWriter;
  30 import java.util.ArrayList;
  31 import java.util.List;
  32 import java.util.regex.Pattern;
  33 import javax.swing.JFileChooser;
  34 import javax.swing.filechooser.FileNameExtensionFilter;
  35 import jdk.internal.jline.console.completer.Completer;
  36 import jdk.internal.jline.console.UserInterruptException;
  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.FunctionCallTree;
  45 import jdk.nashorn.api.tree.IdentifierTree;
  46 import jdk.nashorn.api.tree.InstanceOfTree;
  47 import jdk.nashorn.api.tree.MemberSelectTree;
  48 import jdk.nashorn.api.tree.NewTree;
  49 import jdk.nashorn.api.tree.SimpleTreeVisitorES5_1;
  50 import jdk.nashorn.api.tree.Tree;
  51 import jdk.nashorn.api.tree.UnaryTree;
  52 import jdk.nashorn.api.tree.Parser;
  53 import jdk.nashorn.api.scripting.NashornException;
  54 import jdk.nashorn.tools.PartialParser;
  55 import jdk.nashorn.internal.objects.NativeSyntaxError;
  56 import jdk.nashorn.internal.objects.Global;
  57 import jdk.nashorn.internal.runtime.ECMAException;
  58 import jdk.nashorn.internal.runtime.Context;
  59 import jdk.nashorn.internal.runtime.ScriptEnvironment;
  60 import jdk.nashorn.internal.runtime.ScriptRuntime;
  61 
  62 /**
  63  * A simple source completer for nashorn. Handles code completion for
  64  * expressions as well as handles incomplete single line code.
  65  */
  66 final class NashornCompleter implements Completer {
  67     private final Context context;
  68     private final Global global;
  69     private final ScriptEnvironment env;
  70     private final PartialParser partialParser;
  71     private final PropertiesHelper propsHelper;
  72     private final Parser parser;
  73     private static final boolean BACKSLASH_FILE_SEPARATOR = File.separatorChar == '\\';
  74 
  75     NashornCompleter(final Context context, final Global global,
  76             final PartialParser partialParser, final PropertiesHelper propsHelper) {
  77         this.context = context;
  78         this.global = global;
  79         this.env = context.getEnv();
  80         this.partialParser = partialParser;
  81         this.propsHelper = propsHelper;
  82         this.parser = createParser(env);
  83     }
  84 
  85 
  86     /**
  87      * Is this a ECMAScript SyntaxError thrown for parse issue at the given line and column?
  88      *
  89      * @param exp Throwable to check
  90      * @param line line number to check
  91      * @param column column number to check
  92      *
  93      * @return true if the given Throwable is a ECMAScript SyntaxError at given line, column


 169                     continue;
 170                 } else {
 171                     // print anything else and bail out!
 172                     err.println(pexp);
 173                     if (env._dump_on_error) {
 174                         pexp.printStackTrace(err);
 175                     }
 176                     return null;
 177                 }
 178             }
 179 
 180             // We have complete parseable code!
 181             return buf.toString();
 182         }
 183     }
 184 
 185     // Pattern to match a unfinished member selection expression. object part and "."
 186     // but property name missing pattern.
 187     private static final Pattern SELECT_PROP_MISSING = Pattern.compile(".*\\.\\s*");
 188 
 189     // Pattern to match load call
 190     private static final Pattern LOAD_CALL = Pattern.compile("\\s*load\\s*\\(\\s*");
 191 
 192     @Override
 193     public int complete(final String test, final int cursor, final List<CharSequence> result) {
 194         // check that cursor is at the end of test string. Do not complete in the middle!
 195         if (cursor != test.length()) {
 196             return cursor;
 197         }
 198 
 199         // get the start of the last expression embedded in the given code
 200         // using the partial parsing support - so that we can complete expressions
 201         // inside statements, function call argument lists, array index etc.
 202         final int exprStart = partialParser.getLastExpressionStart(context, test);
 203         if (exprStart == -1) {
 204             return cursor;
 205         }
 206 
 207 
 208         // extract the last expression string
 209         final String exprStr = test.substring(exprStart);
 210 
 211         // do we have an incomplete member selection expression that misses property name?
 212         final boolean endsWithDot = SELECT_PROP_MISSING.matcher(exprStr).matches();
 213 
 214         // If this is an incomplete member selection, then it is not legal code.
 215         // Make it legal by adding a random property name "x" to it.
 216         final String completeExpr = endsWithDot? exprStr + "x" : exprStr;
 217 
 218         final ExpressionTree topExpr = getTopLevelExpression(parser, completeExpr);
 219         if (topExpr == null) {
 220             // special case for load call that looks like "load(" with optional whitespaces
 221             if (LOAD_CALL.matcher(test).matches()) {
 222                 // throw a file dialog box
 223                 final JFileChooser chooser = new JFileChooser();
 224                 chooser.setFileFilter(new FileNameExtensionFilter("JavaScript Files", "js"));
 225                 int retVal = chooser.showOpenDialog(null);
 226                 if (retVal == JFileChooser.APPROVE_OPTION) {
 227                     String name = chooser.getSelectedFile().getAbsolutePath();
 228                     // handle '\' file separator
 229                     if (BACKSLASH_FILE_SEPARATOR) {
 230                         name = name.replace("\\", "\\\\");
 231                     }
 232                     result.add("\"" + name + "\")");
 233                     return cursor + name.length() + 3;
 234                 }
 235             }
 236 
 237             // did not parse to be a top level expression, no suggestions!
 238             return cursor;
 239         }
 240 
 241 
 242         // Find 'right most' expression of the top level expression
 243         final Tree rightMostExpr = getRightMostExpression(topExpr);
 244         if (rightMostExpr instanceof MemberSelectTree) {
 245             return completeMemberSelect(exprStr, cursor, result, (MemberSelectTree)rightMostExpr, endsWithDot);
 246         } else if (rightMostExpr instanceof IdentifierTree) {
 247             return completeIdentifier(exprStr, cursor, result, (IdentifierTree)rightMostExpr);
 248         } else {
 249             // expression that we cannot handle for completion
 250             return cursor;
 251         }
 252     }
 253 
 254     // Internals only below this point
 255 
 256     // fill properties of the incomplete member expression


< prev index next >