• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / latte / 20077192222

09 Dec 2025 08:15PM UTC coverage: 94.815% (+0.007%) from 94.808%
20077192222

push

github

dg
added CustomFunctionCallNode for custom functions

12 of 12 new or added lines in 2 files covered. (100.0%)

1 existing line in 1 file now uncovered.

5486 of 5786 relevant lines covered (94.82%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.0
/src/Tools/LinterExtension.php
1
<?php
2

3
/**
4
 * This file is part of the Latte (https://latte.nette.org)
5
 * Copyright (c) 2008 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Latte\Tools;
11

12
use Latte;
13
use Latte\Compiler\Node;
14
use Latte\Compiler\Nodes\Php;
15
use Latte\Compiler\Nodes\Php\Expression;
16
use Latte\Compiler\Nodes\TemplateNode;
17
use Latte\Compiler\NodeTraverser;
18
use Latte\Compiler\Position;
19

20

21
/**
22
 * Linter extension for validating filters, functions, classes and methods.
23
 */
24
final class LinterExtension extends Latte\Extension
25
{
26
        private ?Latte\Engine $engine = null;
27

28

29
        public function beforeCompile(Latte\Engine $engine): void
1✔
30
        {
31
                $this->engine = $engine;
1✔
32
        }
1✔
33

34

35
        public function getPasses(): array
36
        {
37
                return [
38
                        'linter' => $this->linterPass(...),
1✔
39
                ];
40
        }
41

42

43
        private function linterPass(TemplateNode $node): void
1✔
44
        {
45
                (new NodeTraverser)->traverse($node, function (Node $node) {
1✔
46
                        if ($node instanceof Php\FilterNode) {
1✔
47
                                $this->validateFilter($node);
1✔
48
                        }
49

50
                        if ($node instanceof Expression\FunctionCallNode && $node->name instanceof Php\NameNode) {
1✔
51
                                $this->validateFunction($node);
1✔
52
                        }
53

54
                        if ($node instanceof Expression\NewNode && $node->class instanceof Php\NameNode) {
1✔
55
                                $this->validateClass($node);
1✔
56
                        }
57

58
                        if ($node instanceof Expression\StaticMethodCallNode
1✔
59
                                && $node->class instanceof Php\NameNode
1✔
60
                                && $node->name instanceof Php\IdentifierNode
1✔
61
                        ) {
62
                                $this->validateStaticMethod($node);
1✔
63
                        }
64
                });
1✔
65
        }
1✔
66

67

68
        private function validateFilter(Php\FilterNode $node): void
1✔
69
        {
70
                $name = $node->name->name;
1✔
71
                $filters = $this->engine->getFilters();
1✔
72

73
                if (!isset($filters[$name])) {
1✔
74
                        $this->reportWarning("Unknown filter |$name", $node->position);
1✔
75
                }
76
        }
1✔
77

78

79
        private function validateFunction(Expression\FunctionCallNode $node): void
1✔
80
        {
81
                $name = (string) $node->name;
1✔
82
                if (!function_exists($name)) {
1✔
83
                        $this->reportWarning("Unknown function $name()", $node->position);
1✔
84
                }
85
        }
1✔
86

87

88
        private function validateClass(Expression\NewNode $node): void
1✔
89
        {
90
                $className = (string) $node->class;
1✔
91
                if (!class_exists($className)) {
1✔
92
                        $this->reportWarning("Unknown class $className", $node->position);
1✔
93
                }
94
        }
1✔
95

96

97
        private function validateStaticMethod(Expression\StaticMethodCallNode $node): void
1✔
98
        {
99
                $className = (string) $node->class;
1✔
100
                $methodName = $node->name->name;
1✔
101

102
                if (!class_exists($className)) {
1✔
UNCOV
103
                        $this->reportWarning("Unknown class $className", $node->position);
×
104
                } elseif (!method_exists($className, $methodName)) {
1✔
105
                        $this->reportWarning("Unknown method $className::$methodName()", $node->position);
1✔
106
                }
107
        }
1✔
108

109

110
        private function reportWarning(string $message, ?Position $position): void
1✔
111
        {
112
                $pos = '';
1✔
113
                if ($position) {
1✔
114
                        $pos = ' on line ' . $position->line;
1✔
115
                        if ($position->column) {
1✔
116
                                $pos .= ' at column ' . $position->column;
1✔
117
                        }
118
                }
119
                trigger_error($message . $pos, E_USER_WARNING);
1✔
120
        }
1✔
121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc