1 /* 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 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.jshell; 27 28 import java.util.List; 29 30 /** 31 * Provides analysis utilities for source code input. 32 * Optional functionality that provides for a richer interactive experience. 33 * Includes completion analysis: 34 * Is the input a complete snippet of code? 35 * Do I need to prompt for more input? 36 * Would adding a semicolon make it complete? 37 * Is there more than one snippet? 38 * etc. 39 * Also includes completion suggestions, as might be used in tab-completion. 40 * 41 */ 42 public abstract class SourceCodeAnalysis { 43 44 /** 45 * Given an input string, find the first snippet of code (one statement, 46 * definition, import, or expression) and evaluate if it is complete. 47 * @param input the input source string 48 * @return a CompletionInfo instance with location and completeness info 49 */ 50 public abstract CompletionInfo analyzeCompletion(String input); 51 52 /** 53 * Compute possible follow-ups for the given input. 54 * Uses information from the current <code>JShell</code> state, including 55 * type information, to filter the suggestions. 56 * @param input the user input, so far 57 * @param cursor the current position of the cursors in the given {@code input} text 58 * @param anchor outgoing parameter - when an option will be completed, the text between 59 * the anchor and cursor will be deleted and replaced with the given option 60 * @return list of candidate continuations of the given input. 61 */ 62 public abstract List<Suggestion> completionSuggestions(String input, int cursor, int[] anchor); 63 64 /** 65 * Compute a description/help string for the given user's input. 66 * @param input the snippet the user wrote so far 67 * @param cursor the current position of the cursors in the given {@code input} text 68 * @return description/help string for the given user's input 69 */ 70 public abstract String documentation(String input, int cursor); 71 72 /** 73 * Internal only constructor 74 */ 75 SourceCodeAnalysis() {} 76 77 /** 78 * The result of <code>analyzeCompletion(String input)</code>. 79 * Describes the completeness and position of the first snippet in the given input. 80 */ 81 public static class CompletionInfo { 82 83 public CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) { 84 this.completeness = completeness; 85 this.unitEndPos = unitEndPos; 86 this.source = source; 87 this.remaining = remaining; 88 } 89 90 /** 91 * The analyzed completeness of the input. 92 */ 93 public final Completeness completeness; 94 95 /** 96 * The end of the first unit of source. 97 */ 98 public final int unitEndPos; 99 100 /** 101 * Source code for the first unit of code input. For example, first 102 * statement, or first method declaration. Trailing semicolons will 103 * be added, as needed 104 */ 105 public final String source; 106 107 /** 108 * Input remaining after the source 109 */ 110 public final String remaining; 111 } 112 113 /** 114 * Describes the completeness of the given input. 115 */ 116 public enum Completeness { 117 /** 118 * The input is a complete source snippet (declaration or statement) as is. 119 */ 120 COMPLETE(true), 121 122 /** 123 * With this addition of a semicolon the input is a complete source snippet. 124 * This will only be returned when the end of input is encountered. 125 */ 126 COMPLETE_WITH_SEMI(true), 127 128 /** 129 * There must be further source beyond the given input in order for it 130 * to be complete. A semicolon would not complete it. 131 * This will only be returned when the end of input is encountered. 132 */ 133 DEFINITELY_INCOMPLETE(false), 134 135 /** 136 * A statement with a trailing (non-terminated) empty statement. 137 * Though technically it would be a complete statement 138 * with the addition of a semicolon, it is rare 139 * that that assumption is the desired behavior. 140 * The input is considered incomplete. Comments and white-space are 141 * still considered empty. 142 */ 143 CONSIDERED_INCOMPLETE(false), 144 145 146 /** 147 * An empty input. 148 * The input is considered incomplete. Comments and white-space are 149 * still considered empty. 150 */ 151 EMPTY(false), 152 153 /** 154 * The completeness of the input could not be determined because it 155 * contains errors. Error detection is not a goal of completeness 156 * analysis, however errors interfered with determining its completeness. 157 * The input is considered complete because evaluating is the best 158 * mechanism to get error information. 159 */ 160 UNKNOWN(true); 161 162 /** 163 * Is the first snippet of source complete. For example, "x=" is not 164 * complete, but "x=2" is complete, even though a subsequent line could 165 * make it "x=2+2". Already erroneous code is marked complete. 166 */ 167 public final boolean isComplete; 168 169 Completeness(boolean isComplete) { 170 this.isComplete = isComplete; 171 } 172 } 173 174 /** 175 * A candidate for continuation of the given user's input. 176 */ 177 public static class Suggestion { 178 179 /** 180 * Create a {@code Suggestion} instance. 181 * @param continuation a candidate continuation of the user's input 182 * @param isSmart is the candidate "smart" 183 */ 184 public Suggestion(String continuation, boolean isSmart) { 185 this.continuation = continuation; 186 this.isSmart = isSmart; 187 } 188 189 /** 190 * The candidate continuation of the given user's input. 191 */ 192 public final String continuation; 193 194 /** 195 * Is it an input continuation that matches the target type and is thus more 196 * likely to be the desired continuation. A smart continuation 197 * is preferred. 198 */ 199 public final boolean isSmart; 200 } 201 }