From 77e9206cb70a23efc38488bc7c9bd264c9138e77 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 14 Sep 2026 19:24:19 +0200 Subject: [PATCH] Resolve types of arrow function parameters used as arguments Bumps php-parser-in-go to pick up its new arrow function type resolution, and tracks arrow function parameter types in the collector so a typed arrow parameter passed into a call is qualified from the file's use imports. Outer variables captured by the arrow are kept. --- go.mod | 2 +- go.sum | 4 ++-- internal/apply/apply_test.go | 5 +++++ internal/collect/collect.go | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ba5a6d55..fcadf34b 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/rectorphp/argtyper go 1.26 -require github.com/rectorphp/php-parser-in-go v0.1.1 +require github.com/rectorphp/php-parser-in-go v0.1.2-0.20260914171035-ef8c7cbb139d diff --git a/go.sum b/go.sum index 6593ebc7..572d788d 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,7 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/rectorphp/php-parser-in-go v0.1.1 h1:9jMbxAtDBjubUlPFKB5lbbvpXn8Otxq9eG77Q7moqwk= -github.com/rectorphp/php-parser-in-go v0.1.1/go.mod h1:6p9QnZnLGc9uruvKuSXlVt4uSIY5Rqe6h2aj9+hEBG8= +github.com/rectorphp/php-parser-in-go v0.1.2-0.20260914171035-ef8c7cbb139d h1:T26rEJvnupxPmDhRGulHue2rj83Ncl6DtjCLbbMFjT4= +github.com/rectorphp/php-parser-in-go v0.1.2-0.20260914171035-ef8c7cbb139d/go.mod h1:6p9QnZnLGc9uruvKuSXlVt4uSIY5Rqe6h2aj9+hEBG8= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= diff --git a/internal/apply/apply_test.go b/internal/apply/apply_test.go index 9e16cca8..f506379f 100644 --- a/internal/apply/apply_test.go +++ b/internal/apply/apply_test.go @@ -200,6 +200,11 @@ func TestApply(t *testing.T) { }, want: " $this->save($lead); }\n}", + want: " $this->save($lead); }\n}", + }, { name: "qualifies typed parameter argument from use import", target: "save($lead); }\n}", diff --git a/internal/collect/collect.go b/internal/collect/collect.go index 4170e2d6..f58b0b54 100644 --- a/internal/collect/collect.go +++ b/internal/collect/collect.go @@ -75,6 +75,10 @@ func (c *collector) walk(node ast.Vertex, sc scope) { case *ast.ExprClosure: sc.params = c.paramClasses(typed.Params, sc.classFQCN) sc.locals = c.localClasses(typed.Stmts) + case *ast.ExprArrowFunction: + // arrow functions capture outer variables, so keep the inherited params + // and locals and overlay the arrow's own typed parameters. + sc.params = merge(sc.params, c.paramClasses(typed.Params, sc.classFQCN)) } c.visit(node, sc) @@ -291,6 +295,21 @@ func (c *collector) classFromType(typeNode ast.Vertex, enclosing string) string return name } +// merge overlays the over map onto a copy of base, with over winning on clashes. +func merge(base, over map[string]string) map[string]string { + if len(over) == 0 { + return base + } + merged := make(map[string]string, len(base)+len(over)) + for name, class := range base { + merged[name] = class + } + for name, class := range over { + merged[name] = class + } + return merged +} + // shortName returns the last segment of a fully qualified name, the form used // as a method lookup key. func shortName(fqcn string) string {