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