Skip to content

Fix ofType matching for subclasses and interfaces - #75

Open
dajiaohuang wants to merge 1 commit into
Athari:masterfrom
dajiaohuang:fix/oftype-class-assignability-20261028
Open

dajiaohuang wants to merge 1 commit into
Athari:masterfrom
dajiaohuang:fix/oftype-class-assignability-20261028

Conversation

@dajiaohuang

@dajiaohuang dajiaohuang commented Oct 28, 2026 •

Copy link
Copy Markdown

Summary

Enumerable::ofType() currently matches the exact concrete class name. That drops objects whose actual class is a subclass of the requested class, and objects implementing a requested interface. Use PHP's instanceof semantics instead and clarify the documented behavior.

The regression test uses only synthetic objects: an anonymous Exception subclass is retained when filtering by Exception::class and Throwable::class.

Validation

  • composer validate --strict
  • Focused testOfType (PHP 8.4.27, PHPUnit 8.5.56)
  • Full unit suite: 189 tests, 758 assertions (PHP 8.4.27, PHPUnit 8.5.56)
  • git diff --check

A coverage report and the broader PHP CI matrix were not run; task-local Xdebug setup could not be completed after TLS secure-channel failures. No coverage/CI result is claimed.

Summary by CodeRabbit

  • New Features
    • Type filtering now includes objects that extend the requested class or implement the requested interface, rather than only objects with an exact class match. This makes ofType results more inclusive for class hierarchies and interfaces.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 01e93672-316f-4335-9a98-7d8f352103e8
Commits

Reviewing files that changed from the base of the PR and between 9a0c87c and 0d753f0.

Files selected for processing: 2
  • Tests/Unit/EnumerableTest.php
  • YaLinqo/Enumerable.php

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Walkthrough

Enumerable::ofType() now includes subclasses and interface implementations in its fallback filter. The documentation describes this behavior, and tests check subclass matches for Exception and Throwable.

Changes

ofType filtering

Layer / File(s) Summary
Document and verify subtype matching
YaLinqo/Enumerable.php, Tests/Unit/EnumerableTest.php
The documentation describes class and interface matching. The fallback filter uses instanceof, and tests cover an Exception subclass queried by Exception and Throwable.

Priority: Low

Estimated code review effort: 2 (Simple) | ~7 minutes

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: Minimal · up to 0d753

The change includes subclasses and interface implementations without altering scalar filtering or retained keys. No actionable merge-blocking risk remains.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed Hark, the title speaks true! The change makes Enumerable::ofType() use instanceof, so subclasses and interface implementations are kept, not just exact class-name matches. The title names that primary…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

Hark, the title speaks true! The change makes Enumerable::ofType() use instanceof, so subclasses and interface implementations are kept, not just exact class-name matches. The title names that primary change: the matching fix for subclasses and interfaces. It is short, clear, and free of filler.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 2 files.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Hmm, subclasses pass the gate,
Interfaces join the line,
Exception meets its parent,
Tests mark each match in time,
The filter sees the type, not just the name.

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

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix ofType matching for subclasses and interfaces

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Match subclasses and interface implementations when filtering objects by type.
• Document assignable class and interface matching while retaining built-in type filters.
• Add regression assertions for an Exception subclass filtered by Exception and Throwable.
Diagram

graph TD
  S["Source sequence"] --> O["ofType"] --> D{"Built-in type?"}
  D -->|yes| B["Built-in predicate"] --> W["where filter"] --> R["Filtered sequence"]
  D -->|no| I["instanceof check"] --> W
Loading
High-Level Assessment

Keep the instanceof predicate: it directly expresses PHP class and interface assignability within the existing filter path. A separate hierarchy lookup would add complexity without improving this behavior.

Files changed (2) +11 / -2

Bug fix (1) +2 / -2
Enumerable.phpUse assignability for named object types +2/-2

Use assignability for named object types

• Replaces exact concrete-class comparison with instanceof for the class-or-interface branch of ofType. Clarifies the parameter documentation; predefined type predicates remain unchanged.

YaLinqo/Enumerable.php

Tests (1) +9 / -0
EnumerableTest.phpCover subclass and interface filtering +9/-0

Cover subclass and interface filtering

• Extends testOfType with an anonymous Exception subclass. Identity assertions verify that filtering by Exception and Throwable retains that object.

Tests/Unit/EnumerableTest.php

This branch has not been deployed

No deployments
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