/*
 * Copyright (c) 2015, 2019, 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.Collection;
import java.util.Collections;
import java.util.List;

A Snippet represents a snippet of Java source code as passed to JShell.eval(String). It is associated only with the JShell instance that created it. An instance of Snippet (including its subclasses) is immutable: an access to any of its methods will always return the same result. For information about the current state of the snippet within the JShell state engine, query JShell passing the Snippet.

Because it is immutable, Snippet (and subclasses) is thread-safe.

Author:Robert Field
See Also:
Since:9
/** * A Snippet represents a snippet of Java source code as passed to * {@link jdk.jshell.JShell#eval(java.lang.String)}. It is associated only with the * {@link jdk.jshell.JShell JShell} instance that created it. * An instance of Snippet (including its subclasses) is immutable: an access to * any of its methods will always return the same result. * For information about the current state of the snippet within the JShell * state engine, query {@code JShell} passing the Snippet. * <p> * Because it is immutable, {@code Snippet} (and subclasses) is thread-safe. * * @author Robert Field * @since 9 * @see jdk.jshell.JShell#status */
public abstract class Snippet {
Describes the general kind of snippet. The Kind is an immutable property of a Snippet. It is accessed with Snippet.kind(). The Kind can be used to determine which subclass of Snippet it is. For example, JShell.eval(String) eval("int three() return 3; }")} will return a snippet creation event. The Kind of that Snippet will be METHOD, from which you know that the subclass of Snippet is MethodSnippet and it can be cast as such.
/** * Describes the general kind of snippet. * The {@code Kind} is an immutable property of a Snippet. * It is accessed with {@link jdk.jshell.Snippet#kind()}. * The {@code Kind} can be used to determine which * subclass of Snippet it is. For example, * {@link jdk.jshell.JShell#eval(java.lang.String) eval("int three() { return 3; }")} will * return a snippet creation event. The {@code Kind} of that Snippet * will be {@code METHOD}, from which you know that the subclass * of {@code Snippet} is {@code MethodSnippet} and it can be * cast as such. */
public enum Kind {
An import declaration: import ... The snippet is an instance of ImportSnippet.

An import can be a single type import (SubKind.SINGLE_TYPE_IMPORT_SUBKIND), a static single import (SubKind.SINGLE_STATIC_IMPORT_SUBKIND), an on-demand type import (SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND), or a static on-demand type import (SubKind.SINGLE_STATIC_IMPORT_SUBKIND) -- use Snippet.subKind() to distinguish.

An import declaration is persistent.

@jls7.5 Import Declarations
/** * An import declaration: {@code import} ... * The snippet is an instance of {@link jdk.jshell.ImportSnippet}. * <P> * An import can be a single type import * ({@link jdk.jshell.Snippet.SubKind#SINGLE_TYPE_IMPORT_SUBKIND}), * a static single import * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}), * an on-demand type import * ({@link jdk.jshell.Snippet.SubKind#TYPE_IMPORT_ON_DEMAND_SUBKIND}), * or a static on-demand type import * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}) -- * use {@link jdk.jshell.Snippet#subKind()} to distinguish. * * <P> * An import declaration is {@linkplain Kind#isPersistent() persistent}. * * @jls 7.5 Import Declarations */
IMPORT(true),
A type declaration. Which includes: NormalClassDeclaration, EnumDeclaration, NormalInterfaceDeclaration, and AnnotationTypeDeclaration. The snippet is an instance of TypeDeclSnippet.

A type declaration may be an interface SubKind.INTERFACE_SUBKIND, classes SubKind.CLASS_SUBKIND, enums, and annotation interfaces -- see SubKind to differentiate.

A type declaration is persistent.

@jls7.6 Top Level Type Declarations
/** * A type declaration. * Which includes: NormalClassDeclaration, EnumDeclaration, * NormalInterfaceDeclaration, and AnnotationTypeDeclaration. * The snippet is an instance of {@link jdk.jshell.TypeDeclSnippet}. * <P> * A type declaration may be an interface * {@link jdk.jshell.Snippet.SubKind#INTERFACE_SUBKIND}, * classes {@link jdk.jshell.Snippet.SubKind#CLASS_SUBKIND}, enums, and * annotation interfaces -- see {@link jdk.jshell.Snippet.SubKind} to * differentiate. * * <P> * A type declaration is {@linkplain Kind#isPersistent() persistent}. * * @jls 7.6 Top Level Type Declarations */
TYPE_DECL(true),
A method declaration. The snippet is an instance of MethodSnippet.

A method declaration is persistent.

@jls8.4 Method Declarations
/** * A method declaration. * The snippet is an instance of {@link jdk.jshell.MethodSnippet}. * * <P> * A method declaration is {@linkplain Kind#isPersistent() persistent}. * * @jls 8.4 Method Declarations */
METHOD(true),
One variable declaration. Corresponding to one VariableDeclarator. The snippet is an instance of VarSnippet.

The variable may be with or without initializer, or be a temporary variable representing an expression -- see SubKindto differentiate.

A variable declaration is persistent.

@jls8.3 Field Declarations
/** * One variable declaration. * Corresponding to one <i>VariableDeclarator</i>. * The snippet is an instance of {@link jdk.jshell.VarSnippet}. * <P> * The variable may be with or without initializer, or be a temporary * variable representing an expression -- see * {@link jdk.jshell.Snippet.SubKind}to differentiate. * * <P> * A variable declaration is {@linkplain Kind#isPersistent() persistent}. * * @jls 8.3 Field Declarations */
VAR(true),
An expression, with or without side-effects. The snippet is an instance of ExpressionSnippet.

The expression is currently either a simple named reference to a variable (SubKind.VAR_VALUE_SUBKIND) or an assignment (both of which have natural referencing names) -- see SubKind to differentiate. All other expression forms (operators, method calls, ...) generate a scratch variable and so are instead of the VAR Kind.

@jls15 Expressions
/** * An expression, with or without side-effects. * The snippet is an instance of {@link jdk.jshell.ExpressionSnippet}. * <P> * The expression is currently either a simple named reference to a * variable ({@link jdk.jshell.Snippet.SubKind#VAR_VALUE_SUBKIND}) or an * assignment (both of which have natural referencing * names) -- see {@link jdk.jshell.Snippet.SubKind} to differentiate. * All other expression forms (operators, method calls, ...) generate a * scratch variable and so are instead of the VAR Kind. * * @jls 15 Expressions */
EXPRESSION(false),
A statement. The snippet is an instance of StatementSnippet.
@jls14.5 Statements
/** * A statement. * The snippet is an instance of {@link jdk.jshell.StatementSnippet}. * * @jls 14.5 Statements */
STATEMENT(false),
A syntactically incorrect input for which the specific kind could not be determined. The snippet is an instance of ErroneousSnippet.
/** * A syntactically incorrect input for which the specific * kind could not be determined. * The snippet is an instance of {@link jdk.jshell.ErroneousSnippet}. */
ERRONEOUS(false); private final boolean isPersistent; Kind(boolean isPersistent) { this.isPersistent = isPersistent; }
Indicates whether this Kind of Snippet is persistent. Only declarations are persistent because they influence future Snippets.

Note that though the Kind of a Snippet may be persistent, that does not mean that the Snippet will persist; For example it may be invalid or have been dropped. See: Status.isDefined().

Returns:true if this Kind of Snippet is visible to subsequent evaluations; otherwise false
/** * Indicates whether this {@code Kind} of Snippet is persistent. Only * declarations are persistent because they influence future Snippets. * <p> * Note that though the {@code Kind} of * a Snippet may be persistent, that does not mean that the Snippet will * persist; For example it may be invalid or have been dropped. See: * {@link jdk.jshell.Snippet.Status#isDefined()}. * * @return {@code true} if this {@code Kind} of {@code Snippet} is * visible to subsequent evaluations; otherwise {@code false} */
public boolean isPersistent() { return isPersistent; } }
The detailed variety of a snippet. This is a sub-classification of the Kind. The Kind of a SubKind is accessible with kind().
/** * The detailed variety of a snippet. This is a sub-classification of the * Kind. The Kind of a SubKind is accessible with * {@link jdk.jshell.Snippet.SubKind#kind()}. */
public enum SubKind {
Single-Type-Import Declaration. An import declaration of a single type.
@jls7.5.1 Single-Type-Import Declarations
/** * Single-Type-Import Declaration. * An import declaration of a single type. * @jls 7.5.1 Single-Type-Import Declarations */
SINGLE_TYPE_IMPORT_SUBKIND(Kind.IMPORT),
Type-Import-on-Demand Declaration. A non-static "star" import.
@jls7.5.2 Type-Import-on-Demand Declarations
/** * Type-Import-on-Demand Declaration. * A non-static "star" import. * @jls 7.5.2 Type-Import-on-Demand Declarations */
TYPE_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
Single-Static-Import Declaration. An import of a static member.
@jls7.5.3 Single-Static-Import Declarations
/** * Single-Static-Import Declaration. * An import of a static member. * @jls 7.5.3 Single-Static-Import Declarations */
SINGLE_STATIC_IMPORT_SUBKIND(Kind.IMPORT),
Static-Import-on-Demand Declaration. A static "star" import of all static members of a named type.
@jls7.5.4 Static-Import-on-Demand Declarations
/** * Static-Import-on-Demand Declaration. * A static "star" import of all static members of a named type. * @jls 7.5.4 Static-Import-on-Demand Declarations */
STATIC_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
A class declaration. A SubKind of Kind.TYPE_DECL.
@jls8.1 Class Declarations
/** * A class declaration. * A {@code SubKind} of {@link Kind#TYPE_DECL}. * @jls 8.1 Class Declarations */
CLASS_SUBKIND(Kind.TYPE_DECL),
An interface declaration. A SubKind of Kind.TYPE_DECL.
@jls9.1 Interface Declarations
/** * An interface declaration. * A {@code SubKind} of {@link Kind#TYPE_DECL}. * @jls 9.1 Interface Declarations */
INTERFACE_SUBKIND(Kind.TYPE_DECL),
An enum declaration. A SubKind of Kind.TYPE_DECL.
@jls8.9 Enum Types
/** * An enum declaration. * A {@code SubKind} of {@link Kind#TYPE_DECL}. * @jls 8.9 Enum Types */
ENUM_SUBKIND(Kind.TYPE_DECL),
A record declaration. A SubKind of Kind.TYPE_DECL.
@jls8.10 Record Types
Since:14
/** * A record declaration. * A {@code SubKind} of {@link Kind#TYPE_DECL}. * @jls 8.10 Record Types * @since 14 * */
RECORD_SUBKIND(Kind.TYPE_DECL),
An annotation interface declaration. A SubKind of Kind.TYPE_DECL.
@jls9.6 Annotation Types
/** * An annotation interface declaration. A {@code SubKind} of * {@link Kind#TYPE_DECL}. * @jls 9.6 Annotation Types */
ANNOTATION_TYPE_SUBKIND(Kind.TYPE_DECL),
A method. The only SubKind for Kind.METHOD.
@jls8.4 Method Declarations
/** * A method. The only {@code SubKind} for {@link Kind#METHOD}. * @jls 8.4 Method Declarations */
METHOD_SUBKIND(Kind.METHOD),
A variable declaration without initializer. A SubKind of Kind.VAR.
@jls8.3 Field Declarations
/** * A variable declaration without initializer. * A {@code SubKind} of {@link Kind#VAR}. * @jls 8.3 Field Declarations */
VAR_DECLARATION_SUBKIND(Kind.VAR, true, true),
A variable declaration with an initializer expression. A SubKind of Kind.VAR.
@jls8.3 Field Declarations
/** * A variable declaration with an initializer expression. A * {@code SubKind} of {@link Kind#VAR}. * @jls 8.3 Field Declarations */
VAR_DECLARATION_WITH_INITIALIZER_SUBKIND(Kind.VAR, true, true),
An expression whose value has been stored in a temporary variable. A SubKind of Kind.VAR.
@jls15 Expressions
/** * An expression whose value has been stored in a temporary variable. A * {@code SubKind} of {@link Kind#VAR}. * @jls 15 Expressions */
TEMP_VAR_EXPRESSION_SUBKIND(Kind.VAR, true, true),
A simple variable reference expression. A SubKind of Kind.EXPRESSION.
@jls15.11 Field Access Expressions
/** * A simple variable reference expression. A {@code SubKind} of * {@link Kind#EXPRESSION}. * @jls 15.11 Field Access Expressions */
VAR_VALUE_SUBKIND(Kind.EXPRESSION, true, true),
An assignment expression. A SubKind of Kind.EXPRESSION.
@jls15.26 Assignment Operators
/** * An assignment expression. A {@code SubKind} of * {@link Kind#EXPRESSION}. * @jls 15.26 Assignment Operators */
ASSIGNMENT_SUBKIND(Kind.EXPRESSION, true, true),
An expression which has not been wrapped in a temporary variable (reserved). A SubKind of Kind.EXPRESSION.
/** * An expression which has not been wrapped in a temporary variable * (reserved). A {@code SubKind} of {@link Kind#EXPRESSION}. */
OTHER_EXPRESSION_SUBKIND(Kind.EXPRESSION, true, true),
A statement. The only SubKind for Kind.STATEMENT.
@jls14.5 Statements
/** * A statement. The only {@code SubKind} for {@link Kind#STATEMENT}. * @jls 14.5 Statements */
STATEMENT_SUBKIND(Kind.STATEMENT, true, false),
An unknown snippet. The only SubKind for Kind.ERRONEOUS.
/** * An unknown snippet. The only {@code SubKind} for * {@link Kind#ERRONEOUS}. */
UNKNOWN_SUBKIND(Kind.ERRONEOUS, false, false); private final boolean isExecutable; private final boolean hasValue; private final Kind kind; SubKind(Kind kind) { this.kind = kind; this.isExecutable = false; this.hasValue = false; } SubKind(Kind kind, boolean isExecutable, boolean hasValue) { this.kind = kind; this.isExecutable = isExecutable; this.hasValue = hasValue; }
Indicates whether this SubKind is executable.
Returns:true if this SubKind can be executed; otherwise false
/** * Indicates whether this {@code SubKind} is executable. * * @return {@code true} if this {@code SubKind} can * be executed; otherwise {@code false} */
public boolean isExecutable() { return isExecutable; }
Indicates whether this SubKind is executable and is non-void.
Returns:true if this SubKind has a value; otherwise false
/** * Indicates whether this {@code SubKind} is executable and * is non-{@code void}. * * @return {@code true} if this {@code SubKind} has * a value; otherwise {@code false} */
public boolean hasValue() { return hasValue; }
The Kind that corresponds to this SubKind.
Returns:the fixed Kind for this SubKind
/** * The {@link Snippet.Kind} that corresponds to this {@code SubKind}. * * @return the fixed {@code Kind} for this {@code SubKind} */
public Kind kind() { return kind; } }
Describes the current state of a Snippet. This is a dynamic property of a Snippet within the JShell state -- thus is retrieved with a JShell.status(Snippet) query on JShell}.

The Status changes as the state changes. For example, creation of another snippet with eval may resolve dependencies of this Snippet (or invalidate those dependencies), or overwrite this Snippet changing its Status.

Important properties associated with Status are: isDefined(), if it is visible to other existing and new snippets; and isActive(), if, as the JShell state changes, the snippet will update, possibly changing Status. An executable Snippet can only be executed if it is in the the VALID Status.

See Also:
/** * Describes the current state of a Snippet. * This is a dynamic property of a Snippet within the JShell state -- * thus is retrieved with a {@linkplain * jdk.jshell.JShell#status(jdk.jshell.Snippet) query on {@code JShell}}. * <p> * The {@code Status} changes as the state changes. * For example, creation of another snippet with * {@link jdk.jshell.JShell#eval(java.lang.String) eval} * may resolve dependencies of this Snippet (or invalidate those dependencies), or * {@linkplain jdk.jshell.Snippet.Status#OVERWRITTEN overwrite} * this Snippet changing its * {@code Status}. * <p> * Important properties associated with {@code Status} are: * {@link jdk.jshell.Snippet.Status#isDefined()}, if it is visible to other * existing and new snippets; and * {@link jdk.jshell.Snippet.Status#isActive()}, if, as the * JShell state changes, the snippet will update, possibly * changing {@code Status}. * An executable Snippet can only be executed if it is in the the * {@link jdk.jshell.Snippet.Status#VALID} {@code Status}. * @see JShell#status(jdk.jshell.Snippet) */
public enum Status {
The snippet is a valid snippet (in the context of current JShell state). Only snippets with VALID Status can be executed (though not all VALID snippets have executable code).

The snippet is defined (isDefined() == true). If the snippet is a declaration or import (Kind.isPersistent()), it is visible to other snippets

The snippet will update as dependents change (isActive() == true), its status could become RECOVERABLE_DEFINED, RECOVERABLE_NOT_DEFINED, DROPPED, or OVERWRITTEN.

/** * The snippet is a valid snippet * (in the context of current {@code JShell} state). * Only snippets with {@code VALID} * {@code Status} can be executed (though not all * {@code VALID} snippets have executable code). * <p> * The snippet is defined * ({@link Status#isDefined() isDefined() == true}). * If the snippet is a declaration or import * ({@link Snippet.Kind#isPersistent()}), * it is visible to other snippets * <p> * The snippet will update as dependents change * ({@link Status#isActive() isActive() == true}), its * status could become {@code RECOVERABLE_DEFINED}, {@code RECOVERABLE_NOT_DEFINED}, * {@code DROPPED}, or {@code OVERWRITTEN}. */
VALID(true, true),
The snippet is a declaration snippet with potentially recoverable unresolved references or other issues in its body (in the context of current JShell state). Only a DeclarationSnippet can have this Status.

The snippet has a valid signature and it is visible to other snippets (isDefined() == true) and thus can be referenced in existing or new snippets but the snippet cannot be executed. An UnresolvedReferenceException will be thrown on an attempt to execute it.

The snippet will update as dependents change (isActive() == true), its status could become VALID, RECOVERABLE_NOT_DEFINED, DROPPED, or OVERWRITTEN.

Note: both RECOVERABLE_DEFINED and RECOVERABLE_NOT_DEFINED indicate potentially recoverable errors, they differ in that, for RECOVERABLE_DEFINED, the snippet is defined.

/** * The snippet is a declaration snippet with potentially recoverable * unresolved references or other issues in its body * (in the context of current {@code JShell} state). * Only a {@link jdk.jshell.DeclarationSnippet} can have this * {@code Status}. * <p> * The snippet has a valid signature and it is visible to other * snippets * ({@link Status#isDefined() isDefined() == true}) * and thus can be referenced in existing or new snippets * but the snippet cannot be executed. * An {@link UnresolvedReferenceException} will be thrown on an attempt * to execute it. * <p> * The snippet will update as dependents change * ({@link Status#isActive() isActive() == true}), its * status could become {@code VALID}, {@code RECOVERABLE_NOT_DEFINED}, * {@code DROPPED}, or {@code OVERWRITTEN}. * <p> * Note: both {@code RECOVERABLE_DEFINED} and {@code RECOVERABLE_NOT_DEFINED} * indicate potentially recoverable errors, they differ in that, for * {@code RECOVERABLE_DEFINED}, the snippet is * {@linkplain Status#isDefined() defined}. */
RECOVERABLE_DEFINED(true, true),
The snippet is a declaration snippet with potentially recoverable unresolved references or other issues (in the context of current JShell state). Only a DeclarationSnippet can have this Status.

The snippet has an invalid signature or the implementation is otherwise unable to define it. The snippet it is not visible to other snippets (isDefined() == false) and thus cannot be referenced or executed.

The snippet will update as dependents change (isActive() == true), its status could become VALID, RECOVERABLE_DEFINED, DROPPED, or OVERWRITTEN.

Note: both RECOVERABLE_DEFINED and RECOVERABLE_NOT_DEFINED indicate potentially recoverable errors, they differ in that, for RECOVERABLE_DEFINED, the snippet is defined.

/** * The snippet is a declaration snippet with potentially recoverable * unresolved references or other issues * (in the context of current {@code JShell} state). * Only a {@link jdk.jshell.DeclarationSnippet} can have this * {@code Status}. * <p> * The snippet has an invalid signature or the implementation is * otherwise unable to define it. * The snippet it is not visible to other snippets * ({@link Status#isDefined() isDefined() == false}) * and thus cannot be referenced or executed. * <p> * The snippet will update as dependents change * ({@link Status#isActive() isActive() == true}), its * status could become {@code VALID}, {@code RECOVERABLE_DEFINED}, * {@code DROPPED}, or {@code OVERWRITTEN}. * <p> * Note: both {@code RECOVERABLE_DEFINED} and {@code RECOVERABLE_NOT_DEFINED} * indicate potentially recoverable errors, they differ in that, for * {@code RECOVERABLE_DEFINED}, the snippet is * {@linkplain Status#isDefined() defined}. */
RECOVERABLE_NOT_DEFINED(true, false),
The snippet is inactive because of an explicit call to the JShell.drop(Snippet).

The snippet is not visible to other snippets (isDefined() == false) and thus cannot be referenced or executed.

The snippet will not update as dependents change (isActive() == false), its Status will never change again.

/** * The snippet is inactive because of an explicit call to * the {@link JShell#drop(Snippet)}. * <p> * The snippet is not visible to other snippets * ({@link Status#isDefined() isDefined() == false}) * and thus cannot be referenced or executed. * <p> * The snippet will not update as dependents change * ({@link Status#isActive() isActive() == false}), its * {@code Status} will never change again. */
DROPPED(false, false),
The snippet is inactive because it has been replaced by a new snippet. This occurs when the new snippet added with eval matches a previous snippet. A TypeDeclSnippet will match another TypeDeclSnippet if the names match. For example class X { } will overwrite class X { int ii; } or interface X { }. A MethodSnippet will match another MethodSnippet if the names and parameter types match. For example void m(int a) { } will overwrite int m(int a) { return a+a; }. A VarSnippet will match another VarSnippet if the names match. For example double z; will overwrite long z = 2L;. Only a PersistentSnippet can have this Status.

The snippet is not visible to other snippets (isDefined() == false) and thus cannot be referenced or executed.

The snippet will not update as dependents change (isActive() == false), its Status will never change again.

/** * The snippet is inactive because it has been replaced by a new * snippet. This occurs when the new snippet added with * {@link jdk.jshell.JShell#eval(java.lang.String) eval} matches a previous snippet. * A {@code TypeDeclSnippet} will match another * {@code TypeDeclSnippet} if the names match. * For example {@code class X { }} will overwrite * {@code class X { int ii; }} or * {@code interface X { }}. * A {@code MethodSnippet} will match another * {@code MethodSnippet} if the names and parameter types * match. * For example {@code void m(int a) { }} will overwrite * {@code int m(int a) { return a+a; }}. * A {@code VarSnippet} will match another * {@code VarSnippet} if the names match. * For example {@code double z;} will overwrite * {@code long z = 2L;}. * Only a {@link jdk.jshell.PersistentSnippet} can have this * {@code Status}. * <p> * The snippet is not visible to other snippets * ({@link Status#isDefined() isDefined() == false}) * and thus cannot be referenced or executed. * <p> * The snippet will not update as dependents change * ({@link Status#isActive() isActive() == false}), its * {@code Status} will never change again. */
OVERWRITTEN(false, false),
The snippet is inactive because it failed compilation on initial evaluation and it is not capable of becoming valid with further changes to the JShell state.

The snippet is not visible to other snippets (isDefined() == false) and thus cannot be referenced or executed.

The snippet will not update as dependents change (isActive() == false), its Status will never change again.

/** * The snippet is inactive because it failed compilation on initial * evaluation and it is not capable of becoming valid with further * changes to the JShell state. * <p> * The snippet is not visible to other snippets * ({@link Status#isDefined() isDefined() == false}) * and thus cannot be referenced or executed. * <p> * The snippet will not update as dependents change * ({@link Status#isActive() isActive() == false}), its * {@code Status} will never change again. */
REJECTED(false, false),
The snippet is inactive because it does not yet exist. Used only in SnippetEvent.previousStatus for new snippets. JShell.status(Snippet) will never return this Status.

Vacuously, isDefined() and isActive() are both defined false.

/** * The snippet is inactive because it does not yet exist. * Used only in {@link SnippetEvent#previousStatus} for new * snippets. * {@link jdk.jshell.JShell#status(jdk.jshell.Snippet) JShell.status(Snippet)} * will never return this {@code Status}. * <p> * Vacuously, {@link Status#isDefined() isDefined()} and * {@link Status#isActive() isActive()} are both defined {@code false}. */
NONEXISTENT(false, false); private final boolean isActive; private final boolean isDefined; Status(boolean isActive, boolean isDefined) { this.isActive = isActive; this.isDefined = isDefined; }
Indicates whether the Snippet is active, that is, will a persistent snippet be re-evaluated when a new JShell.eval(String) or JShell.drop(Snippet) that could change its status is invoked. This is more broad than isDefined() since a Snippet which is RECOVERABLE_NOT_DEFINED will be updated.
Returns:true if the Snippet is active; otherwise false
/** * Indicates whether the Snippet is active, that is, * will a {@linkplain jdk.jshell.PersistentSnippet persistent} * snippet be re-evaluated when a new * {@link JShell#eval(java.lang.String) JShell.eval(String)} or * {@link JShell#drop(jdk.jshell.Snippet) * JShell.drop(Snippet)} that could change * its status is invoked. This is more broad than * {@link Status#isDefined()} since a Snippet which is * {@link Status#RECOVERABLE_NOT_DEFINED} * will be updated. * * @return {@code true} if the Snippet is active; otherwise {@code false} */
public boolean isActive() { return isActive; }
Indicates whether the snippet is currently part of the defined state of the JShell. Is it visible to compilation of other snippets?
Returns:true if the Snippet is defined; otherwise false
/** * Indicates whether the snippet is currently part of the defined state * of the JShell. Is it visible to compilation of other snippets? * @return {@code true} if the Snippet is defined; otherwise * {@code false} */
public boolean isDefined() { return isDefined; } } static final String UNASSOCIATED_ID = "*UNASSOCIATED*"; private final Key key; private final String source; private final Wrap guts; final String unitName; private final SubKind subkind; private int seq; private String id; private OuterWrap outer; private Status status; private List<String> unresolved; private DiagList diagnostics; private final DiagList syntheticDiags; Snippet(Key key, String userSource, Wrap guts, String unitName, SubKind subkind, DiagList syntheticDiags) { this.key = key; this.source = userSource; this.guts = guts; this.unitName = unitName; this.subkind = subkind; this.syntheticDiags = syntheticDiags==null ? new DiagList() : syntheticDiags; this.status = Status.NONEXISTENT; setSequenceNumber(0); } /**** public access ****/
The unique identifier for the snippet. No two active snippets will have the same id(). Value of id has no prescribed meaning. The details of how the id is generated and the mechanism to change it is documented in Builder.idGenerator(BiFunction).
Returns:the snippet id string.
/** * The unique identifier for the snippet. No two active snippets will have * the same id(). Value of id has no prescribed meaning. The details of * how the id is generated and the mechanism to change it is documented in * {@link JShell.Builder#idGenerator(BiFunction)}. * @return the snippet id string. */
public String id() { return id; }
The Kind for the snippet. Indicates the subclass of Snippet.
See Also:
Returns:the Kind of the snippet
/** * The {@link jdk.jshell.Snippet.Kind} for the snippet. * Indicates the subclass of Snippet. * @return the Kind of the snippet * @see Snippet.Kind */
public Kind kind() { return subkind.kind(); }
Return the SubKind of snippet. The SubKind is useful for feedback to users.
Returns:the SubKind corresponding to this snippet
/** * Return the {@link SubKind} of snippet. * The SubKind is useful for feedback to users. * @return the SubKind corresponding to this snippet */
public SubKind subKind() { return subkind; }
Return the source code of the snippet.
Returns:the source code corresponding to this snippet
/** * Return the source code of the snippet. * @return the source code corresponding to this snippet */
public String source() { return source; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Snippet:"); if (key() != null) { sb.append(key().toString()); } sb.append('-'); sb.append(source); return sb.toString(); } //**** internal access **** String name() { return unitName; } Key key() { return key; } List<String> unresolved() { return Collections.unmodifiableList(unresolved); } DiagList diagnostics() { return diagnostics; } DiagList syntheticDiags() { return syntheticDiags; }
Returns:the corralled guts
/** * @return the corralled guts */
Wrap corralled() { return null; } Collection<String> declareReferences() { return null; } Collection<String> bodyReferences() { return null; } String importLine(JShell state) { return ""; } void setId(String id) { this.id = id; } final void setSequenceNumber(int seq) { this.seq = seq; } void setOuterWrap(OuterWrap outer) { this.outer = outer; } void setCompilationStatus(Status status, List<String> unresolved, DiagList diagnostics) { this.status = status; this.unresolved = unresolved; this.diagnostics = diagnostics; } void setDiagnostics(DiagList diagnostics) { this.diagnostics = diagnostics; } void setFailed(DiagList diagnostics) { this.seq = -1; this.outer = null; this.status = Status.REJECTED; this.unresolved = Collections.emptyList(); this.diagnostics = diagnostics; } void setDropped() { this.status = Status.DROPPED; } void setOverwritten() { this.status = Status.OVERWRITTEN; } Status status() { return status; } String className() { return outer.className(); } String classFullName() { return outer.classFullName(); }
Top-level wrap
Returns:
/** * Top-level wrap * @return */
OuterWrap outerWrap() { return outer; }
Basically, class version for this Key.
Returns:int
/** * Basically, class version for this Key. * @return int */
int sequenceNumber() { return seq; } Wrap guts() { return guts; } boolean isExecutable() { return subkind.isExecutable(); } }