Skip to content

Added Sized interface#1731

Open
Elec332 wants to merge 2 commits intojline:masterfrom
Elec332:sized
Open

Added Sized interface#1731
Elec332 wants to merge 2 commits intojline:masterfrom
Elec332:sized

Conversation

@Elec332
Copy link
Copy Markdown
Contributor

@Elec332 Elec332 commented Mar 30, 2026

This pull requests attempts to unify the way you can access the size of objects (like terminals).

Additional benefits:
You can now access the size of Display.
This would later also allow places that have:

Size ret = new Size();
ret.copy(this.size);
return ret;

to change to:

return new Size(this);

or

return new Size(this.size);

Summary by CodeRabbit

  • Refactor
    • Consolidated sizing across terminals and UI components onto a common size contract for consistent resize behavior.
  • Bug Fixes
    • Improved resize propagation/order so components and virtual consoles apply and report dimensions more reliably.
    • Deprecated legacy integer-based resize methods in favor of the unified sizing API.
  • Tests
    • Updated tests to use the unified sizing API and component-driven resize paths.

Copy link
Copy Markdown
Member

@gnodet gnodet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I appreciate the thought behind unifying size access, but I'm not convinced this abstraction carries its weight.

Core concern: no concrete consumer for Sized

The new interface introduces a common type across Terminal, Size, Display, and ScreenTerminal — but there's no code that actually uses Sized as a type. The only consumer is the Size(Sized) constructor, which doesn't add much over the existing new Size(cols, rows) or size.copy(other) patterns.

In practice, these types are never used interchangeably — terminal code always knows whether it's working with a Terminal, a Display, or a Size. There's no method that would benefit from accepting a generic "anything with dimensions" parameter.

The PR adds API surface (a new public interface, final modifiers on existing methods, duplicate getter pairs on Size) without simplifying existing code or enabling new capabilities.

Additional issues if the PR moves forward:

  • Making getColumns() / getRows() final is a binary-incompatible change for any external code that subclasses Size
  • Sized.java has broken Javadoc HTML (<li> tags without a <ul> wrapper)
  • The naming tension between getWidth()/getHeight() (pixel-oriented) and getColumns()/getRows() (terminal-standard) adds confusion, especially with both pairs now on Size

Could you share a concrete use case where polymorphism over Sized simplifies existing code or enables something new? That would help evaluate whether the added API surface is justified.

Claude Code on behalf of Guillaume Nodet

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Introduce a new org.jline.terminal.Sized interface and migrate sizing APIs to use Sized; update Terminal, Size, Display, builtin terminals/components, and several terminal implementations and tests to accept/implement Sized, deprecating some int-based overloads.

Changes

Cohort / File(s) Summary
New interface
terminal/src/main/java/org/jline/terminal/Sized.java
Add Sized interface declaring int getColumns() and int getRows().
Core terminal API
terminal/src/main/java/org/jline/terminal/Terminal.java
Terminal now extends Sized; add setSize(Sized) contract and make prior setSize(Size) a default that delegates; annotate accessors with @Override.
Size value object
terminal/src/main/java/org/jline/terminal/Size.java
Size implements Sized; add Size(Sized) constructor, copy(Sized) overload, and mark accessors @Override.
Display implementation
terminal/src/main/java/org/jline/utils/Display.java
Display implements Sized; change resize(Size)resize(Sized) and annotate accessors with @Override.
Builtins (terminals & components)
builtins/src/main/java/org/jline/builtins/ScreenTerminal.java, builtins/src/main/java/org/jline/builtins/SwingTerminal.java, builtins/src/main/java/org/jline/builtins/WebTerminal.java, builtins/src/main/java/org/jline/builtins/Tmux.java
Updated to accept/implement Sized; added/overrode setSize(Sized) in Swing/Web terminals and components; deprecated int overloads; Tmux now derives console size from terminal.
Terminal implementations
terminal/src/main/java/org/jline/terminal/impl/AbstractPosixTerminal.java, .../AbstractWindowsTerminal.java, .../DumbTerminal.java, .../LineDisciplineTerminal.java
setSize signatures changed to accept Sized; conversion to Size preserved at PTY/legacy boundaries; getSize() return construction simplified.
Tests updated
builtins/src/test/.../ScreenTerminalTest.java, builtins/src/test/.../TerminalTest.java, terminal/src/test/.../GraphemeClusterModeTest.java, terminal/src/test/.../DisplayTest.java, console/src/test/.../TailTipWidgetsTest.java
Tests adjusted to use Size/Sized-based setSize calls or component-based size setting; imports updated in some tests.
Miscellaneous
assorted files (...)
Added @Override annotations, switched imports from Size to Sized where appropriate, and suppressed deprecation/lint on deprecated int overloads.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

chore

Poem

🐰 I hopped through code with nimble paws,

Columns counted, rows applause.
A tiny interface found its place,
Sizes snug in every space.
Hooray — a tidy, measured chase!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.19% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Added Sized interface' directly and accurately summarizes the main change: introducing a new Sized interface for standardizing size access across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@Elec332
Copy link
Copy Markdown
Contributor Author

Elec332 commented Mar 31, 2026

This pull is intended to be part of a (very slow) wider push towards standardizing some names, in this case dimension names.
Besides that, Sized can later (in perhaps a 5.0, or other breaking update) start to replace places that consume a Size currently. This will also allow JLine to e.g. express a direct relation between the ScreenTerminal and LineDescipleTerminal in WebTerminal/SwingTerminal/TMux ect, where you can then use LineDescipeTerminal.setSize(ScreenTerminal.this) instead of akward copying with Size.
I also do not think it would cause naming tension, as it is clearly defined that getWidth() and getHeight() is in character cells, and width/height is already used aswell (as can be seen, some places only required an @OverRide on an existing function).
The reason it would be good to start standardizing around width/height es explained further below:

Currently JLine uses width/height and rows/columns (and sometimes "line" as row name) without any clear definition when which name is supposed to be used, see:

Builtins:
-> ScreenTerminal uses width/height everywhere (also fields)
-> Nano uses width/heigh and rows/columns everywhere without too much apparent logic. Some public functions use/are called width/height, some use/are called columns.
-> (Posix)Commands use columns for internal calculation.
-> Most other classes use solely width/height for internal calculations & external parameters.

Console:
-> For y only rows are really used, for x it uses both width and column.

Jansi-Core
-> AnsiConsole/AnsiPrintStream & AnsiOutputStream use width
-> Ansi uses both x/y (width/height) and row/column
-> AnsiProcessor uses column

Reader:
-> Internal functions/fields are mostly width, but due to external objects (like Size) a lot of references to columns.
--> New name/variant for height/row: parameters/functions like "getLine"

Terminal:
-> Most classes (like Display) primarily use rows/colums for fields/parameters, but use width for local variables.

FFM Terminal:
-> Windows uses width/height
-> Linux primarily uses rows/columns

JNI Terminal:
-> Similar to FFM Terminal

Additionally, some classes also have places where they use x/y instead of col/row.

Also:
There are multiple functions throughtout all JLine subproject with names like "columnValue/columnLength" ect.
In the context of terminals the rows are the height, and the columns are the width. This means a row runs horizontally, so a function name like "columnLength" is pretty illogical for getting the width of a string at a given y value.
There are also both functions like "columnValue" and "getRow", which both accomplish the same. A 3rd variant called "getLine(int line)" also exists.
-> All these different names for functionally the same can be confusing when trying to read/use the code and find common patterns.

Other point:
In almost most functions (outside JLine) where some for of coordinates or x/y values are used the first variable will be width/x and the height/y.
In JLine, most public function follow the x/y / width/height / column/row order, but there are also (mainly private) functions where the order is y/x. Because sometimes both variants are used within the same class, maintainers have to be extra carefull when updating the code, because method 1 may be x/y, but the next y/x (ScreenTerminal for example), causing unnessecary burden for developers.
-> e.g. Terminal.setSize(new Size(x, y)) / ScreenTerminal.setSize(x, y) effectively different than Display.resize(y, x)

I appreciate that there is a lot of legacy here, and that e.g. the x/y order is perhaps more "rendering oriented" and that the x/y order makes sense in some places.
Maybe this can be the starting point of a wider discussion on field/parameter/function names related to width/height/column/row(/line?).

This 1 small pull might seem a bit random on its own, and im sorry for not explaining it further in my initial message (I hope this message explains better where this comes from), but I kept it small as you indicated you prefer smaller pulls.

PS: Will will open a PR for some set/getSize related bugs in Swing/WebTerminal later, preferably after this is merged.

@Elec332
Copy link
Copy Markdown
Contributor Author

Elec332 commented Apr 1, 2026

#1755 looks like a great step in the right direction concerning some of the things listed above.
It would seem the decision has been made to standardize around rows/cols.

I still think the Sized interface has merit, though the functions would need to be renamed getRows/Columns to match the new direction. Combined with #1755 the new resize functions & new Size constructor could then also take a Sized instead of a size.

Going back to my previous example: This will also allow JLine to e.g. express a direct relation between the ScreenTerminal and LineDescipleTerminal in WebTerminal/SwingTerminal/TMux ect, where you can then use LineDescipeTerminal.setSize(ScreenTerminal.this), or between a Terminal and Display: Display.setSize(Terminal.this) instead of akward copying with Size.

@gnodet
Copy link
Copy Markdown
Member

gnodet commented Apr 8, 2026

We can revisit once #1755 has been merged.

@Elec332 Elec332 reopened this Apr 9, 2026
@Elec332
Copy link
Copy Markdown
Contributor Author

Elec332 commented Apr 9, 2026

NOTE:
All checks will fail, as 7d21f09 introduced a compile error.
#1773 has been submitted to resolve it, but I didnt include it in this pull to prevent merge conflicts.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
builtins/src/main/java/org/jline/builtins/ScreenTerminal.java (1)

2111-2116: ⚠️ Potential issue | 🔴 Critical

Fix compile blocker: wrong dump(...) argument type.

At Line 2115, dump(screen, cursor) passes long[][] (screen is declared as private long[][] screen), but the dump overloads accept long[]. This causes a type mismatch compilation error.

Minimal fix
-        dump(screen, cursor);
+        dump(dumpBuffer, cursor);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java` around lines
2111 - 2116, The call dump(screen, cursor) is passing the 2D field screen
(long[][]) to an overload that expects a 1D long[]; replace that call with
dump(dumpBuffer, cursor) (using the previously created long[] dumpBuffer) so the
argument types match the dump(long[] buffer, int[] cursor) overload and the
cursor is filled correctly.
🧹 Nitpick comments (2)
terminal/src/test/java/org/jline/terminal/impl/GraphemeClusterModeTest.java (1)

326-326: Add a comment explaining why this stub method is empty.

SonarCloud flags this empty method. Since this is an intentional stub for testing Terminal interface default methods, add a brief comment to clarify.

📝 Proposed fix
-            public void setSize(Sized size) {}
+            public void setSize(Sized size) {
+                // Intentional no-op: stub for testing default interface methods
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@terminal/src/test/java/org/jline/terminal/impl/GraphemeClusterModeTest.java`
at line 326, The empty setSize(Sized size) method is an intentional stub used to
exercise Terminal interface default-method behavior in tests; update the stub to
include a brief comment above the method (e.g., "Intentionally empty: stub
implementation for testing default methods of Terminal/Sized") so static
analysis (SonarCloud) understands it is deliberate and not a missing
implementation—place the comment directly above the setSize(Sized size) method
in the anonymous test implementation.
builtins/src/main/java/org/jline/builtins/ScreenTerminal.java (1)

1758-1759: Make the setSize(Sized) null contract explicit.

At Line 1759, passing null causes an implicit NPE. Consider either validating with Objects.requireNonNull(...) or returning false consistently for invalid input.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java` around lines
1758 - 1759, The setSize(Sized) method currently throws an implicit NPE when
passed null; make the null contract explicit by validating the input at the
start of setSize(Sized) (either call Objects.requireNonNull(sized, "sized must
not be null") to throw a clear NPE or check sized == null and return false) and
then forward to the existing setSize(int, int) call; update the method body
around setSize(Sized) to perform this check so callers get a consistent,
documented behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@builtins/src/main/java/org/jline/builtins/SwingTerminal.java`:
- Around line 250-255: In setSize(Sized sz) ensure you call checkClosed() before
mutating the component: move the closed-state check to the top of
SwingTerminal.setSize(Sized) so that checkClosed() runs before invoking
component.setSize(sz) and before calling super.setSize(component), preventing
state changes when the terminal is already closed.

In `@builtins/src/main/java/org/jline/builtins/WebTerminal.java`:
- Around line 211-216: In setSize(Sized sz) ensure the terminal closed-guard
runs before mutating the component: call checkClosed() at the start of
WebTerminal.setSize(Sized) so you validate the terminal state prior to invoking
component.setSize(sz); keep the existing conditional and subsequent
super.setSize(component) behavior (i.e., call checkClosed(), then if
(component.setSize(sz)) { super.setSize(component); }).

In `@builtins/src/test/java/org/jline/builtins/TerminalTest.java`:
- Around line 250-251: The test currently calls
webTerminal.getComponent().setSize(new Size(40, 20)) which mismatches the API
used for swingTerminal and may not exist on TerminalComponent; change the test
to use the same API as swingTerminal by calling webTerminal.setSize(new Size(40,
20)) (or, if TerminalComponent only exposes layout sizing, call
webTerminal.getComponent().setPreferredSize(new Size(40, 20)) and remove the
assertTrue) so the call matches available methods on TerminalComponent/Terminal.
- Around line 270-277: The test wrongly assumes
webTerminal.getComponent().setSize(Size) returns a boolean; replace those
boolean assertions with direct size-validity checks against the terminal bounds
(use ScreenTerminal.MAX_SIZE and the same Size values). For example, instead of
asserting the return of setSize, call the validation logic (e.g., a static
predicate like ScreenTerminal.isValidSize(Size) or inline checks: width/height
>= minimum && <= ScreenTerminal.MAX_SIZE) for each Size used; keep the same Size
inputs and assertions (assertTrue/assertFalse) but applied to the validation
predicate rather than webTerminal.getComponent().setSize(...).

In `@terminal/src/main/java/org/jline/terminal/Terminal.java`:
- Around line 759-765: The change introduced a new abstract method
setSize(Sized) on the Terminal interface which breaks source compatibility for
existing implementations that only implement setSize(Size); to fix, revert to
keeping the original abstract contract by making setSize(Size) the required
method on Terminal (remove the default implementation) and provide
setSize(Sized) as a default helper that delegates to setSize(Size) (i.e.,
implement setSize(Sized) to call setSize((Size) sized) or equivalent), so
existing implementers need not change while new callers can use the Sized
overload; update the Terminal interface methods setSize(Size) and setSize(Sized)
accordingly.

---

Outside diff comments:
In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java`:
- Around line 2111-2116: The call dump(screen, cursor) is passing the 2D field
screen (long[][]) to an overload that expects a 1D long[]; replace that call
with dump(dumpBuffer, cursor) (using the previously created long[] dumpBuffer)
so the argument types match the dump(long[] buffer, int[] cursor) overload and
the cursor is filled correctly.

---

Nitpick comments:
In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java`:
- Around line 1758-1759: The setSize(Sized) method currently throws an implicit
NPE when passed null; make the null contract explicit by validating the input at
the start of setSize(Sized) (either call Objects.requireNonNull(sized, "sized
must not be null") to throw a clear NPE or check sized == null and return false)
and then forward to the existing setSize(int, int) call; update the method body
around setSize(Sized) to perform this check so callers get a consistent,
documented behavior.

In `@terminal/src/test/java/org/jline/terminal/impl/GraphemeClusterModeTest.java`:
- Line 326: The empty setSize(Sized size) method is an intentional stub used to
exercise Terminal interface default-method behavior in tests; update the stub to
include a brief comment above the method (e.g., "Intentionally empty: stub
implementation for testing default methods of Terminal/Sized") so static
analysis (SonarCloud) understands it is deliberate and not a missing
implementation—place the comment directly above the setSize(Sized size) method
in the anonymous test implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f879dcfc-31b0-427f-aea3-f8dfdf7a9d61

📥 Commits

Reviewing files that changed from the base of the PR and between 0b951d6 and 33fdec5.

📒 Files selected for processing (17)
  • builtins/src/main/java/org/jline/builtins/ScreenTerminal.java
  • builtins/src/main/java/org/jline/builtins/SwingTerminal.java
  • builtins/src/main/java/org/jline/builtins/Tmux.java
  • builtins/src/main/java/org/jline/builtins/WebTerminal.java
  • builtins/src/test/java/org/jline/builtins/ScreenTerminalTest.java
  • builtins/src/test/java/org/jline/builtins/TerminalTest.java
  • console/src/test/java/org/jline/widget/TailTipWidgetsTest.java
  • terminal/src/main/java/org/jline/terminal/Size.java
  • terminal/src/main/java/org/jline/terminal/Sized.java
  • terminal/src/main/java/org/jline/terminal/Terminal.java
  • terminal/src/main/java/org/jline/terminal/impl/AbstractPosixTerminal.java
  • terminal/src/main/java/org/jline/terminal/impl/AbstractWindowsTerminal.java
  • terminal/src/main/java/org/jline/terminal/impl/DumbTerminal.java
  • terminal/src/main/java/org/jline/terminal/impl/LineDisciplineTerminal.java
  • terminal/src/main/java/org/jline/utils/Display.java
  • terminal/src/test/java/org/jline/terminal/impl/GraphemeClusterModeTest.java
  • terminal/src/test/java/org/jline/utils/DisplayTest.java
✅ Files skipped from review due to trivial changes (1)
  • console/src/test/java/org/jline/widget/TailTipWidgetsTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • terminal/src/main/java/org/jline/terminal/Sized.java

Comment on lines +759 to +765
// Deprecation is awkward, as in its current state setSize(Size) would always cause deprecation warnings,
// because it doesn't auto-map to setSize(Sized)
// @Deprecated
// @SuppressWarnings("java:S1133") // Intentional deprecation; removal planned for a future major version
default void setSize(Size size) {
setSize((Sized) size);
}
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Is adding a new abstract method to an existing public Java interface binary/source compatible with already-compiled implementations?

💡 Result:

No.

  • Source compatibility: Not compatible. Any existing class that implements the interface will fail to recompile until it provides an implementation of the new abstract method.
  • Binary compatibility (already-compiled implementations): In the JLS sense of “will preexisting binaries still link?”, adding a method is binary compatible—old class files that implemented the interface can still load/link. However, if code compiled against the new interface ever tries to call the newly-added method on an old implementation, the call can fail at runtime (typically AbstractMethodError) because the old class file doesn’t provide that method. [1]
  • How Java 8+ solves this for interface evolution: Add the new method as a default method (with an implementation) to avoid breaking existing implementers. [2]

Sources: [1] Java Language Specification, Binary Compatibility (§13.4.12). [2] Default methods rationale/usage (Java interface evolution).


🏁 Script executed:

# First, let's locate the Terminal.java file
fd -type f -name "Terminal.java" | head -20

Repository: jline/jline3

Length of output: 226


🏁 Script executed:

# Then read the specific lines mentioned in the review (759-775 and surrounding context)
if [ -f "terminal/src/main/java/org/jline/terminal/Terminal.java" ]; then
  sed -n '750,780p' "terminal/src/main/java/org/jline/terminal/Terminal.java" | cat -n
fi

Repository: jline/jline3

Length of output: 1540


Public API compatibility break: new abstract interface method.

Line 775 introduces setSize(Sized) as an abstract method on the Terminal interface. Existing implementations that only implement setSize(Size) will fail to recompile, as they must now provide an implementation of the new abstract method. This breaks source compatibility.

The suggested alternative preserves backward compatibility by making setSize(Size) abstract (the original contract) and setSize(Sized) a default method, ensuring existing implementations continue to work without modification.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@terminal/src/main/java/org/jline/terminal/Terminal.java` around lines 759 -
765, The change introduced a new abstract method setSize(Sized) on the Terminal
interface which breaks source compatibility for existing implementations that
only implement setSize(Size); to fix, revert to keeping the original abstract
contract by making setSize(Size) the required method on Terminal (remove the
default implementation) and provide setSize(Sized) as a default helper that
delegates to setSize(Size) (i.e., implement setSize(Sized) to call
setSize((Size) sized) or equivalent), so existing implementers need not change
while new callers can use the Sized overload; update the Terminal interface
methods setSize(Size) and setSize(Sized) accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was intentional to prevent having to use

@Override
    public void setSize(Size size) {
        setSize((Sized) size);
    }

    @Override
    public void setSize(Sized sz) {
       // Actual implementation
    }

everywhere.

7d21f09 already broke source compatibility in the Terminal interface, so 1 more slight change isn't a big issue.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Elec332, understood — the design is intentional: by making setSize(Sized) the abstract contract, implementors only need to provide a single setSize(Sized) method instead of two overloads with boilerplate delegation. The setSize(Size) default then serves as a transparent bridge for legacy callers.

Given that the previous commit already introduced a source-compatibility break in Terminal, the incremental impact here is consistent with that direction. The tradeoff (one-time migration for implementors vs. perpetual boilerplate in every implementation) clearly favors your approach.


🧠 Learnings used
Learnt from: CR
Repo: jline/jline3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:03:07.932Z
Learning: Applies to **/terminal/**/*.java : Follow existing patterns for terminal feature pairs, such as hasFocusSupport()/trackFocus() method naming

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 9, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java`:
- Around line 1758-1759: The public synchronized method setSize(Sized)
dereferences its Sized parameter without a null check; add a defensive null
guard at the start of setSize(Sized) (e.g., if sized == null return false or
throw IllegalArgumentException) before calling sized.getColumns()/getRows(), so
callers cannot cause an NPE; update the method body of setSize(Sized) (which
delegates to setSize(int,int)) to perform this check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1284a8f2-ce40-4778-b040-8fe001575fdf

📥 Commits

Reviewing files that changed from the base of the PR and between 33fdec5 and 847034c.

📒 Files selected for processing (3)
  • builtins/src/main/java/org/jline/builtins/ScreenTerminal.java
  • builtins/src/main/java/org/jline/builtins/SwingTerminal.java
  • builtins/src/main/java/org/jline/builtins/WebTerminal.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • builtins/src/main/java/org/jline/builtins/WebTerminal.java
  • builtins/src/main/java/org/jline/builtins/SwingTerminal.java

Comment on lines +1758 to +1759
public synchronized boolean setSize(Sized sized) {
return setSize(sized.getColumns(), sized.getRows());
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against null in setSize(Sized)

Line [1758] accepts a nullable reference and Line [1759] dereferences it unconditionally. A defensive check avoids avoidable runtime NPEs from public API callers.

Suggested fix
 public synchronized boolean setSize(Sized sized) {
+    if (sized == null) {
+        return false;
+    }
     return setSize(sized.getColumns(), sized.getRows());
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public synchronized boolean setSize(Sized sized) {
return setSize(sized.getColumns(), sized.getRows());
public synchronized boolean setSize(Sized sized) {
if (sized == null) {
return false;
}
return setSize(sized.getColumns(), sized.getRows());
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@builtins/src/main/java/org/jline/builtins/ScreenTerminal.java` around lines
1758 - 1759, The public synchronized method setSize(Sized) dereferences its
Sized parameter without a null check; add a defensive null guard at the start of
setSize(Sized) (e.g., if sized == null return false or throw
IllegalArgumentException) before calling sized.getColumns()/getRows(), so
callers cannot cause an NPE; update the method body of setSize(Sized) (which
delegates to setSize(int,int)) to perform this check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While valid, this method mimics the logic in all similar methods introduced in 7d21f09

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh api repos/jline/jline3/commits/7d21f09e65bb4305db1c87086ee7e5a2ed872215 --jq '.files[].filename' 2>/dev/null
gh api "repos/jline/jline3/commits/7d21f09e65bb4305db1c87086ee7e5a2ed872215" 2>/dev/null | python3 -c "
import sys, json
data = json.load(sys.stdin)
for f in data.get('files', []):
    print('=== FILE:', f['filename'], '===')
    print(f.get('patch',''))
    print()
" 2>/dev/null | head -200

Length of output: 11790


🏁 Script executed:

#!/bin/bash
gh api "repos/jline/jline3/commits/7d21f09e65bb4305db1c87086ee7e5a2ed872215" 2>/dev/null | python3 -c "
import sys, json
data = json.load(sys.stdin)
for f in data.get('files', []):
    if any(x in f['filename'] for x in ['Terminal.java', 'LineDiscipline', 'AbstractPosix', 'AbstractWindows', 'DumbTerminal', 'Display.java', 'Size.java']):
        print('=== FILE:', f['filename'], '===')
        print(f.get('patch',''))
        print()
" 2>/dev/null

Length of output: 46937


@Elec332, that's a fair point. Looking at the commit you referenced, the established pattern throughout the codebase — including setSize(Size size) in ScreenTerminal, Terminal.setSize(Size), and Display.resize(Size) — consistently omits null guards and dereferences the parameter directly. The current setSize(Sized sized) faithfully follows that same convention. I'll withdraw this suggestion.


✏️ Learnings added
Learnt from: Elec332
Repo: jline/jline3 PR: 1731
File: builtins/src/main/java/org/jline/builtins/ScreenTerminal.java:1758-1759
Timestamp: 2026-04-09T00:49:13.994Z
Learning: In jline/jline3, the established pattern for `setSize(Size/Sized)` and similar methods (e.g., `Display.resize(Size)`) across `ScreenTerminal`, `Terminal`, `LineDisciplineTerminal`, and related classes is to dereference the parameter directly without null checks. Do not suggest null guards for these methods.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: jline/jline3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-31T12:03:07.932Z
Learning: Applies to **/terminal/**/*.java : Follow existing patterns for terminal feature pairs, such as hasFocusSupport()/trackFocus() method naming

@Elec332
Copy link
Copy Markdown
Contributor Author

Elec332 commented Apr 9, 2026

https://github.com/jline/jline3/pull/1731/changes#diff-7d3965be21a6be8c7016d4f1c854762143045c3173d8ba1f6d0f03796e6a1314R172

Could be fixed by renaming the new method Size.copyFrom(Sized), which would both allow a deprecated tag and also make it a bit more clear what the function does (as "copy" could both nean copy from or to). Since you may find that a bit drastic I did not go this route yet, but this could easily be done upon request.

@Elec332 Elec332 requested a review from gnodet April 9, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants