diff --git a/llvm/lib/Support/YAMLTraits.cpp b/llvm/lib/Support/YAMLTraits.cpp index 56b557646100b..0d694d5b9d45b 100644 --- a/llvm/lib/Support/YAMLTraits.cpp +++ b/llvm/lib/Support/YAMLTraits.cpp @@ -838,26 +838,40 @@ void Output::newLineCheck(bool EmptySequence) { return; unsigned Indent = StateStack.size() - 1; - bool OutputDash = false; - - if (StateStack.back() == inSeqFirstElement || - StateStack.back() == inSeqOtherElement) { - OutputDash = true; - } else if ((StateStack.size() > 1) && - ((StateStack.back() == inMapFirstKey) || - inFlowSeqAnyElement(StateStack.back()) || - (StateStack.back() == inFlowMapFirstKey)) && - inSeqAnyElement(StateStack[StateStack.size() - 2])) { - --Indent; - OutputDash = true; + bool PossiblyNestedSeq = false; + auto I = StateStack.rbegin(), E = StateStack.rend(); + + if (inSeqAnyElement(*I)) { + PossiblyNestedSeq = true; // Not possibly but always. + ++Indent; + } else if (*I == inMapFirstKey || *I == inFlowMapFirstKey || + inFlowSeqAnyElement(*I)) { + PossiblyNestedSeq = true; + ++I; // Skip back(). } - for (unsigned i = 0; i < Indent; ++i) { - output(" "); + unsigned OutputDashCount = 0; + if (PossiblyNestedSeq) { + // Count up consecutive inSeqFirstElement from the end, unless + // inSeqFirstElement is the top of nested sequence. + while (I != E) { + // Don't count the top of nested sequence. + if (!inSeqAnyElement(*I)) + break; + + ++OutputDashCount; + + // Stop counting if consecutive inSeqFirstElement ends. + if (*I++ != inSeqFirstElement) + break; + } } - if (OutputDash) { + + for (unsigned I = OutputDashCount; I < Indent; ++I) + output(" "); + + for (unsigned I = 0; I < OutputDashCount; ++I) output("- "); - } } void Output::paddedKey(StringRef key) { diff --git a/llvm/unittests/Support/YAMLIOTest.cpp b/llvm/unittests/Support/YAMLIOTest.cpp index a7d1b338719f3..c0e9c57a77f19 100644 --- a/llvm/unittests/Support/YAMLIOTest.cpp +++ b/llvm/unittests/Support/YAMLIOTest.cpp @@ -1537,6 +1537,93 @@ TEST(YAMLIO, TestReadWriteMySecondsSequence) { } } +//===----------------------------------------------------------------------===// +// Test nested sequence +//===----------------------------------------------------------------------===// +using NestedStringSeq1 = llvm::SmallVector; +using NestedStringSeq2 = std::array; +using NestedStringSeq3 = std::vector; + +LLVM_YAML_IS_SEQUENCE_VECTOR(NestedStringSeq1) +LLVM_YAML_IS_SEQUENCE_VECTOR(NestedStringSeq2) + +struct MappedStringSeq3 { + NestedStringSeq3 Seq3; +}; + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, MappedStringSeq3 &seq) { + io.mapRequired("Seq3", seq.Seq3); + } +}; + +using NestedIntSeq1 = std::array; +using NestedIntSeq2 = std::array; +using NestedIntSeq3 = std::array; + +LLVM_YAML_IS_SEQUENCE_VECTOR(NestedIntSeq1) +LLVM_YAML_IS_SEQUENCE_VECTOR(NestedIntSeq2) + +template std::string ParseAndEmit(llvm::StringRef YAML) { + Ty seq3; + Input yin(YAML); + yin >> seq3; + std::string out; + llvm::raw_string_ostream ostr(out); + Output yout(ostr); + yout << seq3; + return out; +} + +TEST(YAMLIO, TestNestedSequence) { + { + llvm::StringRef Seq3YAML(R"YAML(--- +- - [ 1000, 1001 ] + - [ 1010, 1011 ] +- - [ 1100, 1101 ] + - [ 1110, 1111 ] +... +)YAML"); + + std::string out = ParseAndEmit(Seq3YAML); + EXPECT_EQ(out, Seq3YAML); + } + + { + llvm::StringRef Seq3YAML(R"YAML(--- +- - - '000' + - '001' + - - '010' + - '011' +- - - '100' + - '101' + - - '110' + - '111' +... +)YAML"); + + std::string out = ParseAndEmit(Seq3YAML); + EXPECT_EQ(out, Seq3YAML); + } + + { + llvm::StringRef Seq3YAML(R"YAML(--- +Seq3: + - - - '000' + - '001' + - - '010' + - '011' + - - - '100' + - '101' + - - '110' + - '111' +... +)YAML"); + + std::string out = ParseAndEmit(Seq3YAML); + EXPECT_EQ(out, Seq3YAML); + } +} //===----------------------------------------------------------------------===// // Test dynamic typing