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

nette / latte / 23977766277

04 Apr 2026 11:15AM UTC coverage: 95.035% (+0.005%) from 95.03%
23977766277

Pull #414

github

web-flow
Merge e3196a2ac into 5d932e273
Pull Request #414: Dedent: fixed indentation preservation for paired tags inside HTML

8 of 9 new or added lines in 1 file covered. (88.89%)

27 existing lines in 5 files now uncovered.

5685 of 5982 relevant lines covered (95.04%)

0.95 hits per line

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

96.15
/src/Latte/Essential/Nodes/SwitchNode.php
1
<?php declare(strict_types=1);
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
namespace Latte\Essential\Nodes;
9

10
use Latte\CompileException;
11
use Latte\Compiler\Nodes\FragmentNode;
12
use Latte\Compiler\Nodes\Php\Expression\ArrayNode;
13
use Latte\Compiler\Nodes\Php\ExpressionNode;
14
use Latte\Compiler\Nodes\StatementNode;
15
use Latte\Compiler\Nodes\TextNode;
16
use Latte\Compiler\PrintContext;
17
use Latte\Compiler\Tag;
18

19

20
/**
21
 * {switch $expr} {case $val} ... {default} ... {/switch}
22
 * Uses strict comparison (===) without fallthrough.
23
 */
24
class SwitchNode extends StatementNode
25
{
26
        public ?ExpressionNode $expression;
27

28
        /** @var array<array{?ArrayNode, FragmentNode}> */
29
        public array $cases = [];
30

31

32
        /** @return \Generator<int, ?list<string>, array{FragmentNode, Tag}, static> */
33
        public static function create(Tag $tag): \Generator
1✔
34
        {
35
                if ($tag->isNAttribute()) {
1✔
UNCOV
36
                        throw new CompileException('Attribute n:switch is not supported.', $tag->position);
×
37
                }
38

39
                $node = $tag->node = new static;
1✔
40
                $node->expression = $tag->parser->isEnd()
1✔
41
                        ? null
1✔
42
                        : $tag->parser->parseExpression();
1✔
43

44
                [$content, $nextTag] = yield ['case', 'default'];
1✔
45
                foreach ($content->children as $child) {
1✔
46
                        if (!$child instanceof TextNode || !$child->isWhitespace()) {
1✔
UNCOV
47
                                throw new CompileException('No content is allowed between {switch} and {case}', $child->position);
×
48
                        }
49
                }
50

51
                $default = 0;
1✔
52
                while (true) {
1✔
53
                        if ($nextTag->name === 'case') {
1✔
54
                                $nextTag->expectArguments();
1✔
55
                                $case = $nextTag->parser->parseArguments();
1✔
56
                                [$content, $nextTag] = yield ['case', 'default'];
1✔
57
                                $node->cases[] = [$case, $content];
1✔
58

59
                        } elseif ($nextTag->name === 'default') {
1✔
60
                                if ($default++) {
1✔
61
                                        throw new CompileException('Tag {switch} may only contain one {default} clause.', $nextTag->position);
1✔
62
                                }
63
                                [$content, $nextTag] = yield ['case', 'default'];
1✔
64
                                $node->cases[] = [null, $content];
1✔
65

66
                        } else {
67
                                return $node;
1✔
68
                        }
69
                }
70
        }
71

72

73
        public function print(PrintContext $context): string
1✔
74
        {
75
                $res = $context->format(
1✔
76
                        '$ʟ_switch = (%node) %line;',
1✔
77
                        $this->expression,
1✔
78
                        $this->position,
1✔
79
                );
80
                $first = true;
1✔
81
                $default = null;
1✔
82
                foreach ($this->cases as $i => [$case, $content]) {
1✔
83
                        if (!$case) {
1✔
84
                                $default = $content->print($context);
1✔
85
                                continue;
1✔
86
                        } elseif (!$first) {
1✔
87
                                $res .= 'else';
1✔
88
                        }
89

90
                        $first = false;
1✔
91
                        $res .= $context->format(
1✔
92
                                'if (in_array($ʟ_switch, %node, true)) %line { %node } ',
1✔
93
                                $case,
94
                                $this->tagPositions[$i + 1] ?? null,
1✔
95
                                $content,
96
                        );
97
                }
98

99
                if ($default) {
1✔
100
                        $res .= $first ? $default : 'else { ' . $default . ' } ';
1✔
101
                }
102
                return $res;
1✔
103
        }
104

105

106
        public function &getIterator(): \Generator
1✔
107
        {
108
                if ($this->expression) {
1✔
109
                        yield $this->expression;
1✔
110
                }
111
                foreach ($this->cases as [&$case, &$stmt]) {
1✔
112
                        if ($case) {
1✔
113
                                yield $case;
1✔
114
                        }
115
                        yield $stmt;
1✔
116
                }
117
        }
1✔
118
}
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