Skip to content

fix(io): update Reader.read to respect Liskov Substitution Principle#23

Merged
cesarcoatl merged 2 commits intomainfrom
fix/io/lang-Readable-liskov-substitution-principle
Apr 17, 2026
Merged

fix(io): update Reader.read to respect Liskov Substitution Principle#23
cesarcoatl merged 2 commits intomainfrom
fix/io/lang-Readable-liskov-substitution-principle

Conversation

@cesarcoatl
Copy link
Copy Markdown
Member

@cesarcoatl cesarcoatl commented Apr 17, 2026

flagged by ty

Summary by Sourcery

Align Reader.read signature with the Java Reader.read(CharBuffer) contract to better respect type relationships.

Bug Fixes:

  • Correct Reader.read type signature to take a CharBuffer instead of arbitrary arguments, matching the Java API and fixing LSP violations.

Enhancements:

  • Import CharBuffer and update Reader stubs to use a precise CharBuffer parameter type for read().

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 17, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refines the java.io.Reader.read API to a specific CharBuffer-based signature in both the runtime shim and stub, aligning it with the Java Reader contract and Liskov Substitution Principle.

Class diagram for updated java_io_Reader_read_signature

classDiagram
    class Object
    class Readable
    class Closeable
    class CharBuffer

    class Reader{
        +read(cb: CharBuffer) int
        +mark(int) void
        +markSupported() bool
        +nullReader() Reader
        +ready() bool
        +reset() void
        +skip(long) long
    }

    Reader --|> Object
    Reader ..|> Readable
    Reader ..|> Closeable
    Reader --> CharBuffer : uses_in_read
Loading

File-Level Changes

Change Details Files
Tighten Reader.read signature to accept a CharBuffer instead of arbitrary arguments.
  • Change Reader.read implementation signature from a variadic *args form to a single cb parameter.
  • Update the runtime type hint from (*Any) -> int to (CharBuffer) -> int to match the Java Reader.read(CharBuffer) overload.
  • Import CharBuffer into the stubs module to support the new type annotation.
  • Update the Reader.read stub signature from *args: Any to cb: CharBuffer for type checking consistency.
src/java/io/__init__.py
stubs/stubs/java/io/__init__.pyi

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Narrowing Reader.read from *args: Any to a single CharBuffer parameter makes all other valid Java Reader.read(...) overloads impossible to express; consider using overloads or a more general signature (e.g., multiple @overload definitions) instead of a single CharBuffer-only variant.
  • If this change is specifically targeting the Readable.read(CharBuffer) method, it may be clearer to model that as a separate Readable-interface method or a dedicated overload, rather than repurposing the primary Reader.read to only accept CharBuffer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Narrowing `Reader.read` from `*args: Any` to a single `CharBuffer` parameter makes all other valid Java `Reader.read(...)` overloads impossible to express; consider using overloads or a more general signature (e.g., multiple `@overload` definitions) instead of a single `CharBuffer`-only variant.
- If this change is specifically targeting the `Readable.read(CharBuffer)` method, it may be clearer to model that as a separate `Readable`-interface method or a dedicated overload, rather than repurposing the primary `Reader.read` to only accept `CharBuffer`.

## Individual Comments

### Comment 1
<location path="stubs/stubs/java/io/__init__.pyi" line_range="116" />
<code_context>
     @staticmethod
     def nullReader() -> Reader: ...
-    def read(self, *args: Any) -> int: ...
+    def read(self, cb: CharBuffer) -> int: ...
     def ready(self) -> bool: ...
     def reset(self) -> None: ...
</code_context>
<issue_to_address>
**suggestion:** The stub now models only a single `read(CharBuffer)` shape; consider overloads if other `read` variants are intended.

The old `*args: Any` signature was imprecise but did indicate multiple `read` variants. If this stub is meant to cover the full Java API (e.g., `read()`, `read(char[], int, int)`), representing each as an explicit `@overload` would be more accurate than a single `read(self, cb: CharBuffer) -> int` signature.

Suggested implementation:

```
    @staticmethod
    def nullReader() -> Reader: ...

    @overload
    def read(self) -> int: ...
    @overload
    def read(self, cb: CharBuffer) -> int: ...
    @overload
    def read(self, cbuf: list[str]) -> int: ...
    @overload
    def read(self, cbuf: list[str], off: int, length: int) -> int: ...

    def ready(self) -> bool: ...

```

`.

Here are the edits:

<file_operations>
<file_operation operation="edit" file_path="stubs/stubs/java/io/__init__.pyi">
<<<<<<< SEARCH
    @staticmethod
    def nullReader() -> Reader: ...
    def read(self, cb: CharBuffer) -> int: ...
    def ready(self) -> bool: ...
=======
    @staticmethod
    def nullReader() -> Reader: ...

    @overload
    def read(self) -> int: ...
    @overload
    def read(self, cb: CharBuffer) -> int: ...
    @overload
    def read(self, cbuf: list[str]) -> int: ...
    @overload
    def read(self, cbuf: list[str], off: int, length: int) -> int: ...

    def ready(self) -> bool: ...
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>
1. Ensure `from typing import overload` is present at the top of `stubs/stubs/java/io/__init__.pyi`. If the file already imports from `typing`, extend that import to include `overload`.
2. If your codebase uses a different type to model Java `char[]` (e.g., `Sequence[str]` or a custom `CharArray`), adjust the `cbuf: list[str]` annotations accordingly to match your existing conventions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@staticmethod
def nullReader() -> Reader: ...
def read(self, *args: Any) -> int: ...
def read(self, cb: CharBuffer) -> int: ...
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: The stub now models only a single read(CharBuffer) shape; consider overloads if other read variants are intended.

The old *args: Any signature was imprecise but did indicate multiple read variants. If this stub is meant to cover the full Java API (e.g., read(), read(char[], int, int)), representing each as an explicit @overload would be more accurate than a single read(self, cb: CharBuffer) -> int signature.

Suggested implementation:

    @staticmethod
    def nullReader() -> Reader: ...

    @overload
    def read(self) -> int: ...
    @overload
    def read(self, cb: CharBuffer) -> int: ...
    @overload
    def read(self, cbuf: list[str]) -> int: ...
    @overload
    def read(self, cbuf: list[str], off: int, length: int) -> int: ...

    def ready(self) -> bool: ...

`.

Here are the edits:

<file_operations>
<file_operation operation="edit" file_path="stubs/stubs/java/io/init.pyi">
<<<<<<< SEARCH
@staticmethod
def nullReader() -> Reader: ...
def read(self, cb: CharBuffer) -> int: ...
def ready(self) -> bool: ...

@staticmethod
def nullReader() -> Reader: ...

@overload
def read(self) -> int: ...
@overload
def read(self, cb: CharBuffer) -> int: ...
@overload
def read(self, cbuf: list[str]) -> int: ...
@overload
def read(self, cbuf: list[str], off: int, length: int) -> int: ...

def ready(self) -> bool: ...

REPLACE
</file_operation>
</file_operations>

<additional_changes>

  1. Ensure from typing import overload is present at the top of stubs/stubs/java/io/__init__.pyi. If the file already imports from typing, extend that import to include overload.
  2. If your codebase uses a different type to model Java char[] (e.g., Sequence[str] or a custom CharArray), adjust the cbuf: list[str] annotations accordingly to match your existing conventions.

@cesarcoatl cesarcoatl merged commit 7aaaa57 into main Apr 17, 2026
5 checks passed
@cesarcoatl cesarcoatl deleted the fix/io/lang-Readable-liskov-substitution-principle branch April 17, 2026 02:43
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.

1 participant