1//===-- DiagnosticsYaml.h -- Serialiazation for Diagnosticss ---*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file defines the structure of a YAML document for serializing
12/// diagnostics.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H
17#define LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H
18
19#include "clang/Tooling/Core/Diagnostic.h"
20#include "clang/Tooling/ReplacementsYaml.h"
21#include "llvm/Support/YAMLTraits.h"
22#include <string>
23
24LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Diagnostic)
25
26namespace llvm {
27namespace yaml {
28
29template <> struct MappingTraits<clang::tooling::Diagnostic> {
30  /// \brief Helper to (de)serialize a Diagnostic since we don't have direct
31  /// access to its data members.
32  class NormalizedDiagnostic {
33  public:
34    NormalizedDiagnostic(const IO &)
35        : DiagLevel(clang::tooling::Diagnostic::Level::Warning) {}
36
37    NormalizedDiagnostic(const IO &, const clang::tooling::Diagnostic &D)
38        : DiagnosticName(D.DiagnosticName), Message(D.Message), Fix(D.Fix),
39          Notes(D.Notes), DiagLevel(D.DiagLevel),
40          BuildDirectory(D.BuildDirectory) {}
41
42    clang::tooling::Diagnostic denormalize(const IO &) {
43      return clang::tooling::Diagnostic(DiagnosticName, Message, Fix, Notes,
44                                        DiagLevel, BuildDirectory);
45    }
46
47    std::string DiagnosticName;
48    clang::tooling::DiagnosticMessage Message;
49    llvm::StringMap<clang::tooling::Replacements> Fix;
50    SmallVector<clang::tooling::DiagnosticMessage, 1> Notes;
51    clang::tooling::Diagnostic::Level DiagLevel;
52    std::string BuildDirectory;
53  };
54
55  static void mapping(IO &Io, clang::tooling::Diagnostic &D) {
56    MappingNormalization<NormalizedDiagnostic, clang::tooling::Diagnostic> Keys(
57        Io, D);
58    Io.mapRequired("DiagnosticName", Keys->DiagnosticName);
59
60    // FIXME: Export properly all the different fields.
61
62    std::vector<clang::tooling::Replacement> Fixes;
63    for (auto &Replacements : Keys->Fix) {
64      for (auto &Replacement : Replacements.second) {
65        Fixes.push_back(Replacement);
66      }
67    }
68    Io.mapRequired("Replacements", Fixes);
69    for (auto &Fix : Fixes) {
70      llvm::Error Err = Keys->Fix[Fix.getFilePath()].add(Fix);
71      if (Err) {
72        // FIXME: Implement better conflict handling.
73        llvm::errs() << "Fix conflicts with existing fix: "
74                     << llvm::toString(std::move(Err)) << "\n";
75      }
76    }
77  }
78};
79
80/// \brief Specialized MappingTraits to describe how a
81/// TranslationUnitDiagnostics is (de)serialized.
82template <> struct MappingTraits<clang::tooling::TranslationUnitDiagnostics> {
83  static void mapping(IO &Io, clang::tooling::TranslationUnitDiagnostics &Doc) {
84    Io.mapRequired("MainSourceFile", Doc.MainSourceFile);
85
86    std::vector<clang::tooling::Diagnostic> Diagnostics;
87    for (auto &Diagnostic : Doc.Diagnostics) {
88      // FIXME: Export all diagnostics, not just the ones with fixes.
89      // Update MappingTraits<clang::tooling::Diagnostic>::mapping.
90      if (Diagnostic.Fix.size() > 0) {
91        Diagnostics.push_back(Diagnostic);
92      }
93    }
94    Io.mapRequired("Diagnostics", Diagnostics);
95    Doc.Diagnostics = Diagnostics;
96  }
97};
98} // end namespace yaml
99} // end namespace llvm
100
101#endif // LLVM_CLANG_TOOLING_DIAGNOSTICSYAML_H
102