1 /*
   2  * Copyright (c) 2015, 2019, 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.Collection;
  29 import java.util.Collections;
  30 import java.util.List;
  31 
  32 /**
  33  * A Snippet represents a snippet of Java source code as passed to
  34  * {@link jdk.jshell.JShell#eval(java.lang.String)}.  It is associated only with the
  35  * {@link jdk.jshell.JShell JShell} instance that created it.
  36  * An instance of Snippet (including its subclasses) is immutable: an access to
  37  * any of its methods will always return the same result.
  38  * For information about the current state of the snippet within the JShell
  39  * state engine, query {@code JShell} passing the Snippet.
  40  * <p>
  41  * Because it is immutable, {@code Snippet} (and subclasses) is thread-safe.
  42  *
  43  * @author Robert Field
  44  * @since 9
  45  * @see jdk.jshell.JShell#status
  46  */
  47 public abstract class Snippet {
  48 
  49     /**
  50      * Describes the general kind of snippet.
  51      * The {@code Kind} is an immutable property of a Snippet.
  52      * It is accessed with {@link jdk.jshell.Snippet#kind()}.
  53      * The {@code Kind} can be used to determine which
  54      * subclass of Snippet it is. For example,
  55      * {@link jdk.jshell.JShell#eval(java.lang.String) eval("int three() { return 3; }")} will
  56      * return a snippet creation event.  The {@code Kind} of that Snippet
  57      * will be {@code METHOD}, from which you know that the subclass
  58      * of {@code Snippet} is {@code MethodSnippet} and it can be
  59      * cast as such.
  60      */
  61     public enum Kind {
  62         /**
  63          * An import declaration: {@code import} ...
  64          * The snippet is an instance of {@link jdk.jshell.ImportSnippet}.
  65          * <P>
  66          * An import can be a single type import
  67          * ({@link jdk.jshell.Snippet.SubKind#SINGLE_TYPE_IMPORT_SUBKIND}),
  68          * a static single import
  69          * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}),
  70          * an on-demand type import
  71          * ({@link jdk.jshell.Snippet.SubKind#TYPE_IMPORT_ON_DEMAND_SUBKIND}),
  72          * or a static on-demand type import
  73          * ({@link jdk.jshell.Snippet.SubKind#SINGLE_STATIC_IMPORT_SUBKIND}) --
  74          * use {@link jdk.jshell.Snippet#subKind()} to distinguish.
  75          *
  76          * <P>
  77          * An import declaration is {@linkplain Kind#isPersistent() persistent}.
  78          *
  79          * @jls 7.5 Import Declarations
  80          */
  81         IMPORT(true),
  82 
  83         /**
  84          * A type declaration.
  85          * Which includes: NormalClassDeclaration, EnumDeclaration,
  86          * NormalInterfaceDeclaration, and AnnotationTypeDeclaration.
  87          * The snippet is an instance of {@link jdk.jshell.TypeDeclSnippet}.
  88          * <P>
  89          * A type declaration may be an interface
  90          * {@link jdk.jshell.Snippet.SubKind#INTERFACE_SUBKIND},
  91          * classes {@link jdk.jshell.Snippet.SubKind#CLASS_SUBKIND}, enums, and
  92          * annotation interfaces -- see {@link jdk.jshell.Snippet.SubKind} to
  93          * differentiate.
  94          *
  95          * <P>
  96          * A type declaration is {@linkplain Kind#isPersistent() persistent}.
  97          *
  98          * @jls 7.6 Top Level Type Declarations
  99          */
 100         TYPE_DECL(true),
 101 
 102         /**
 103          * A method declaration.
 104          * The snippet is an instance of {@link jdk.jshell.MethodSnippet}.
 105          *
 106          * <P>
 107          * A method declaration is {@linkplain Kind#isPersistent() persistent}.
 108          *
 109          * @jls 8.4 Method Declarations
 110          */
 111         METHOD(true),
 112 
 113         /**
 114          * One variable declaration.
 115          * Corresponding to one <i>VariableDeclarator</i>.
 116          * The snippet is an instance of {@link jdk.jshell.VarSnippet}.
 117          * <P>
 118          * The variable may be with or without initializer, or be a temporary
 119          * variable representing an expression -- see
 120          * {@link jdk.jshell.Snippet.SubKind}to differentiate.
 121          *
 122          * <P>
 123          * A variable declaration is {@linkplain Kind#isPersistent() persistent}.
 124          *
 125          * @jls 8.3 Field Declarations
 126          */
 127         VAR(true),
 128 
 129         /**
 130          * An expression, with or without side-effects.
 131          * The snippet is an instance of {@link jdk.jshell.ExpressionSnippet}.
 132          * <P>
 133          * The expression is currently either a simple named reference to a
 134          * variable ({@link jdk.jshell.Snippet.SubKind#VAR_VALUE_SUBKIND}) or an
 135          * assignment (both of which have natural referencing
 136          * names) -- see {@link jdk.jshell.Snippet.SubKind} to differentiate.
 137          * All other expression forms (operators, method calls, ...) generate a
 138          * scratch variable and so are instead of the VAR Kind.
 139          *
 140          * @jls 15 Expressions
 141          */
 142         EXPRESSION(false),
 143 
 144         /**
 145          * A statement.
 146          * The snippet is an instance of {@link jdk.jshell.StatementSnippet}.
 147          *
 148          * @jls 14.5 Statements
 149          */
 150         STATEMENT(false),
 151 
 152         /**
 153          * A syntactically incorrect input for which the specific
 154          * kind could not be determined.
 155          * The snippet is an instance of {@link jdk.jshell.ErroneousSnippet}.
 156          */
 157         ERRONEOUS(false);
 158 
 159         private final boolean isPersistent;
 160 
 161         Kind(boolean isPersistent) {
 162             this.isPersistent = isPersistent;
 163         }
 164 
 165         /**
 166          * Indicates whether this {@code Kind} of Snippet is persistent. Only
 167          * declarations are persistent because they influence future Snippets.
 168          * <p>
 169          * Note that though the {@code Kind} of
 170          * a Snippet may be persistent, that does not mean that the Snippet will
 171          * persist; For example it may be invalid or have been dropped.  See:
 172          * {@link jdk.jshell.Snippet.Status#isDefined()}.
 173          *
 174          * @return {@code true} if this {@code Kind} of {@code Snippet} is
 175          * visible to subsequent evaluations; otherwise {@code false}
 176          */
 177         public boolean isPersistent() {
 178             return isPersistent;
 179         }
 180     }
 181 
 182     /**
 183      * The detailed variety of a snippet.  This is a sub-classification of the
 184      * Kind.  The Kind of a SubKind is accessible with
 185      * {@link jdk.jshell.Snippet.SubKind#kind()}.
 186      */
 187     public enum SubKind {
 188 
 189         /**
 190          * Single-Type-Import Declaration.
 191          * An import declaration of a single type.
 192          * @jls 7.5.1 Single-Type-Import Declarations
 193          */
 194         SINGLE_TYPE_IMPORT_SUBKIND(Kind.IMPORT),
 195 
 196         /**
 197          * Type-Import-on-Demand Declaration.
 198          * A non-static "star" import.
 199          * @jls 7.5.2 Type-Import-on-Demand Declarations
 200          */
 201         TYPE_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
 202 
 203         /**
 204          * Single-Static-Import Declaration.
 205          * An import of a static member.
 206          * @jls 7.5.3 Single-Static-Import Declarations
 207          */
 208         SINGLE_STATIC_IMPORT_SUBKIND(Kind.IMPORT),
 209 
 210         /**
 211          * Static-Import-on-Demand Declaration.
 212          * A static "star" import of all static members of a named type.
 213          * @jls 7.5.4 Static-Import-on-Demand Declarations
 214          */
 215         STATIC_IMPORT_ON_DEMAND_SUBKIND(Kind.IMPORT),
 216 
 217         /**
 218          * A class declaration.
 219          * A {@code SubKind} of {@link Kind#TYPE_DECL}.
 220          * @jls 8.1 Class Declarations
 221          */
 222         CLASS_SUBKIND(Kind.TYPE_DECL),
 223 
 224         /**
 225          * An interface declaration.
 226          * A {@code SubKind} of {@link Kind#TYPE_DECL}.
 227          * @jls 9.1 Interface Declarations
 228          */
 229         INTERFACE_SUBKIND(Kind.TYPE_DECL),
 230 
 231         /**
 232          * An enum declaration.
 233          * A {@code SubKind} of {@link Kind#TYPE_DECL}.
 234          * @jls 8.9 Enum Types
 235          */
 236         ENUM_SUBKIND(Kind.TYPE_DECL),
 237 
 238         /**
 239          * An annotation interface declaration. A {@code SubKind} of
 240          * {@link Kind#TYPE_DECL}.
 241          * @jls 9.6 Annotation Types
 242          */
 243         ANNOTATION_TYPE_SUBKIND(Kind.TYPE_DECL),
 244 
 245         /**
 246          * A method. The only {@code SubKind} for {@link Kind#METHOD}.
 247          * @jls 8.4 Method Declarations
 248          */
 249         METHOD_SUBKIND(Kind.METHOD),
 250 
 251         /**
 252          * A variable declaration without initializer.
 253          * A {@code SubKind} of {@link Kind#VAR}.
 254          * @jls 8.3 Field Declarations
 255          */
 256         VAR_DECLARATION_SUBKIND(Kind.VAR, true, true),
 257 
 258         /**
 259          * A variable declaration with an initializer expression. A
 260          * {@code SubKind} of {@link Kind#VAR}.
 261          * @jls 8.3 Field Declarations
 262          */
 263         VAR_DECLARATION_WITH_INITIALIZER_SUBKIND(Kind.VAR, true, true),
 264 
 265         /**
 266          * An expression whose value has been stored in a temporary variable. A
 267          * {@code SubKind} of {@link Kind#VAR}.
 268          * @jls 15 Expressions
 269          */
 270         TEMP_VAR_EXPRESSION_SUBKIND(Kind.VAR, true, true),
 271 
 272         /**
 273          * A simple variable reference expression. A {@code SubKind} of
 274          * {@link Kind#EXPRESSION}.
 275          * @jls 15.11 Field Access Expressions
 276          */
 277         VAR_VALUE_SUBKIND(Kind.EXPRESSION, true, true),
 278 
 279         /**
 280          * An assignment expression. A {@code SubKind} of
 281          * {@link Kind#EXPRESSION}.
 282          * @jls 15.26 Assignment Operators
 283          */
 284         ASSIGNMENT_SUBKIND(Kind.EXPRESSION, true, true),
 285 
 286         /**
 287          * An expression which has not been wrapped in a temporary variable
 288          * (reserved). A {@code SubKind} of {@link Kind#EXPRESSION}.
 289          */
 290         OTHER_EXPRESSION_SUBKIND(Kind.EXPRESSION, true, true),
 291 
 292         /**
 293          * A statement. The only {@code SubKind} for {@link Kind#STATEMENT}.
 294          * @jls 14.5 Statements
 295          */
 296         STATEMENT_SUBKIND(Kind.STATEMENT, true, false),
 297 
 298         /**
 299          * An unknown snippet. The only {@code SubKind} for
 300          * {@link Kind#ERRONEOUS}.
 301          */
 302         UNKNOWN_SUBKIND(Kind.ERRONEOUS, false, false);
 303 
 304         private final boolean isExecutable;
 305         private final boolean hasValue;
 306         private final Kind kind;
 307 
 308         SubKind(Kind kind) {
 309             this.kind = kind;
 310             this.isExecutable = false;
 311             this.hasValue = false;
 312         }
 313 
 314         SubKind(Kind kind, boolean isExecutable, boolean hasValue) {
 315             this.kind = kind;
 316             this.isExecutable = isExecutable;
 317             this.hasValue = hasValue;
 318         }
 319 
 320         /**
 321          * Indicates whether this {@code SubKind} is executable.
 322          *
 323          * @return {@code true} if this {@code SubKind} can
 324          * be executed; otherwise {@code false}
 325          */
 326         public boolean isExecutable() {
 327             return isExecutable;
 328         }
 329 
 330         /**
 331          * Indicates whether this {@code SubKind} is executable and
 332          * is non-{@code void}.
 333          *
 334          * @return {@code true} if this {@code SubKind} has
 335          * a value; otherwise {@code false}
 336          */
 337         public boolean hasValue() {
 338             return hasValue;
 339         }
 340 
 341         /**
 342          * The {@link Snippet.Kind} that corresponds to this {@code SubKind}.
 343          *
 344          * @return the fixed {@code Kind} for this {@code SubKind}
 345          */
 346         public Kind kind() {
 347             return kind;
 348         }
 349     }
 350 
 351     /**
 352      * Describes the current state of a Snippet.
 353      * This is a dynamic property of a Snippet within the JShell state --
 354      * thus is retrieved with a {@linkplain
 355      * jdk.jshell.JShell#status(jdk.jshell.Snippet) query on {@code JShell}}.
 356      * <p>
 357      * The {@code Status} changes as the state changes.
 358      * For example, creation of another snippet with
 359      * {@link jdk.jshell.JShell#eval(java.lang.String) eval}
 360      * may resolve dependencies of this Snippet (or invalidate those dependencies), or
 361      * {@linkplain jdk.jshell.Snippet.Status#OVERWRITTEN overwrite}
 362      * this Snippet changing its
 363      * {@code Status}.
 364      * <p>
 365      * Important properties associated with {@code Status} are:
 366      * {@link jdk.jshell.Snippet.Status#isDefined()}, if it is visible to other
 367      * existing and new snippets; and
 368      * {@link jdk.jshell.Snippet.Status#isActive()}, if, as the
 369      * JShell state changes, the snippet will update, possibly
 370      * changing {@code Status}.
 371      * An executable Snippet can only be executed if it is in the the
 372      * {@link jdk.jshell.Snippet.Status#VALID} {@code Status}.
 373      * @see JShell#status(jdk.jshell.Snippet)
 374      */
 375     public enum Status {
 376         /**
 377          * The snippet is a valid snippet
 378          * (in the context of current {@code JShell} state).
 379          * Only snippets with {@code VALID}
 380          * {@code Status} can be executed (though not all
 381          * {@code VALID} snippets have executable code).
 382          * <p>
 383          * The snippet is defined
 384          * ({@link Status#isDefined() isDefined() == true}).
 385          * If the snippet is a declaration or import
 386          * ({@link Snippet.Kind#isPersistent()}),
 387          * it is visible to other snippets
 388          * <p>
 389          * The snippet will update as dependents change
 390          * ({@link Status#isActive() isActive() == true}), its
 391          * status could become {@code RECOVERABLE_DEFINED}, {@code RECOVERABLE_NOT_DEFINED},
 392          * {@code DROPPED}, or {@code OVERWRITTEN}.
 393          */
 394         VALID(true, true),
 395 
 396         /**
 397          * The snippet is a declaration snippet with potentially recoverable
 398          * unresolved references or other issues in its body
 399          * (in the context of current {@code JShell} state).
 400          * Only a {@link jdk.jshell.DeclarationSnippet} can have this
 401          * {@code Status}.
 402          * <p>
 403          * The snippet has a valid signature and it is visible to other
 404          * snippets
 405          * ({@link Status#isDefined() isDefined() == true})
 406          * and thus can be referenced in existing or new snippets
 407          * but the snippet cannot be executed.
 408          * An {@link UnresolvedReferenceException} will be thrown on an attempt
 409          * to execute it.
 410          * <p>
 411          * The snippet will update as dependents change
 412          * ({@link Status#isActive() isActive() == true}), its
 413          * status could become {@code VALID}, {@code RECOVERABLE_NOT_DEFINED},
 414          * {@code DROPPED}, or {@code OVERWRITTEN}.
 415          * <p>
 416          * Note: both {@code RECOVERABLE_DEFINED} and {@code RECOVERABLE_NOT_DEFINED}
 417          * indicate potentially recoverable errors, they differ in that, for
 418          * {@code RECOVERABLE_DEFINED}, the snippet is
 419          * {@linkplain Status#isDefined() defined}.
 420          */
 421         RECOVERABLE_DEFINED(true, true),
 422 
 423         /**
 424          * The snippet is a declaration snippet with potentially recoverable
 425          * unresolved references or other issues
 426          * (in the context of current {@code JShell} state).
 427          * Only a {@link jdk.jshell.DeclarationSnippet} can have this
 428          * {@code Status}.
 429          * <p>
 430          * The snippet has an invalid signature or the implementation is
 431          * otherwise unable to define it.
 432          * The snippet it is not visible to other snippets
 433          * ({@link Status#isDefined() isDefined() == false})
 434          * and thus cannot be referenced or executed.
 435          * <p>
 436          * The snippet will update as dependents change
 437          * ({@link Status#isActive() isActive() == true}), its
 438          * status could become {@code VALID}, {@code RECOVERABLE_DEFINED},
 439          * {@code DROPPED}, or {@code OVERWRITTEN}.
 440          * <p>
 441          * Note: both {@code RECOVERABLE_DEFINED} and {@code RECOVERABLE_NOT_DEFINED}
 442          * indicate potentially recoverable errors, they differ in that, for
 443          * {@code RECOVERABLE_DEFINED}, the snippet is
 444          * {@linkplain Status#isDefined() defined}.
 445          */
 446         RECOVERABLE_NOT_DEFINED(true, false),
 447 
 448         /**
 449          * The snippet is inactive because of an explicit call to
 450          * the {@link JShell#drop(Snippet)}.
 451          * <p>
 452          * The snippet is not visible to other snippets
 453          * ({@link Status#isDefined() isDefined() == false})
 454          * and thus cannot be referenced or executed.
 455          * <p>
 456          * The snippet will not update as dependents change
 457          * ({@link Status#isActive() isActive() == false}), its
 458          * {@code Status} will never change again.
 459          */
 460         DROPPED(false, false),
 461 
 462         /**
 463          * The snippet is inactive because it has been replaced by a new
 464          * snippet.  This occurs when the new snippet added with
 465          * {@link jdk.jshell.JShell#eval(java.lang.String) eval} matches a previous snippet.
 466          * A {@code TypeDeclSnippet} will match another
 467          * {@code TypeDeclSnippet} if the names match.
 468          * For example {@code class X { }} will overwrite
 469          * {@code class X { int ii; }} or
 470          * {@code interface X { }}.
 471          * A {@code MethodSnippet} will match another
 472          * {@code MethodSnippet} if the names and parameter types
 473          * match.
 474          * For example {@code void m(int a) { }} will overwrite
 475          * {@code int m(int a) { return a+a; }}.
 476          * A {@code VarSnippet} will match another
 477          * {@code VarSnippet} if the names match.
 478          * For example {@code double z;} will overwrite
 479          * {@code long z = 2L;}.
 480          * Only a {@link jdk.jshell.PersistentSnippet} can have this
 481          * {@code Status}.
 482          * <p>
 483          * The snippet is not visible to other snippets
 484          * ({@link Status#isDefined() isDefined() == false})
 485          * and thus cannot be referenced or executed.
 486          * <p>
 487          * The snippet will not update as dependents change
 488          * ({@link Status#isActive() isActive() == false}), its
 489          * {@code Status} will never change again.
 490          */
 491         OVERWRITTEN(false, false),
 492 
 493         /**
 494          * The snippet is inactive because it failed compilation on initial
 495          * evaluation and it is not capable of becoming valid with further
 496          * changes to the JShell state.
 497          * <p>
 498          * The snippet is not visible to other snippets
 499          * ({@link Status#isDefined() isDefined() == false})
 500          * and thus cannot be referenced or executed.
 501          * <p>
 502          * The snippet will not update as dependents change
 503          * ({@link Status#isActive() isActive() == false}), its
 504          * {@code Status} will never change again.
 505          */
 506         REJECTED(false, false),
 507 
 508         /**
 509          * The snippet is inactive because it does not yet exist.
 510          * Used only in {@link SnippetEvent#previousStatus} for new
 511          * snippets.
 512          * {@link jdk.jshell.JShell#status(jdk.jshell.Snippet) JShell.status(Snippet)}
 513          * will never return this {@code Status}.
 514          * <p>
 515          * Vacuously, {@link Status#isDefined() isDefined()} and
 516          * {@link Status#isActive() isActive()} are both defined {@code false}.
 517          */
 518         NONEXISTENT(false, false);
 519 
 520         private final boolean isActive;
 521         private final boolean isDefined;
 522 
 523         Status(boolean isActive, boolean isDefined) {
 524             this.isActive = isActive;
 525             this.isDefined = isDefined;
 526         }
 527 
 528         /**
 529          * Indicates whether the Snippet is active, that is,
 530          * will a {@linkplain jdk.jshell.PersistentSnippet persistent}
 531          * snippet be re-evaluated when a new
 532          * {@link JShell#eval(java.lang.String) JShell.eval(String)} or
 533          * {@link JShell#drop(jdk.jshell.Snippet)
 534          * JShell.drop(Snippet)} that could change
 535          * its status is invoked.  This is more broad than
 536          * {@link Status#isDefined()} since a Snippet which is
 537          * {@link Status#RECOVERABLE_NOT_DEFINED}
 538          * will be updated.
 539          *
 540          * @return {@code true} if the Snippet is active; otherwise {@code false}
 541          */
 542         public boolean isActive() {
 543             return isActive;
 544         }
 545 
 546         /**
 547          * Indicates whether the snippet is currently part of the defined state
 548          * of the JShell. Is it visible to compilation of other snippets?
 549          * @return {@code true} if the Snippet is defined; otherwise
 550          * {@code false}
 551          */
 552         public boolean isDefined() {
 553             return isDefined;
 554         }
 555     }
 556 
 557     static final String UNASSOCIATED_ID = "*UNASSOCIATED*";
 558 
 559     private final Key key;
 560     private final String source;
 561     private final Wrap guts;
 562     final String unitName;
 563     private final SubKind subkind;
 564 
 565     private int seq;
 566     private String id;
 567     private OuterWrap outer;
 568     private Status status;
 569     private List<String> unresolved;
 570     private DiagList diagnostics;
 571     private final DiagList syntheticDiags;
 572 
 573     Snippet(Key key, String userSource, Wrap guts, String unitName,
 574             SubKind subkind, DiagList syntheticDiags) {
 575         this.key = key;
 576         this.source = userSource;
 577         this.guts = guts;
 578         this.unitName = unitName;
 579         this.subkind = subkind;
 580         this.syntheticDiags = syntheticDiags==null
 581                 ? new DiagList()
 582                 : syntheticDiags;
 583         this.status = Status.NONEXISTENT;
 584         setSequenceNumber(0);
 585     }
 586 
 587     /**** public access ****/
 588 
 589     /**
 590      * The unique identifier for the snippet. No two active snippets will have
 591      * the same id().  Value of id has no prescribed meaning.  The details of
 592      * how the id is generated and the mechanism to change it is documented in
 593      * {@link JShell.Builder#idGenerator(BiFunction)}.
 594      * @return the snippet id string.
 595      */
 596     public String id() {
 597         return id;
 598     }
 599 
 600     /**
 601      * The {@link jdk.jshell.Snippet.Kind} for the snippet.
 602      * Indicates the subclass of Snippet.
 603      * @return the Kind of the snippet
 604      * @see Snippet.Kind
 605      */
 606     public Kind kind() {
 607         return subkind.kind();
 608     }
 609 
 610     /**
 611      * Return the {@link SubKind} of snippet.
 612      * The SubKind is useful for feedback to users.
 613      * @return the SubKind corresponding to this snippet
 614      */
 615     public SubKind subKind() {
 616         return subkind;
 617     }
 618 
 619     /**
 620      * Return the source code of the snippet.
 621      * @return the source code corresponding to this snippet
 622      */
 623     public String source() {
 624         return source;
 625     }
 626 
 627     @Override
 628     public String toString() {
 629         StringBuilder sb = new StringBuilder();
 630         sb.append("Snippet:");
 631         if (key() != null) {
 632             sb.append(key().toString());
 633         }
 634         sb.append('-');
 635         sb.append(source);
 636         return sb.toString();
 637     }
 638 
 639     //**** internal access ****
 640 
 641     String name() {
 642         return unitName;
 643     }
 644 
 645     Key key() {
 646         return key;
 647     }
 648 
 649     List<String> unresolved() {
 650         return Collections.unmodifiableList(unresolved);
 651     }
 652 
 653     DiagList diagnostics() {
 654         return diagnostics;
 655     }
 656 
 657     DiagList syntheticDiags() {
 658         return syntheticDiags;
 659     }
 660 
 661     /**
 662      * @return the corralled guts
 663      */
 664     Wrap corralled() {
 665         return null;
 666     }
 667 
 668     Collection<String> declareReferences() {
 669         return null;
 670     }
 671 
 672     Collection<String> bodyReferences() {
 673         return null;
 674     }
 675 
 676     String importLine(JShell state) {
 677         return "";
 678     }
 679 
 680     void setId(String id) {
 681         this.id = id;
 682     }
 683 
 684     final void setSequenceNumber(int seq) {
 685         this.seq = seq;
 686     }
 687 
 688     void setOuterWrap(OuterWrap outer) {
 689         this.outer = outer;
 690     }
 691 
 692     void setCompilationStatus(Status status, List<String> unresolved, DiagList diagnostics) {
 693         this.status = status;
 694         this.unresolved = unresolved;
 695         this.diagnostics = diagnostics;
 696     }
 697 
 698     void setDiagnostics(DiagList diagnostics) {
 699         this.diagnostics = diagnostics;
 700     }
 701 
 702     void setFailed(DiagList diagnostics) {
 703         this.seq = -1;
 704         this.outer = null;
 705         this.status = Status.REJECTED;
 706         this.unresolved = Collections.emptyList();
 707         this.diagnostics = diagnostics;
 708     }
 709 
 710     void setDropped() {
 711         this.status = Status.DROPPED;
 712     }
 713 
 714     void setOverwritten() {
 715         this.status = Status.OVERWRITTEN;
 716     }
 717 
 718     Status status() {
 719         return status;
 720     }
 721 
 722     String className() {
 723         return outer.className();
 724     }
 725 
 726     String classFullName() {
 727         return outer.classFullName();
 728     }
 729 
 730     /**
 731      * Top-level wrap
 732      * @return
 733      */
 734     OuterWrap outerWrap() {
 735         return outer;
 736     }
 737 
 738     /**
 739      * Basically, class version for this Key.
 740      * @return int
 741      */
 742     int sequenceNumber() {
 743         return seq;
 744     }
 745 
 746     Wrap guts() {
 747         return guts;
 748     }
 749 
 750     boolean isExecutable() {
 751         return subkind.isExecutable();
 752     }
 753 
 754 }