Pass through arbitrary Expr nodes in TypeWriter, add castInt() helper - #42
Merged
JohnathonKoster merged 2 commits intoJul 19, 2026
Merged
Conversation
TypeWriter::write() only passed FuncCall instances through untouched;
any other manually-built PhpParser AST node (e.g. a Cast\Int_ for a
literal (int) cast) fell through to TypeAnalyzer::typeOf(), which
only understands scalars/arrays/null/bool/Closure and throws
"Support type: object" for anything else. That made it impossible to
embed a hand-built expression - like an (int) cast around an env()
call - as a config value anywhere it'd end up nested inside an array
(which is effectively everywhere, since ArrayWriter recurses through
TypeWriter::write() for every item).
FuncCall already extends PhpParser\Node\Expr, so broadening the
passthrough check to any Expr is a strict generalization: everything
that worked before (FuncCall) still works, and any other expression
node - casts, ternaries, etc. - can now be used as a config value too.
Added FunctionWriter::castInt() as a small fluent helper built on top
of this, so callers get `(int) ...` the same way they already get
env()/basePath()/etc., instead of reaching for raw PhpParser node
construction:
ConfigWriter::f()->castInt(ConfigWriter::f()->env('LIMIT', 20))
// => (int) env('LIMIT', 20)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
TypeWriter::write()only passesFuncCallinstances through untouched. Any other hand-built AST node — say aCast\Int_for a literal(int)cast — falls through toTypeAnalyzer::typeOf(), which only understands scalars/arrays/null/bool/Closureand throws:the moment that node ends up nested inside an array (which is effectively everywhere, since
ArrayWriterrecurses throughTypeWriter::write()for every item). So there was no way to write something like(int) env('LIMIT', 20)as a config value — only the function-call form,intval(env('LIMIT', 20)), worked, even though the two aren't the same syntax you actually want when replicating an existing config file's style.Solution
FuncCallalready extendsPhpParser\Node\Expr, so broadening the passthrough check frominstanceof FuncCalltoinstanceof Expris a strict generalization — everything that worked before still works, and any other expression node (casts, ternaries, etc.) can now be used as a config value too.Added
FunctionWriter::castInt(Expr $expr): Cast\Int_as a small fluent helper on top of that, matching the style of the existingenv()/basePath()/etc. helpers:Testing
New case in
LaravelFunctionCallTestassertingcastInt(env(...))renders as(int) env(...). Same 2 pre-existing, unrelated failures as before (closure param formatting); nothing else regressed.Note: branches off
master, independent of #41 (this PR doesn't depend on it, and vice versa) — I merged both locally into a scratch branch to confirm they work together, which they do.