12#include "llvm/Support/Registry.h"
23 if (!llvm::sys::fs::exists(Path)) {
30 if (llvm::sys::fs::is_directory(Path)) {
45 auto BufferOrError = llvm::MemoryBuffer::getFile(Path);
47 const std::error_code EC = BufferOrError.getError();
53 return llvm::json::parse(BufferOrError.get()->getBuffer());
57 if (llvm::sys::fs::exists(Path)) {
64 llvm::StringRef Dir = llvm::sys::path::parent_path(Path);
65 if (!Dir.empty() && !llvm::sys::fs::is_directory(Dir)) {
81 llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text);
89 OutStream << llvm::formatv(
"{0:2}\n",
Value);
95 if (OutStream.has_error()) {
98 OutStream.error().message())
102 return llvm::Error::success();
109std::map<SummaryName, JSONFormat::FormatInfo> JSONFormat::initFormatInfos() {
110 std::map<SummaryName, FormatInfo> FormatInfos;
111 for (
const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
112 std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
113 bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second;
115 llvm::report_fatal_error(
116 "FormatInfo is already registered for summary: " +
117 Info->ForSummary.str());
137EntityId JSONFormat::entityIdFromJSON(
const uint64_t EntityIdIndex)
const {
138 return makeEntityId(
static_cast<size_t>(EntityIdIndex));
141uint64_t JSONFormat::entityIdToJSON(EntityId EI)
const {
142 return static_cast<uint64_t
>(
getIndex(EI));
149llvm::Expected<BuildNamespaceKind>
151 auto OptBuildNamespaceKind =
153 if (!OptBuildNamespaceKind) {
156 BuildNamespaceKindStr)
159 return *OptBuildNamespaceKind;
172JSONFormat::buildNamespaceFromJSON(
const Object &BuildNamespaceObject)
const {
173 auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString(
"kind");
174 if (!OptBuildNamespaceKindStr) {
177 "BuildNamespaceKind",
"kind",
"string")
188 auto OptNameStr = BuildNamespaceObject.getString(
"name");
192 "BuildNamespaceName",
"name",
"string")
196 return {BuildNamespace(*ExpectedKind, *OptNameStr)};
210llvm::Expected<NestedBuildNamespace> JSONFormat::nestedBuildNamespaceFromJSON(
211 const Array &NestedBuildNamespaceArray)
const {
212 std::vector<BuildNamespace> Namespaces;
214 size_t NamespaceCount = NestedBuildNamespaceArray.size();
215 Namespaces.reserve(NamespaceCount);
217 for (
const auto &[Index, BuildNamespaceValue] :
218 llvm::enumerate(NestedBuildNamespaceArray)) {
220 const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject();
221 if (!BuildNamespaceObject) {
224 "BuildNamespace", Index,
"object")
228 auto ExpectedBuildNamespace = buildNamespaceFromJSON(*BuildNamespaceObject);
229 if (!ExpectedBuildNamespace) {
235 Namespaces.push_back(std::move(*ExpectedBuildNamespace));
238 return NestedBuildNamespace(std::move(Namespaces));
241Array JSONFormat::nestedBuildNamespaceToJSON(
244 const auto &Namespaces = getNamespaces(NBN);
245 Result.reserve(Namespaces.size());
247 for (
const auto &BN : Namespaces) {
248 Result.push_back(buildNamespaceToJSON(BN));
258llvm::Expected<EntityName>
259JSONFormat::entityNameFromJSON(
const Object &EntityNameObject)
const {
260 const auto OptUSR = EntityNameObject.getString(
"usr");
268 const auto OptSuffix = EntityNameObject.getString(
"suffix");
272 "Suffix",
"suffix",
"string")
276 const Array *OptNamespaceArray = EntityNameObject.getArray(
"namespace");
277 if (!OptNamespaceArray) {
280 "NestedBuildNamespace",
"namespace",
"array")
284 auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*OptNamespaceArray);
285 if (!ExpectedNamespace) {
292 return EntityName{*OptUSR, *OptSuffix, std::move(*ExpectedNamespace)};
298 Result[
"suffix"] = getSuffix(EN);
299 Result[
"namespace"] = nestedBuildNamespaceToJSON(getNamespace(EN));
307llvm::Expected<EntityLinkageType>
310 if (!OptEntityLinkageType) {
313 EntityLinkageTypeStr)
316 return *OptEntityLinkageType;
329JSONFormat::entityLinkageFromJSON(
const Object &EntityLinkageObject)
const {
330 auto OptLinkageStr = EntityLinkageObject.getString(
"type");
331 if (!OptLinkageStr) {
334 "EntityLinkageType",
"type",
"string")
339 if (!ExpectedLinkageType) {
345 return EntityLinkage(*ExpectedLinkageType);
358llvm::Expected<std::pair<EntityName, EntityId>>
359JSONFormat::entityIdTableEntryFromJSON(
360 const Object &EntityIdTableEntryObject)
const {
362 const Object *OptEntityNameObject =
363 EntityIdTableEntryObject.getObject(
"name");
364 if (!OptEntityNameObject) {
367 "EntityName",
"name",
"object")
371 auto ExpectedEntityName = entityNameFromJSON(*OptEntityNameObject);
372 if (!ExpectedEntityName) {
378 const Value *EntityIdIntValue = EntityIdTableEntryObject.get(
"id");
379 if (!EntityIdIntValue) {
383 "number (unsigned 64-bit integer)")
387 const std::optional<uint64_t> OptEntityIdInt =
388 EntityIdIntValue->getAsUINT64();
389 if (!OptEntityIdInt) {
393 "number (unsigned 64-bit integer)")
397 EntityId EI = entityIdFromJSON(*OptEntityIdInt);
399 return std::make_pair(std::move(*ExpectedEntityName), std::move(EI));
405 Entry[
"id"] = entityIdToJSON(EI);
406 Entry[
"name"] = entityNameToJSON(EN);
414llvm::Expected<EntityIdTable>
415JSONFormat::entityIdTableFromJSON(
const Array &EntityIdTableArray)
const {
416 EntityIdTable IdTable;
417 std::map<EntityName, EntityId> &Entities = getEntities(IdTable);
419 for (
const auto &[Index, EntityIdTableEntryValue] :
420 llvm::enumerate(EntityIdTableArray)) {
422 const Object *OptEntityIdTableEntryObject =
423 EntityIdTableEntryValue.getAsObject();
424 if (!OptEntityIdTableEntryObject) {
427 "EntityIdTable entry", Index,
"object")
431 auto ExpectedEntityIdTableEntry =
432 entityIdTableEntryFromJSON(*OptEntityIdTableEntryObject);
433 if (!ExpectedEntityIdTableEntry)
439 auto [EntityIt, EntityInserted] =
440 Entities.emplace(std::move(*ExpectedEntityIdTableEntry));
441 if (!EntityInserted) {
444 "EntityIdTable entry", Index,
454 Array EntityIdTableArray;
455 const auto &Entities = getEntities(IdTable);
456 EntityIdTableArray.reserve(Entities.size());
458 for (
const auto &[EntityName, EntityId] : Entities) {
459 EntityIdTableArray.push_back(
460 entityIdTableEntryToJSON(EntityName, EntityId));
463 return EntityIdTableArray;
470llvm::Expected<std::pair<EntityId, EntityLinkage>>
471JSONFormat::linkageTableEntryFromJSON(
472 const Object &LinkageTableEntryObject)
const {
473 const Value *EntityIdIntValue = LinkageTableEntryObject.get(
"id");
474 if (!EntityIdIntValue) {
478 "number (unsigned 64-bit integer)")
482 const std::optional<uint64_t> OptEntityIdInt =
483 EntityIdIntValue->getAsUINT64();
484 if (!OptEntityIdInt) {
488 "number (unsigned 64-bit integer)")
492 EntityId EI = entityIdFromJSON(*OptEntityIdInt);
494 const Object *OptEntityLinkageObject =
495 LinkageTableEntryObject.getObject(
"linkage");
496 if (!OptEntityLinkageObject) {
499 "EntityLinkage",
"linkage",
"object")
503 auto ExpectedEntityLinkage = entityLinkageFromJSON(*OptEntityLinkageObject);
504 if (!ExpectedEntityLinkage) {
510 return std::make_pair(std::move(EI), std::move(*ExpectedEntityLinkage));
516 Entry[
"id"] = entityIdToJSON(EI);
517 Entry[
"linkage"] = entityLinkageToJSON(EL);
529llvm::Expected<std::map<EntityId, EntityLinkage>>
530JSONFormat::linkageTableFromJSON(
const Array &LinkageTableArray,
531 std::set<EntityId> ExpectedIds)
const {
532 std::map<EntityId, EntityLinkage> LinkageTable;
534 for (
const auto &[Index, LinkageTableEntryValue] :
535 llvm::enumerate(LinkageTableArray)) {
536 const Object *OptLinkageTableEntryObject =
537 LinkageTableEntryValue.getAsObject();
538 if (!OptLinkageTableEntryObject) {
541 "LinkageTable entry", Index,
"object")
545 auto ExpectedLinkageTableEntry =
546 linkageTableEntryFromJSON(*OptLinkageTableEntryObject);
547 if (!ExpectedLinkageTableEntry) {
553 const EntityId EI = ExpectedLinkageTableEntry->first;
555 auto [It, Inserted] =
556 LinkageTable.insert(std::move(*ExpectedLinkageTableEntry));
560 "LinkageTable entry", Index, It->first)
564 if (ExpectedIds.erase(EI) == 0) {
566 std::errc::invalid_argument,
573 if (!ExpectedIds.empty()) {
575 std::errc::invalid_argument,
577 *ExpectedIds.begin())
584Array JSONFormat::linkageTableToJSON(
585 const std::map<EntityId, EntityLinkage> &LinkageTable)
const {
587 Result.reserve(LinkageTable.size());
589 for (
const auto &[EI, EL] : LinkageTable) {
590 Result.push_back(linkageTableEntryToJSON(EI, EL));
static std::optional< NonLoc > getIndex(ProgramStateRef State, const ElementRegion *ER, CharKind CK)
static Decl::Kind getKind(const Decl *D)
static std::string getUSR(const Decl *D)
Represents a single namespace in the build process.
Manages entity name interning and provides efficient EntityId handles.
Lightweight opaque handle representing an entity in an EntityIdTable.
Represents the linkage properties of an entity in the program model.
Uniquely identifies an entity in a program.
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
ErrorBuilder & context(const char *Msg)
Add context information as a plain string.
llvm::Error build() const
Build and return the final error.
static ErrorBuilder wrap(llvm::Error E)
Wrap an existing error and optionally add context.
Represents a hierarchical sequence of build namespaces.
Uniquely identifies an analysis summary.
llvm::StringRef str() const
Explicit conversion to the underlying string representation.
StringRef getName(const HeaderType T)
constexpr const char * InvalidBuildNamespaceKind
constexpr const char * ReadingFromField
constexpr const char * FailedToReadObjectAtIndex
constexpr const char * InvalidEntityLinkageType
constexpr const char * FileIsDirectory
constexpr const char * FileNotFound
constexpr const char * FailedToReadObjectAtField
constexpr const char * FileExists
constexpr const char * ReadingFromIndex
constexpr const char * FailedInsertionOnDuplication
constexpr const char * FailedToDeserializeLinkageTableExtraId
constexpr const char * FailedToWriteFile
constexpr const char * FailedToDeserializeLinkageTableMissingId
constexpr const char * FileIsNotJSON
constexpr const char * FailedToReadFile
constexpr const char * ParentDirectoryNotFound
SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr)
llvm::StringRef summaryNameToJSON(const SummaryName &SN)
std::optional< EntityLinkageType > entityLinkageTypeFromString(llvm::StringRef Str)
Parses a string produced by entityLinkageTypeToString().
std::optional< BuildNamespaceKind > buildNamespaceKindFromString(llvm::StringRef Str)
Parses a string produced by buildNamespaceKindToString().
llvm::Expected< EntityLinkageType > entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr)
llvm::Error writeJSON(Value &&Value, llvm::StringRef Path)
llvm::Expected< BuildNamespaceKind > buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr)
llvm::json::Object Object
llvm::Expected< Value > readJSON(llvm::StringRef Path)
constexpr const char * JSONFormatFileExtension
llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK)
llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT)
llvm::StringRef buildNamespaceKindToString(BuildNamespaceKind BNK)
Returns the canonical string representation of BNK used for serialization and display (e....
llvm::StringRef entityLinkageTypeToString(EntityLinkageType LT)
Returns the canonical string representation of LT used for serialization and display (e....
@ Result
The result type of a method or function.
template class CLANG_TEMPLATE_ABI Registry< clang::ssaf::JSONFormat::FormatInfo >