From 675e51d27629c8d7d61da86d42ff74efd34866be Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 24 Jan 2023 15:02:24 +0100 Subject: [PATCH 1/6] Update license years (last time) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 00837045..0138f8f0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2023 Fabien Potencier +Copyright (c) 2004-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 7432eef094c3864a3700f3c9c14c9a76e6cfa257 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Sun, 5 Feb 2023 10:12:16 +0100 Subject: [PATCH 2/6] [Tests] Migrate data providers to static ones --- Tests/ParserTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/ParserTest.php b/Tests/ParserTest.php index 0941075b..b09ff090 100644 --- a/Tests/ParserTest.php +++ b/Tests/ParserTest.php @@ -124,14 +124,14 @@ public function testSpecifications($expected, $yaml, $comment) $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment); } - public function getDataFormSpecifications() + public static function getDataFormSpecifications() { - return $this->loadTestsFromFixtureFiles('index.yml'); + return self::loadTestsFromFixtureFiles('index.yml'); } - public function getNonStringMappingKeysData() + public static function getNonStringMappingKeysData() { - return $this->loadTestsFromFixtureFiles('nonStringKeys.yml'); + return self::loadTestsFromFixtureFiles('nonStringKeys.yml'); } /** @@ -2390,7 +2390,7 @@ public function testParsingIniThrowsException() $this->parser->parse($ini); } - private function loadTestsFromFixtureFiles($testsFile) + private static function loadTestsFromFixtureFiles($testsFile) { $parser = new Parser(); From c8336db26f05e4382e20179eee628cd7f03399bc Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Wed, 14 Dec 2022 15:42:16 +0100 Subject: [PATCH 3/6] Migrate to `static` data providers using `rector/rector` --- Tests/Command/LintCommandTest.php | 2 +- Tests/DumperTest.php | 4 +-- Tests/InlineTest.php | 42 +++++++++++++++---------------- Tests/ParserTest.php | 32 +++++++++++------------ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/Tests/Command/LintCommandTest.php b/Tests/Command/LintCommandTest.php index 90e20455..4d3024cc 100644 --- a/Tests/Command/LintCommandTest.php +++ b/Tests/Command/LintCommandTest.php @@ -179,7 +179,7 @@ public function testComplete(array $input, array $expectedSuggestions) $this->assertSame($expectedSuggestions, $tester->complete($input)); } - public function provideCompletionSuggestions() + public static function provideCompletionSuggestions() { yield 'option' => [['--format', ''], ['txt', 'json', 'github']]; } diff --git a/Tests/DumperTest.php b/Tests/DumperTest.php index 16551f18..721b04ca 100644 --- a/Tests/DumperTest.php +++ b/Tests/DumperTest.php @@ -225,7 +225,7 @@ public function testEscapedEscapeSequencesInQuotedScalar($input, $expected) $this->assertSameData($input, $this->parser->parse($expected)); } - public function getEscapeSequences() + public static function getEscapeSequences() { return [ 'empty string' => ['', "''"], @@ -275,7 +275,7 @@ public function testDumpObjectAsMap($object, $expected) $this->assertSameData($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); } - public function objectAsMapProvider() + public static function objectAsMapProvider() { $tests = []; diff --git a/Tests/InlineTest.php b/Tests/InlineTest.php index f71509d2..8cd2582f 100644 --- a/Tests/InlineTest.php +++ b/Tests/InlineTest.php @@ -56,7 +56,7 @@ public function testParsePhpConstants($yaml, $value) $this->assertSame($value, $actual); } - public function getTestsForParsePhpConstants() + public static function getTestsForParsePhpConstants() { return [ ['!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT], @@ -195,7 +195,7 @@ public function testParseReferences($yaml, $expected) $this->assertSame($expected, Inline::parse($yaml, 0, $references)); } - public function getDataForParseReferences() + public static function getDataForParseReferences() { return [ 'scalar' => ['*var', 'var-value'], @@ -245,7 +245,7 @@ public function testParseUnquotedScalarStartingWithReservedIndicator($indicator) Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } - public function getReservedIndicators() + public static function getReservedIndicators() { return [['@'], ['`']]; } @@ -261,7 +261,7 @@ public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } - public function getScalarIndicators() + public static function getScalarIndicators() { return [['|'], ['>'], ['%']]; } @@ -274,7 +274,7 @@ public function testIsHash($array, $expected) $this->assertSame($expected, Inline::isHash($array)); } - public function getDataForIsHash() + public static function getDataForIsHash() { return [ [[], false], @@ -284,7 +284,7 @@ public function getDataForIsHash() ]; } - public function getTestsForParse() + public static function getTestsForParse() { return [ ['', ''], @@ -370,7 +370,7 @@ public function getTestsForParse() ]; } - public function getTestsForParseWithMapObjects() + public static function getTestsForParseWithMapObjects() { return [ ['', ''], @@ -451,7 +451,7 @@ public function getTestsForParseWithMapObjects() ]; } - public function getTestsForDump() + public static function getTestsForDump() { return [ ['null', null], @@ -549,7 +549,7 @@ public function testParseTimestampAsDateTimeObject(string $yaml, int $year, int $this->assertSame($timezone, $date->format('O')); } - public function getTimestampTests(): array + public static function getTimestampTests(): array { return [ 'canonical' => ['2001-12-15T02:59:43.1Z', 2001, 12, 15, 2, 59, 43, 100000, '+0000'], @@ -591,7 +591,7 @@ public function testDumpUnitEnum() $this->assertSame("!php/const Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR", Inline::dump(FooUnitEnum::BAR)); } - public function getDateTimeDumpTests() + public static function getDateTimeDumpTests() { $tests = []; @@ -612,7 +612,7 @@ public function testParseBinaryData($data) $this->assertSame('Hello world', Inline::parse($data)); } - public function getBinaryData() + public static function getBinaryData() { return [ 'enclosed with double quotes' => ['!!binary "SGVsbG8gd29ybGQ="'], @@ -632,7 +632,7 @@ public function testParseInvalidBinaryData($data, $expectedMessage) Inline::parse($data); } - public function getInvalidBinaryData() + public static function getInvalidBinaryData() { return [ 'length not a multiple of four' => ['!!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'], @@ -674,7 +674,7 @@ public function testParseMissingMappingValueAsNull($yaml, $expected) $this->assertSame($expected, Inline::parse($yaml)); } - public function getTestsForNullValues() + public static function getTestsForNullValues() { return [ 'null before closing curly brace' => ['{foo:}', ['foo' => null]], @@ -697,7 +697,7 @@ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expec $this->assertSame($expected, Inline::parse($yaml)); } - public function getNotPhpCompatibleMappingKeyData() + public static function getNotPhpCompatibleMappingKeyData() { return [ 'boolean-true' => ['{true: "foo"}', ['true' => 'foo']], @@ -776,7 +776,7 @@ public function testParseOctalNumbers($expected, $yaml) self::assertSame($expected, Inline::parse($yaml)); } - public function getTestsForOctalNumbers() + public static function getTestsForOctalNumbers() { return [ 'positive octal number' => [28, '0o34'], @@ -797,7 +797,7 @@ public function testParseOctalNumbersYaml11Notation(int $expected, string $yaml, self::assertSame($expected, Inline::parse($yaml)); } - public function getTestsForOctalNumbersYaml11Notation() + public static function getTestsForOctalNumbersYaml11Notation() { return [ 'positive octal number' => [28, '034', '0o34'], @@ -818,7 +818,7 @@ public function testPhpObjectWithEmptyValue($expected, $value) $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_OBJECT)); } - public function phpObjectTagWithEmptyValueProvider() + public static function phpObjectTagWithEmptyValueProvider() { return [ [false, '!php/object'], @@ -842,7 +842,7 @@ public function testPhpConstTagWithEmptyValue($expected, $value) $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_CONSTANT)); } - public function phpConstTagWithEmptyValueProvider() + public static function phpConstTagWithEmptyValueProvider() { return [ ['', '!php/const'], @@ -894,7 +894,7 @@ public function testUnquotedExclamationMarkThrows(string $value) Inline::parse($value); } - public function unquotedExclamationMarkThrowsProvider() + public static function unquotedExclamationMarkThrowsProvider() { return [ ['!'], @@ -926,7 +926,7 @@ public function testQuotedExclamationMark($expected, string $value) } // This provider should stay consistent with unquotedExclamationMarkThrowsProvider - public function quotedExclamationMarkProvider() + public static function quotedExclamationMarkProvider() { return [ ['!', '"!"'], @@ -956,7 +956,7 @@ public function testParseIdeographicSpace(string $yaml, string $expected) $this->assertSame($expected, Inline::parse($yaml)); } - public function ideographicSpaceProvider(): array + public static function ideographicSpaceProvider(): array { return [ ["\u{3000}", ' '], diff --git a/Tests/ParserTest.php b/Tests/ParserTest.php index b09ff090..98e5e73e 100644 --- a/Tests/ParserTest.php +++ b/Tests/ParserTest.php @@ -144,7 +144,7 @@ public function testTabsAsIndentationInYaml(string $given, string $expectedMessa $this->parser->parse($given); } - public function invalidIndentation(): array + public static function invalidIndentation(): array { return [ [ @@ -189,7 +189,7 @@ public function testValidTokenSeparation(string $given, array $expected) $this->assertSameData($expected, $actual); } - public function validTokenSeparators(): array + public static function validTokenSeparators(): array { return [ [ @@ -222,7 +222,7 @@ public function testEndOfTheDocumentMarker() $this->assertEquals('foo', $this->parser->parse($yaml)); } - public function getBlockChompingTests() + public static function getBlockChompingTests() { $tests = []; @@ -586,7 +586,7 @@ public function testObjectForMap($yaml, $expected) $this->assertSameData($expected, $this->parser->parse($yaml, $flags)); } - public function getObjectForMapTests() + public static function getObjectForMapTests() { $tests = []; @@ -833,7 +833,7 @@ public function testNonStringFollowedByCommentEmbeddedInMapping() $this->assertSame($expected, $this->parser->parse($yaml)); } - public function getParseExceptionNotAffectedMultiLineStringLastResortParsing() + public static function getParseExceptionNotAffectedMultiLineStringLastResortParsing() { $tests = []; @@ -975,7 +975,7 @@ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber Yaml::parse($input); } - public function getParseExceptionOnDuplicateData() + public static function getParseExceptionOnDuplicateData() { $tests = []; @@ -1280,7 +1280,7 @@ public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expec $this->assertSame($expectedParserResult, $this->parser->parse($yaml)); } - public function getCommentLikeStringInScalarBlockData() + public static function getCommentLikeStringInScalarBlockData() { $tests = []; @@ -1465,7 +1465,7 @@ public function testParseBinaryData($data) $this->assertSame(['data' => 'Hello world'], $this->parser->parse($data)); } - public function getBinaryData() + public static function getBinaryData() { return [ 'enclosed with double quotes' => ['data: !!binary "SGVsbG8gd29ybGQ="'], @@ -1497,7 +1497,7 @@ public function testParseInvalidBinaryData($data, $expectedMessage) $this->parser->parse($data); } - public function getInvalidBinaryData() + public static function getInvalidBinaryData() { return [ 'length not a multiple of four' => ['data: !!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'], @@ -1563,7 +1563,7 @@ public function testParserThrowsExceptionWithCorrectLineNumber($lineNumber, $yam $this->parser->parse($yaml); } - public function parserThrowsExceptionWithCorrectLineNumberProvider() + public static function parserThrowsExceptionWithCorrectLineNumberProvider() { return [ [ @@ -1720,7 +1720,7 @@ public function testParseQuotedStringContainingEscapedQuotationCharacters(string $this->assertSame($expected, $this->parser->parse($yaml)); } - public function escapedQuotationCharactersInQuotedStrings() + public static function escapedQuotationCharactersInQuotedStrings() { return [ 'single quoted string' => [ @@ -1778,7 +1778,7 @@ public function testParseMultiLineMappingValue($yaml, $expected, $parseError) $this->assertSame($expected, $this->parser->parse($yaml)); } - public function multiLineDataProvider() + public static function multiLineDataProvider() { $tests = []; @@ -1845,7 +1845,7 @@ public function testInlineNotationSpanningMultipleLines($expected, string $yaml) $this->assertSame($expected, $this->parser->parse($yaml)); } - public function inlineNotationSpanningMultipleLinesProvider(): array + public static function inlineNotationSpanningMultipleLinesProvider(): array { return [ 'mapping' => [ @@ -2234,7 +2234,7 @@ public function testCustomTagSupport($expected, $yaml) $this->assertSameData($expected, $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS)); } - public function taggedValuesProvider() + public static function taggedValuesProvider() { return [ 'scalars' => [ @@ -2658,7 +2658,7 @@ public function testDetectCircularReferences($yaml) $this->parser->parse($yaml, Yaml::PARSE_CUSTOM_TAGS); } - public function circularReferenceProvider() + public static function circularReferenceProvider() { $tests = []; @@ -2698,7 +2698,7 @@ public function testParseIndentedMappings($yaml, $expected) $this->assertSame($expected, $this->parser->parse($yaml)); } - public function indentedMappingData() + public static function indentedMappingData() { $tests = []; From a3fedae8e229562958bb0c87e50b60a30210b5a2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 14 Feb 2023 09:53:37 +0100 Subject: [PATCH 4/6] Fix merge --- Tests/InlineTest.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Tests/InlineTest.php b/Tests/InlineTest.php index bcaa3159..5d8d1405 100644 --- a/Tests/InlineTest.php +++ b/Tests/InlineTest.php @@ -54,7 +54,7 @@ public function testParsePhpConstants($yaml, $value) $this->assertSame($value, $actual); } - public function getTestsForParsePhpConstants() + public static function getTestsForParsePhpConstants() { return [ ['!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT], @@ -225,7 +225,7 @@ public function testParseReferences($yaml, $expected) $this->assertSame($expected, Inline::parse($yaml, 0, $references)); } - public function getDataForParseReferences() + public static function getDataForParseReferences() { return [ 'scalar' => ['*var', 'var-value'], @@ -275,7 +275,7 @@ public function testParseUnquotedScalarStartingWithReservedIndicator($indicator) Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } - public function getReservedIndicators() + public static function getReservedIndicators() { return [['@'], ['`']]; } @@ -291,7 +291,7 @@ public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } - public function getScalarIndicators() + public static function getScalarIndicators() { return [['|'], ['>'], ['%']]; } @@ -304,7 +304,7 @@ public function testIsHash($array, $expected) $this->assertSame($expected, Inline::isHash($array)); } - public function getDataForIsHash() + public static function getDataForIsHash() { return [ [[], false], @@ -314,7 +314,7 @@ public function getDataForIsHash() ]; } - public function getTestsForParse() + public static function getTestsForParse() { return [ ['', ''], @@ -400,7 +400,7 @@ public function getTestsForParse() ]; } - public function getTestsForParseWithMapObjects() + public static function getTestsForParseWithMapObjects() { return [ ['', ''], @@ -481,7 +481,7 @@ public function getTestsForParseWithMapObjects() ]; } - public function getTestsForDump() + public static function getTestsForDump() { return [ ['null', null], @@ -583,7 +583,7 @@ public function testParseTimestampAsDateTimeObject(string $yaml, int $year, int $this->assertSame($timezone, $date->format('O')); } - public function getTimestampTests(): array + public static function getTimestampTests(): array { return [ 'canonical' => ['2001-12-15T02:59:43.1Z', 2001, 12, 15, 2, 59, 43, 100000, '+0000'], @@ -632,7 +632,7 @@ public function testParseBackedEnumValue() $this->assertSame(FooBackedEnum::BAR->value, Inline::parse("!php/enum Symfony\Component\Yaml\Tests\Fixtures\FooBackedEnum::BAR->value", Yaml::PARSE_CONSTANT)); } - public function getDateTimeDumpTests() + public static function getDateTimeDumpTests() { $tests = []; @@ -653,7 +653,7 @@ public function testParseBinaryData($data) $this->assertSame('Hello world', Inline::parse($data)); } - public function getBinaryData() + public static function getBinaryData() { return [ 'enclosed with double quotes' => ['!!binary "SGVsbG8gd29ybGQ="'], @@ -673,7 +673,7 @@ public function testParseInvalidBinaryData($data, $expectedMessage) Inline::parse($data); } - public function getInvalidBinaryData() + public static function getInvalidBinaryData() { return [ 'length not a multiple of four' => ['!!binary "SGVsbG8d29ybGQ="', '/The normalized base64 encoded data \(data without whitespace characters\) length must be a multiple of four \(\d+ bytes given\)/'], @@ -715,7 +715,7 @@ public function testParseMissingMappingValueAsNull($yaml, $expected) $this->assertSame($expected, Inline::parse($yaml)); } - public function getTestsForNullValues() + public static function getTestsForNullValues() { return [ 'null before closing curly brace' => ['{foo:}', ['foo' => null]], @@ -738,7 +738,7 @@ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expec $this->assertSame($expected, Inline::parse($yaml)); } - public function getNotPhpCompatibleMappingKeyData() + public static function getNotPhpCompatibleMappingKeyData() { return [ 'boolean-true' => ['{true: "foo"}', ['true' => 'foo']], @@ -817,7 +817,7 @@ public function testParseOctalNumbers($expected, $yaml) self::assertSame($expected, Inline::parse($yaml)); } - public function getTestsForOctalNumbers() + public static function getTestsForOctalNumbers() { return [ 'positive octal number' => [28, '0o34'], @@ -834,7 +834,7 @@ public function testParseOctalNumbersYaml11Notation(string $expected, string $ya self::assertSame($expected, Inline::parse($yaml)); } - public function getTestsForOctalNumbersYaml11Notation() + public static function getTestsForOctalNumbersYaml11Notation() { return [ 'positive octal number' => ['034', '034'], @@ -856,7 +856,7 @@ public function testPhpObjectWithEmptyValue(string $value) Inline::parse($value, Yaml::PARSE_OBJECT); } - public function phpObjectTagWithEmptyValueProvider() + public static function phpObjectTagWithEmptyValueProvider() { return [ ['!php/object'], @@ -890,7 +890,7 @@ public function testPhpEnumTagWithEmptyValue(string $value) Inline::parse(str_replace('!php/const', '!php/enum', $value), Yaml::PARSE_CONSTANT); } - public function phpConstTagWithEmptyValueProvider() + public static function phpConstTagWithEmptyValueProvider() { return [ ['!php/const'], @@ -926,7 +926,7 @@ public function testUnquotedExclamationMarkThrows(string $value) Inline::parse($value); } - public function unquotedExclamationMarkThrowsProvider() + public static function unquotedExclamationMarkThrowsProvider() { return [ ['!'], @@ -958,7 +958,7 @@ public function testQuotedExclamationMark($expected, string $value) } // This provider should stay consistent with unquotedExclamationMarkThrowsProvider - public function quotedExclamationMarkProvider() + public static function quotedExclamationMarkProvider() { return [ ['!', '"!"'], @@ -988,7 +988,7 @@ public function testParseIdeographicSpace(string $yaml, string $expected) $this->assertSame($expected, Inline::parse($yaml)); } - public function ideographicSpaceProvider(): array + public static function ideographicSpaceProvider(): array { return [ ["\u{3000}", ' '], From 3713e20d93e46e681e51605d213027e48dab3469 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 21 Feb 2023 17:34:40 +0100 Subject: [PATCH 5/6] Fix phpdocs in components --- Inline.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Inline.php b/Inline.php index 8118a43a..04c9690c 100644 --- a/Inline.php +++ b/Inline.php @@ -50,9 +50,9 @@ public static function initialize(int $flags, int $parsedLineNumber = null, stri /** * Converts a YAML string to a PHP value. * - * @param string $value A YAML string - * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior - * @param array $references Mapping of variable names to values + * @param string|null $value A YAML string + * @param int $flags A bit field of Yaml::PARSE_* constants to customize the YAML parser behavior + * @param array $references Mapping of variable names to values * * @return mixed * From 4cd2e3ea301aadd76a4172756296fe552fb45b0b Mon Sep 17 00:00:00 2001 From: Brad Treloar Date: Thu, 20 Apr 2023 12:56:18 +0930 Subject: [PATCH 6/6] [Dumper] Trim leading newlines when checking if value begins with a space --- Dumper.php | 28 +++++++++++++++++++--------- Tests/DumperTest.php | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/Dumper.php b/Dumper.php index 679d533c..99346aa1 100644 --- a/Dumper.php +++ b/Dumper.php @@ -69,9 +69,7 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): } if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : ''; + $blockIndentationIndicator = $this->getBlockIndentationIndicator($value); if (isset($value[-2]) && "\n" === $value[-2] && "\n" === $value[-1]) { $blockChompingIndicator = '+'; @@ -98,9 +96,7 @@ public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): $output .= sprintf('%s%s !%s', $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', $value->getTag()); if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; + $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue()); $output .= sprintf(' |%s', $blockIndentationIndicator); foreach (explode("\n", $value->getValue()) as $row) { @@ -145,9 +141,7 @@ private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, i $output = sprintf('%s!%s', $prefix ? $prefix.' ' : '', $value->getTag()); if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value->getValue()) && false !== strpos($value->getValue(), "\n") && false === strpos($value->getValue(), "\r\n")) { - // If the first line starts with a space character, the spec requires a blockIndicationIndicator - // http://www.yaml.org/spec/1.2/spec.html#id2793979 - $blockIndentationIndicator = (' ' === substr($value->getValue(), 0, 1)) ? (string) $this->indentation : ''; + $blockIndentationIndicator = $this->getBlockIndentationIndicator($value->getValue()); $output .= sprintf(' |%s', $blockIndentationIndicator); foreach (explode("\n", $value->getValue()) as $row) { @@ -163,4 +157,20 @@ private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, i return $output."\n".$this->dump($value->getValue(), $inline - 1, $indent, $flags); } + + private function getBlockIndentationIndicator(string $value): string + { + $lines = explode("\n", $value); + + // If the first line (that is neither empty nor contains only spaces) + // starts with a space character, the spec requires a block indentation indicator + // http://www.yaml.org/spec/1.2/spec.html#id2793979 + foreach ($lines as $line) { + if ('' !== trim($line, ' ')) { + return (' ' === substr($line, 0, 1)) ? (string) $this->indentation : ''; + } + } + + return ''; + } } diff --git a/Tests/DumperTest.php b/Tests/DumperTest.php index 721b04ca..5a96a6c4 100644 --- a/Tests/DumperTest.php +++ b/Tests/DumperTest.php @@ -710,6 +710,42 @@ public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasLeadingSpace $this->assertSame($data, $this->parser->parse($yml)); } + public function testDumpMultiLineStringAsScalarBlockWhenFirstLineIsEmptyAndSecondLineHasLeadingSpace() + { + $data = [ + 'data' => [ + 'multi_line' => "\n the second line has leading spaces\nThe third line does not.", + ], + ]; + + $expected = "data:\n multi_line: |4-\n\n the second line has leading spaces\n The third line does not."; + + $yml = $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); + $this->assertSame($expected, $yml); + $this->assertSame($data, $this->parser->parse($yml)); + } + + public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasOnlySpaces() + { + $data = [ + 'data' => [ + 'multi_line' => " \nthe second line\nThe third line.", + ], + ]; + + $expectedData = [ + 'data' => [ + 'multi_line' => "\nthe second line\nThe third line.", + ], + ]; + + $expectedYml = "data:\n multi_line: |-\n \n the second line\n The third line."; + + $yml = $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); + $this->assertSame($expectedYml, $yml); + $this->assertSame($expectedData, $this->parser->parse($yml)); + } + public function testCarriageReturnFollowedByNewlineIsMaintainedWhenDumpingAsMultiLineLiteralBlock() { $data = ["a\r\nb\nc"];