Skip to content

Commit 3920972

Browse files
authored
[YAML] Fix incorrect dash output in nested sequences (#116488)
Nested sequences could be defined but the YAML output was incorrect. `Output::newLineCheck()` was not able to emit multiple dashes `- ` and YAML parser sometimes didn't accept its output as the result. This fixes for emitting corresponding dashes for consecutive `inSeqFirstElement`, but suppresses emission to the top `inSeqFirstElement`. This also fixes for emitting flow elements onto nested sequences.
1 parent 04cc492 commit 3920972

File tree

2 files changed

+117
-16
lines changed

2 files changed

+117
-16
lines changed

llvm/lib/Support/YAMLTraits.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -837,26 +837,40 @@ void Output::newLineCheck(bool EmptySequence) {
837837
return;
838838

839839
unsigned Indent = StateStack.size() - 1;
840-
bool OutputDash = false;
841-
842-
if (StateStack.back() == inSeqFirstElement ||
843-
StateStack.back() == inSeqOtherElement) {
844-
OutputDash = true;
845-
} else if ((StateStack.size() > 1) &&
846-
((StateStack.back() == inMapFirstKey) ||
847-
inFlowSeqAnyElement(StateStack.back()) ||
848-
(StateStack.back() == inFlowMapFirstKey)) &&
849-
inSeqAnyElement(StateStack[StateStack.size() - 2])) {
850-
--Indent;
851-
OutputDash = true;
840+
bool PossiblyNestedSeq = false;
841+
auto I = StateStack.rbegin(), E = StateStack.rend();
842+
843+
if (inSeqAnyElement(*I)) {
844+
PossiblyNestedSeq = true; // Not possibly but always.
845+
++Indent;
846+
} else if (*I == inMapFirstKey || *I == inFlowMapFirstKey ||
847+
inFlowSeqAnyElement(*I)) {
848+
PossiblyNestedSeq = true;
849+
++I; // Skip back().
852850
}
853851

854-
for (unsigned i = 0; i < Indent; ++i) {
855-
output(" ");
852+
unsigned OutputDashCount = 0;
853+
if (PossiblyNestedSeq) {
854+
// Count up consecutive inSeqFirstElement from the end, unless
855+
// inSeqFirstElement is the top of nested sequence.
856+
while (I != E) {
857+
// Don't count the top of nested sequence.
858+
if (!inSeqAnyElement(*I))
859+
break;
860+
861+
++OutputDashCount;
862+
863+
// Stop counting if consecutive inSeqFirstElement ends.
864+
if (*I++ != inSeqFirstElement)
865+
break;
866+
}
856867
}
857-
if (OutputDash) {
868+
869+
for (unsigned I = OutputDashCount; I < Indent; ++I)
870+
output(" ");
871+
872+
for (unsigned I = 0; I < OutputDashCount; ++I)
858873
output("- ");
859-
}
860874
}
861875

862876
void Output::paddedKey(StringRef key) {

llvm/unittests/Support/YAMLIOTest.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,93 @@ TEST(YAMLIO, TestReadWriteMySecondsSequence) {
15371537
}
15381538
}
15391539

1540+
//===----------------------------------------------------------------------===//
1541+
// Test nested sequence
1542+
//===----------------------------------------------------------------------===//
1543+
using NestedStringSeq1 = llvm::SmallVector<std::string, 2>;
1544+
using NestedStringSeq2 = std::array<NestedStringSeq1, 2>;
1545+
using NestedStringSeq3 = std::vector<NestedStringSeq2>;
1546+
1547+
LLVM_YAML_IS_SEQUENCE_VECTOR(NestedStringSeq1)
1548+
LLVM_YAML_IS_SEQUENCE_VECTOR(NestedStringSeq2)
1549+
1550+
struct MappedStringSeq3 {
1551+
NestedStringSeq3 Seq3;
1552+
};
1553+
1554+
template <> struct llvm::yaml::MappingTraits<MappedStringSeq3> {
1555+
static void mapping(IO &io, MappedStringSeq3 &seq) {
1556+
io.mapRequired("Seq3", seq.Seq3);
1557+
}
1558+
};
1559+
1560+
using NestedIntSeq1 = std::array<int, 2>;
1561+
using NestedIntSeq2 = std::array<NestedIntSeq1, 2>;
1562+
using NestedIntSeq3 = std::array<NestedIntSeq2, 2>;
1563+
1564+
LLVM_YAML_IS_SEQUENCE_VECTOR(NestedIntSeq1)
1565+
LLVM_YAML_IS_SEQUENCE_VECTOR(NestedIntSeq2)
1566+
1567+
template <typename Ty> std::string ParseAndEmit(llvm::StringRef YAML) {
1568+
Ty seq3;
1569+
Input yin(YAML);
1570+
yin >> seq3;
1571+
std::string out;
1572+
llvm::raw_string_ostream ostr(out);
1573+
Output yout(ostr);
1574+
yout << seq3;
1575+
return out;
1576+
}
1577+
1578+
TEST(YAMLIO, TestNestedSequence) {
1579+
{
1580+
llvm::StringRef Seq3YAML(R"YAML(---
1581+
- - [ 1000, 1001 ]
1582+
- [ 1010, 1011 ]
1583+
- - [ 1100, 1101 ]
1584+
- [ 1110, 1111 ]
1585+
...
1586+
)YAML");
1587+
1588+
std::string out = ParseAndEmit<NestedIntSeq3>(Seq3YAML);
1589+
EXPECT_EQ(out, Seq3YAML);
1590+
}
1591+
1592+
{
1593+
llvm::StringRef Seq3YAML(R"YAML(---
1594+
- - - '000'
1595+
- '001'
1596+
- - '010'
1597+
- '011'
1598+
- - - '100'
1599+
- '101'
1600+
- - '110'
1601+
- '111'
1602+
...
1603+
)YAML");
1604+
1605+
std::string out = ParseAndEmit<NestedStringSeq3>(Seq3YAML);
1606+
EXPECT_EQ(out, Seq3YAML);
1607+
}
1608+
1609+
{
1610+
llvm::StringRef Seq3YAML(R"YAML(---
1611+
Seq3:
1612+
- - - '000'
1613+
- '001'
1614+
- - '010'
1615+
- '011'
1616+
- - - '100'
1617+
- '101'
1618+
- - '110'
1619+
- '111'
1620+
...
1621+
)YAML");
1622+
1623+
std::string out = ParseAndEmit<MappedStringSeq3>(Seq3YAML);
1624+
EXPECT_EQ(out, Seq3YAML);
1625+
}
1626+
}
15401627

15411628
//===----------------------------------------------------------------------===//
15421629
// Test dynamic typing

0 commit comments

Comments
 (0)