Summary
Several linter rules crash when the parser encounters a dynamic method call where the method name is a concatenation expression, e.g.:
$value = \strval($item->{'get' . $p}());
The specific failure is Undefined property: PhpParser\Node\Expr\BinaryOp\Concat::$name thrown from RequestHelperFunctionWherePossible.php:20 (and a matching line in RequestValidation.php:30).
Reproducer
Put this in any .php file under a Laravel app and run tlint lint (or duster lint --using=tlint) against the containing directory:
<?php
namespace App\Test;
class Probe
{
public function foo($item, string $p): string
{
return (string) $item->{'get' . $p}();
}
}
Running against the file directly does not crash; only directory mode reliably triggers it (presumably because of internal node-state accumulation across parsed files).
Root cause (best guess)
Linters/RequestHelperFunctionWherePossible.php:20:
$node instanceof Node\Expr\MethodCall
&& $node->name->name === 'get'
...
Node\Expr\MethodCall::$name is typed Identifier | Expr. For dynamic method calls ($obj->{expr}()) the parser yields an Expr such as BinaryOp\Concat, which has no ->name property. The rule needs to guard with $node->name instanceof Node\Identifier before reaching into ->name.
The same pattern appears in RequestValidation.php:30.
Impact
tlint lint <dir> / duster lint --using=tlint fails hard instead of skipping the problematic node
- The directory-mode crash blocks full-repo lint runs in tooling that invokes tlint against project directories
- Targeted flows (
--dirty, --diff=<branch>) are unaffected because they feed tlint individual files
Environment
- Duster 3.4.2 (bundles TLint)
- PHP 8.3.27
- Laravel 12 app
Happy to open a PR adding the instanceof Node\Identifier guard if that's the accepted fix direction.
Summary
Several linter rules crash when the parser encounters a dynamic method call where the method name is a concatenation expression, e.g.:
The specific failure is
Undefined property: PhpParser\Node\Expr\BinaryOp\Concat::$namethrown fromRequestHelperFunctionWherePossible.php:20(and a matching line inRequestValidation.php:30).Reproducer
Put this in any
.phpfile under a Laravel app and runtlint lint(orduster lint --using=tlint) against the containing directory:Running against the file directly does not crash; only directory mode reliably triggers it (presumably because of internal node-state accumulation across parsed files).
Root cause (best guess)
Linters/RequestHelperFunctionWherePossible.php:20:Node\Expr\MethodCall::$nameis typedIdentifier | Expr. For dynamic method calls ($obj->{expr}()) the parser yields anExprsuch asBinaryOp\Concat, which has no->nameproperty. The rule needs to guard with$node->name instanceof Node\Identifierbefore reaching into->name.The same pattern appears in
RequestValidation.php:30.Impact
tlint lint <dir>/duster lint --using=tlintfails hard instead of skipping the problematic node--dirty,--diff=<branch>) are unaffected because they feed tlint individual filesEnvironment
Happy to open a PR adding the
instanceof Node\Identifierguard if that's the accepted fix direction.