Skip to content

Commit c5a7e7f

Browse files
Merge branch '3.0' into 3.1
* 3.0: (25 commits) Fix merge [HttpFoundation] Use UPSERT for sessions stored in PgSql >= 9.5 [Console] fixed PHPDoc [travis] HHVM 3.12 LTS Fix feature detection for IE [Form] Fixed collapsed choice attributes [Console] added explanation of messages usage in a progress bar force enabling the external XML entity loaders [Yaml] properly count skipped comment lines [WebProfilerBundle] Fix invalid CSS style Added progressive jpeg to mime types guesser [Yaml] Fix wrong line number when comments are inserted in the middle of a block. Fixed singular of committee Do not inject web debug toolbar on attachments bumped Symfony version to 3.0.8 updated VERSION for 3.0.7 updated CHANGELOG for 3.0.7 bumped Symfony version to 2.8.8 updated VERSION for 2.8.7 updated CHANGELOG for 2.8.7 ... Conflicts: src/Symfony/Component/HttpKernel/Kernel.php src/Symfony/Component/PropertyAccess/StringUtil.php src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php src/Symfony/Component/Yaml/Parser.php src/Symfony/Component/Yaml/Tests/ParserTest.php
2 parents 56832b4 + 18bba0c commit c5a7e7f

File tree

2 files changed

+141
-19
lines changed

2 files changed

+141
-19
lines changed

Parser.php

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ class Parser
2929
private $currentLineNb = -1;
3030
private $currentLine = '';
3131
private $refs = array();
32+
private $skippedLineNumbers = array();
33+
private $locallySkippedLineNumbers = array();
3234

3335
/**
3436
* Constructor.
3537
*
3638
* @param int $offset The offset of YAML document (used for line numbers in error messages)
3739
* @param int|null $totalNumberOfLines The overall number of lines being parsed
40+
* @param int[] $skippedLineNumbers Number of comment lines that have been skipped by the parser
3841
*/
39-
public function __construct($offset = 0, $totalNumberOfLines = null)
42+
public function __construct($offset = 0, $totalNumberOfLines = null, array $skippedLineNumbers = array())
4043
{
4144
$this->offset = $offset;
4245
$this->totalNumberOfLines = $totalNumberOfLines;
46+
$this->skippedLineNumbers = $skippedLineNumbers;
4347
}
4448

4549
/**
@@ -124,25 +128,18 @@ public function parse($value, $flags = 0)
124128

125129
// array
126130
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
127-
$c = $this->getRealCurrentLineNb() + 1;
128-
$parser = new self($c, $this->totalNumberOfLines);
129-
$parser->refs = &$this->refs;
130-
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $flags);
131+
$data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $flags);
131132
} else {
132133
if (isset($values['leadspaces'])
133134
&& preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches)
134135
) {
135136
// this is a compact notation element, add to next block and parse
136-
$c = $this->getRealCurrentLineNb();
137-
$parser = new self($c, $this->totalNumberOfLines);
138-
$parser->refs = &$this->refs;
139-
140137
$block = $values['value'];
141138
if ($this->isNextLineIndented()) {
142139
$block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1);
143140
}
144141

145-
$data[] = $parser->parse($block, $flags);
142+
$data[] = $this->parseBlock($this->getRealCurrentLineNb(), $block, $flags);
146143
} else {
147144
$data[] = $this->parseValue($values['value'], $flags, $context);
148145
}
@@ -198,10 +195,7 @@ public function parse($value, $flags = 0)
198195
} else {
199196
$value = $this->getNextEmbedBlock();
200197
}
201-
$c = $this->getRealCurrentLineNb() + 1;
202-
$parser = new self($c, $this->totalNumberOfLines);
203-
$parser->refs = &$this->refs;
204-
$parsed = $parser->parse($value, $flags);
198+
$parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags);
205199

206200
if (!is_array($parsed)) {
207201
throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
@@ -249,10 +243,7 @@ public function parse($value, $flags = 0)
249243
$data[$key] = null;
250244
}
251245
} else {
252-
$c = $this->getRealCurrentLineNb() + 1;
253-
$parser = new self($c, $this->totalNumberOfLines);
254-
$parser->refs = &$this->refs;
255-
$value = $parser->parse($this->getNextEmbedBlock(), $flags);
246+
$value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags);
256247
// Spec: Keys MUST be unique; first one wins.
257248
// But overwriting is allowed when a merge node is used in current block.
258249
if ($allowOverwrite || !isset($data[$key])) {
@@ -346,14 +337,42 @@ public function parse($value, $flags = 0)
346337
return empty($data) ? null : $data;
347338
}
348339

340+
private function parseBlock($offset, $yaml, $flags)
341+
{
342+
$skippedLineNumbers = $this->skippedLineNumbers;
343+
344+
foreach ($this->locallySkippedLineNumbers as $lineNumber) {
345+
if ($lineNumber < $offset) {
346+
continue;
347+
}
348+
349+
$skippedLineNumbers[] = $lineNumber;
350+
}
351+
352+
$parser = new self($offset, $this->totalNumberOfLines, $skippedLineNumbers);
353+
$parser->refs = &$this->refs;
354+
355+
return $parser->parse($yaml, $flags);
356+
}
357+
349358
/**
350359
* Returns the current line number (takes the offset into account).
351360
*
352361
* @return int The current line number
353362
*/
354363
private function getRealCurrentLineNb()
355364
{
356-
return $this->currentLineNb + $this->offset;
365+
$realCurrentLineNumber = $this->currentLineNb + $this->offset;
366+
367+
foreach ($this->skippedLineNumbers as $skippedLineNumber) {
368+
if ($skippedLineNumber > $realCurrentLineNumber) {
369+
break;
370+
}
371+
372+
++$realCurrentLineNumber;
373+
}
374+
375+
return $realCurrentLineNumber;
357376
}
358377

359378
/**
@@ -456,6 +475,14 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false)
456475

457476
// we ignore "comment" lines only when we are not inside a scalar block
458477
if (empty($blockScalarIndentations) && $this->isCurrentLineComment()) {
478+
// remember ignored comment lines (they are used later in nested
479+
// parser calls to determine real line numbers)
480+
//
481+
// CAUTION: beware to not populate the global property here as it
482+
// will otherwise influence the getRealCurrentLineNb() call here
483+
// for consecutive comment lines and subsequent embedded blocks
484+
$this->locallySkippedLineNumbers[] = $this->getRealCurrentLineNb();
485+
459486
continue;
460487
}
461488

@@ -491,10 +518,18 @@ private function moveToNextLine()
491518

492519
/**
493520
* Moves the parser to the previous line.
521+
*
522+
* @return bool
494523
*/
495524
private function moveToPreviousLine()
496525
{
526+
if ($this->currentLineNb < 1) {
527+
return false;
528+
}
529+
497530
$this->currentLine = $this->lines[--$this->currentLineNb];
531+
532+
return true;
498533
}
499534

500535
/**

Tests/ParserTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,25 @@ public function testSequenceInMappingStartedBySingleDashLine()
693693
$this->assertSame($expected, $this->parser->parse($yaml));
694694
}
695695

696+
public function testSequenceFollowedByCommentEmbeddedInMapping()
697+
{
698+
$yaml = <<<EOT
699+
a:
700+
b:
701+
- c
702+
# comment
703+
d: e
704+
EOT;
705+
$expected = array(
706+
'a' => array(
707+
'b' => array('c'),
708+
'd' => 'e',
709+
),
710+
);
711+
712+
$this->assertSame($expected, $this->parser->parse($yaml));
713+
}
714+
696715
/**
697716
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
698717
*/
@@ -1243,6 +1262,74 @@ public function testParseDateAsMappingValue()
12431262

12441263
$this->assertEquals(array('date' => $expectedDate), $this->parser->parse($yaml, Yaml::PARSE_DATETIME));
12451264
}
1265+
1266+
/**
1267+
* @param $lineNumber
1268+
* @param $yaml
1269+
* @dataProvider parserThrowsExceptionWithCorrectLineNumberProvider
1270+
*/
1271+
public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yaml)
1272+
{
1273+
$this->setExpectedException(
1274+
'\Symfony\Component\Yaml\Exception\ParseException',
1275+
sprintf('Unexpected characters near "," at line %d (near "bar: "123",").', $lineNumber)
1276+
);
1277+
1278+
$this->parser->parse($yaml);
1279+
}
1280+
1281+
public function parserThrowsExceptionWithCorrectLineNumberProvider()
1282+
{
1283+
return array(
1284+
array(
1285+
4,
1286+
<<<YAML
1287+
foo:
1288+
-
1289+
# bar
1290+
bar: "123",
1291+
YAML
1292+
),
1293+
array(
1294+
5,
1295+
<<<YAML
1296+
foo:
1297+
-
1298+
# bar
1299+
# bar
1300+
bar: "123",
1301+
YAML
1302+
),
1303+
array(
1304+
8,
1305+
<<<YAML
1306+
foo:
1307+
-
1308+
# foobar
1309+
baz: 123
1310+
bar:
1311+
-
1312+
# bar
1313+
bar: "123",
1314+
YAML
1315+
),
1316+
array(
1317+
10,
1318+
<<<YAML
1319+
foo:
1320+
-
1321+
# foobar
1322+
# foobar
1323+
baz: 123
1324+
bar:
1325+
-
1326+
# bar
1327+
# bar
1328+
bar: "123",
1329+
YAML
1330+
),
1331+
);
1332+
}
12461333
}
12471334

12481335
class B

0 commit comments

Comments
 (0)