Skip to content

Commit 4c2e68f

Browse files
committed
Merge branch '3.0' into 3.1
* 3.0: [Yaml] fix exception contexts People - person singularization [Yaml] properly handle unindented collections [Serializer] Add test for ignored attributes during denormalization chomp newlines only at the end of YAML documents Fixed server status command when port has been omitted Update UPGRADE FROM 2.x to 3.0 fix removed commands wording in upgrade file Catch \Throwable Catch \Throwable [DependencyInjection] Avoid generating call_user_func in more cases [Validator] Support for DateTimeImmutable [FrameworkBundle] update upgrade instructions Use levenshtein level for better Bundle matching [WebProfilerBundle] Fix CORS ajax security issues remove methods that were needed for PHP 5.3 [DX][DI] Make Autowiring exceptions more future friendly
2 parents 407e31a + 06766b4 commit 4c2e68f

File tree

2 files changed

+56
-13
lines changed

2 files changed

+56
-13
lines changed

Parser.php

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Parser
2424
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
2525

2626
private $offset = 0;
27+
private $totalNumberOfLines;
2728
private $lines = array();
2829
private $currentLineNb = -1;
2930
private $currentLine = '';
@@ -32,11 +33,13 @@ class Parser
3233
/**
3334
* Constructor.
3435
*
35-
* @param int $offset The offset of YAML document (used for line numbers in error messages)
36+
* @param int $offset The offset of YAML document (used for line numbers in error messages)
37+
* @param int|null $totalNumberOfLines The overall number of lines being parsed
3638
*/
37-
public function __construct($offset = 0)
39+
public function __construct($offset = 0, $totalNumberOfLines = null)
3840
{
3941
$this->offset = $offset;
42+
$this->totalNumberOfLines = $totalNumberOfLines;
4043
}
4144

4245
/**
@@ -85,6 +88,10 @@ public function parse($value, $flags = 0)
8588
$value = $this->cleanup($value);
8689
$this->lines = explode("\n", $value);
8790

91+
if (null === $this->totalNumberOfLines) {
92+
$this->totalNumberOfLines = count($this->lines);
93+
}
94+
8895
if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
8996
$mbEncoding = mb_internal_encoding();
9097
mb_internal_encoding('UTF-8');
@@ -106,7 +113,7 @@ public function parse($value, $flags = 0)
106113
$isRef = $mergeNode = false;
107114
if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values)) {
108115
if ($context && 'mapping' == $context) {
109-
throw new ParseException('You cannot define a sequence item when in a mapping');
116+
throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine);
110117
}
111118
$context = 'sequence';
112119

@@ -118,7 +125,7 @@ public function parse($value, $flags = 0)
118125
// array
119126
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
120127
$c = $this->getRealCurrentLineNb() + 1;
121-
$parser = new self($c);
128+
$parser = new self($c, $this->totalNumberOfLines);
122129
$parser->refs = &$this->refs;
123130
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $flags);
124131
} else {
@@ -127,7 +134,7 @@ public function parse($value, $flags = 0)
127134
) {
128135
// this is a compact notation element, add to next block and parse
129136
$c = $this->getRealCurrentLineNb();
130-
$parser = new self($c);
137+
$parser = new self($c, $this->totalNumberOfLines);
131138
$parser->refs = &$this->refs;
132139

133140
$block = $values['value'];
@@ -145,7 +152,7 @@ public function parse($value, $flags = 0)
145152
}
146153
} elseif (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) {
147154
if ($context && 'sequence' == $context) {
148-
throw new ParseException('You cannot define a mapping item when in a sequence');
155+
throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine);
149156
}
150157
$context = 'mapping';
151158

@@ -192,7 +199,7 @@ public function parse($value, $flags = 0)
192199
$value = $this->getNextEmbedBlock();
193200
}
194201
$c = $this->getRealCurrentLineNb() + 1;
195-
$parser = new self($c);
202+
$parser = new self($c, $this->totalNumberOfLines);
196203
$parser->refs = &$this->refs;
197204
$parsed = $parser->parse($value, $flags);
198205

@@ -243,7 +250,7 @@ public function parse($value, $flags = 0)
243250
}
244251
} else {
245252
$c = $this->getRealCurrentLineNb() + 1;
246-
$parser = new self($c);
253+
$parser = new self($c, $this->totalNumberOfLines);
247254
$parser->refs = &$this->refs;
248255
$value = $parser->parse($this->getNextEmbedBlock(), $flags);
249256
// Spec: Keys MUST be unique; first one wins.
@@ -266,7 +273,7 @@ public function parse($value, $flags = 0)
266273
} else {
267274
// multiple documents are not supported
268275
if ('---' === $this->currentLine) {
269-
throw new ParseException('Multiple documents are not supported.');
276+
throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine);
270277
}
271278

272279
// 1-liner optionally followed by newline(s)
@@ -511,7 +518,7 @@ private function parseValue($value, $flags, $context)
511518
}
512519

513520
if (!array_key_exists($value, $this->refs)) {
514-
throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
521+
throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine);
515522
}
516523

517524
return $this->refs[$value];
@@ -609,6 +616,8 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0)
609616
if ($notEOF) {
610617
$blockLines[] = '';
611618
$this->moveToPreviousLine();
619+
} elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) {
620+
$blockLines[] = '';
612621
}
613622

614623
// folded style
@@ -715,6 +724,11 @@ private function isCurrentLineComment()
715724
return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
716725
}
717726

727+
private function isCurrentLineLastLineInDocument()
728+
{
729+
return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1);
730+
}
731+
718732
/**
719733
* Cleanups a YAML string to be parsed.
720734
*
@@ -792,7 +806,7 @@ private function isNextLineUnIndentedCollection()
792806
*/
793807
private function isStringUnIndentedCollectionItem()
794808
{
795-
return 0 === strpos($this->currentLine, '- ');
809+
return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- ');
796810
}
797811

798812
/**

Tests/ParserTest.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ public function testShortcutKeyUnindentedCollectionException()
633633

634634
/**
635635
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
636-
* @expectedExceptionMessage Multiple documents are not supported.
636+
* @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/
637637
*/
638638
public function testMultipleDocumentsNotSupportedException()
639639
{
@@ -665,6 +665,34 @@ public function testSequenceInAMapping()
665665
);
666666
}
667667

668+
public function testSequenceInMappingStartedBySingleDashLine()
669+
{
670+
$yaml = <<<EOT
671+
a:
672+
-
673+
b:
674+
-
675+
bar: baz
676+
- foo
677+
d: e
678+
EOT;
679+
$expected = array(
680+
'a' => array(
681+
array(
682+
'b' => array(
683+
array(
684+
'bar' => 'baz',
685+
),
686+
),
687+
),
688+
'foo',
689+
),
690+
'd' => 'e',
691+
);
692+
693+
$this->assertSame($expected, $this->parser->parse($yaml));
694+
}
695+
668696
/**
669697
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
670698
*/
@@ -1014,6 +1042,7 @@ public function getCommentLikeStringInScalarBlockData()
10141042
foo
10151043
# bar
10161044
baz
1045+
10171046
EOT
10181047
,
10191048
),
@@ -1042,7 +1071,7 @@ public function getCommentLikeStringInScalarBlockData()
10421071
$expected = array(
10431072
'foo' => array(
10441073
'bar' => array(
1045-
'scalar-block' => 'line1 line2>',
1074+
'scalar-block' => "line1 line2>\n",
10461075
),
10471076
'baz' => array(
10481077
'foobar' => null,

0 commit comments

Comments
 (0)