llvm.org GIT mirror llvm / d6a4ded
[YAMLIO] Remove trailing spaces when outputting maps llvm::yaml::Output::paddedKey unconditionally outputs spaces, which are superfluous if the value to be dumped is a sequence or map. Change `bool NeedsNewLine` to `StringRef Padding` so that it can be overridden to `\n` if the value is a sequence or map. An empty map/sequence is special. It is printed as `{}` or `[]` without a newline, while a non-empty map/sequence follows a newline. To handle this distinction, add another variable `PaddingBeforeContainer` and does the special handling in endMapping/endSequence. Reviewed By: grimar, jhenderson Differential Revision: https://reviews.llvm.org/D64566 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365869 91177308-0d34-0410-b5e6-96231b3b80d8 Fangrui Song 3 months ago
7 changed file(s) with 74 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
16191619 bool NeedBitValueComma = false;
16201620 bool NeedFlowSequenceComma = false;
16211621 bool EnumerationMatchFound = false;
1622 bool NeedsNewLine = false;
16231622 bool WriteDefaultValues = false;
1623 StringRef Padding;
1624 StringRef PaddingBeforeContainer;
16241625 };
16251626
16261627 /// YAML I/O does conversion based on types. But often native data types
445445
446446 void Output::beginMapping() {
447447 StateStack.push_back(inMapFirstKey);
448 NeedsNewLine = true;
448 PaddingBeforeContainer = Padding;
449 Padding = "\n";
449450 }
450451
451452 bool Output::mapTag(StringRef Tag, bool Use) {
473474 }
474475 // Tags inside maps in sequences should act as keys in the map from a
475476 // formatting perspective, so we always want a newline in a sequence.
476 NeedsNewLine = true;
477 Padding = "\n";
477478 }
478479 }
479480 return Use;
481482
482483 void Output::endMapping() {
483484 // If we did not map anything, we should explicitly emit an empty map
484 if (StateStack.back() == inMapFirstKey)
485 if (StateStack.back() == inMapFirstKey) {
486 Padding = PaddingBeforeContainer;
487 newLineCheck();
485488 output("{}");
489 Padding = "\n";
490 }
486491 StateStack.pop_back();
487492 }
488493
547552
548553 unsigned Output::beginSequence() {
549554 StateStack.push_back(inSeqFirstElement);
550 NeedsNewLine = true;
555 PaddingBeforeContainer = Padding;
556 Padding = "\n";
551557 return 0;
552558 }
553559
554560 void Output::endSequence() {
555561 // If we did not emit anything, we should explicitly emit an empty sequence
556 if (StateStack.back() == inSeqFirstElement)
562 if (StateStack.back() == inSeqFirstElement) {
563 Padding = PaddingBeforeContainer;
564 newLineCheck();
557565 output("[]");
566 Padding = "\n";
567 }
558568 StateStack.pop_back();
559569 }
560570
745755 output(s);
746756 if (StateStack.empty() || (!inFlowSeqAnyElement(StateStack.back()) &&
747757 !inFlowMapAnyKey(StateStack.back())))
748 NeedsNewLine = true;
758 Padding = "\n";
749759 }
750760
751761 void Output::outputNewLine() {
758768 //
759769
760770 void Output::newLineCheck() {
761 if (!NeedsNewLine)
771 if (Padding != "\n") {
772 output(Padding);
773 Padding = {};
762774 return;
763 NeedsNewLine = false;
764
775 }
765776 outputNewLine();
777 Padding = {};
766778
767779 if (StateStack.size() == 0)
768780 return;
796808 output(":");
797809 const char *spaces = " ";
798810 if (key.size() < strlen(spaces))
799 output(&spaces[key.size()]);
811 Padding = &spaces[key.size()];
800812 else
801 output(" ");
813 Padding = " ";
802814 }
803815
804816 void Output::flowKey(StringRef Key) {
126126 ASSERT_EQ(OStream.str(), "---\n"
127127 "bar: 2\n"
128128 "foo: 1\n"
129 "qux: \n"
129 "qux:\n"
130130 " baz: true\n"
131131 "...\n");
132132 }
146146 ASSERT_EQ(OStream.str(), "---\n"
147147 "bar: 0x2\n"
148148 "foo: 1\n"
149 "qux: \n"
149 "qux:\n"
150150 " baz: true\n"
151151 "...\n");
152152 }
25272527 ostr.flush();
25282528 EXPECT_EQ(1, Context.A);
25292529 EXPECT_EQ("---\n"
2530 "Simple: \n"
2530 "Simple:\n"
25312531 " B: 0\n"
25322532 " C: 0\n"
25332533 " Context: 1\n"
25422542 ostr.flush();
25432543 EXPECT_EQ(2, Context.A);
25442544 EXPECT_EQ("---\n"
2545 "Simple: \n"
2545 "Simple:\n"
25462546 " B: 2\n"
25472547 " C: 3\n"
25482548 " Context: 2\n"
25552555
25562556 TEST(YAMLIO, TestCustomMapping) {
25572557 std::map x;
2558 x["foo"] = 1;
2559 x["bar"] = 2;
25602558
25612559 std::string out;
25622560 llvm::raw_string_ostream ostr(out);
25632561 Output xout(ostr, nullptr, 0);
25642562
2563 xout << x;
2564 ostr.flush();
2565 EXPECT_EQ("---\n"
2566 "{}\n"
2567 "...\n",
2568 out);
2569
2570 x["foo"] = 1;
2571 x["bar"] = 2;
2572
2573 out.clear();
25652574 xout << x;
25662575 ostr.flush();
25672576 EXPECT_EQ("---\n"
25942603 xout << x;
25952604 ostr.flush();
25962605 EXPECT_EQ("---\n"
2597 "bar: \n"
2606 "bar:\n"
25982607 " foo: 3\n"
25992608 " bar: 4\n"
2600 "foo: \n"
2609 "foo:\n"
26012610 " foo: 1\n"
26022611 " bar: 2\n"
26032612 "...\n",
26112620 EXPECT_EQ(2, y["foo"].bar);
26122621 EXPECT_EQ(3, y["bar"].foo);
26132622 EXPECT_EQ(4, y["bar"].bar);
2623 }
2624
2625 struct FooBarMapMap {
2626 std::map fbm;
2627 };
2628
2629 template <> struct MappingTraits {
2630 static void mapping(IO &io, FooBarMapMap &x) {
2631 io.mapRequired("fbm", x.fbm);
2632 }
2633 };
2634
2635 TEST(YAMLIO, TestEmptyMapWrite) {
2636 FooBarMapMap cont;
2637 std::string str;
2638 llvm::raw_string_ostream OS(str);
2639 Output yout(OS);
2640 yout << cont;
2641 EXPECT_EQ(OS.str(), "---\nfbm: {}\n...\n");
2642 }
2643
2644 TEST(YAMLIO, TestEmptySequenceWrite) {
2645 FooBarContainer cont;
2646 std::string str;
2647 llvm::raw_string_ostream OS(str);
2648 Output yout(OS);
2649 yout << cont;
2650 EXPECT_EQ(OS.str(), "---\nfbs: []\n...\n");
26142651 }
26152652
26162653 static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) {
148148 "--- !tapi-tbe\n"
149149 "TbeVersion: 1.0\n"
150150 "Arch: AArch64\n"
151 "Symbols: \n"
151 "Symbols:\n"
152152 " bar: { Type: Func, Weak: true }\n"
153153 " foo: { Type: NoType, Size: 99, Warning: Does nothing }\n"
154154 " nor: { Type: Func, Undefined: true }\n"
204204 "TbeVersion: 1.0\n"
205205 "SoName: nosyms.so\n"
206206 "Arch: x86_64\n"
207 "NeededLibs: \n"
207 "NeededLibs:\n"
208208 " - libc.so\n"
209209 " - libfoo.so\n"
210210 " - libbar.so\n"
158158 "compatibility-version: 0\n"
159159 "swift-version: 5\n"
160160 "objc-constraint: retain_release\n"
161 "exports: \n"
161 "exports:\n"
162162 " - archs: [ i386 ]\n"
163163 " symbols: [ _sym1 ]\n"
164164 " weak-def-symbols: [ _sym2 ]\n"
181181 "current-version: 1.2.3\n"
182182 "compatibility-version: 0\n"
183183 "swift-version: 5\n"
184 "exports: \n"
184 "exports:\n"
185185 " - archs: [ i386 ]\n"
186186 " symbols: [ _sym1 ]\n"
187187 " weak-def-symbols: [ _sym2 ]\n"