Skip to content

fix(resolution): case-insensitive names pass the prefilter; PHP => fn() is a bare call - #2141

Merged
colbymchenry merged 1 commit into
mainfrom
fix/php-case-and-arrow-calls
Sep 30, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
fix/php-case-and-arrow-calls

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Problem

  1. Case-insensitive languages lost calls before resolution. hasAnyPossibleMatch checks a case-sensitive set of known names. In PHP, Pascal, CFML, COBOL and VB.NET, a call in another case (formatprice() for FormatPrice, TestBox's ToMatchWithCase()) was dropped before fuzzy matching, which is case-insensitive for exactly these languages, could run. Found while testing fix(resolution): fuzzy matching is exact-case outside case-insensitive languages #2139.
  2. Every PHP call after => read as a method call. isBarePhpCall treated any > before the name as ->. So in Laravel-style arrays ('total' => count($items), 'by' => user()->id, 'label' => trans('…')) the bare-call rule ("a bare PHP call is a function") never applied, and fuzzy picked a same-named method.

Change

  • In ReferenceResolver, case-insensitive languages also pass the prefilter through hasAnyPossibleMatchIgnoringCase, which checks the name or any . / :: / -> part against a lowercased copy of the known-name set. The copy is built on first use and reset with the caches.
  • isBarePhpCall requires ->, ?-> or :: before the name. That also makes the else-arm of $x ? a : fn() a bare call.
  • matchFuzzy: an instantiates reference never names a method.

Measured (edges, wasm, main vs branch)

repo edges
BookStack (PHP) −166 / +23 removed: trans() → LocaleDefinition::trans (61), new Response → ImageStorageDisk::response (55), user() → a guard's user method (23), url() (16), config() (7), count() (3). Added: user() → BookStack's own user() helper (23)
TestBox (CFML) +2 ToMatchWithCase → toMatchWithCase, makepublic → makePublic
fw1 (CFML) +1
horse (Pascal) +3 FPC accept() → a same-named method; a bare Delphi call can reach an inherited method, so this isn't ruled out
gin, excalidraw 0

Tests

fuzzy-case-sensitivity.test.ts adds a PHP call in another case and a PHP => array. Both fail on main. The full suite passes (5600).

🤖 Generated with Claude Code

…n()` is a bare call

- The name prefilter checks a case-SENSITIVE set of known names, so in PHP,
  Pascal, CFML, COBOL and VB.NET — whose identifiers ignore case — a call
  written in another case (`formatprice()` for `FormatPrice`, TestBox's
  `ToMatchWithCase()`) was dropped before any strategy ran. Those languages
  now also check a lowercase set (built lazily, only when asked).
- `isBarePhpCall` took any `>` before a name for `->`: every call after `=>`
  in a PHP array (`'total' => count($items)`, `'by' => user()->id`,
  `'label' => trans('…')`) was a member call, and found a same-named method
  — 166 wrong edges on BookStack (`trans` → LocaleDefinition::trans,
  `new Response` → ImageStorageDisk::response, `url()`, `config()`, `count()`).
  It now requires `->` / `?->` / `::`.
- A fuzzy `instantiates` never names a method.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry merged commit ca3bb44 into main Sep 30, 2026
@colbymchenry
colbymchenry deleted the fix/php-case-and-arrow-calls branch September 30, 2026 08:31
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