Index: include/clang/Tooling/DiagnosticsYaml.h =================================================================== --- include/clang/Tooling/DiagnosticsYaml.h +++ include/clang/Tooling/DiagnosticsYaml.h @@ -56,7 +56,9 @@ MappingNormalization Keys( Io, D); Io.mapRequired("DiagnosticName", Keys->DiagnosticName); - + Io.mapRequired("Message", Keys->Message.Message); + Io.mapRequired("FileOffset", Keys->Message.FileOffset); + Io.mapRequired("FilePath", Keys->Message.FilePath); // FIXME: Export properly all the different fields. std::vector Fixes; @@ -65,7 +67,7 @@ Fixes.push_back(Replacement); } } - Io.mapRequired("Replacements", Fixes); + Io.mapOptional("Replacements", Fixes); for (auto &Fix : Fixes) { llvm::Error Err = Keys->Fix[Fix.getFilePath()].add(Fix); if (Err) { @@ -82,17 +84,7 @@ template <> struct MappingTraits { static void mapping(IO &Io, clang::tooling::TranslationUnitDiagnostics &Doc) { Io.mapRequired("MainSourceFile", Doc.MainSourceFile); - - std::vector Diagnostics; - for (auto &Diagnostic : Doc.Diagnostics) { - // FIXME: Export all diagnostics, not just the ones with fixes. - // Update MappingTraits::mapping. - if (Diagnostic.Fix.size() > 0) { - Diagnostics.push_back(Diagnostic); - } - } - Io.mapRequired("Diagnostics", Diagnostics); - Doc.Diagnostics = Diagnostics; + Io.mapRequired("Diagnostics", Doc.Diagnostics); } }; } // end namespace yaml Index: unittests/Tooling/CMakeLists.txt =================================================================== --- unittests/Tooling/CMakeLists.txt +++ unittests/Tooling/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_unittest(ToolingTests CommentHandlerTest.cpp CompilationDatabaseTest.cpp + DiagnosticsYamlTest.cpp FixItTest.cpp LookupTest.cpp QualTypeNamesTest.cpp Index: unittests/Tooling/DiagnosticsYamlTest.cpp =================================================================== --- /dev/null +++ unittests/Tooling/DiagnosticsYamlTest.cpp @@ -0,0 +1,170 @@ +//===- unittests/Tooling/DiagnosticsYamlTest.cpp - Serialization tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tests for serialization of Diagnostics. +// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Core/Diagnostic.h" +#include "clang/Tooling/DiagnosticsYaml.h" +#include "clang/Tooling/ReplacementsYaml.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang::tooling; + +TEST(DiagnosticsYamlTest, SerializesDiagnostics) { + TranslationUnitDiagnostics TUD; + TUD.MainSourceFile = "path/to/source.cpp"; + DiagnosticMessage Message1; + Message1.Message = "message #1"; + Message1.FileOffset = 55; + Message1.FilePath = "path/to/source.cpp"; + StringMap Fix1{ + {"path/to/source.cpp", Replacements(Replacement("path/to/source.cpp", 100, + 12, "replacement #1"))}}; + DiagnosticMessage Message2; + Message2.Message = "message #2"; + Message2.FileOffset = 60; + Message2.FilePath = "path/to/header.h"; + StringMap Fix2{ + {"path/to/header.h", + Replacements(Replacement("path/to/header.h", 62, 2, "replacement #2"))}}; + SmallVector EmptyNotes; + TUD.Diagnostics.emplace_back("diagnostic#1", Message1, Fix1, EmptyNotes, + Diagnostic::Warning, "path/to/build/directory"); + TUD.Diagnostics.emplace_back("diagnostic#2", Message2, Fix2, EmptyNotes, + Diagnostic::Error, + "path/to/another/build/directory"); + + std::string YamlContent; + raw_string_ostream YamlContentStream(YamlContent); + + yaml::Output YAML(YamlContentStream); + YAML << TUD; + + ASSERT_STREQ("---\n" + "MainSourceFile: path/to/source.cpp\n" + "Diagnostics: \n" + " - DiagnosticName: \"diagnostic#1\"\n" + " Message: \"message #1\"\n" + " FileOffset: 55\n" + " FilePath: path/to/source.cpp\n" + " Replacements: \n" + " - FilePath: path/to/source.cpp\n" + " Offset: 100\n" + " Length: 12\n" + " ReplacementText: \"replacement #1\"\n" + " - DiagnosticName: \"diagnostic#2\"\n" + " Message: \"message #2\"\n" + " FileOffset: 60\n" + " FilePath: path/to/header.h\n" + " Replacements: \n" + " - FilePath: path/to/header.h\n" + " Offset: 62\n" + " Length: 2\n" + " ReplacementText: \"replacement #2\"\n" + "...\n", + YamlContentStream.str().c_str()); +} + +TEST(DiagnosticsYamlTest, SerializesDiagnosticWithNoFix) { + TranslationUnitDiagnostics TUD; + TUD.MainSourceFile = "path/to/source.cpp"; + DiagnosticMessage Message; + Message.Message = "message #1"; + Message.FileOffset = 55; + Message.FilePath = "path/to/source.cpp"; + StringMap EmptyReplacements; + SmallVector EmptyNotes; + TUD.Diagnostics.emplace_back("diagnostic#1", Message, EmptyReplacements, + EmptyNotes, Diagnostic::Warning, + "path/to/build/directory"); + + std::string YamlContent; + raw_string_ostream YamlContentStream(YamlContent); + + yaml::Output YAML(YamlContentStream); + YAML << TUD; + + ASSERT_STREQ("---\n" + "MainSourceFile: path/to/source.cpp\n" + "Diagnostics: \n" + " - DiagnosticName: \"diagnostic#1\"\n" + " Message: \"message #1\"\n" + " FileOffset: 55\n" + " FilePath: path/to/source.cpp\n" + "...\n", + YamlContentStream.str().c_str()); +} + +TEST(DiagnosticsYamlTest, DeserializesDiagnostics) { + std::string YamlContent = "---\n" + "MainSourceFile: path/to/source.cpp\n" + "Diagnostics: \n" + " - DiagnosticName: 'diagnostic#1'\n" + " Message: 'message #1'\n" + " FileOffset: 55\n" + " FilePath: path/to/source.cpp\n" + " Replacements: \n" + " - FilePath: path/to/source.cpp\n" + " Offset: 100\n" + " Length: 12\n" + " ReplacementText: 'replacement #1'\n" + " - DiagnosticName: 'diagnostic#2'\n" + " Message: 'message #2'\n" + " FileOffset: 60\n" + " FilePath: path/to/header.h\n" + " Replacements: \n" + " - FilePath: path/to/header.h\n" + " Offset: 62\n" + " Length: 2\n" + " ReplacementText: 'replacement #2'\n" + "...\n"; + TranslationUnitDiagnostics TUDActual; + yaml::Input YAML(YamlContent); + YAML >> TUDActual; + ASSERT_FALSE(YAML.error()); + ASSERT_EQ(2u, TUDActual.Diagnostics.size()); + ASSERT_EQ("path/to/source.cpp", TUDActual.MainSourceFile); + + auto getFixes = [](const StringMap &Fix) { + std::vector Fixes; + for (auto &Replacements : Fix) { + for (auto &Replacement : Replacements.second) { + Fixes.push_back(Replacement); + } + } + return Fixes; + }; + + Diagnostic D1 = TUDActual.Diagnostics[0]; + ASSERT_EQ("diagnostic#1", D1.DiagnosticName); + ASSERT_EQ("message #1", D1.Message.Message); + ASSERT_EQ(55u, D1.Message.FileOffset); + ASSERT_EQ("path/to/source.cpp", D1.Message.FilePath); + std::vector Fixes1 = getFixes(D1.Fix); + ASSERT_EQ(1u, Fixes1.size()); + ASSERT_EQ("path/to/source.cpp", Fixes1[0].getFilePath()); + ASSERT_EQ(100, Fixes1[0].getOffset()); + ASSERT_EQ(12, Fixes1[0].getLength()); + ASSERT_EQ("replacement #1", Fixes1[0].getReplacementText()); + + Diagnostic D2 = TUDActual.Diagnostics[1]; + ASSERT_EQ("diagnostic#2", D2.DiagnosticName); + ASSERT_EQ("message #2", D2.Message.Message); + ASSERT_EQ(60, D2.Message.FileOffset); + ASSERT_EQ("path/to/header.h", D2.Message.FilePath); + std::vector Fixes2 = getFixes(D2.Fix); + ASSERT_EQ(1u, Fixes2.size()); + ASSERT_EQ("path/to/header.h", Fixes2[0].getFilePath()); + ASSERT_EQ(62, Fixes2[0].getOffset()); + ASSERT_EQ(2, Fixes2[0].getLength()); + ASSERT_EQ("replacement #2", Fixes2[0].getReplacementText()); +} \ No newline at end of file