1//===- SharedLexicalRepresentationFormat.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 "SSAFAnalysesCommon.h"
10#include "clang/ScalableStaticAnalysis/Analyses/SharedLexicalRepresentation/SharedLexicalRepresentation.h"
11#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
12#include "llvm/Support/Error.h"
13#include "llvm/Support/JSON.h"
14#include "llvm/Support/Registry.h"
15
16#include <memory>
17#include <utility>
18#include <vector>
19
20using namespace clang;
21using namespace ssaf;
22using Array = llvm::json::Array;
23using Object = llvm::json::Object;
24using Value = llvm::json::Value;
25
26namespace clang::ssaf {
27
28EntitySourceLocationsSummary
29buildEntitySourceLocationsSummary(std::vector<SourceLocationRecord> Locs) {
30 return EntitySourceLocationsSummary(std::move(Locs));
31}
32
33llvm::ArrayRef<SourceLocationRecord>
34getDeclLocations(const EntitySourceLocationsSummary &S) {
35 return S.DeclLocations;
36}
37
38} // namespace clang::ssaf
39
40static constexpr llvm::StringLiteral DeclLocationsKey = "decl_locations";
41static constexpr llvm::StringLiteral FilePathKey = "file_path";
42static constexpr llvm::StringLiteral LineKey = "line";
43static constexpr llvm::StringLiteral ColumnKey = "column";
44
45static Object sourceLocationRecordToJSON(const SourceLocationRecord &R) {
46 return Object{{.K: FilePathKey.data(), .V: R.FilePath},
47 {.K: LineKey.data(), .V: static_cast<int64_t>(R.Line)},
48 {.K: ColumnKey.data(), .V: static_cast<int64_t>(R.Column)}};
49}
50
51static llvm::Expected<SourceLocationRecord>
52sourceLocationRecordFromJSON(const Value &V) {
53 const Object *Obj = V.getAsObject();
54 if (!Obj)
55 return makeSawButExpectedError(Saw: V, Expected: "an object {%s, %s, %s}",
56 ExpectedArgs: FilePathKey.data(), ExpectedArgs: LineKey.data(),
57 ExpectedArgs: ColumnKey.data());
58
59 auto FilePath = Obj->getString(K: FilePathKey);
60 if (!FilePath)
61 return makeSawButExpectedError(Saw: *Obj, Expected: "an object with a string field %s",
62 ExpectedArgs: FilePathKey.data());
63
64 auto Line = Obj->getInteger(K: LineKey);
65 if (!Line)
66 return makeSawButExpectedError(Saw: *Obj, Expected: "an object with an integer field %s",
67 ExpectedArgs: LineKey.data());
68
69 auto Column = Obj->getInteger(K: ColumnKey);
70 if (!Column)
71 return makeSawButExpectedError(Saw: *Obj, Expected: "an object with an integer field %s",
72 ExpectedArgs: ColumnKey.data());
73
74 SourceLocationRecord R;
75 R.FilePath = FilePath->str();
76 R.Line = static_cast<unsigned>(*Line);
77 R.Column = static_cast<unsigned>(*Column);
78 return R;
79}
80
81static Object serialize(const EntitySummary &ES, JSONFormat::EntityIdToJSONFn) {
82 const auto &S = static_cast<const EntitySourceLocationsSummary &>(ES);
83 Array Locs;
84 for (const auto &R : getDeclLocations(S))
85 Locs.push_back(E: sourceLocationRecordToJSON(R));
86 return Object{{.K: DeclLocationsKey.data(), .V: std::move(Locs)}};
87}
88
89static llvm::Expected<std::unique_ptr<EntitySummary>>
90deserialize(const Object &Data, EntityIdTable &,
91 JSONFormat::EntityIdFromJSONFn) {
92 const Array *Locs = Data.getArray(K: DeclLocationsKey);
93 if (!Locs)
94 return makeSawButExpectedError(Saw: Object(Data),
95 Expected: "an Object with an array field %s",
96 ExpectedArgs: DeclLocationsKey.data());
97
98 std::vector<SourceLocationRecord> Records;
99 Records.reserve(n: Locs->size());
100 for (const Value &V : *Locs) {
101 auto R = sourceLocationRecordFromJSON(V);
102 if (!R)
103 return R.takeError();
104 Records.push_back(x: std::move(*R));
105 }
106 return std::make_unique<EntitySourceLocationsSummary>(
107 args: buildEntitySourceLocationsSummary(Locs: std::move(Records)));
108}
109
110namespace {
111struct SharedLexicalRepresentationJSONFormatInfo final
112 : JSONFormat::FormatInfo {
113 SharedLexicalRepresentationJSONFormatInfo()
114 : JSONFormat::FormatInfo(EntitySourceLocationsSummary::summaryName(),
115 serialize, deserialize) {}
116};
117} // namespace
118
119static llvm::Registry<JSONFormat::FormatInfo>::Add<
120 SharedLexicalRepresentationJSONFormatInfo>
121 RegisterSharedLexicalRepresentationJSONFormatInfo(
122 EntitySourceLocationsSummary::Name,
123 "JSON Format info for EntitySourceLocationsSummary");
124
125namespace clang::ssaf {
126// NOLINTNEXTLINE(misc-use-internal-linkage)
127volatile int SharedLexicalRepresentationJSONFormatAnchorSource = 0;
128} // namespace clang::ssaf
129