Skip to content

Commit ac3adf2

Browse files
authored
fix(view): preserve source location in text elements (#1999)
1 parent 4c492ff commit ac3adf2

5 files changed

Lines changed: 38 additions & 1 deletion

File tree

packages/view/src/Elements/ElementFactory.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ public function make(Token $token, Element $parent): ?Element
6161
return null;
6262
}
6363

64-
$element = new TextElement(text: $text);
64+
$element = new TextElement(
65+
text: $text,
66+
token: $token,
67+
);
6568
} elseif ($token->type === TokenType::WHITESPACE) {
6669
$element = new WhitespaceElement($token->content);
6770
} elseif ($token->type !== TokenType::PHP && (! $token->tag || $token->type === TokenType::COMMENT)) {

packages/view/src/Elements/TextElement.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Tempest\View\Elements;
66

77
use Tempest\View\Element;
8+
use Tempest\View\Parser\Token;
89

910
use function Tempest\Support\str;
1011

@@ -14,6 +15,7 @@ final class TextElement implements Element
1415

1516
public function __construct(
1617
private readonly string $text,
18+
public readonly ?Token $token = null,
1719
) {}
1820

1921
public function compile(): string

packages/view/src/Parser/TempestViewCompiler.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Tempest\View\Element;
1313
use Tempest\View\Elements\ElementFactory;
1414
use Tempest\View\Elements\RootElement;
15+
use Tempest\View\Elements\TextElement;
1516
use Tempest\View\Exceptions\ViewNotFound;
1617
use Tempest\View\Exceptions\XmlDeclarationCouldNotBeParsed;
1718
use Tempest\View\ShouldBeRemoved;
@@ -234,6 +235,13 @@ private function sourceLineMarker(int $sourceLine): string
234235
/** @return array{sourcePath: string|null, sourceLine: int}|null */
235236
private function resolveSourceLocation(Element $element): ?array
236237
{
238+
if ($element instanceof TextElement && $element->token !== null) {
239+
return [
240+
'sourcePath' => $element->token->sourcePath,
241+
'sourceLine' => $element->token->line,
242+
];
243+
}
244+
237245
if ($element instanceof WithToken) {
238246
return [
239247
'sourcePath' => $element->token->sourcePath,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<x-standalone-base>
2+
{{ missing_slot_expression_function() }}
3+
</x-standalone-base>

packages/view/tests/StandaloneViewRendererTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,27 @@ public function test_maps_source_path_and_line_for_slot_content_errors(): void
191191
}
192192
}
193193

194+
#[Test]
195+
public function test_maps_source_path_and_line_for_slot_expression_errors(): void
196+
{
197+
$viewConfig = new ViewConfig()->addViewComponents(
198+
__DIR__ . '/Fixtures/x-standalone-base.view.php',
199+
);
200+
201+
$renderer =
202+
TempestViewRenderer::make(
203+
viewConfig: $viewConfig,
204+
);
205+
206+
try {
207+
$renderer->render(view(__DIR__ . '/Fixtures/standalone-error-slot-expression-usage.view.php'));
208+
$this->fail('Expected a view compilation exception.');
209+
} catch (ViewCompilationFailed $exception) {
210+
$this->assertSame(__DIR__ . '/Fixtures/standalone-error-slot-expression-usage.view.php', $exception->sourcePath);
211+
$this->assertSame(2, $exception->sourceLine);
212+
}
213+
}
214+
194215
#[Test]
195216
public function test_maps_source_path_and_line_for_expression_attribute_errors_after_component_rendering(): void
196217
{

0 commit comments

Comments
 (0)