Skip to content

Commit 46fb48e

Browse files
committed
Add filter parameter types to code to allow statical analysis [WIP]
1 parent 379921e commit 46fb48e

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

src/Latte/Compiler/TemplateGenerator.php

+43-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
use Latte;
1313
use Latte\ContentType;
14+
use Latte\Essential\Blueprint;
15+
use Nette\PhpGenerator as Php;
1416

1517

1618
/**
@@ -38,6 +40,7 @@ public function generate(
3840
string $className,
3941
?string $comment = null,
4042
bool $strictMode = false,
43+
array $filters = [],
4144
): string {
4245
$context = new PrintContext($node->contentType);
4346
$scope = $context->getVariableScope();
@@ -78,13 +81,18 @@ public function generate(
7881
. ($method['body'] ? "\t\t$method[body]\n" : '') . "\t}";
7982
}
8083

84+
$comment .= "\n@property Filters$className \$filters";
85+
$comment = str_replace('*/', '* /', $comment);
86+
$comment = str_replace("\n", "\n * ", "/**\n" . trim($comment)) . "\n */\n";
87+
8188
$code = "<?php\n\n"
8289
. ($strictMode ? "declare(strict_types=1);\n\n" : '')
8390
. "use Latte\\Runtime as LR;\n\n"
84-
. ($comment === null ? '' : '/** ' . str_replace('*/', '* /', $comment) . " */\n")
91+
. $comment
8592
. "final class $className extends Latte\\Runtime\\Template\n{\n"
8693
. implode("\n\n", $members)
87-
. "\n}\n";
94+
. "\n}\n\n\n"
95+
. $this->generateStub($node, 'Filters' . $className, $filters);
8896

8997
$code = PhpHelpers::optimizeEcho($code);
9098
$code = PhpHelpers::reformatCode($code);
@@ -124,6 +132,39 @@ private function generateBlocks(array $blocks, PrintContext $context): void
124132
}
125133

126134

135+
private function generateStub(Node $node, string $className, $filters): string
136+
{
137+
if (!class_exists(Php\ClassType::class)) {
138+
return '';
139+
}
140+
141+
$used = [];
142+
(new NodeTraverser)->traverse($node, function (Node $node) use (&$used) {
143+
if ($node instanceof Nodes\Php\FilterNode) {
144+
$used[$node->name->name] = true;
145+
}
146+
});
147+
148+
$class = new Php\ClassType($className);
149+
$filters = array_intersect_key($filters, $used);
150+
foreach ($filters as $name => $callback) {
151+
$func = (new Php\Factory)->fromCallable($callback);
152+
$type = Blueprint::printType($func->getReturnType(), $func->isReturnNullable(), null) ?: 'mixed';
153+
$params = [];
154+
$list = $func->getParameters();
155+
foreach ($list as $param) {
156+
$variadic = $func->isVariadic() && $param === end($list);
157+
$params[] = (Blueprint::printType($param->getType(), $param->isNullable(), null) ?: 'mixed')
158+
. ($variadic ? '...' : '');
159+
}
160+
161+
$class->addComment('@property callable(' . implode(', ', $params) . "): $type \$$name");
162+
}
163+
164+
return (string) $class;
165+
}
166+
167+
127168
/**
128169
* @param Nodes\Php\ParameterNode[] $params
129170
*/

src/Latte/Engine.php

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ public function generate(TemplateNode $node, string $name): string
191191
$this->getTemplateClass($name),
192192
$comment,
193193
$this->strictTypes,
194+
$this->getFilters(),
194195
);
195196
}
196197

src/Latte/Essential/Blueprint.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public function addFunctions(Php\ClassType $class, array $funcs): void
9595
}
9696

9797

98-
private function printType(?string $type, bool $nullable, ?Php\PhpNamespace $namespace): string
98+
public static function printType(?string $type, bool $nullable, ?Php\PhpNamespace $namespace): string
9999
{
100100
if ($type === null) {
101101
return '';
@@ -123,7 +123,7 @@ public function printParameters(
123123
$list = $function->getParameters();
124124
foreach ($list as $param) {
125125
$variadic = $function->isVariadic() && $param === end($list);
126-
$params[] = ltrim($this->printType($param->getType(), $param->isNullable(), $namespace) . ' ')
126+
$params[] = ltrim(self::printType($param->getType(), $param->isNullable(), $namespace) . ' ')
127127
. ($param->isReference() ? '&' : '')
128128
. ($variadic ? '...' : '')
129129
. '$' . $param->getName()

0 commit comments

Comments
 (0)