⚡ Sangsakala Proxy 🏠 Home
Skip to content

No state hints when the state set is declared in a superclass's external spec (Window) and the method in a subclass's (Frame) #456

Closed

Description

@CatarinaGamboa

Impact: state hints disappear when the state set is declared in a superclass's external spec and the failing method is declared in a subclass's spec. That is the natural way to specify a JDK hierarchy: java.awt.Window owns dispose()/pack() and the displayable states, while java.awt.Frame adds setUndecorated.

Minimal reproducer (an external spec and a client, in one directory)

// WindowRefinements.java
@StateSet({"displayable", "notDisplayable"})
@ExternalRefinementsFor("java.awt.Window")
interface WindowRefinements {
    @StateRefinement(to = "notDisplayable(this)")
    void dispose();

    @StateRefinement(to = "displayable(this)")
    void pack();
}

@ExternalRefinementsFor("java.awt.Frame")
interface FrameRefinements {
    @StateRefinement(to = "notDisplayable(this)")
    void Frame(String title);

    @StateRefinement(from = "notDisplayable(this)")
    void setUndecorated(boolean undecorated);
}

// Use.java
public class Use {
    static void borderless() {
        Frame host = new Frame("Playfield");
        host.pack();
        host.setUndecorated(true);
    }
}

Actual (main @ 19991d3): found displayable(host¹⁰) but expected notDisplayable(host¹⁰), with no hints.

With the same methods in one @ExternalRefinementsFor("java.awt.Frame") interface, the error is the same but it comes with hints:

Hints:
  - Call host.dispose() before this call to move host from displayable to notDisplayable
  - In state displayable, host can call: dispose(), pack()

Expected: the same hints when the state set and the methods come from the specs of the receiver's superclasses.

The IDE's state-machine view has the same gap (filed separately in vscode-liquidjava).

Real-world scenario. One of the exercises for the error-message study is LITIENGINE's GameWindow. It calls setUndecorated(true) on a frame that is still displayable when switching borderless to borderless, which throws IllegalComponentStateException: The frame is displayable., and the developers fixed it with dispose() (d596e546). The study spec splits Window and Frame as above, so the error has no hint.

In VS Code (LITIENGINE study exercise, verifier main @ 19991d3, extension main @ 80bed18). No hints. The fix, dispose(), is in the if branches just above:

A1_09 in VS Code

Activity

  1. added
    bugSomething isn't working
    real-world-findingFound when experimenting liquidjava in real world repos or OSS
    studyNeeded before the error-message user study
    on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingerror messagesRelated to error messagesreal-world-findingFound when experimenting liquidjava in real world repos or OSSstudyNeeded before the error-message user study

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions