LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd - JSONExpr.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 99 0.0 %
Date: 2018-05-20 00:06:23 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- JSONExpr.h - JSON expressions, parsing and serialization - 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             : // FIXME: rename to JSON.h now that the scope is wider?
      11             : 
      12             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
      13             : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
      14             : 
      15             : #include "llvm/ADT/SmallVector.h"
      16             : #include "llvm/ADT/StringRef.h"
      17             : #include "llvm/Support/Error.h"
      18             : #include "llvm/Support/FormatVariadic.h"
      19             : #include "llvm/Support/raw_ostream.h"
      20             : #include <map>
      21             : 
      22             : namespace clang {
      23             : namespace clangd {
      24             : namespace json {
      25             : 
      26             : // An Expr is an JSON value of unknown type.
      27             : // They can be copied, but should generally be moved.
      28             : //
      29             : // === Composing expressions ===
      30             : //
      31             : // You can implicitly construct Exprs from:
      32             : //   - strings: std::string, SmallString, formatv, StringRef, char*
      33             : //              (char*, and StringRef are references, not copies!)
      34             : //   - numbers
      35             : //   - booleans
      36             : //   - null: nullptr
      37             : //   - arrays: {"foo", 42.0, false}
      38             : //   - serializable things: types with toJSON(const T&)->Expr, found by ADL
      39             : //
      40             : // They can also be constructed from object/array helpers:
      41             : //   - json::obj is a type like map<StringExpr, Expr>
      42             : //   - json::ary is a type like vector<Expr>
      43             : // These can be list-initialized, or used to build up collections in a loop.
      44             : // json::ary(Collection) converts all items in a collection to Exprs.
      45             : //
      46             : // === Inspecting expressions ===
      47             : //
      48             : // Each Expr is one of the JSON kinds:
      49             : //   null    (nullptr_t)
      50             : //   boolean (bool)
      51             : //   number  (double)
      52             : //   string  (StringRef)
      53             : //   array   (json::ary)
      54             : //   object  (json::obj)
      55             : //
      56             : // The kind can be queried directly, or implicitly via the typed accessors:
      57             : //   if (Optional<StringRef> S = E.asString()
      58             : //     assert(E.kind() == Expr::String);
      59             : //
      60             : // Array and Object also have typed indexing accessors for easy traversal:
      61             : //   Expected<Expr> E = parse(R"( {"options": {"font": "sans-serif"}} )");
      62             : //   if (json::obj* O = E->asObject())
      63             : //     if (json::obj* Opts = O->getObject("options"))
      64             : //       if (Optional<StringRef> Font = Opts->getString("font"))
      65             : //         assert(Opts->at("font").kind() == Expr::String);
      66             : //
      67             : // === Converting expressions to objects ===
      68             : //
      69             : // The convention is to have a deserializer function findable via ADL:
      70             : //     fromJSON(const json::Expr&, T&)->bool
      71             : // Deserializers are provided for:
      72             : //   - bool
      73             : //   - int
      74             : //   - double
      75             : //   - std::string
      76             : //   - vector<T>, where T is deserializable
      77             : //   - map<string, T>, where T is deserializable
      78             : //   - Optional<T>, where T is deserializable
      79             : //
      80             : // ObjectMapper can help writing fromJSON() functions for object types:
      81             : //   bool fromJSON(const Expr &E, MyStruct &R) {
      82             : //     ObjectMapper O(E);
      83             : //     if (!O || !O.map("mandatory_field", R.MandatoryField))
      84             : //       return false;
      85             : //     O.map("optional_field", R.OptionalField);
      86             : //     return true;
      87             : //   }
      88             : //
      89             : // === Serialization ===
      90             : //
      91             : // Exprs can be serialized to JSON:
      92             : //   1) raw_ostream << Expr                    // Basic formatting.
      93             : //   2) raw_ostream << formatv("{0}", Expr)    // Basic formatting.
      94             : //   3) raw_ostream << formatv("{0:2}", Expr)  // Pretty-print with indent 2.
      95             : //
      96             : // And parsed:
      97             : //   Expected<Expr> E = json::parse("[1, 2, null]");
      98             : //   assert(E && E->kind() == Expr::Array);
      99             : class Expr {
     100             : public:
     101             :   enum Kind {
     102             :     Null,
     103             :     Boolean,
     104             :     Number,
     105             :     String,
     106             :     Array,
     107             :     Object,
     108             :   };
     109             :   class ObjectExpr;
     110             :   class ObjectKey;
     111             :   class ArrayExpr;
     112             : 
     113             :   // It would be nice to have Expr() be null. But that would make {} null too...
     114           0 :   Expr(const Expr &M) { copyFrom(M); }
     115             :   Expr(Expr &&M) { moveFrom(std::move(M)); }
     116             :   // "cheating" move-constructor for moving from initializer_list.
     117           0 :   Expr(const Expr &&M) { moveFrom(std::move(M)); }
     118           0 :   Expr(std::initializer_list<Expr> Elements) : Expr(ArrayExpr(Elements)) {}
     119           0 :   Expr(ArrayExpr &&Elements) : Type(T_Array) {
     120             :     create<ArrayExpr>(std::move(Elements));
     121             :   }
     122           0 :   Expr(ObjectExpr &&Properties) : Type(T_Object) {
     123             :     create<ObjectExpr>(std::move(Properties));
     124             :   }
     125             :   // Strings: types with value semantics.
     126             :   Expr(std::string &&V) : Type(T_String) { create<std::string>(std::move(V)); }
     127           0 :   Expr(const std::string &V) : Type(T_String) { create<std::string>(V); }
     128             :   Expr(const llvm::SmallVectorImpl<char> &V) : Type(T_String) {
     129             :     create<std::string>(V.begin(), V.end());
     130             :   }
     131             :   Expr(const llvm::formatv_object_base &V) : Expr(V.str()){};
     132             :   // Strings: types with reference semantics.
     133           0 :   Expr(llvm::StringRef V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
     134           0 :   Expr(const char *V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
     135           0 :   Expr(std::nullptr_t) : Type(T_Null) {}
     136             :   // Prevent implicit conversions to boolean.
     137             :   template <typename T, typename = typename std::enable_if<
     138             :                             std::is_same<T, bool>::value>::type>
     139           0 :   Expr(T B) : Type(T_Boolean) {
     140             :     create<bool>(B);
     141             :   }
     142             :   // Numbers: arithmetic types that are not boolean.
     143             :   template <
     144             :       typename T,
     145             :       typename = typename std::enable_if<std::is_arithmetic<T>::value>::type,
     146             :       typename = typename std::enable_if<std::integral_constant<
     147             :           bool, !std::is_same<T, bool>::value>::value>::type>
     148           0 :   Expr(T D) : Type(T_Number) {
     149             :     create<double>(D);
     150             :   }
     151             :   // Types with a toJSON(const T&)->Expr function, found by ADL.
     152             :   template <typename T,
     153             :             typename = typename std::enable_if<std::is_same<
     154             :                 Expr, decltype(toJSON(*(const T *)nullptr))>::value>>
     155             :   Expr(const T &V) : Expr(toJSON(V)) {}
     156             : 
     157             :   Expr &operator=(const Expr &M) {
     158             :     destroy();
     159             :     copyFrom(M);
     160             :     return *this;
     161             :   }
     162             :   Expr &operator=(Expr &&M) {
     163             :     destroy();
     164             :     moveFrom(std::move(M));
     165             :     return *this;
     166             :   }
     167           0 :   ~Expr() { destroy(); }
     168             : 
     169             :   Kind kind() const {
     170             :     switch (Type) {
     171             :     case T_Null:
     172             :       return Null;
     173             :     case T_Boolean:
     174             :       return Boolean;
     175             :     case T_Number:
     176             :       return Number;
     177             :     case T_String:
     178             :     case T_StringRef:
     179             :       return String;
     180             :     case T_Object:
     181             :       return Object;
     182             :     case T_Array:
     183             :       return Array;
     184             :     }
     185             :     llvm_unreachable("Unknown kind");
     186             :   }
     187             : 
     188             :   // Typed accessors return None/nullptr if the Expr is not of this type.
     189             :   llvm::Optional<std::nullptr_t> asNull() const {
     190           0 :     if (LLVM_LIKELY(Type == T_Null))
     191             :       return nullptr;
     192             :     return llvm::None;
     193             :   }
     194             :   llvm::Optional<bool> asBoolean() const {
     195           0 :     if (LLVM_LIKELY(Type == T_Boolean))
     196             :       return as<bool>();
     197             :     return llvm::None;
     198             :   }
     199             :   llvm::Optional<double> asNumber() const {
     200           0 :     if (LLVM_LIKELY(Type == T_Number))
     201             :       return as<double>();
     202             :     return llvm::None;
     203             :   }
     204           0 :   llvm::Optional<int64_t> asInteger() const {
     205           0 :     if (LLVM_LIKELY(Type == T_Number)) {
     206           0 :       double D = as<double>();
     207           0 :       if (LLVM_LIKELY(std::modf(D, &D) == 0 &&
     208             :                       D >= std::numeric_limits<int64_t>::min() &&
     209           0 :                       D <= std::numeric_limits<int64_t>::max()))
     210           0 :         return D;
     211             :     }
     212             :     return llvm::None;
     213             :   }
     214             :   llvm::Optional<llvm::StringRef> asString() const {
     215           0 :     if (Type == T_String)
     216             :       return llvm::StringRef(as<std::string>());
     217           0 :     if (LLVM_LIKELY(Type == T_StringRef))
     218             :       return as<llvm::StringRef>();
     219             :     return llvm::None;
     220             :   }
     221             :   const ObjectExpr *asObject() const {
     222           0 :     return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
     223             :   }
     224             :   ObjectExpr *asObject() {
     225           0 :     return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
     226             :   }
     227             :   const ArrayExpr *asArray() const {
     228           0 :     return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
     229             :   }
     230             :   ArrayExpr *asArray() {
     231           0 :     return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
     232             :   }
     233             : 
     234             :   friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Expr &);
     235             : 
     236             : private:
     237             :   void destroy();
     238             :   void copyFrom(const Expr &M);
     239             :   // We allow moving from *const* Exprs, by marking all members as mutable!
     240             :   // This hack is needed to support initializer-list syntax efficiently.
     241             :   // (std::initializer_list<T> is a container of const T).
     242             :   void moveFrom(const Expr &&M);
     243             : 
     244             :   template <typename T, typename... U> void create(U &&... V) {
     245           0 :     new (&as<T>()) T(std::forward<U>(V)...);
     246             :   }
     247             :   template <typename T> T &as() const {
     248           0 :     return *reinterpret_cast<T *>(Union.buffer);
     249             :   }
     250             : 
     251             :   template <typename Indenter>
     252             :   void print(llvm::raw_ostream &, const Indenter &) const;
     253             :   friend struct llvm::format_provider<clang::clangd::json::Expr>;
     254             : 
     255             :   enum ExprType : char {
     256             :     T_Null,
     257             :     T_Boolean,
     258             :     T_Number,
     259             :     T_StringRef,
     260             :     T_String,
     261             :     T_Object,
     262             :     T_Array,
     263             :   };
     264             :   mutable ExprType Type;
     265             : 
     266             : public:
     267             :   // ObjectKey is a used to capture keys in Expr::ObjectExpr. Like Expr but:
     268             :   //   - only strings are allowed
     269             :   //   - it's optimized for the string literal case (Owned == nullptr)
     270             :   class ObjectKey {
     271             :   public:
     272             :     ObjectKey(const char *S) : Data(S) {}
     273           0 :     ObjectKey(llvm::StringRef S) : Data(S) {}
     274             :     ObjectKey(std::string &&V)
     275             :         : Owned(new std::string(std::move(V))), Data(*Owned) {}
     276             :     ObjectKey(const std::string &V) : Owned(new std::string(V)), Data(*Owned) {}
     277             :     ObjectKey(const llvm::SmallVectorImpl<char> &V)
     278             :         : ObjectKey(std::string(V.begin(), V.end())) {}
     279             :     ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {}
     280             : 
     281             :     ObjectKey(const ObjectKey &C) { *this = C; }
     282             :     ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
     283             :     ObjectKey &operator=(const ObjectKey &C) {
     284             :       if (C.Owned) {
     285             :         Owned.reset(new std::string(*C.Owned));
     286             :         Data = *Owned;
     287             :       } else {
     288             :         Data = C.Data;
     289             :       }
     290             :       return *this;
     291             :     }
     292             :     ObjectKey &operator=(ObjectKey &&) = default;
     293             : 
     294             :     operator llvm::StringRef() const { return Data; }
     295             : 
     296             :     friend bool operator<(const ObjectKey &L, const ObjectKey &R) {
     297           0 :       return L.Data < R.Data;
     298             :     }
     299             : 
     300             :     // "cheating" move-constructor for moving from initializer_list.
     301           0 :     ObjectKey(const ObjectKey &&V) {
     302             :       Owned = std::move(V.Owned);
     303           0 :       Data = V.Data;
     304             :     }
     305             : 
     306             :   private:
     307             :     mutable std::unique_ptr<std::string> Owned; // mutable for cheating.
     308             :     llvm::StringRef Data;
     309             :   };
     310             : 
     311             :   class ObjectExpr : public std::map<ObjectKey, Expr> {
     312             :   public:
     313           0 :     explicit ObjectExpr() {}
     314             :     // Use a custom struct for list-init, because pair forces extra copies.
     315             :     struct KV;
     316             :     explicit ObjectExpr(std::initializer_list<KV> Properties);
     317             : 
     318             :     // Allow [] as if Expr was default-constructible as null.
     319             :     Expr &operator[](const ObjectKey &K) {
     320             :       return emplace(K, Expr(nullptr)).first->second;
     321             :     }
     322             :     Expr &operator[](ObjectKey &&K) {
     323             :       return emplace(std::move(K), Expr(nullptr)).first->second;
     324             :     }
     325             : 
     326             :     // Look up a property, returning nullptr if it doesn't exist.
     327             :     json::Expr *get(const ObjectKey &K) {
     328             :       auto I = find(K);
     329           0 :       if (I == end())
     330             :         return nullptr;
     331           0 :       return &I->second;
     332             :     }
     333             :     const json::Expr *get(const ObjectKey &K) const {
     334             :       auto I = find(K);
     335           0 :       if (I == end())
     336             :         return nullptr;
     337           0 :       return &I->second;
     338             :     }
     339             :     // Typed accessors return None/nullptr if
     340             :     //   - the property doesn't exist
     341             :     //   - or it has the wrong type
     342           0 :     llvm::Optional<std::nullptr_t> getNull(const ObjectKey &K) const {
     343           0 :       if (auto *V = get(K))
     344           0 :         return V->asNull();
     345             :       return llvm::None;
     346             :     }
     347             :     llvm::Optional<bool> getBoolean(const ObjectKey &K) const {
     348             :       if (auto *V = get(K))
     349             :         return V->asBoolean();
     350             :       return llvm::None;
     351             :     }
     352           0 :     llvm::Optional<double> getNumber(const ObjectKey &K) const {
     353           0 :       if (auto *V = get(K))
     354             :         return V->asNumber();
     355             :       return llvm::None;
     356             :     }
     357           0 :     llvm::Optional<int64_t> getInteger(const ObjectKey &K) const {
     358           0 :       if (auto *V = get(K))
     359           0 :         return V->asInteger();
     360             :       return llvm::None;
     361             :     }
     362           0 :     llvm::Optional<llvm::StringRef> getString(const ObjectKey &K) const {
     363           0 :       if (auto *V = get(K))
     364             :         return V->asString();
     365             :       return llvm::None;
     366             :     }
     367             :     const ObjectExpr *getObject(const ObjectKey &K) const {
     368             :       if (auto *V = get(K))
     369             :         return V->asObject();
     370             :       return nullptr;
     371             :     }
     372           0 :     ObjectExpr *getObject(const ObjectKey &K) {
     373           0 :       if (auto *V = get(K))
     374             :         return V->asObject();
     375             :       return nullptr;
     376             :     }
     377             :     const ArrayExpr *getArray(const ObjectKey &K) const {
     378             :       if (auto *V = get(K))
     379             :         return V->asArray();
     380             :       return nullptr;
     381             :     }
     382           0 :     ArrayExpr *getArray(const ObjectKey &K) {
     383           0 :       if (auto *V = get(K))
     384             :         return V->asArray();
     385             :       return nullptr;
     386             :     }
     387             :   };
     388             : 
     389           0 :   class ArrayExpr : public std::vector<Expr> {
     390             :   public:
     391             :     explicit ArrayExpr() {}
     392           0 :     explicit ArrayExpr(std::initializer_list<Expr> Elements) {
     393           0 :       reserve(Elements.size());
     394           0 :       for (const Expr &V : Elements)
     395           0 :         emplace_back(std::move(V));
     396           0 :     };
     397             :     template <typename Collection> explicit ArrayExpr(const Collection &C) {
     398             :       for (const auto &V : C)
     399             :         emplace_back(V);
     400             :     }
     401             : 
     402             :     // Typed accessors return None/nullptr if the element has the wrong type.
     403             :     llvm::Optional<std::nullptr_t> getNull(size_t I) const {
     404             :       return (*this)[I].asNull();
     405             :     }
     406             :     llvm::Optional<bool> getBoolean(size_t I) const {
     407           0 :       return (*this)[I].asBoolean();
     408             :     }
     409             :     llvm::Optional<double> getNumber(size_t I) const {
     410             :       return (*this)[I].asNumber();
     411             :     }
     412             :     llvm::Optional<int64_t> getInteger(size_t I) const {
     413           0 :       return (*this)[I].asInteger();
     414             :     }
     415             :     llvm::Optional<llvm::StringRef> getString(size_t I) const {
     416             :       return (*this)[I].asString();
     417             :     }
     418             :     const ObjectExpr *getObject(size_t I) const {
     419             :       return (*this)[I].asObject();
     420             :     }
     421             :     ObjectExpr *getObject(size_t I) { return (*this)[I].asObject(); }
     422             :     const ArrayExpr *getArray(size_t I) const { return (*this)[I].asArray(); }
     423           0 :     ArrayExpr *getArray(size_t I) { return (*this)[I].asArray(); }
     424             :   };
     425             : 
     426             : private:
     427             :   mutable llvm::AlignedCharArrayUnion<bool, double, llvm::StringRef,
     428             :                                       std::string, ArrayExpr, ObjectExpr>
     429             :       Union;
     430             : };
     431             : 
     432             : bool operator==(const Expr &, const Expr &);
     433             : inline bool operator!=(const Expr &L, const Expr &R) { return !(L == R); }
     434           0 : inline bool operator==(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
     435           0 :   return llvm::StringRef(L) == llvm::StringRef(R);
     436             : }
     437             : inline bool operator!=(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
     438             :   return !(L == R);
     439             : }
     440             : 
     441           0 : struct Expr::ObjectExpr::KV {
     442             :   ObjectKey K;
     443             :   Expr V;
     444             : };
     445             : 
     446           0 : inline Expr::ObjectExpr::ObjectExpr(std::initializer_list<KV> Properties) {
     447           0 :   for (const auto &P : Properties)
     448           0 :     emplace(std::move(P.K), std::move(P.V));
     449           0 : }
     450             : 
     451             : // Give Expr::{Object,Array} more convenient names for literal use.
     452             : using obj = Expr::ObjectExpr;
     453             : using ary = Expr::ArrayExpr;
     454             : 
     455             : // Standard deserializers.
     456           0 : inline bool fromJSON(const json::Expr &E, std::string &Out) {
     457           0 :   if (auto S = E.asString()) {
     458           0 :     Out = *S;
     459             :     return true;
     460             :   }
     461             :   return false;
     462             : }
     463             : inline bool fromJSON(const json::Expr &E, int &Out) {
     464           0 :   if (auto S = E.asInteger()) {
     465           0 :     Out = *S;
     466             :     return true;
     467             :   }
     468             :   return false;
     469             : }
     470             : inline bool fromJSON(const json::Expr &E, double &Out) {
     471             :   if (auto S = E.asNumber()) {
     472             :     Out = *S;
     473             :     return true;
     474             :   }
     475             :   return false;
     476             : }
     477             : inline bool fromJSON(const json::Expr &E, bool &Out) {
     478           0 :   if (auto S = E.asBoolean()) {
     479           0 :     Out = *S;
     480             :     return true;
     481             :   }
     482             :   return false;
     483             : }
     484             : template <typename T>
     485           0 : bool fromJSON(const json::Expr &E, llvm::Optional<T> &Out) {
     486           0 :   if (E.asNull()) {
     487             :     Out = llvm::None;
     488           0 :     return true;
     489             :   }
     490             :   T Result;
     491           0 :   if (!fromJSON(E, Result))
     492             :     return false;
     493             :   Out = std::move(Result);
     494             :   return true;
     495             : }
     496           0 : template <typename T> bool fromJSON(const json::Expr &E, std::vector<T> &Out) {
     497             :   if (auto *A = E.asArray()) {
     498           0 :     Out.clear();
     499           0 :     Out.resize(A->size());
     500           0 :     for (size_t I = 0; I < A->size(); ++I)
     501           0 :       if (!fromJSON((*A)[I], Out[I]))
     502             :         return false;
     503             :     return true;
     504             :   }
     505             :   return false;
     506             : }
     507             : template <typename T>
     508           0 : bool fromJSON(const json::Expr &E, std::map<std::string, T> &Out) {
     509             :   if (auto *O = E.asObject()) {
     510             :     Out.clear();
     511           0 :     for (const auto &KV : *O)
     512           0 :       if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
     513             :         return false;
     514             :     return true;
     515             :   }
     516             :   return false;
     517             : }
     518             : 
     519             : // Helper for mapping JSON objects onto protocol structs.
     520             : // See file header for example.
     521             : class ObjectMapper {
     522             : public:
     523           0 :   ObjectMapper(const json::Expr &E) : O(E.asObject()) {}
     524             : 
     525             :   // True if the expression is an object.
     526             :   // Must be checked before calling map().
     527             :   operator bool() { return O; }
     528             : 
     529             :   // Maps a property to a field, if it exists.
     530           0 :   template <typename T> bool map(const char *Prop, T &Out) {
     531             :     assert(*this && "Must check this is an object before calling map()");
     532           0 :     if (const json::Expr *E = O->get(Prop))
     533           0 :       return fromJSON(*E, Out);
     534             :     return false;
     535             :   }
     536             : 
     537             :   // Optional requires special handling, because missing keys are OK.
     538           0 :   template <typename T> bool map(const char *Prop, llvm::Optional<T> &Out) {
     539             :     assert(*this && "Must check this is an object before calling map()");
     540           0 :     if (const json::Expr *E = O->get(Prop))
     541           0 :       return fromJSON(*E, Out);
     542             :     Out = llvm::None;
     543           0 :     return true;
     544             :   }
     545             : 
     546             : private:
     547             :   const json::obj *O;
     548             : };
     549             : 
     550             : llvm::Expected<Expr> parse(llvm::StringRef JSON);
     551             : 
     552           0 : class ParseError : public llvm::ErrorInfo<ParseError> {
     553             :   const char *Msg;
     554             :   unsigned Line, Column, Offset;
     555             : 
     556             : public:
     557             :   static char ID;
     558             :   ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset)
     559             :       : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {}
     560           0 :   void log(llvm::raw_ostream &OS) const override {
     561           0 :     OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
     562           0 :   }
     563             :   std::error_code convertToErrorCode() const override {
     564             :     return llvm::inconvertibleErrorCode();
     565             :   }
     566             : };
     567             : 
     568             : } // namespace json
     569             : } // namespace clangd
     570             : } // namespace clang
     571             : 
     572             : namespace llvm {
     573             : template <> struct format_provider<clang::clangd::json::Expr> {
     574             :   static void format(const clang::clangd::json::Expr &, raw_ostream &,
     575             :                      StringRef);
     576             : };
     577             : } // namespace llvm
     578             : 
     579             : #endif

Generated by: LCOV version 1.13