1//===- JSONFormatImpl.cpp -------------------------------------------------===//
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#include "JSONFormatImpl.h"
10
11#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
12#include "llvm/Support/Registry.h"
13#include "llvm/TargetParser/Triple.h"
14
15using namespace clang;
16using namespace ssaf;
17
18LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
19LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::AnalysisResultRegistry::Codec>)
20
21static SerializationFormatRegistry::Add<JSONFormat>
22 RegisterJSONFormat("json", "JSON serialization format");
23
24namespace clang::ssaf {
25
26// NOLINTNEXTLINE(misc-use-internal-linkage)
27volatile int JSONFormatAnchorSource = 0;
28
29//----------------------------------------------------------------------------
30// JSON Reader and Writer
31//----------------------------------------------------------------------------
32
33llvm::Expected<Value> readJSON(llvm::StringRef Path) {
34 if (!llvm::sys::fs::exists(Path)) {
35 return ErrorBuilder::create(EC: std::errc::no_such_file_or_directory,
36 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
37 ArgVals: ErrorMessages::FileNotFound)
38 .build();
39 }
40
41 if (llvm::sys::fs::is_directory(Path)) {
42 return ErrorBuilder::create(EC: std::errc::is_a_directory,
43 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
44 ArgVals: ErrorMessages::FileIsDirectory)
45 .build();
46 }
47
48 if (!Path.ends_with(Suffix: JSONFormatFileExtension)) {
49 return ErrorBuilder::create(EC: std::errc::invalid_argument,
50 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
51 ArgVals: llvm::formatv(Fmt: ErrorMessages::FileIsNotJSON,
52 Vals: JSONFormatFileExtension))
53 .build();
54 }
55
56 auto BufferOrError = llvm::MemoryBuffer::getFile(Filename: Path);
57 if (!BufferOrError) {
58 const std::error_code EC = BufferOrError.getError();
59 return ErrorBuilder::create(EC, Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
60 ArgVals: EC.message())
61 .build();
62 }
63
64 return llvm::json::parse(JSON: BufferOrError.get()->getBuffer());
65}
66
67llvm::Error writeJSON(Value &&V, llvm::StringRef Path) {
68 if (llvm::sys::fs::exists(Path)) {
69 return ErrorBuilder::create(EC: std::errc::file_exists,
70 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
71 ArgVals: ErrorMessages::FileExists)
72 .build();
73 }
74
75 llvm::StringRef Dir = llvm::sys::path::parent_path(path: Path);
76 if (!Dir.empty() && !llvm::sys::fs::is_directory(Path: Dir)) {
77 return ErrorBuilder::create(EC: std::errc::no_such_file_or_directory,
78 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
79 ArgVals: ErrorMessages::ParentDirectoryNotFound)
80 .build();
81 }
82
83 if (!Path.ends_with(Suffix: JSONFormatFileExtension)) {
84 return ErrorBuilder::create(EC: std::errc::invalid_argument,
85 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
86 ArgVals: llvm::formatv(Fmt: ErrorMessages::FileIsNotJSON,
87 Vals: JSONFormatFileExtension))
88 .build();
89 }
90
91 std::error_code EC;
92 llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text);
93
94 if (EC) {
95 return ErrorBuilder::create(EC, Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
96 ArgVals: EC.message())
97 .build();
98 }
99
100 OutStream << llvm::formatv(Fmt: "{0:2}\n", Vals&: V);
101 OutStream.flush();
102
103 // This path handles post-write stream errors (e.g. ENOSPC after buffered
104 // writes). It is difficult to exercise in unit tests so it is intentionally
105 // left without test coverage.
106 if (OutStream.has_error()) {
107 return ErrorBuilder::create(EC: OutStream.error(),
108 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
109 ArgVals: OutStream.error().message())
110 .build();
111 }
112
113 return llvm::Error::success();
114}
115
116//----------------------------------------------------------------------------
117// JSONFormat Static Methods
118//----------------------------------------------------------------------------
119
120std::map<SummaryName, JSONFormat::FormatInfo> JSONFormat::initFormatInfos() {
121 std::map<SummaryName, FormatInfo> FormatInfos;
122 for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
123 std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
124 bool Inserted = FormatInfos.try_emplace(k: Info->ForSummary, args&: *Info).second;
125 if (!Inserted) {
126 llvm::report_fatal_error(
127 reason: "FormatInfo is already registered for summary: " +
128 Info->ForSummary.str());
129 }
130 }
131 return FormatInfos;
132}
133
134void JSONFormat::forEachRegisteredAnalysis(
135 llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> Callback) const {
136 for (const auto &Entry : llvm::Registry<FormatInfo>::entries())
137 Callback(Entry.getName(), Entry.getDesc());
138}
139
140//----------------------------------------------------------------------------
141// SummaryName
142//----------------------------------------------------------------------------
143
144SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) {
145 return SummaryName(SummaryNameStr.str());
146}
147
148llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); }
149
150//----------------------------------------------------------------------------
151// Summary Type field
152//----------------------------------------------------------------------------
153
154llvm::Expected<llvm::StringRef> readSummaryType(const Object &RootObject) {
155 std::optional<llvm::StringRef> OptType = RootObject.getString(K: JSONTypeKey);
156 if (!OptType) {
157 return ErrorBuilder::create(EC: std::errc::invalid_argument,
158 Fmt: ErrorMessages::FailedToReadObjectAtField,
159 ArgVals: "summary type", ArgVals: JSONTypeKey, ArgVals: "string")
160 .build();
161 }
162 return *OptType;
163}
164
165llvm::Error checkSummaryType(const Object &RootObject,
166 llvm::StringRef ExpectedType) {
167 auto ExpectedActual = readSummaryType(RootObject);
168 if (!ExpectedActual) {
169 return ExpectedActual.takeError();
170 }
171 if (*ExpectedActual != ExpectedType) {
172 return ErrorBuilder::create(EC: std::errc::invalid_argument,
173 Fmt: ErrorMessages::MismatchedSummaryType,
174 ArgVals&: ExpectedType, ArgVals: JSONTypeKey, ArgVals&: *ExpectedActual)
175 .build();
176 }
177 return llvm::Error::success();
178}
179
180//----------------------------------------------------------------------------
181// AnalysisName
182//----------------------------------------------------------------------------
183
184AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr) {
185 return AnalysisName(AnalysisNameStr.str());
186}
187
188llvm::StringRef analysisNameToJSON(const AnalysisName &AN) { return AN.str(); }
189
190//----------------------------------------------------------------------------
191// EntityId
192//----------------------------------------------------------------------------
193
194EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const {
195 return makeEntityId(Index: static_cast<size_t>(EntityIdIndex));
196}
197
198uint64_t JSONFormat::entityIdToJSON(EntityId EI) const {
199 return static_cast<uint64_t>(getIndex(X&: EI));
200}
201
202llvm::Expected<EntityId>
203JSONFormat::entityIdFromJSONObject(const Object &EntityIdObject) {
204 if (EntityIdObject.size() != 1) {
205 return ErrorBuilder::create(EC: std::errc::invalid_argument,
206 Fmt: ErrorMessages::FailedToReadEntityIdObject,
207 ArgVals: JSONEntityIdKey)
208 .build();
209 }
210
211 const llvm::json::Value *AtVal = EntityIdObject.get(K: JSONEntityIdKey);
212 if (!AtVal) {
213 return ErrorBuilder::create(EC: std::errc::invalid_argument,
214 Fmt: ErrorMessages::FailedToReadEntityIdObject,
215 ArgVals: JSONEntityIdKey)
216 .build();
217 }
218
219 std::optional<uint64_t> OptEntityIdIndex = AtVal->getAsUINT64();
220 if (!OptEntityIdIndex) {
221 return ErrorBuilder::create(EC: std::errc::invalid_argument,
222 Fmt: ErrorMessages::FailedToReadEntityIdObject,
223 ArgVals: JSONEntityIdKey)
224 .build();
225 }
226
227 return makeEntityId(Index: static_cast<size_t>(*OptEntityIdIndex));
228}
229
230Object JSONFormat::entityIdToJSONObject(EntityId EI) {
231 Object Result;
232 Result[JSONEntityIdKey] = static_cast<uint64_t>(getIndex(X&: EI));
233 return Result;
234}
235
236//----------------------------------------------------------------------------
237// BuildNamespaceKind
238//----------------------------------------------------------------------------
239
240llvm::Expected<BuildNamespaceKind>
241buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr) {
242 auto OptBuildNamespaceKind =
243 buildNamespaceKindFromString(Str: BuildNamespaceKindStr);
244 if (!OptBuildNamespaceKind) {
245 return ErrorBuilder::create(EC: std::errc::invalid_argument,
246 Fmt: ErrorMessages::InvalidBuildNamespaceKind,
247 ArgVals&: BuildNamespaceKindStr)
248 .build();
249 }
250 return *OptBuildNamespaceKind;
251}
252
253// Provided for consistency with respect to rest of the codebase.
254llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) {
255 return buildNamespaceKindToString(BNK);
256}
257
258//----------------------------------------------------------------------------
259// BuildNamespace
260//----------------------------------------------------------------------------
261
262llvm::Expected<BuildNamespace>
263JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const {
264 auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString(K: "kind");
265 if (!OptBuildNamespaceKindStr) {
266 return ErrorBuilder::create(EC: std::errc::invalid_argument,
267 Fmt: ErrorMessages::FailedToReadObjectAtField,
268 ArgVals: "BuildNamespaceKind", ArgVals: "kind", ArgVals: "string")
269 .build();
270 }
271
272 auto ExpectedKind = buildNamespaceKindFromJSON(BuildNamespaceKindStr: *OptBuildNamespaceKindStr);
273 if (!ExpectedKind) {
274 return ErrorBuilder::wrap(E: ExpectedKind.takeError())
275 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "BuildNamespaceKind", ArgVals: "kind")
276 .build();
277 }
278
279 auto OptNameStr = BuildNamespaceObject.getString(K: "name");
280 if (!OptNameStr) {
281 return ErrorBuilder::create(EC: std::errc::invalid_argument,
282 Fmt: ErrorMessages::FailedToReadObjectAtField,
283 ArgVals: "BuildNamespaceName", ArgVals: "name", ArgVals: "string")
284 .build();
285 }
286
287 return {BuildNamespace(*ExpectedKind, *OptNameStr)};
288}
289
290Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const {
291 Object Result;
292 Result["kind"] = buildNamespaceKindToJSON(BNK: getKind(X: BN));
293 Result["name"] = getName(X: BN);
294 return Result;
295}
296
297//----------------------------------------------------------------------------
298// NestedBuildNamespace
299//----------------------------------------------------------------------------
300
301llvm::Expected<NestedBuildNamespace> JSONFormat::nestedBuildNamespaceFromJSON(
302 const Array &NestedBuildNamespaceArray) const {
303 std::vector<BuildNamespace> Namespaces;
304
305 size_t NamespaceCount = NestedBuildNamespaceArray.size();
306 Namespaces.reserve(n: NamespaceCount);
307
308 for (const auto &[Index, BuildNamespaceValue] :
309 llvm::enumerate(First: NestedBuildNamespaceArray)) {
310 const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject();
311 if (!BuildNamespaceObject) {
312 return ErrorBuilder::create(EC: std::errc::invalid_argument,
313 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
314 ArgVals: "BuildNamespace", ArgVals&: Index, ArgVals: "object")
315 .build();
316 }
317
318 auto ExpectedBuildNamespace = buildNamespaceFromJSON(BuildNamespaceObject: *BuildNamespaceObject);
319 if (!ExpectedBuildNamespace) {
320 return ErrorBuilder::wrap(E: ExpectedBuildNamespace.takeError())
321 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "BuildNamespace", ArgVals&: Index)
322 .build();
323 }
324
325 Namespaces.push_back(x: std::move(*ExpectedBuildNamespace));
326 }
327
328 return NestedBuildNamespace(std::move(Namespaces));
329}
330
331Array JSONFormat::nestedBuildNamespaceToJSON(
332 const NestedBuildNamespace &NBN) const {
333 Array Result;
334 const auto &Namespaces = getNamespaces(X: NBN);
335 Result.reserve(S: Namespaces.size());
336
337 for (const auto &BN : Namespaces) {
338 Result.push_back(E: buildNamespaceToJSON(BN));
339 }
340
341 return Result;
342}
343
344//----------------------------------------------------------------------------
345// EntityName
346//----------------------------------------------------------------------------
347
348/// Reads "usr" and "suffix" fields from an EntityName JSON object.
349/// Shared core logic for both TU and LU entity name deserialization.
350static llvm::Expected<std::pair<llvm::StringRef, llvm::StringRef>>
351entityNameCoreFromJSON(const Object &EntityNameObject) {
352 const auto OptUSR = EntityNameObject.getString(K: "usr");
353 if (!OptUSR) {
354 return ErrorBuilder::create(EC: std::errc::invalid_argument,
355 Fmt: ErrorMessages::FailedToReadObjectAtField, ArgVals: "USR",
356 ArgVals: "usr", ArgVals: "string")
357 .build();
358 }
359
360 const auto OptSuffix = EntityNameObject.getString(K: "suffix");
361 if (!OptSuffix) {
362 return ErrorBuilder::create(EC: std::errc::invalid_argument,
363 Fmt: ErrorMessages::FailedToReadObjectAtField,
364 ArgVals: "Suffix", ArgVals: "suffix", ArgVals: "string")
365 .build();
366 }
367
368 return std::make_pair(x: *OptUSR, y: *OptSuffix);
369}
370
371llvm::Expected<EntityName>
372JSONFormat::tuEntityNameFromJSON(const Object &EntityNameObject) const {
373 auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
374 if (!ExpectedCore)
375 return ExpectedCore.takeError();
376
377 auto [USR, Suffix] = *ExpectedCore;
378 return EntityName{USR, Suffix, NestedBuildNamespace()};
379}
380
381Object JSONFormat::tuEntityNameToJSON(const EntityName &EN) const {
382 Object Result;
383 Result["usr"] = getUSR(X: EN);
384 Result["suffix"] = getSuffix(X: EN);
385 return Result;
386}
387
388llvm::Expected<EntityName>
389JSONFormat::luEntityNameFromJSON(const Object &EntityNameObject) const {
390 auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
391 if (!ExpectedCore)
392 return ExpectedCore.takeError();
393
394 auto [USR, Suffix] = *ExpectedCore;
395
396 const Array *OptNamespaceArray = EntityNameObject.getArray(K: "namespace");
397 if (!OptNamespaceArray) {
398 return ErrorBuilder::create(EC: std::errc::invalid_argument,
399 Fmt: ErrorMessages::FailedToReadObjectAtField,
400 ArgVals: "NestedBuildNamespace", ArgVals: "namespace", ArgVals: "array")
401 .build();
402 }
403
404 auto ExpectedNamespace = nestedBuildNamespaceFromJSON(NestedBuildNamespaceArray: *OptNamespaceArray);
405 if (!ExpectedNamespace) {
406 return ErrorBuilder::wrap(E: ExpectedNamespace.takeError())
407 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "NestedBuildNamespace",
408 ArgVals: "namespace")
409 .build();
410 }
411
412 return EntityName{USR, Suffix, std::move(*ExpectedNamespace)};
413}
414
415Object JSONFormat::luEntityNameToJSON(const EntityName &EN) const {
416 Object Result;
417 Result["usr"] = getUSR(X: EN);
418 Result["suffix"] = getSuffix(X: EN);
419 Result["namespace"] = nestedBuildNamespaceToJSON(NBN: getNamespace(X: EN));
420 return Result;
421}
422
423//----------------------------------------------------------------------------
424// EntityLinkageType
425//----------------------------------------------------------------------------
426
427llvm::Expected<EntityLinkageType>
428entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr) {
429 auto OptEntityLinkageType = entityLinkageTypeFromString(Str: EntityLinkageTypeStr);
430 if (!OptEntityLinkageType) {
431 return ErrorBuilder::create(EC: std::errc::invalid_argument,
432 Fmt: ErrorMessages::InvalidEntityLinkageType,
433 ArgVals&: EntityLinkageTypeStr)
434 .build();
435 }
436 return *OptEntityLinkageType;
437}
438
439// Provided for consistency with respect to rest of the codebase.
440llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT) {
441 return entityLinkageTypeToString(LT);
442}
443
444//----------------------------------------------------------------------------
445// TargetTriple
446//----------------------------------------------------------------------------
447
448llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple) {
449 std::string Normalized = llvm::Triple::normalize(Str: Triple);
450 if (Normalized != Triple) {
451 return ErrorBuilder::create(EC: std::errc::invalid_argument,
452 Fmt: ErrorMessages::TargetTripleNotNormalized,
453 ArgVals&: Triple, ArgVals&: Normalized)
454 .build();
455 }
456 return llvm::Error::success();
457}
458
459//----------------------------------------------------------------------------
460// EntityLinkage
461//----------------------------------------------------------------------------
462
463llvm::Expected<EntityLinkage>
464JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const {
465 auto OptLinkageStr = EntityLinkageObject.getString(K: "type");
466 if (!OptLinkageStr) {
467 return ErrorBuilder::create(EC: std::errc::invalid_argument,
468 Fmt: ErrorMessages::FailedToReadObjectAtField,
469 ArgVals: "EntityLinkageType", ArgVals: "type", ArgVals: "string")
470 .build();
471 }
472
473 auto ExpectedLinkageType = entityLinkageTypeFromJSON(EntityLinkageTypeStr: *OptLinkageStr);
474 if (!ExpectedLinkageType) {
475 return ErrorBuilder::wrap(E: ExpectedLinkageType.takeError())
476 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityLinkageType", ArgVals: "type")
477 .build();
478 }
479
480 return EntityLinkage(*ExpectedLinkageType);
481}
482
483Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const {
484 Object Result;
485 Result["type"] = entityLinkageTypeToJSON(LT: getLinkage(X: EL));
486 return Result;
487}
488
489//----------------------------------------------------------------------------
490// EntityIdTableEntry
491//----------------------------------------------------------------------------
492
493/// Shared logic for reading the "id" field from an EntityIdTableEntry object.
494static llvm::Expected<EntityId>
495entityIdTableEntryIdFromJSON(const Object &EntityIdTableEntryObject,
496 llvm::function_ref<EntityId(uint64_t)> MakeId) {
497 const Value *EntityIdIntValue = EntityIdTableEntryObject.get(K: "id");
498 if (!EntityIdIntValue) {
499 return ErrorBuilder::create(EC: std::errc::invalid_argument,
500 Fmt: ErrorMessages::FailedToReadObjectAtField,
501 ArgVals: "EntityId", ArgVals: "id",
502 ArgVals: "number (unsigned 64-bit integer)")
503 .build();
504 }
505
506 const std::optional<uint64_t> OptEntityIdInt =
507 EntityIdIntValue->getAsUINT64();
508 if (!OptEntityIdInt) {
509 return ErrorBuilder::create(EC: std::errc::invalid_argument,
510 Fmt: ErrorMessages::FailedToReadObjectAtField,
511 ArgVals: "EntityId", ArgVals: "id",
512 ArgVals: "number (unsigned 64-bit integer)")
513 .build();
514 }
515
516 return MakeId(*OptEntityIdInt);
517}
518
519llvm::Expected<std::pair<EntityName, EntityId>>
520JSONFormat::tuEntityIdTableEntryFromJSON(
521 const Object &EntityIdTableEntryObject) const {
522
523 const Object *OptEntityNameObject =
524 EntityIdTableEntryObject.getObject(K: "name");
525 if (!OptEntityNameObject) {
526 return ErrorBuilder::create(EC: std::errc::invalid_argument,
527 Fmt: ErrorMessages::FailedToReadObjectAtField,
528 ArgVals: "EntityName", ArgVals: "name", ArgVals: "object")
529 .build();
530 }
531
532 auto ExpectedEntityName = tuEntityNameFromJSON(EntityNameObject: *OptEntityNameObject);
533 if (!ExpectedEntityName) {
534 return ErrorBuilder::wrap(E: ExpectedEntityName.takeError())
535 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityName", ArgVals: "name")
536 .build();
537 }
538
539 auto ExpectedId = entityIdTableEntryIdFromJSON(
540 EntityIdTableEntryObject,
541 MakeId: [this](uint64_t V) { return entityIdFromJSON(EntityIdIndex: V); });
542 if (!ExpectedId)
543 return ExpectedId.takeError();
544
545 return std::make_pair(x: std::move(*ExpectedEntityName), y: std::move(*ExpectedId));
546}
547
548Object JSONFormat::tuEntityIdTableEntryToJSON(const EntityName &EN,
549 EntityId EI) const {
550 Object Entry;
551 Entry["id"] = entityIdToJSON(EI);
552 Entry["name"] = tuEntityNameToJSON(EN);
553 return Entry;
554}
555
556llvm::Expected<std::pair<EntityName, EntityId>>
557JSONFormat::luEntityIdTableEntryFromJSON(
558 const Object &EntityIdTableEntryObject) const {
559
560 const Object *OptEntityNameObject =
561 EntityIdTableEntryObject.getObject(K: "name");
562 if (!OptEntityNameObject) {
563 return ErrorBuilder::create(EC: std::errc::invalid_argument,
564 Fmt: ErrorMessages::FailedToReadObjectAtField,
565 ArgVals: "EntityName", ArgVals: "name", ArgVals: "object")
566 .build();
567 }
568
569 auto ExpectedEntityName = luEntityNameFromJSON(EntityNameObject: *OptEntityNameObject);
570 if (!ExpectedEntityName) {
571 return ErrorBuilder::wrap(E: ExpectedEntityName.takeError())
572 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityName", ArgVals: "name")
573 .build();
574 }
575
576 auto ExpectedId = entityIdTableEntryIdFromJSON(
577 EntityIdTableEntryObject,
578 MakeId: [this](uint64_t V) { return entityIdFromJSON(EntityIdIndex: V); });
579 if (!ExpectedId)
580 return ExpectedId.takeError();
581
582 return std::make_pair(x: std::move(*ExpectedEntityName), y: std::move(*ExpectedId));
583}
584
585Object JSONFormat::luEntityIdTableEntryToJSON(const EntityName &EN,
586 EntityId EI) const {
587 Object Entry;
588 Entry["id"] = entityIdToJSON(EI);
589 Entry["name"] = luEntityNameToJSON(EN);
590 return Entry;
591}
592
593//----------------------------------------------------------------------------
594// EntityIdTable
595//----------------------------------------------------------------------------
596
597/// Shared logic for deserializing an EntityIdTable from a JSON array.
598/// \p EntryReader is called for each entry object to produce an
599/// (EntityName, EntityId) pair.
600static llvm::Expected<EntityIdTable> entityIdTableFromJSONImpl(
601 const Array &EntityIdTableArray,
602 llvm::function_ref<
603 llvm::Expected<std::pair<EntityName, EntityId>>(const Object &)>
604 EntryReader,
605 llvm::function_ref<std::map<EntityName, EntityId> &(EntityIdTable &)>
606 GetEntities) {
607 EntityIdTable IdTable;
608 std::map<EntityName, EntityId> &Entities = GetEntities(IdTable);
609
610 for (const auto &[Index, EntityIdTableEntryValue] :
611 llvm::enumerate(First: EntityIdTableArray)) {
612 const Object *OptEntityIdTableEntryObject =
613 EntityIdTableEntryValue.getAsObject();
614 if (!OptEntityIdTableEntryObject) {
615 return ErrorBuilder::create(EC: std::errc::invalid_argument,
616 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
617 ArgVals: "EntityIdTable entry", ArgVals&: Index, ArgVals: "object")
618 .build();
619 }
620
621 auto ExpectedEntityIdTableEntry = EntryReader(*OptEntityIdTableEntryObject);
622 if (!ExpectedEntityIdTableEntry) {
623 return ErrorBuilder::wrap(E: ExpectedEntityIdTableEntry.takeError())
624 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "EntityIdTable entry",
625 ArgVals&: Index)
626 .build();
627 }
628
629 auto [EntityIt, EntityInserted] =
630 Entities.emplace(args: std::move(*ExpectedEntityIdTableEntry));
631 if (!EntityInserted) {
632 return ErrorBuilder::create(EC: std::errc::invalid_argument,
633 Fmt: ErrorMessages::FailedInsertionOnDuplication,
634 ArgVals: "EntityIdTable entry", ArgVals&: Index,
635 ArgVals&: EntityIt->second)
636 .build();
637 }
638 }
639
640 return IdTable;
641}
642
643llvm::Expected<EntityIdTable>
644JSONFormat::tuEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
645 return entityIdTableFromJSONImpl(
646 EntityIdTableArray,
647 EntryReader: [this](const Object &O) { return tuEntityIdTableEntryFromJSON(EntityIdTableEntryObject: O); },
648 GetEntities: [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
649 return getEntities(X&: T);
650 });
651}
652
653Array JSONFormat::tuEntityIdTableToJSON(const EntityIdTable &IdTable) const {
654 Array EntityIdTableArray;
655 const auto &Entities = getEntities(X: IdTable);
656 EntityIdTableArray.reserve(S: Entities.size());
657
658 for (const auto &[EntityName, EntityId] : Entities) {
659 EntityIdTableArray.push_back(
660 E: tuEntityIdTableEntryToJSON(EN: EntityName, EI: EntityId));
661 }
662
663 return EntityIdTableArray;
664}
665
666llvm::Expected<EntityIdTable>
667JSONFormat::luEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
668 return entityIdTableFromJSONImpl(
669 EntityIdTableArray,
670 EntryReader: [this](const Object &O) { return luEntityIdTableEntryFromJSON(EntityIdTableEntryObject: O); },
671 GetEntities: [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
672 return getEntities(X&: T);
673 });
674}
675
676Array JSONFormat::luEntityIdTableToJSON(const EntityIdTable &IdTable) const {
677 Array EntityIdTableArray;
678 const auto &Entities = getEntities(X: IdTable);
679 EntityIdTableArray.reserve(S: Entities.size());
680
681 for (const auto &[EntityName, EntityId] : Entities) {
682 EntityIdTableArray.push_back(
683 E: luEntityIdTableEntryToJSON(EN: EntityName, EI: EntityId));
684 }
685
686 return EntityIdTableArray;
687}
688
689//----------------------------------------------------------------------------
690// LinkageTableEntry
691//----------------------------------------------------------------------------
692
693llvm::Expected<std::pair<EntityId, EntityLinkage>>
694JSONFormat::linkageTableEntryFromJSON(
695 const Object &LinkageTableEntryObject) const {
696 const Value *EntityIdIntValue = LinkageTableEntryObject.get(K: "id");
697 if (!EntityIdIntValue) {
698 return ErrorBuilder::create(EC: std::errc::invalid_argument,
699 Fmt: ErrorMessages::FailedToReadObjectAtField,
700 ArgVals: "EntityId", ArgVals: "id",
701 ArgVals: "number (unsigned 64-bit integer)")
702 .build();
703 }
704
705 const std::optional<uint64_t> OptEntityIdInt =
706 EntityIdIntValue->getAsUINT64();
707 if (!OptEntityIdInt) {
708 return ErrorBuilder::create(EC: std::errc::invalid_argument,
709 Fmt: ErrorMessages::FailedToReadObjectAtField,
710 ArgVals: "EntityId", ArgVals: "id",
711 ArgVals: "number (unsigned 64-bit integer)")
712 .build();
713 }
714
715 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
716
717 const Object *OptEntityLinkageObject =
718 LinkageTableEntryObject.getObject(K: "linkage");
719 if (!OptEntityLinkageObject) {
720 return ErrorBuilder::create(EC: std::errc::invalid_argument,
721 Fmt: ErrorMessages::FailedToReadObjectAtField,
722 ArgVals: "EntityLinkage", ArgVals: "linkage", ArgVals: "object")
723 .build();
724 }
725
726 auto ExpectedEntityLinkage = entityLinkageFromJSON(EntityLinkageObject: *OptEntityLinkageObject);
727 if (!ExpectedEntityLinkage) {
728 return ErrorBuilder::wrap(E: ExpectedEntityLinkage.takeError())
729 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityLinkage", ArgVals: "linkage")
730 .build();
731 }
732
733 return std::make_pair(x: std::move(EI), y: std::move(*ExpectedEntityLinkage));
734}
735
736Object JSONFormat::linkageTableEntryToJSON(EntityId EI,
737 const EntityLinkage &EL) const {
738 Object Entry;
739 Entry["id"] = entityIdToJSON(EI);
740 Entry["linkage"] = entityLinkageToJSON(EL);
741 return Entry;
742}
743
744//----------------------------------------------------------------------------
745// LinkageTable
746//----------------------------------------------------------------------------
747
748// ExpectedIds is the set of EntityIds from the IdTable that must appear in the
749// linkage table—no more, no fewer. It is taken by value because it is consumed
750// during parsing: each successfully matched id is erased from the set, and any
751// ids remaining at the end are reported as missing.
752llvm::Expected<std::map<EntityId, EntityLinkage>>
753JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray,
754 std::set<EntityId> ExpectedIds) const {
755 std::map<EntityId, EntityLinkage> LinkageTable;
756
757 for (const auto &[Index, LinkageTableEntryValue] :
758 llvm::enumerate(First: LinkageTableArray)) {
759 const Object *OptLinkageTableEntryObject =
760 LinkageTableEntryValue.getAsObject();
761 if (!OptLinkageTableEntryObject) {
762 return ErrorBuilder::create(EC: std::errc::invalid_argument,
763 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
764 ArgVals: "LinkageTable entry", ArgVals&: Index, ArgVals: "object")
765 .build();
766 }
767
768 auto ExpectedLinkageTableEntry =
769 linkageTableEntryFromJSON(LinkageTableEntryObject: *OptLinkageTableEntryObject);
770 if (!ExpectedLinkageTableEntry) {
771 return ErrorBuilder::wrap(E: ExpectedLinkageTableEntry.takeError())
772 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "LinkageTable entry", ArgVals&: Index)
773 .build();
774 }
775
776 const EntityId EI = ExpectedLinkageTableEntry->first;
777
778 auto [It, Inserted] =
779 LinkageTable.insert(x: std::move(*ExpectedLinkageTableEntry));
780 if (!Inserted) {
781 return ErrorBuilder::create(EC: std::errc::invalid_argument,
782 Fmt: ErrorMessages::FailedInsertionOnDuplication,
783 ArgVals: "LinkageTable entry", ArgVals&: Index, ArgVals: It->first)
784 .build();
785 }
786
787 if (ExpectedIds.erase(x: EI) == 0) {
788 return ErrorBuilder::create(
789 EC: std::errc::invalid_argument,
790 Fmt: ErrorMessages::FailedToDeserializeLinkageTableExtraId, ArgVals: EI)
791 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "LinkageTable entry", ArgVals&: Index)
792 .build();
793 }
794 }
795
796 if (!ExpectedIds.empty()) {
797 return ErrorBuilder::create(
798 EC: std::errc::invalid_argument,
799 Fmt: ErrorMessages::FailedToDeserializeLinkageTableMissingId,
800 ArgVals: *ExpectedIds.begin())
801 .build();
802 }
803
804 return LinkageTable;
805}
806
807Array JSONFormat::linkageTableToJSON(
808 const std::map<EntityId, EntityLinkage> &LinkageTable) const {
809 Array Result;
810 Result.reserve(S: LinkageTable.size());
811
812 for (const auto &[EI, EL] : LinkageTable) {
813 Result.push_back(E: linkageTableEntryToJSON(EI, EL));
814 }
815
816 return Result;
817}
818
819//----------------------------------------------------------------------------
820// EntitySummary
821//----------------------------------------------------------------------------
822
823llvm::Expected<std::unique_ptr<EntitySummary>>
824JSONFormat::entitySummaryFromJSON(const SummaryName &SN,
825 const Object &EntitySummaryObject,
826 EntityIdTable &IdTable) const {
827 auto InfoIt = FormatInfos.find(x: SN);
828 if (InfoIt == FormatInfos.end()) {
829 return ErrorBuilder::create(
830 EC: std::errc::invalid_argument,
831 Fmt: ErrorMessages::FailedToDeserializeEntitySummaryNoFormatInfo, ArgVals: SN)
832 .build();
833 }
834
835 const auto &InfoEntry = InfoIt->second;
836 assert(InfoEntry.ForSummary == SN);
837
838 return InfoEntry.Deserialize(EntitySummaryObject, IdTable,
839 entityIdFromJSONObject);
840}
841
842llvm::Expected<Object>
843JSONFormat::entitySummaryToJSON(const SummaryName &SN,
844 const EntitySummary &ES) const {
845 auto InfoIt = FormatInfos.find(x: SN);
846 if (InfoIt == FormatInfos.end()) {
847 return ErrorBuilder::create(
848 EC: std::errc::invalid_argument,
849 Fmt: ErrorMessages::FailedToSerializeEntitySummaryNoFormatInfo, ArgVals: SN)
850 .build();
851 }
852
853 const auto &InfoEntry = InfoIt->second;
854 assert(InfoEntry.ForSummary == SN);
855
856 return InfoEntry.Serialize(ES, entityIdToJSONObject);
857}
858
859//----------------------------------------------------------------------------
860// EntityDataMapEntry
861//----------------------------------------------------------------------------
862
863llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
864JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
865 const SummaryName &SN,
866 EntityIdTable &IdTable) const {
867
868 const Value *EntityIdIntValue = EntityDataMapEntryObject.get(K: "entity_id");
869 if (!EntityIdIntValue) {
870 return ErrorBuilder::create(EC: std::errc::invalid_argument,
871 Fmt: ErrorMessages::FailedToReadObjectAtField,
872 ArgVals: "EntityId", ArgVals: "entity_id",
873 ArgVals: "number (unsigned 64-bit integer)")
874 .build();
875 }
876
877 const std::optional<uint64_t> OptEntityIdInt =
878 EntityIdIntValue->getAsUINT64();
879 if (!OptEntityIdInt) {
880 return ErrorBuilder::create(EC: std::errc::invalid_argument,
881 Fmt: ErrorMessages::FailedToReadObjectAtField,
882 ArgVals: "EntityId", ArgVals: "entity_id",
883 ArgVals: "number (unsigned 64-bit integer)")
884 .build();
885 }
886
887 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
888
889 const Object *OptEntitySummaryObject =
890 EntityDataMapEntryObject.getObject(K: "entity_summary");
891 if (!OptEntitySummaryObject) {
892 return ErrorBuilder::create(EC: std::errc::invalid_argument,
893 Fmt: ErrorMessages::FailedToReadObjectAtField,
894 ArgVals: "EntitySummary", ArgVals: "entity_summary", ArgVals: "object")
895 .build();
896 }
897
898 auto ExpectedEntitySummary =
899 entitySummaryFromJSON(SN, EntitySummaryObject: *OptEntitySummaryObject, IdTable);
900 if (!ExpectedEntitySummary) {
901 return ErrorBuilder::wrap(E: ExpectedEntitySummary.takeError())
902 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntitySummary",
903 ArgVals: "entity_summary")
904 .build();
905 }
906
907 if (*ExpectedEntitySummary == nullptr) {
908 return ErrorBuilder::create(
909 EC: std::errc::invalid_argument,
910 Fmt: ErrorMessages::FailedToDeserializeEntitySummaryMissingData, ArgVals: SN)
911 .build();
912 }
913
914 auto ActualSN = (*ExpectedEntitySummary)->getSummaryName();
915 if (SN != ActualSN) {
916 return ErrorBuilder::create(
917 EC: std::errc::invalid_argument,
918 Fmt: ErrorMessages::
919 FailedToDeserializeEntitySummaryMismatchedSummaryName,
920 ArgVals: SN, ArgVals&: ActualSN)
921 .build();
922 }
923
924 return std::make_pair(x: std::move(EI), y: std::move(*ExpectedEntitySummary));
925}
926
927llvm::Expected<Object> JSONFormat::entityDataMapEntryToJSON(
928 const EntityId EI, const std::unique_ptr<EntitySummary> &EntitySummary,
929 const SummaryName &SN) const {
930 Object Entry;
931
932 Entry["entity_id"] = entityIdToJSON(EI);
933
934 if (!EntitySummary) {
935 ErrorBuilder::fatal(
936 Fmt: ErrorMessages::FailedToSerializeEntitySummaryMissingData, ArgVals: SN);
937 }
938
939 const auto ActualSN = EntitySummary->getSummaryName();
940 if (SN != ActualSN) {
941 ErrorBuilder::fatal(
942 Fmt: ErrorMessages::FailedToSerializeEntitySummaryMismatchedSummaryName, ArgVals: SN,
943 ArgVals: ActualSN);
944 }
945
946 auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, ES: *EntitySummary);
947 if (!ExpectedEntitySummaryObject) {
948 return ErrorBuilder::wrap(E: ExpectedEntitySummaryObject.takeError())
949 .context(Fmt: ErrorMessages::WritingToField, ArgVals: "EntitySummary",
950 ArgVals: "entity_summary")
951 .build();
952 }
953
954 Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject);
955
956 return Entry;
957}
958
959//----------------------------------------------------------------------------
960// EntityDataMap
961//----------------------------------------------------------------------------
962
963llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
964JSONFormat::entityDataMapFromJSON(const SummaryName &SN,
965 const Array &EntityDataArray,
966 EntityIdTable &IdTable) const {
967 std::map<EntityId, std::unique_ptr<EntitySummary>> EntityDataMap;
968
969 for (const auto &[Index, EntityDataMapEntryValue] :
970 llvm::enumerate(First: EntityDataArray)) {
971 const Object *OptEntityDataMapEntryObject =
972 EntityDataMapEntryValue.getAsObject();
973 if (!OptEntityDataMapEntryObject) {
974 return ErrorBuilder::create(EC: std::errc::invalid_argument,
975 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
976 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: "object")
977 .build();
978 }
979
980 auto ExpectedEntityDataMapEntry =
981 entityDataMapEntryFromJSON(EntityDataMapEntryObject: *OptEntityDataMapEntryObject, SN, IdTable);
982 if (!ExpectedEntityDataMapEntry) {
983 return ErrorBuilder::wrap(E: ExpectedEntityDataMapEntry.takeError())
984 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "EntitySummary entry",
985 ArgVals&: Index)
986 .build();
987 }
988
989 auto [DataIt, DataInserted] =
990 EntityDataMap.insert(x: std::move(*ExpectedEntityDataMapEntry));
991 if (!DataInserted) {
992 return ErrorBuilder::create(EC: std::errc::invalid_argument,
993 Fmt: ErrorMessages::FailedInsertionOnDuplication,
994 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: DataIt->first)
995 .build();
996 }
997 }
998
999 return std::move(EntityDataMap);
1000}
1001
1002llvm::Expected<Array> JSONFormat::entityDataMapToJSON(
1003 const SummaryName &SN,
1004 const std::map<EntityId, std::unique_ptr<EntitySummary>> &EntityDataMap)
1005 const {
1006 Array Result;
1007 Result.reserve(S: EntityDataMap.size());
1008
1009 for (const auto &[Index, EntityDataMapEntry] :
1010 llvm::enumerate(First: EntityDataMap)) {
1011 const auto &[EntityId, EntitySummary] = EntityDataMapEntry;
1012
1013 auto ExpectedEntityDataMapEntryObject =
1014 entityDataMapEntryToJSON(EI: EntityId, EntitySummary, SN);
1015
1016 if (!ExpectedEntityDataMapEntryObject) {
1017 return ErrorBuilder::wrap(E: ExpectedEntityDataMapEntryObject.takeError())
1018 .context(Fmt: ErrorMessages::WritingToIndex, ArgVals: "EntitySummary entry", ArgVals&: Index)
1019 .build();
1020 }
1021
1022 Result.push_back(E: std::move(*ExpectedEntityDataMapEntryObject));
1023 }
1024
1025 return Result;
1026}
1027
1028//----------------------------------------------------------------------------
1029// SummaryDataMapEntry
1030//----------------------------------------------------------------------------
1031
1032llvm::Expected<
1033 std::pair<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
1034JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject,
1035 EntityIdTable &IdTable) const {
1036
1037 std::optional<llvm::StringRef> OptSummaryNameStr =
1038 SummaryDataMapEntryObject.getString(K: "summary_name");
1039 if (!OptSummaryNameStr) {
1040 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1041 Fmt: ErrorMessages::FailedToReadObjectAtField,
1042 ArgVals: "SummaryName", ArgVals: "summary_name", ArgVals: "string")
1043 .build();
1044 }
1045
1046 SummaryName SN = summaryNameFromJSON(SummaryNameStr: *OptSummaryNameStr);
1047
1048 const Array *OptEntityDataArray =
1049 SummaryDataMapEntryObject.getArray(K: "summary_data");
1050 if (!OptEntityDataArray) {
1051 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1052 Fmt: ErrorMessages::FailedToReadObjectAtField,
1053 ArgVals: "EntitySummary entries", ArgVals: "summary_data",
1054 ArgVals: "array")
1055 .build();
1056 }
1057
1058 auto ExpectedEntityDataMap =
1059 entityDataMapFromJSON(SN, EntityDataArray: *OptEntityDataArray, IdTable);
1060 if (!ExpectedEntityDataMap) {
1061 return ErrorBuilder::wrap(E: ExpectedEntityDataMap.takeError())
1062 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntitySummary entries",
1063 ArgVals: "summary_data")
1064 .build();
1065 }
1066
1067 return std::make_pair(x: std::move(SN), y: std::move(*ExpectedEntityDataMap));
1068}
1069
1070llvm::Expected<Object> JSONFormat::summaryDataMapEntryToJSON(
1071 const SummaryName &SN,
1072 const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const {
1073 Object Result;
1074
1075 Result["summary_name"] = summaryNameToJSON(SN);
1076
1077 auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, EntityDataMap: SD);
1078 if (!ExpectedSummaryDataArray) {
1079 return ErrorBuilder::wrap(E: ExpectedSummaryDataArray.takeError())
1080 .context(Fmt: ErrorMessages::WritingToField, ArgVals: "EntitySummary entries",
1081 ArgVals: "summary_data")
1082 .build();
1083 }
1084
1085 Result["summary_data"] = std::move(*ExpectedSummaryDataArray);
1086
1087 return Result;
1088}
1089
1090//----------------------------------------------------------------------------
1091// SummaryDataMap
1092//----------------------------------------------------------------------------
1093
1094llvm::Expected<
1095 std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
1096JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray,
1097 EntityIdTable &IdTable) const {
1098 std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
1099 SummaryDataMap;
1100
1101 for (const auto &[Index, SummaryDataMapEntryValue] :
1102 llvm::enumerate(First: SummaryDataArray)) {
1103 const Object *OptSummaryDataMapEntryObject =
1104 SummaryDataMapEntryValue.getAsObject();
1105 if (!OptSummaryDataMapEntryObject) {
1106 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1107 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
1108 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: "object")
1109 .build();
1110 }
1111
1112 auto ExpectedSummaryDataMapEntry =
1113 summaryDataMapEntryFromJSON(SummaryDataMapEntryObject: *OptSummaryDataMapEntryObject, IdTable);
1114 if (!ExpectedSummaryDataMapEntry) {
1115 return ErrorBuilder::wrap(E: ExpectedSummaryDataMapEntry.takeError())
1116 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "SummaryData entry", ArgVals&: Index)
1117 .build();
1118 }
1119
1120 auto [SummaryIt, SummaryInserted] =
1121 SummaryDataMap.emplace(args: std::move(*ExpectedSummaryDataMapEntry));
1122 if (!SummaryInserted) {
1123 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1124 Fmt: ErrorMessages::FailedInsertionOnDuplication,
1125 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: SummaryIt->first)
1126 .build();
1127 }
1128 }
1129
1130 return std::move(SummaryDataMap);
1131}
1132
1133llvm::Expected<Array> JSONFormat::summaryDataMapToJSON(
1134 const std::map<SummaryName,
1135 std::map<EntityId, std::unique_ptr<EntitySummary>>>
1136 &SummaryDataMap) const {
1137 Array Result;
1138 Result.reserve(S: SummaryDataMap.size());
1139
1140 for (const auto &[Index, SummaryDataMapEntry] :
1141 llvm::enumerate(First: SummaryDataMap)) {
1142 const auto &[SummaryName, DataMap] = SummaryDataMapEntry;
1143
1144 auto ExpectedSummaryDataMapObject =
1145 summaryDataMapEntryToJSON(SN: SummaryName, SD: DataMap);
1146 if (!ExpectedSummaryDataMapObject) {
1147 return ErrorBuilder::wrap(E: ExpectedSummaryDataMapObject.takeError())
1148 .context(Fmt: ErrorMessages::WritingToIndex, ArgVals: "SummaryData entry", ArgVals&: Index)
1149 .build();
1150 }
1151
1152 Result.push_back(E: std::move(*ExpectedSummaryDataMapObject));
1153 }
1154
1155 return std::move(Result);
1156}
1157
1158//----------------------------------------------------------------------------
1159// EncodingDataMapEntry
1160//----------------------------------------------------------------------------
1161
1162llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
1163JSONFormat::encodingDataMapEntryFromJSON(
1164 const Object &EntityDataMapEntryObject) const {
1165 const Value *EntityIdIntValue = EntityDataMapEntryObject.get(K: "entity_id");
1166 if (!EntityIdIntValue) {
1167 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1168 Fmt: ErrorMessages::FailedToReadObjectAtField,
1169 ArgVals: "EntityId", ArgVals: "entity_id",
1170 ArgVals: "number (unsigned 64-bit integer)")
1171 .build();
1172 }
1173
1174 const std::optional<uint64_t> OptEntityIdInt =
1175 EntityIdIntValue->getAsUINT64();
1176 if (!OptEntityIdInt) {
1177 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1178 Fmt: ErrorMessages::FailedToReadObjectAtField,
1179 ArgVals: "EntityId", ArgVals: "entity_id",
1180 ArgVals: "number (unsigned 64-bit integer)")
1181 .build();
1182 }
1183
1184 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
1185
1186 const Object *OptEntitySummaryObject =
1187 EntityDataMapEntryObject.getObject(K: "entity_summary");
1188 if (!OptEntitySummaryObject) {
1189 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1190 Fmt: ErrorMessages::FailedToReadObjectAtField,
1191 ArgVals: "EntitySummary", ArgVals: "entity_summary", ArgVals: "object")
1192 .build();
1193 }
1194
1195 std::unique_ptr<EntitySummaryEncoding> Encoding(
1196 new JSONEntitySummaryEncoding(Value(Object(*OptEntitySummaryObject))));
1197
1198 return std::make_pair(x: std::move(EI), y: std::move(Encoding));
1199}
1200
1201Object JSONFormat::encodingDataMapEntryToJSON(
1202 EntityId EI, const std::unique_ptr<EntitySummaryEncoding> &Encoding) const {
1203 Object Entry;
1204 Entry["entity_id"] = entityIdToJSON(EI);
1205
1206 // All EntitySummaryEncoding objects stored in a TUSummaryEncoding or
1207 // LUSummaryEncoding read by JSONFormat are JSONEntitySummaryEncoding
1208 // instances, since encodingDataMapEntryFromJSON is the only place that
1209 // creates them.
1210 auto *JSONEncoding = static_cast<JSONEntitySummaryEncoding *>(Encoding.get());
1211 Entry["entity_summary"] = JSONEncoding->Data;
1212
1213 return Entry;
1214}
1215
1216//----------------------------------------------------------------------------
1217// EncodingDataMap
1218//----------------------------------------------------------------------------
1219
1220llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
1221JSONFormat::encodingDataMapFromJSON(const Array &EntityDataArray) const {
1222 std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>> EncodingDataMap;
1223
1224 for (const auto &[Index, EntityDataMapEntryValue] :
1225 llvm::enumerate(First: EntityDataArray)) {
1226 const Object *OptEntityDataMapEntryObject =
1227 EntityDataMapEntryValue.getAsObject();
1228 if (!OptEntityDataMapEntryObject) {
1229 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1230 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
1231 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: "object")
1232 .build();
1233 }
1234
1235 auto ExpectedEntry =
1236 encodingDataMapEntryFromJSON(EntityDataMapEntryObject: *OptEntityDataMapEntryObject);
1237 if (!ExpectedEntry) {
1238 return ErrorBuilder::wrap(E: ExpectedEntry.takeError())
1239 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "EntitySummary entry",
1240 ArgVals&: Index)
1241 .build();
1242 }
1243
1244 auto [DataIt, DataInserted] =
1245 EncodingDataMap.insert(x: std::move(*ExpectedEntry));
1246 if (!DataInserted) {
1247 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1248 Fmt: ErrorMessages::FailedInsertionOnDuplication,
1249 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: DataIt->first)
1250 .build();
1251 }
1252 }
1253
1254 return std::move(EncodingDataMap);
1255}
1256
1257Array JSONFormat::encodingDataMapToJSON(
1258 const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
1259 &EncodingDataMap) const {
1260 Array Result;
1261 Result.reserve(S: EncodingDataMap.size());
1262
1263 for (const auto &[EI, Encoding] : EncodingDataMap) {
1264 Result.push_back(E: encodingDataMapEntryToJSON(EI, Encoding));
1265 }
1266
1267 return Result;
1268}
1269
1270//----------------------------------------------------------------------------
1271// EncodingSummaryDataMapEntry
1272//----------------------------------------------------------------------------
1273
1274llvm::Expected<std::pair<
1275 SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
1276JSONFormat::encodingSummaryDataMapEntryFromJSON(
1277 const Object &SummaryDataMapEntryObject) const {
1278 std::optional<llvm::StringRef> OptSummaryNameStr =
1279 SummaryDataMapEntryObject.getString(K: "summary_name");
1280 if (!OptSummaryNameStr) {
1281 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1282 Fmt: ErrorMessages::FailedToReadObjectAtField,
1283 ArgVals: "SummaryName", ArgVals: "summary_name", ArgVals: "string")
1284 .build();
1285 }
1286
1287 SummaryName SN = summaryNameFromJSON(SummaryNameStr: *OptSummaryNameStr);
1288
1289 const Array *OptEntityDataArray =
1290 SummaryDataMapEntryObject.getArray(K: "summary_data");
1291 if (!OptEntityDataArray) {
1292 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1293 Fmt: ErrorMessages::FailedToReadObjectAtField,
1294 ArgVals: "EntitySummary entries", ArgVals: "summary_data",
1295 ArgVals: "array")
1296 .build();
1297 }
1298
1299 auto ExpectedEncodingDataMap = encodingDataMapFromJSON(EntityDataArray: *OptEntityDataArray);
1300 if (!ExpectedEncodingDataMap) {
1301 return ErrorBuilder::wrap(E: ExpectedEncodingDataMap.takeError())
1302 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntitySummary entries",
1303 ArgVals: "summary_data")
1304 .build();
1305 }
1306
1307 return std::make_pair(x: std::move(SN), y: std::move(*ExpectedEncodingDataMap));
1308}
1309
1310Object JSONFormat::encodingSummaryDataMapEntryToJSON(
1311 const SummaryName &SN,
1312 const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
1313 &EncodingMap) const {
1314 Object Result;
1315
1316 Result["summary_name"] = summaryNameToJSON(SN);
1317 Result["summary_data"] = encodingDataMapToJSON(EncodingDataMap: EncodingMap);
1318
1319 return Result;
1320}
1321
1322//----------------------------------------------------------------------------
1323// EncodingSummaryDataMap
1324//----------------------------------------------------------------------------
1325
1326llvm::Expected<std::map<
1327 SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
1328JSONFormat::encodingSummaryDataMapFromJSON(
1329 const Array &SummaryDataArray) const {
1330 std::map<SummaryName,
1331 std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
1332 EncodingSummaryDataMap;
1333
1334 for (const auto &[Index, SummaryDataMapEntryValue] :
1335 llvm::enumerate(First: SummaryDataArray)) {
1336 const Object *OptSummaryDataMapEntryObject =
1337 SummaryDataMapEntryValue.getAsObject();
1338 if (!OptSummaryDataMapEntryObject) {
1339 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1340 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
1341 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: "object")
1342 .build();
1343 }
1344
1345 auto ExpectedEntry =
1346 encodingSummaryDataMapEntryFromJSON(SummaryDataMapEntryObject: *OptSummaryDataMapEntryObject);
1347 if (!ExpectedEntry) {
1348 return ErrorBuilder::wrap(E: ExpectedEntry.takeError())
1349 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "SummaryData entry", ArgVals&: Index)
1350 .build();
1351 }
1352
1353 auto [SummaryIt, SummaryInserted] =
1354 EncodingSummaryDataMap.emplace(args: std::move(*ExpectedEntry));
1355 if (!SummaryInserted) {
1356 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1357 Fmt: ErrorMessages::FailedInsertionOnDuplication,
1358 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: SummaryIt->first)
1359 .build();
1360 }
1361 }
1362
1363 return std::move(EncodingSummaryDataMap);
1364}
1365
1366Array JSONFormat::encodingSummaryDataMapToJSON(
1367 const std::map<SummaryName,
1368 std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
1369 &EncodingSummaryDataMap) const {
1370 Array Result;
1371 Result.reserve(S: EncodingSummaryDataMap.size());
1372
1373 for (const auto &[SN, EncodingMap] : EncodingSummaryDataMap) {
1374 Result.push_back(E: encodingSummaryDataMapEntryToJSON(SN, EncodingMap));
1375 }
1376
1377 return Result;
1378}
1379
1380} // namespace clang::ssaf
1381