Skip to content

fix(parser): 未限定 Name::class 编译期解析为 FQCN - #23

Merged
ctfang merged 1 commit into
mainfrom
cursor/fix-class-const-compile-time-eee5
Nov 12, 2026
Merged

ctfang merged 1 commit into
mainfrom
cursor/fix-class-const-compile-time-eee5

Conversation

@ctfang

@ctfang ctfang commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

问题

在命名空间内写 Bar::class 时,若 Foo\Bar 尚未加载,Origami 会在解析期把常量固化为短名 Bar;后续加载该类也不会改变该字符串。官方 PHP 则在编译期按当前命名空间与 use 展开为 Foo\Bar,且不要求类存在、不触发 autoload。

这会导致依赖容器 has(SomeClass::class) 的代码(例如 Loom ServiceScope)在类晚加载时永远匹配失败。

原因

parser/ident_parser.go 处理 Ident::class 时仅在 findFullClassNameByNamespace 返回 ok=true 时才采用展开后的类名;而同一文件中的 parseStaticCall 早已注明:ok=false 时仍可能返回带命名空间前缀的候选 FQCN,必须采用。

修复

  • Name::class 与 parseStaticCall 对齐:findFullClassNameByNamespace 返回非空字符串即作为编译期类名字面量。
  • 不影响 self::class、static::class、parent::class 及 $obj::class(仍走 ClassConstant 运行时节点)。

回归测试

新增 tests/php/class_const_compile_time_test.php,覆盖:

  • 未限定名 + 全限定名 + 加载类前后字符串不变
  • 当前命名空间下的相对名 Baz\Qux::class
  • use ... as 别名
  • 全局 stdClass::class

验证

go run ./zy.go tests/php/class_const_compile_time_test.php
go run ./zy.go tests/php/this_class_const_test.php
go test ./parser/... ./node/...
Open in Web Open in Cursor 

未限定 ClassName::class 先前仅在 findFullClassNameByNamespace 返回
ok=true 时采用 FQCN,类未加载时会固化为短名。与 parseStaticCall 一致,
编译期始终采用返回的候选全名,符合 PHP 不要求类存在且不 autoload 的语义。

Co-authored-by: selden <ctfang@users.noreply.github.com>
@ctfang
ctfang merged commit ba8e741 into main Nov 12, 2026
4 checks passed
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