Skip to content

Commit d4958ba

Browse files
committed
Characterize environment expressions in YAML scalars
1 parent 72326c7 commit d4958ba

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

tests/Feature/Environment/EnvironmentProviderTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Symfony\Lsp\Document\DocumentContextResolver;
99
use Symfony\Lsp\Document\DocumentStore;
1010
use Symfony\Lsp\Document\PositionConverter;
11+
use Symfony\Lsp\Document\Range;
1112
use Symfony\Lsp\Feature\Environment\EnvironmentExtractor;
1213
use Symfony\Lsp\Feature\Environment\EnvironmentIndexRegistry;
1314
use Symfony\Lsp\Feature\Environment\EnvironmentProvider;
@@ -36,6 +37,76 @@ public function testIndexesNamesAndReferencesWithoutValues(): void
3637
self::assertSame(['REAL_ENV'], array_map(static fn ($item): string => $item->name, $twigFacts->references));
3738
}
3839

40+
#[DataProvider('yamlScalarContextProvider')]
41+
public function testSupportsEnvironmentExpressionsInYamlScalarContexts(string $text): void
42+
{
43+
$uri = 'file:///workspace/config/services.yaml';
44+
$documents = new DocumentStore();
45+
$documents->open(new Document($uri, 'yaml', 1, $text));
46+
$projects = new ProjectRegistry();
47+
$projects->replace([$project = new Project('/workspace', 'file:///workspace', '^8.0')]);
48+
$converter = new PositionConverter();
49+
$twigComments = new TwigCommentParser();
50+
$phpComments = new PhpCommentParser();
51+
$yamlComments = new YamlCommentParser();
52+
$xmlComments = new XmlCommentParser();
53+
$extractor = new EnvironmentExtractor($converter, new UriToPathConverter(), $twigComments, $phpComments, $yamlComments, $xmlComments);
54+
$indexes = new EnvironmentIndexRegistry();
55+
$indexes->forProject($project)->replaceSources(
56+
$extractor->extract('file:///workspace/.env', 'dotenv', "PARTIAL_ENV=value\n"),
57+
$extractor->extract($uri, 'yaml', $text),
58+
);
59+
$provider = new EnvironmentProvider(new DocumentContextResolver($documents, $projects), $converter, new LspProtocolMapper(), $indexes, $extractor, $twigComments, $phpComments, $yamlComments, $xmlComments);
60+
61+
$facts = $extractor->extract($uri, 'yaml', $text);
62+
self::assertSame(['COMPLETE_ENV'], array_map(static fn ($reference): string => $reference->name, $facts->references));
63+
self::assertSame($this->protocolRange($converter, $text, (int) strpos($text, 'COMPLETE_ENV'), \strlen('COMPLETE_ENV')), $this->protocolRangeFromObject($facts->references[0]->range));
64+
65+
$completionStart = (int) strpos($text, 'PARTIAL_EN');
66+
$completionOffset = $completionStart + \strlen('PARTIAL_EN');
67+
$completion = $provider->complete($this->positionParams($converter, $uri, $text, $completionOffset)) ?? [];
68+
self::assertSame(['PARTIAL_ENV'], array_column($completion, 'label'));
69+
/** @var array{range: array{start: array{line: int, character: int}, end: array{line: int, character: int}}} $textEdit */
70+
$textEdit = $completion[0]['textEdit'];
71+
self::assertSame($this->protocolRange($converter, $text, $completionStart, \strlen('PARTIAL_EN')), $textEdit['range']);
72+
73+
$malformed = '%env(MALFORMED_ENV%';
74+
$malformedOffset = (int) strpos($text, $malformed);
75+
$diagnostics = $provider->diagnostics(['textDocument' => ['uri' => $uri]]) ?? [];
76+
self::assertSame(['env.malformed_chain'], array_column($diagnostics, 'code'));
77+
self::assertSame($this->protocolRange($converter, $text, $malformedOffset, \strlen($malformed)), $diagnostics[0]['range'] ?? null);
78+
}
79+
80+
/** @return iterable<string, array{string}> */
81+
public static function yamlScalarContextProvider(): iterable
82+
{
83+
yield 'double quoted with escapes' => [<<<'YAML'
84+
complete: "escaped\\n%env(COMPLETE_ENV)%"
85+
completion: "escaped\\t%env(PARTIAL_EN"
86+
malformed: "escaped\\u0020%env(MALFORMED_ENV%"
87+
YAML];
88+
yield 'block scalar' => [<<<'YAML'
89+
complete: |-
90+
%env(COMPLETE_ENV)%
91+
completion: |-
92+
%env(PARTIAL_EN
93+
malformed: |-
94+
%env(MALFORMED_ENV%
95+
YAML];
96+
yield 'block sequence item' => [<<<'YAML'
97+
values:
98+
- '%env(COMPLETE_ENV)%'
99+
- '%env(PARTIAL_EN'
100+
- '%env(MALFORMED_ENV%'
101+
YAML];
102+
yield 'environment section' => [<<<'YAML'
103+
when@test:
104+
complete: '%env(COMPLETE_ENV)%'
105+
completion: '%env(PARTIAL_EN'
106+
malformed: '%env(MALFORMED_ENV%'
107+
YAML];
108+
}
109+
39110
public function testCompletesHoversNavigatesAndDiagnosesProcessors(): void
40111
{
41112
$uri = 'file:///workspace/config/services.yaml';
@@ -200,6 +271,15 @@ private function positionParams(PositionConverter $converter, string $uri, strin
200271
return ['textDocument' => ['uri' => $uri], 'position' => ['line' => $position->line, 'character' => $position->character]];
201272
}
202273
274+
/** @return array{start: array{line: int, character: int}, end: array{line: int, character: int}} */
275+
private function protocolRangeFromObject(Range $range): array
276+
{
277+
return [
278+
'start' => ['line' => $range->start->line, 'character' => $range->start->character],
279+
'end' => ['line' => $range->end->line, 'character' => $range->end->character],
280+
];
281+
}
282+
203283
/** @return array{start: array{line: int, character: int}, end: array{line: int, character: int}} */
204284
private function protocolRange(PositionConverter $converter, string $text, int $offset, int $length): array
205285
{

0 commit comments

Comments
 (0)