blob: f9a31f1de7669494702fa8b3197660cbfadffd85 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jshell;
import java.util.List;
/**
* Provides analysis utilities for source code input.
* Optional functionality that provides for a richer interactive experience.
* Includes completion analysis:
* Is the input a complete snippet of code?
* Do I need to prompt for more input?
* Would adding a semicolon make it complete?
* Is there more than one snippet?
* etc.
* Also includes completion suggestions, as might be used in tab-completion.
*
*/
public abstract class SourceCodeAnalysis {
/**
* Given an input string, find the first snippet of code (one statement,
* definition, import, or expression) and evaluate if it is complete.
* @param input the input source string
* @return a CompletionInfo instance with location and completeness info
*/
public abstract CompletionInfo analyzeCompletion(String input);
/**
* Compute possible follow-ups for the given input.
* Uses information from the current <code>JShell</code> state, including
* type information, to filter the suggestions.
* @param input the user input, so far
* @param cursor the current position of the cursors in the given {@code input} text
* @param anchor outgoing parameter - when an option will be completed, the text between
* the anchor and cursor will be deleted and replaced with the given option
* @return list of candidate continuations of the given input.
*/
public abstract List<Suggestion> completionSuggestions(String input, int cursor, int[] anchor);
/**
* Compute a description/help string for the given user's input.
* @param input the snippet the user wrote so far
* @param cursor the current position of the cursors in the given {@code input} text
* @return description/help string for the given user's input
*/
public abstract String documentation(String input, int cursor);
/**
* Internal only constructor
*/
SourceCodeAnalysis() {}
/**
* The result of <code>analyzeCompletion(String input)</code>.
* Describes the completeness and position of the first snippet in the given input.
*/
public static class CompletionInfo {
public CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) {
this.completeness = completeness;
this.unitEndPos = unitEndPos;
this.source = source;
this.remaining = remaining;
}
/**
* The analyzed completeness of the input.
*/
public final Completeness completeness;
/**
* The end of the first unit of source.
*/
public final int unitEndPos;
/**
* Source code for the first unit of code input. For example, first
* statement, or first method declaration. Trailing semicolons will
* be added, as needed
*/
public final String source;
/**
* Input remaining after the source
*/
public final String remaining;
}
/**
* Describes the completeness of the given input.
*/
public enum Completeness {
/**
* The input is a complete source snippet (declaration or statement) as is.
*/
COMPLETE(true),
/**
* With this addition of a semicolon the input is a complete source snippet.
* This will only be returned when the end of input is encountered.
*/
COMPLETE_WITH_SEMI(true),
/**
* There must be further source beyond the given input in order for it
* to be complete. A semicolon would not complete it.
* This will only be returned when the end of input is encountered.
*/
DEFINITELY_INCOMPLETE(false),
/**
* A statement with a trailing (non-terminated) empty statement.
* Though technically it would be a complete statement
* with the addition of a semicolon, it is rare
* that that assumption is the desired behavior.
* The input is considered incomplete. Comments and white-space are
* still considered empty.
*/
CONSIDERED_INCOMPLETE(false),
/**
* An empty input.
* The input is considered incomplete. Comments and white-space are
* still considered empty.
*/
EMPTY(false),
/**
* The completeness of the input could not be determined because it
* contains errors. Error detection is not a goal of completeness
* analysis, however errors interfered with determining its completeness.
* The input is considered complete because evaluating is the best
* mechanism to get error information.
*/
UNKNOWN(true);
/**
* Is the first snippet of source complete. For example, "x=" is not
* complete, but "x=2" is complete, even though a subsequent line could
* make it "x=2+2". Already erroneous code is marked complete.
*/
public final boolean isComplete;
Completeness(boolean isComplete) {
this.isComplete = isComplete;
}
}
/**
* A candidate for continuation of the given user's input.
*/
public static class Suggestion {
/**
* Create a {@code Suggestion} instance.
* @param continuation a candidate continuation of the user's input
* @param isSmart is the candidate "smart"
*/
public Suggestion(String continuation, boolean isSmart) {
this.continuation = continuation;
this.isSmart = isSmart;
}
/**
* The candidate continuation of the given user's input.
*/
public final String continuation;
/**
* Is it an input continuation that matches the target type and is thus more
* likely to be the desired continuation. A smart continuation
* is preferred.
*/
public final boolean isSmart;
}
}