langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java
author jlahoda
Thu, 12 Nov 2015 15:10:01 +0100
changeset 33715 74b1bed86932
parent 33362 65ec6de1d6b4
child 36160 f42d362d0d17
permissions -rw-r--r--
8141092: JShell: Completion hangs on identifier completion Summary: Avoiding recursive search when computing package completion. Reviewed-by: mcimadamore, rfield

/*
 * 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;
    }
}