blob: 8841ff2b5cf744ed869e2845243db0250663298c [file] [log] [blame]
Sam McCalladbaebc2017-11-21 16:00:53 +00001//===--- JSONExpr.h - JSON expressions, parsing and serialization - C++ -*-===//
Sam McCalldd0566b2017-11-06 15:40:30 +00002//
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
Sam McCalladbaebc2017-11-21 16:00:53 +000010// FIXME: rename to JSON.h now that the scope is wider?
11
Sam McCalldd0566b2017-11-06 15:40:30 +000012#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
13#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_JSON_H
14
Sam McCalldd0566b2017-11-06 15:40:30 +000015#include "llvm/ADT/SmallVector.h"
16#include "llvm/ADT/StringRef.h"
Sam McCalladbaebc2017-11-21 16:00:53 +000017#include "llvm/Support/Error.h"
Sam McCalldd0566b2017-11-06 15:40:30 +000018#include "llvm/Support/FormatVariadic.h"
19#include "llvm/Support/raw_ostream.h"
Eric Liub99d5e82017-12-14 21:22:03 +000020#include <map>
Sam McCalldd0566b2017-11-06 15:40:30 +000021
22namespace clang {
23namespace clangd {
24namespace json {
25
Sam McCalladbaebc2017-11-21 16:00:53 +000026// An Expr is an JSON value of unknown type.
Sam McCalldd0566b2017-11-06 15:40:30 +000027// They can be copied, but should generally be moved.
28//
Sam McCalladbaebc2017-11-21 16:00:53 +000029// === Composing expressions ===
30//
31// You can implicitly construct Exprs from:
Sam McCalldd0566b2017-11-06 15:40:30 +000032// - 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}
Sam McCallff8b8742017-11-30 21:32:29 +000038// - serializable things: types with toJSON(const T&)->Expr, found by ADL
Sam McCalldd0566b2017-11-06 15:40:30 +000039//
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//
Sam McCalladbaebc2017-11-21 16:00:53 +000046// === 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:
Sam McCall1bb272b2017-11-28 09:25:09 +000057// if (Optional<StringRef> S = E.asString()
Sam McCalladbaebc2017-11-21 16:00:53 +000058// 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"}} )");
Sam McCall1bb272b2017-11-28 09:25:09 +000062// if (json::obj* O = E->asObject())
63// if (json::obj* Opts = O->getObject("options"))
64// if (Optional<StringRef> Font = Opts->getString("font"))
Sam McCalladbaebc2017-11-21 16:00:53 +000065// assert(Opts->at("font").kind() == Expr::String);
66//
Sam McCallff8b8742017-11-30 21:32:29 +000067// === 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//
Sam McCalladbaebc2017-11-21 16:00:53 +000089// === Serialization ===
90//
Sam McCalldd0566b2017-11-06 15:40:30 +000091// 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.
Sam McCalladbaebc2017-11-21 16:00:53 +000095//
96// And parsed:
97// Expected<Expr> E = json::parse("[1, 2, null]");
98// assert(E && E->kind() == Expr::Array);
Sam McCalldd0566b2017-11-06 15:40:30 +000099class Expr {
100public:
Sam McCalladbaebc2017-11-21 16:00:53 +0000101 enum Kind {
102 Null,
103 Boolean,
104 Number,
105 String,
106 Array,
107 Object,
108 };
109 class ObjectExpr;
Sam McCalldd0566b2017-11-06 15:40:30 +0000110 class ObjectKey;
Sam McCalladbaebc2017-11-21 16:00:53 +0000111 class ArrayExpr;
Sam McCalldd0566b2017-11-06 15:40:30 +0000112
113 // It would be nice to have Expr() be null. But that would make {} null too...
114 Expr(const Expr &M) { copyFrom(M); }
115 Expr(Expr &&M) { moveFrom(std::move(M)); }
116 // "cheating" move-constructor for moving from initializer_list.
117 Expr(const Expr &&M) { moveFrom(std::move(M)); }
Sam McCalladbaebc2017-11-21 16:00:53 +0000118 Expr(std::initializer_list<Expr> Elements) : Expr(ArrayExpr(Elements)) {}
119 Expr(ArrayExpr &&Elements) : Type(T_Array) {
120 create<ArrayExpr>(std::move(Elements));
121 }
122 Expr(ObjectExpr &&Properties) : Type(T_Object) {
123 create<ObjectExpr>(std::move(Properties));
Sam McCalldd0566b2017-11-06 15:40:30 +0000124 }
125 // Strings: types with value semantics.
126 Expr(std::string &&V) : Type(T_String) { create<std::string>(std::move(V)); }
127 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 Expr(llvm::StringRef V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
134 Expr(const char *V) : Type(T_StringRef) { create<llvm::StringRef>(V); }
135 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 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 Expr(T D) : Type(T_Number) {
149 create<double>(D);
150 }
Sam McCallff8b8742017-11-30 21:32:29 +0000151 // Types with a toJSON(const T&)->Expr function, found by ADL.
Sam McCalldd0566b2017-11-06 15:40:30 +0000152 template <typename T,
153 typename = typename std::enable_if<std::is_same<
Sam McCallff8b8742017-11-30 21:32:29 +0000154 Expr, decltype(toJSON(*(const T *)nullptr))>::value>>
155 Expr(const T &V) : Expr(toJSON(V)) {}
Sam McCalldd0566b2017-11-06 15:40:30 +0000156
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 ~Expr() { destroy(); }
168
Sam McCalladbaebc2017-11-21 16:00:53 +0000169 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 }
Aaron Ballmanfeeb0b72017-11-21 22:24:13 +0000185 llvm_unreachable("Unknown kind");
Sam McCalladbaebc2017-11-21 16:00:53 +0000186 }
187
188 // Typed accessors return None/nullptr if the Expr is not of this type.
Sam McCall1bb272b2017-11-28 09:25:09 +0000189 llvm::Optional<std::nullptr_t> asNull() const {
Sam McCalladbaebc2017-11-21 16:00:53 +0000190 if (LLVM_LIKELY(Type == T_Null))
191 return nullptr;
192 return llvm::None;
193 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000194 llvm::Optional<bool> asBoolean() const {
195 if (LLVM_LIKELY(Type == T_Boolean))
Sam McCalladbaebc2017-11-21 16:00:53 +0000196 return as<bool>();
197 return llvm::None;
198 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000199 llvm::Optional<double> asNumber() const {
Sam McCalladbaebc2017-11-21 16:00:53 +0000200 if (LLVM_LIKELY(Type == T_Number))
201 return as<double>();
202 return llvm::None;
203 }
Sam McCallec109022017-11-28 09:37:43 +0000204 llvm::Optional<int64_t> asInteger() const {
205 if (LLVM_LIKELY(Type == T_Number)) {
206 double D = as<double>();
207 if (LLVM_LIKELY(std::modf(D, &D) == 0 &&
208 D >= std::numeric_limits<int64_t>::min() &&
209 D <= std::numeric_limits<int64_t>::max()))
210 return D;
211 }
212 return llvm::None;
213 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000214 llvm::Optional<llvm::StringRef> asString() const {
Sam McCalladbaebc2017-11-21 16:00:53 +0000215 if (Type == T_String)
216 return llvm::StringRef(as<std::string>());
217 if (LLVM_LIKELY(Type == T_StringRef))
218 return as<llvm::StringRef>();
219 return llvm::None;
220 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000221 const ObjectExpr *asObject() const {
Sam McCalladbaebc2017-11-21 16:00:53 +0000222 return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
223 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000224 ObjectExpr *asObject() {
Sam McCalladbaebc2017-11-21 16:00:53 +0000225 return LLVM_LIKELY(Type == T_Object) ? &as<ObjectExpr>() : nullptr;
226 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000227 const ArrayExpr *asArray() const {
Sam McCalladbaebc2017-11-21 16:00:53 +0000228 return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
229 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000230 ArrayExpr *asArray() {
Sam McCalladbaebc2017-11-21 16:00:53 +0000231 return LLVM_LIKELY(Type == T_Array) ? &as<ArrayExpr>() : nullptr;
232 }
233
Sam McCalldd0566b2017-11-06 15:40:30 +0000234 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Expr &);
235
236private:
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 new (&as<T>()) T(std::forward<U>(V)...);
246 }
247 template <typename T> T &as() const {
248 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
266public:
Sam McCalladbaebc2017-11-21 16:00:53 +0000267 // ObjectKey is a used to capture keys in Expr::ObjectExpr. Like Expr but:
Sam McCalldd0566b2017-11-06 15:40:30 +0000268 // - only strings are allowed
Sam McCalldd0566b2017-11-06 15:40:30 +0000269 // - it's optimized for the string literal case (Owned == nullptr)
270 class ObjectKey {
271 public:
272 ObjectKey(const char *S) : Data(S) {}
273 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; }
Sam McCallc2055482017-11-07 08:57:54 +0000282 ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {}
Sam McCalldd0566b2017-11-06 15:40:30 +0000283 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 return L.Data < R.Data;
298 }
299
300 // "cheating" move-constructor for moving from initializer_list.
301 ObjectKey(const ObjectKey &&V) {
302 Owned = std::move(V.Owned);
303 Data = V.Data;
304 }
305
306 private:
307 mutable std::unique_ptr<std::string> Owned; // mutable for cheating.
308 llvm::StringRef Data;
309 };
310
Sam McCalladbaebc2017-11-21 16:00:53 +0000311 class ObjectExpr : public std::map<ObjectKey, Expr> {
Sam McCalldd0566b2017-11-06 15:40:30 +0000312 public:
Sam McCalladbaebc2017-11-21 16:00:53 +0000313 explicit ObjectExpr() {}
Sam McCalldd0566b2017-11-06 15:40:30 +0000314 // Use a custom struct for list-init, because pair forces extra copies.
315 struct KV;
Sam McCalladbaebc2017-11-21 16:00:53 +0000316 explicit ObjectExpr(std::initializer_list<KV> Properties);
Sam McCalldd0566b2017-11-06 15:40:30 +0000317
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 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000325
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 if (I == end())
330 return nullptr;
331 return &I->second;
332 }
333 const json::Expr *get(const ObjectKey &K) const {
334 auto I = find(K);
335 if (I == end())
336 return nullptr;
337 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 llvm::Optional<std::nullptr_t> getNull(const ObjectKey &K) const {
343 if (auto *V = get(K))
344 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 llvm::Optional<double> getNumber(const ObjectKey &K) const {
353 if (auto *V = get(K))
354 return V->asNumber();
355 return llvm::None;
356 }
Sam McCallec109022017-11-28 09:37:43 +0000357 llvm::Optional<int64_t> getInteger(const ObjectKey &K) const {
358 if (auto *V = get(K))
359 return V->asInteger();
360 return llvm::None;
361 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000362 llvm::Optional<llvm::StringRef> getString(const ObjectKey &K) const {
363 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 ObjectExpr *getObject(const ObjectKey &K) {
373 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 ArrayExpr *getArray(const ObjectKey &K) {
383 if (auto *V = get(K))
384 return V->asArray();
385 return nullptr;
386 }
Sam McCalldd0566b2017-11-06 15:40:30 +0000387 };
388
Sam McCalladbaebc2017-11-21 16:00:53 +0000389 class ArrayExpr : public std::vector<Expr> {
Sam McCalldd0566b2017-11-06 15:40:30 +0000390 public:
Sam McCalladbaebc2017-11-21 16:00:53 +0000391 explicit ArrayExpr() {}
392 explicit ArrayExpr(std::initializer_list<Expr> Elements) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000393 reserve(Elements.size());
394 for (const Expr &V : Elements)
395 emplace_back(std::move(V));
396 };
Sam McCalladbaebc2017-11-21 16:00:53 +0000397 template <typename Collection> explicit ArrayExpr(const Collection &C) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000398 for (const auto &V : C)
399 emplace_back(V);
400 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000401
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 return (*this)[I].asBoolean();
408 }
409 llvm::Optional<double> getNumber(size_t I) const {
410 return (*this)[I].asNumber();
411 }
Sam McCallec109022017-11-28 09:37:43 +0000412 llvm::Optional<int64_t> getInteger(size_t I) const {
413 return (*this)[I].asInteger();
414 }
Sam McCall1bb272b2017-11-28 09:25:09 +0000415 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 ArrayExpr *getArray(size_t I) { return (*this)[I].asArray(); }
Sam McCalldd0566b2017-11-06 15:40:30 +0000424 };
425
426private:
427 mutable llvm::AlignedCharArrayUnion<bool, double, llvm::StringRef,
Sam McCalladbaebc2017-11-21 16:00:53 +0000428 std::string, ArrayExpr, ObjectExpr>
Sam McCalldd0566b2017-11-06 15:40:30 +0000429 Union;
430};
431
Sam McCalladbaebc2017-11-21 16:00:53 +0000432bool operator==(const Expr &, const Expr &);
433inline bool operator!=(const Expr &L, const Expr &R) { return !(L == R); }
434inline bool operator==(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
435 return llvm::StringRef(L) == llvm::StringRef(R);
436}
437inline bool operator!=(const Expr::ObjectKey &L, const Expr::ObjectKey &R) {
438 return !(L == R);
439}
440
441struct Expr::ObjectExpr::KV {
Sam McCalldd0566b2017-11-06 15:40:30 +0000442 ObjectKey K;
443 Expr V;
444};
445
Sam McCalladbaebc2017-11-21 16:00:53 +0000446inline Expr::ObjectExpr::ObjectExpr(std::initializer_list<KV> Properties) {
Sam McCalldd0566b2017-11-06 15:40:30 +0000447 for (const auto &P : Properties)
448 emplace(std::move(P.K), std::move(P.V));
449}
450
451// Give Expr::{Object,Array} more convenient names for literal use.
Sam McCalladbaebc2017-11-21 16:00:53 +0000452using obj = Expr::ObjectExpr;
453using ary = Expr::ArrayExpr;
454
Sam McCallff8b8742017-11-30 21:32:29 +0000455// Standard deserializers.
456inline bool fromJSON(const json::Expr &E, std::string &Out) {
457 if (auto S = E.asString()) {
458 Out = *S;
459 return true;
460 }
461 return false;
462}
463inline bool fromJSON(const json::Expr &E, int &Out) {
464 if (auto S = E.asInteger()) {
465 Out = *S;
466 return true;
467 }
468 return false;
469}
470inline 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}
477inline bool fromJSON(const json::Expr &E, bool &Out) {
478 if (auto S = E.asBoolean()) {
479 Out = *S;
480 return true;
481 }
482 return false;
483}
484template <typename T>
485bool fromJSON(const json::Expr &E, llvm::Optional<T> &Out) {
486 if (E.asNull()) {
487 Out = llvm::None;
488 return true;
489 }
490 T Result;
491 if (!fromJSON(E, Result))
492 return false;
493 Out = std::move(Result);
494 return true;
495}
496template <typename T> bool fromJSON(const json::Expr &E, std::vector<T> &Out) {
497 if (auto *A = E.asArray()) {
498 Out.clear();
499 Out.resize(A->size());
500 for (size_t I = 0; I < A->size(); ++I)
501 if (!fromJSON((*A)[I], Out[I]))
502 return false;
503 return true;
504 }
505 return false;
506}
507template <typename T>
508bool fromJSON(const json::Expr &E, std::map<std::string, T> &Out) {
509 if (auto *O = E.asObject()) {
510 Out.clear();
511 for (const auto &KV : *O)
512 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.
521class ObjectMapper {
522public:
523 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 template <typename T> bool map(const char *Prop, T &Out) {
531 assert(*this && "Must check this is an object before calling map()");
532 if (const json::Expr *E = O->get(Prop))
533 return fromJSON(*E, Out);
534 return false;
535 }
536
537 // Optional requires special handling, because missing keys are OK.
538 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 if (const json::Expr *E = O->get(Prop))
541 return fromJSON(*E, Out);
542 Out = llvm::None;
543 return true;
544 }
545
546private:
547 const json::obj *O;
548};
549
Sam McCalladbaebc2017-11-21 16:00:53 +0000550llvm::Expected<Expr> parse(llvm::StringRef JSON);
551
552class ParseError : public llvm::ErrorInfo<ParseError> {
553 const char *Msg;
554 unsigned Line, Column, Offset;
555
556public:
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 void log(llvm::raw_ostream &OS) const override {
561 OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg);
562 }
563 std::error_code convertToErrorCode() const override {
564 return llvm::inconvertibleErrorCode();
565 }
566};
Sam McCalldd0566b2017-11-06 15:40:30 +0000567
568} // namespace json
569} // namespace clangd
570} // namespace clang
571
572namespace llvm {
573template <> 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