Coverage Report

Created: 2022-07-16 07:03

/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/Path.h"
16
#include "llvm/Support/raw_ostream.h"
17
#include <iterator>
18
19
namespace clang {
20
21
inline raw_ostream &Indent(raw_ostream &Out, const unsigned int Space,
22
4.21k
                           bool IsDot) {
23
21.1k
  for (unsigned int I = 0; I < Space * 2; 
++I16.9k
)
24
16.9k
    Out << (IsDot ? 
"&nbsp;"11.9k
:
" "4.96k
);
25
4.21k
  return Out;
26
4.21k
}
27
28
661
inline std::string JsonFormat(StringRef RawSR, bool AddQuotes) {
29
661
  if (RawSR.empty())
30
28
    return "null";
31
32
  // Trim special characters.
33
633
  std::string Str = RawSR.trim().str();
34
633
  size_t Pos = 0;
35
36
  // Escape backslashes.
37
673
  while (true) {
38
673
    Pos = Str.find('\\', Pos);
39
673
    if (Pos == std::string::npos)
40
633
      break;
41
42
    // Prevent bad conversions.
43
40
    size_t TempPos = (Pos != 0) ? Pos - 1 : 
00
;
44
45
    // See whether the current backslash is not escaped.
46
40
    if (TempPos != Str.find("\\\\", Pos)) {
47
40
      Str.insert(Pos, "\\");
48
40
      ++Pos; // As we insert the backslash move plus one.
49
40
    }
50
51
40
    ++Pos;
52
40
  }
53
54
  // Escape double quotes.
55
633
  Pos = 0;
56
709
  while (true) {
57
709
    Pos = Str.find('\"', Pos);
58
709
    if (Pos == std::string::npos)
59
633
      break;
60
61
    // Prevent bad conversions.
62
76
    size_t TempPos = (Pos != 0) ? 
Pos - 162
:
014
;
63
64
    // See whether the current double quote is not escaped.
65
76
    if (TempPos != Str.find("\\\"", Pos)) {
66
76
      Str.insert(Pos, "\\");
67
76
      ++Pos; // As we insert the escape-character move plus one.
68
76
    }
69
70
76
    ++Pos;
71
76
  }
72
73
  // Remove new-lines.
74
633
  llvm::erase_value(Str, '\n');
75
76
633
  if (!AddQuotes)
77
0
    return Str;
78
79
633
  return '\"' + Str + '\"';
80
633
}
81
82
inline void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc,
83
                                      const SourceManager &SM,
84
168
                                      bool AddBraces = true) {
85
  // Mostly copy-pasted from SourceLocation::print.
86
168
  if (!Loc.isValid()) {
87
0
    Out << "null";
88
0
    return;
89
0
  }
90
91
168
  if (Loc.isFileID()) {
92
163
    PresumedLoc PLoc = SM.getPresumedLoc(Loc);
93
94
163
    if (PLoc.isInvalid()) {
95
0
      Out << "null";
96
0
      return;
97
0
    }
98
    // The macro expansion and spelling pos is identical for file locs.
99
163
    if (AddBraces)
100
158
      Out << "{ ";
101
163
    std::string filename(PLoc.getFilename());
102
163
    if (is_style_windows(llvm::sys::path::Style::native)) {
103
      // Remove forbidden Windows path characters
104
0
      auto RemoveIt =
105
0
          std::remove_if(filename.begin(), filename.end(), [](auto Char) {
106
0
            static const char ForbiddenChars[] = "<>*?\"|";
107
0
            return std::find(std::begin(ForbiddenChars),
108
0
                             std::end(ForbiddenChars),
109
0
                             Char) != std::end(ForbiddenChars);
110
0
          });
111
0
      filename.erase(RemoveIt, filename.end());
112
      // Handle windows-specific path delimiters.
113
0
      std::replace(filename.begin(), filename.end(), '\\', '/');
114
0
    }
115
163
    Out << "\"line\": " << PLoc.getLine()
116
163
        << ", \"column\": " << PLoc.getColumn()
117
163
        << ", \"file\": \"" << filename << "\"";
118
163
    if (AddBraces)
119
158
      Out << " }";
120
163
    return;
121
163
  }
122
123
  // We want 'location: { ..., spelling: { ... }}' but not
124
  // 'location: { ... }, spelling: { ... }', hence the dance
125
  // with braces.
126
5
  Out << "{ ";
127
5
  printSourceLocationAsJson(Out, SM.getExpansionLoc(Loc), SM, false);
128
5
  Out << ", \"spelling\": ";
129
5
  printSourceLocationAsJson(Out, SM.getSpellingLoc(Loc), SM, true);
130
5
  Out << " }";
131
5
}
132
} // namespace clang
133
134
#endif // LLVM_CLANG_BASIC_JSONSUPPORT_H