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