Skip to content

Commit b5149e9

Browse files
committed
bug #610 Add test case for multiline string (jon-ht)
This PR was squashed before being merged into the 1.0-dev branch. Discussion ---------- Add test case for multiline string Fix #608 ``` In YamlSourceManipulator.php line 793: Cannot find the original value "Symfony 5 project Some comments with markdown like [/api/doc/users](/api/doc/users) or `/api/doc/{area}` " ``` Commits ------- 661acb0 remove unnecessary `\n` adding/removing ee7e823 Add test case for multiline string
2 parents 208b4b9 + 661acb0 commit b5149e9

7 files changed

+144
-7
lines changed

src/Util/YamlSourceManipulator.php

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,14 @@ private function changeValueInYaml($value)
459459

460460
$endValuePosition = $this->findEndPositionOfValue($originalVal);
461461

462-
$newYamlValue = $this->convertToYaml($value);
463-
if (!\is_array($originalVal) && \is_array($value)) {
462+
$isMultilineValue = null !== $this->findPositionOfMultilineCharInLine($this->currentPosition);
463+
464+
// In case of multiline, $value is converted as plain string like "Foo\nBar"
465+
// We need to keep it "as is"
466+
$newYamlValue = $isMultilineValue ? rtrim($value, "\n") : $this->convertToYaml($value);
467+
if ((!\is_array($originalVal) && \is_array($value)) ||
468+
($this->isMultilineString($originalVal) && $this->isMultilineString($value))
469+
) {
464470
// we're converting from a scalar to a (multiline) array
465471
// this means we need to break onto the next line
466472

@@ -481,7 +487,13 @@ private function changeValueInYaml($value)
481487
++$newPosition;
482488
}
483489

490+
if ($isMultilineValue) {
491+
// strlen(" |")
492+
$newPosition -= 2;
493+
}
494+
484495
$newContents = substr($this->contents, 0, $this->currentPosition)
496+
.($isMultilineValue ? ' |' : '')
485497
.$newYamlValue
486498
/*
487499
* If the next line is a comment, this means we probably had
@@ -794,16 +806,26 @@ private function findEndPositionOfValue($value, $offset = null)
794806
}
795807

796808
if (is_scalar($value) || null === $value) {
809+
$offset = null === $offset ? $this->currentPosition : $offset;
810+
797811
if (\is_bool($value)) {
798812
// (?i) & (?-i) opens/closes case insensitive match
799813
$pattern = sprintf('(?i)%s(?-i)', $value ? 'true' : 'false');
800814
} elseif (null === $value) {
801815
$pattern = '(~|NULL|null|\n)';
802816
} else {
803-
$pattern = sprintf('\'?"?%s\'?"?', preg_quote($value, '#'));
804-
}
817+
// Multiline value ends with \n.
818+
// If we remove this character, the next property will ne merged with this value
819+
$quotedValue = preg_quote(rtrim($value, "\n"), '#');
820+
$patternValue = $quotedValue;
821+
822+
// Iterates until we find a new line char or we reach end of file
823+
if (null !== $this->findPositionOfMultilineCharInLine($offset)) {
824+
$patternValue = str_replace(["\r\n", "\n"], '\r?\n\s*', $quotedValue);
825+
}
805826

806-
$offset = null === $offset ? $this->currentPosition : $offset;
827+
$pattern = sprintf('\'?"?%s\'?"?', $patternValue);
828+
}
807829

808830
// a value like "foo:" can simply end a file
809831
// this means the value is null
@@ -1187,7 +1209,31 @@ private function indentMultilineYamlArray(string $yaml): string
11871209
// also need to be indented artificially by the same amount
11881210
$yaml = str_replace("\n", "\n".$this->getCurrentIndentation(), $yaml);
11891211

1212+
if ($this->isMultilineString($yaml)) {
1213+
// Remove extra indentation in case of blank line in multiline string
1214+
$yaml = str_replace("\n".$this->getCurrentIndentation()."\n", "\n\n", $yaml);
1215+
}
1216+
11901217
// now indent this level
11911218
return $this->getCurrentIndentation().$yaml;
11921219
}
1220+
1221+
private function findPositionOfMultilineCharInLine(int $position): ?int
1222+
{
1223+
$cursor = $position;
1224+
while (!$this->isCharLineBreak($currentChar = substr($this->contents, $cursor + 1, 1)) && !$this->isEOF($cursor)) {
1225+
if ('|' === $currentChar) {
1226+
return $cursor;
1227+
}
1228+
1229+
++$cursor;
1230+
}
1231+
1232+
return null;
1233+
}
1234+
1235+
private function isMultilineString($value): bool
1236+
{
1237+
return \is_string($value) && false !== strpos($value, "\n");
1238+
}
11931239
}

tests/Util/YamlSourceManipulatorTest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,17 @@ private function getYamlDataTests()
5858
foreach ($finder as $file) {
5959
list($source, $changeCode, $expected) = explode('===', $file->getContents());
6060

61+
// Multiline string ends with an \n
62+
$source = rtrim($source, "\n");
63+
$expected = ltrim($expected, "\n");
64+
6165
$data = Yaml::parse($source);
6266
eval($changeCode);
6367

6468
yield $file->getFilename() => [
65-
'source' => rtrim($source, "\n"),
69+
'source' => $source,
6670
'newData' => $data,
67-
'expectedSource' => ltrim($expected, "\n"),
71+
'expectedSource' => $expected,
6872
];
6973
}
7074

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
nelmio_api_doc:
2+
documentation:
3+
info:
4+
description: |
5+
Multiline string
6+
Second line
7+
===
8+
$data['nelmio_api_doc']['documentation']['info']['description'] = "Multiline string\nSecond line\nThird line";
9+
===
10+
nelmio_api_doc:
11+
documentation:
12+
info:
13+
description: |
14+
Multiline string
15+
Second line
16+
Third line
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
nelmio_api_doc:
2+
documentation:
3+
info:
4+
description: |
5+
Multiline string
6+
Second line
7+
foo: bar
8+
===
9+
$data['nelmio_api_doc']['documentation']['info']['description'] = "Multiline string\nSecond line\nThird line\n";
10+
===
11+
nelmio_api_doc:
12+
documentation:
13+
info:
14+
description: |
15+
Multiline string
16+
Second line
17+
Third line
18+
foo: bar
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
nelmio_api_doc:
2+
documentation:
3+
info:
4+
description: |
5+
Multiline string
6+
Second line
7+
Third line
8+
foo: bar
9+
===
10+
$data['nelmio_api_doc']['documentation']['info']['description'] = "Multiline string\nSecond line\n";
11+
===
12+
nelmio_api_doc:
13+
documentation:
14+
info:
15+
description: |
16+
Multiline string
17+
Second line
18+
foo: bar
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
nelmio_api_doc:
2+
documentation:
3+
info:
4+
description: |
5+
Multiline string
6+
7+
Second line
8+
foo: bar
9+
===
10+
$data['nelmio_api_doc']['documentation']['info']['description'] = "Multiline string\n\nSecond line\nThird line\n";
11+
===
12+
nelmio_api_doc:
13+
documentation:
14+
info:
15+
description: |
16+
Multiline string
17+
18+
Second line
19+
Third line
20+
foo: bar
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
nelmio_api_doc:
2+
documentation:
3+
info:
4+
description: |
5+
Multiline string
6+
Second line
7+
===
8+
9+
===
10+
nelmio_api_doc:
11+
documentation:
12+
info:
13+
description: |
14+
Multiline string
15+
Second line

0 commit comments

Comments
 (0)