Skip to content

fix(checker/php): is_string matches the string type keyword #1474

Description

@dekobon

Summary

Checker::is_string for PHP lists String2 (id 25), which is the string
type keyword, not a string literal. So bca find string reports a hit on
every PHP file carrying a string type annotation.

Evidence

The same distinction is already drawn correctly one predicate over:
php_bool_terminal_kinds! (big-code-analysis-ast/src/macros/kind_sets.rs)
deliberately excludes Float2 (id 52) with a comment saying it is the
float type keyword rather than a literal. String2 is the same shape and
is included in is_string.

Why it is its own issue

This is Checker::is_string, not a metric terminal set — a different
predicate with different consumers (bca find, bca count). Nothing in the
ABC/Halstead path is affected, which is why the 2026-09-14 batch left it
alone rather than widening a metric fix into a classifier change.

It is nonetheless the .claude/rules/grammar-dispatch.md §7 case: sibling
predicates classifying the same node differently drift silently, and each
reads as internally consistent from its own side.

Before fixing

  • Confirm with bca dump which id a string type annotation versus a string
    literal actually carries at the pinned grammar, and enumerate every
    numeric-suffix alias of both (§1).
  • Cross-walk the §7 pairs named in the rule: is_stringget_op_type
    string classification, and check whether Halstead currently agrees or
    disagrees with is_string here.
  • Check the sibling languages in the same group — Java, C#, Kotlin and Groovy
    all have type keywords that could be spelled as a literal-looking kind.

Related


Resolution

Status: Fixed (pending merge)
Commit: c755fafa on branch fix/issue-1474
Root cause: PhpCode::is_string listed Php::String2 (kind_id 25),
the string type keyword — a node the grammar emits only as the sole
child of a primitive_type wrapper. bca find -t string / bca count string reach that predicate through is_string_with_code, so every PHP
type annotation was reported as a string literal. #288's two
justifications for the arm had both been retired already: #1293 moved
String2 into get_op_type's primitive_type-suppression arm, and
#1261 removed the identical keyword aliases from TypeScript and TSX.

PHP was the only language affected — Java, C#, Kotlin and Groovy spell
their string types as type_identifier / predefined_type and list
none of them, and the JS-family String2 aliases are literals. Measured
corpus impact: php/strings.php 24 → 12 hits, php/classes.php
27 → 8 (earlier triage in this thread estimated 24 → 8, which was
wrong).

Activity

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 working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions