/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Basic/JsonSupport.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- JsonSupport.h - JSON Output Utilities --------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLVM_CLANG_BASIC_JSONSUPPORT_H |
10 | | #define LLVM_CLANG_BASIC_JSONSUPPORT_H |
11 | | |
12 | | #include "clang/Basic/LLVM.h" |
13 | | #include "clang/Basic/SourceManager.h" |
14 | | #include "llvm/ADT/StringRef.h" |
15 | | #include "llvm/Support/raw_ostream.h" |
16 | | #include <iterator> |
17 | | |
18 | | namespace clang { |
19 | | |
20 | | inline raw_ostream &Indent(raw_ostream &Out, const unsigned int Space, |
21 | 2.98k | bool IsDot) { |
22 | 15.9k | for (unsigned int I = 0; I < Space * 2; ++I12.9k ) |
23 | 12.9k | Out << (IsDot ? " "10.7k : " "2.21k ); |
24 | 2.98k | return Out; |
25 | 2.98k | } |
26 | | |
27 | 567 | inline std::string JsonFormat(StringRef RawSR, bool AddQuotes) { |
28 | 567 | if (RawSR.empty()) |
29 | 28 | return "null"; |
30 | | |
31 | | // Trim special characters. |
32 | 539 | std::string Str = RawSR.trim().str(); |
33 | 539 | size_t Pos = 0; |
34 | | |
35 | | // Escape backslashes. |
36 | 579 | while (true) { |
37 | 579 | Pos = Str.find('\\', Pos); |
38 | 579 | if (Pos == std::string::npos) |
39 | 539 | break; |
40 | | |
41 | | // Prevent bad conversions. |
42 | 40 | size_t TempPos = (Pos != 0) ? Pos - 1 : 00 ; |
43 | | |
44 | | // See whether the current backslash is not escaped. |
45 | 40 | if (TempPos != Str.find("\\\\", Pos)) { |
46 | 40 | Str.insert(Pos, "\\"); |
47 | 40 | ++Pos; // As we insert the backslash move plus one. |
48 | 40 | } |
49 | | |
50 | 40 | ++Pos; |
51 | 40 | } |
52 | | |
53 | | // Escape double quotes. |
54 | 539 | Pos = 0; |
55 | 615 | while (true) { |
56 | 615 | Pos = Str.find('\"', Pos); |
57 | 615 | if (Pos == std::string::npos) |
58 | 539 | break; |
59 | | |
60 | | // Prevent bad conversions. |
61 | 76 | size_t TempPos = (Pos != 0) ? Pos - 162 : 014 ; |
62 | | |
63 | | // See whether the current double quote is not escaped. |
64 | 76 | if (TempPos != Str.find("\\\"", Pos)) { |
65 | 76 | Str.insert(Pos, "\\"); |
66 | 76 | ++Pos; // As we insert the escape-character move plus one. |
67 | 76 | } |
68 | | |
69 | 76 | ++Pos; |
70 | 76 | } |
71 | | |
72 | | // Remove new-lines. |
73 | 539 | Str.erase(std::remove(Str.begin(), Str.end(), '\n'), Str.end()); |
74 | | |
75 | 539 | if (!AddQuotes) |
76 | 0 | return Str; |
77 | | |
78 | 539 | return '\"' + Str + '\"'; |
79 | 539 | } |
80 | | |
81 | | inline void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, |
82 | | const SourceManager &SM, |
83 | 168 | bool AddBraces = true) { |
84 | | // Mostly copy-pasted from SourceLocation::print. |
85 | 168 | if (!Loc.isValid()) { |
86 | 0 | Out << "null"; |
87 | 0 | return; |
88 | 0 | } |
89 | | |
90 | 168 | if (Loc.isFileID()) { |
91 | 163 | PresumedLoc PLoc = SM.getPresumedLoc(Loc); |
92 | | |
93 | 163 | if (PLoc.isInvalid()) { |
94 | 0 | Out << "null"; |
95 | 0 | return; |
96 | 0 | } |
97 | | // The macro expansion and spelling pos is identical for file locs. |
98 | 163 | if (AddBraces) |
99 | 158 | Out << "{ "; |
100 | 163 | std::string filename(PLoc.getFilename()); |
101 | | #ifdef _WIN32 |
102 | | // Remove forbidden Windows path characters |
103 | | auto RemoveIt = |
104 | | std::remove_if(filename.begin(), filename.end(), [](auto Char) { |
105 | | static const char ForbiddenChars[] = "<>*?\"|"; |
106 | | return std::find(std::begin(ForbiddenChars), std::end(ForbiddenChars), |
107 | | Char) != std::end(ForbiddenChars); |
108 | | }); |
109 | | filename.erase(RemoveIt, filename.end()); |
110 | | // Handle windows-specific path delimiters. |
111 | | std::replace(filename.begin(), filename.end(), '\\', '/'); |
112 | | #endif |
113 | 163 | Out << "\"line\": " << PLoc.getLine() |
114 | 163 | << ", \"column\": " << PLoc.getColumn() |
115 | 163 | << ", \"file\": \"" << filename << "\""; |
116 | 163 | if (AddBraces) |
117 | 158 | Out << " }"; |
118 | 163 | return; |
119 | 163 | } |
120 | | |
121 | | // We want 'location: { ..., spelling: { ... }}' but not |
122 | | // 'location: { ... }, spelling: { ... }', hence the dance |
123 | | // with braces. |
124 | 5 | Out << "{ "; |
125 | 5 | printSourceLocationAsJson(Out, SM.getExpansionLoc(Loc), SM, false); |
126 | 5 | Out << ", \"spelling\": "; |
127 | 5 | printSourceLocationAsJson(Out, SM.getSpellingLoc(Loc), SM, true); |
128 | 5 | Out << " }"; |
129 | 5 | } |
130 | | } // namespace clang |
131 | | |
132 | | #endif // LLVM_CLANG_BASIC_JSONSUPPORT_H |