Skip to content

Commit a269823

Browse files
authored
Implement the unescaping of doc string delimiters (#393)
Closes #326
1 parent 05a7459 commit a269823

File tree

4 files changed

+27
-129
lines changed

4 files changed

+27
-129
lines changed

src/GherkinCompatibilityMode.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ public function shouldSupportNewlineEscapeSequenceInTableCell(): bool
5454
};
5555
}
5656

57+
/**
58+
* @internal
59+
*/
60+
public function shouldUnespaceDocStringDelimiters(): bool
61+
{
62+
return match ($this) {
63+
self::LEGACY => false,
64+
default => true,
65+
};
66+
}
67+
5768
/**
5869
* @internal
5970
*/

src/Lexer.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* @phpstan-type TStepToken array{type: 'Step', value: string, line: int, deferred: bool, keyword_type: string, text: string}
3838
* @phpstan-type TTagToken array{type: 'Tag', value: null, line: int, deferred: bool, tags: list<string>}
3939
* @phpstan-type TTableRowToken array{type: 'TableRow', value: null, line: int, deferred: bool, columns: list<string>}
40+
* @phpstan-type TDocStringSeparator '"""'|'```'
4041
*/
4142
class Lexer
4243
{
@@ -80,6 +81,9 @@ class Lexer
8081
private bool $allowFeature = true;
8182
private bool $allowMultilineArguments = false;
8283
private bool $allowSteps = false;
84+
/**
85+
* @phpstan-var TDocStringSeparator|null
86+
*/
8387
private ?string $pyStringDelimiter = null;
8488

8589
public function __construct(
@@ -719,7 +723,18 @@ protected function scanPyStringContent()
719723

720724
$token = $this->scanText();
721725
// swallow trailing spaces
722-
$token['value'] = (string) preg_replace('/^\s{0,' . $this->pyStringSwallow . '}/u', '', $token['value'] ?? '');
726+
$value = (string) preg_replace('/^\s{0,' . $this->pyStringSwallow . '}/u', '', $token['value'] ?? '');
727+
728+
if ($this->compatibilityMode->shouldUnespaceDocStringDelimiters()) {
729+
\assert($this->pyStringDelimiter !== null);
730+
$escapedDelimiter = match ($this->pyStringDelimiter) {
731+
'"""' => '\\"\\"\\"',
732+
'```' => '\\`\\`\\`',
733+
};
734+
$value = str_replace($escapedDelimiter, $this->pyStringDelimiter, $value);
735+
}
736+
737+
$token['value'] = $value;
723738

724739
return $token;
725740
}

tests/Cucumber/CompatibilityTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class CompatibilityTest extends TestCase
6262
],
6363
'gherkin-32' => [
6464
'complex_background.feature' => 'Rule keyword not supported',
65-
'docstrings.feature' => 'Escaped delimiters in docstrings are not unescaped',
6665
'rule.feature' => 'Rule keyword not supported',
6766
'rule_with_tag.feature' => 'Rule keyword not supported',
6867
'tags.feature' => 'Rule keyword not supported',

tests/Cucumber/expected_variants/gherkin-32/docstrings.feature.expected.yaml

Lines changed: 0 additions & 127 deletions
This file was deleted.

0 commit comments

Comments
 (0)