diff options
Diffstat (limited to 'include/clang/Basic/JsonSupport.h')
-rw-r--r-- | include/clang/Basic/JsonSupport.h | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/include/clang/Basic/JsonSupport.h b/include/clang/Basic/JsonSupport.h new file mode 100644 index 000000000000..bbcc747e6847 --- /dev/null +++ b/include/clang/Basic/JsonSupport.h @@ -0,0 +1,119 @@ +//===- JsonSupport.h - JSON Output Utilities --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_JSONSUPPORT_H +#define LLVM_CLANG_BASIC_JSONSUPPORT_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + + +namespace clang { + +inline raw_ostream &Indent(raw_ostream &Out, const unsigned int Space, + bool IsDot) { + for (unsigned int I = 0; I < Space * 2; ++I) + Out << (IsDot ? " " : " "); + return Out; +} + +inline std::string JsonFormat(StringRef RawSR, bool AddQuotes) { + if (RawSR.empty()) + return "null"; + + // Trim special characters. + std::string Str = RawSR.trim().str(); + size_t Pos = 0; + + // Escape backslashes. + while (true) { + Pos = Str.find('\\', Pos); + if (Pos == std::string::npos) + break; + + // Prevent bad conversions. + size_t TempPos = (Pos != 0) ? Pos - 1 : 0; + + // See whether the current backslash is not escaped. + if (TempPos != Str.find("\\\\", Pos)) { + Str.insert(Pos, "\\"); + ++Pos; // As we insert the backslash move plus one. + } + + ++Pos; + } + + // Escape double quotes. + Pos = 0; + while (true) { + Pos = Str.find('\"', Pos); + if (Pos == std::string::npos) + break; + + // Prevent bad conversions. + size_t TempPos = (Pos != 0) ? Pos - 1 : 0; + + // See whether the current double quote is not escaped. + if (TempPos != Str.find("\\\"", Pos)) { + Str.insert(Pos, "\\"); + ++Pos; // As we insert the escape-character move plus one. + } + + ++Pos; + } + + // Remove new-lines. + Str.erase(std::remove(Str.begin(), Str.end(), '\n'), Str.end()); + + if (!AddQuotes) + return Str; + + return '\"' + Str + '\"'; +} + +inline void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, + const SourceManager &SM, + bool AddBraces = true) { + // Mostly copy-pasted from SourceLocation::print. + if (!Loc.isValid()) { + Out << "null"; + return; + } + + if (Loc.isFileID()) { + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + + if (PLoc.isInvalid()) { + Out << "null"; + return; + } + // The macro expansion and spelling pos is identical for file locs. + if (AddBraces) + Out << "{ "; + Out << "\"line\": " << PLoc.getLine() + << ", \"column\": " << PLoc.getColumn() + << ", \"file\": \"" << PLoc.getFilename() << "\""; + if (AddBraces) + Out << " }"; + return; + } + + // We want 'location: { ..., spelling: { ... }}' but not + // 'location: { ... }, spelling: { ... }', hence the dance + // with braces. + Out << "{ "; + printSourceLocationAsJson(Out, SM.getExpansionLoc(Loc), SM, false); + Out << ", \"spelling\": "; + printSourceLocationAsJson(Out, SM.getSpellingLoc(Loc), SM, true); + Out << " }"; +} +} // namespace clang + +#endif // LLVM_CLANG_BASIC_JSONSUPPORT_H |