clang  15.0.0git
SymbolGraphSerializer.cpp
Go to the documentation of this file.
1 //===- ExtractAPI/Serialization/SymbolGraphSerializer.cpp -------*- C++ -*-===//
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 /// \file
10 /// This file implements the SymbolGraphSerializer.
11 ///
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/Basic/Version.h"
16 #include "clang/ExtractAPI/API.h"
18 #include "llvm/Support/JSON.h"
19 #include "llvm/Support/Path.h"
20 #include "llvm/Support/VersionTuple.h"
21 #include <type_traits>
22 
23 using namespace clang;
24 using namespace clang::extractapi;
25 using namespace llvm;
26 using namespace llvm::json;
27 
28 namespace {
29 
30 /// Helper function to inject a JSON object \p Obj into another object \p Paren
31 /// at position \p Key.
32 void serializeObject(Object &Paren, StringRef Key, Optional<Object> Obj) {
33  if (Obj)
34  Paren[Key] = std::move(Obj.value());
35 }
36 
37 /// Helper function to inject a JSON array \p Array into object \p Paren at
38 /// position \p Key.
39 void serializeArray(Object &Paren, StringRef Key, Optional<Array> Array) {
40  if (Array)
41  Paren[Key] = std::move(Array.value());
42 }
43 
44 /// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version
45 /// format.
46 ///
47 /// A semantic version object contains three numeric fields, representing the
48 /// \c major, \c minor, and \c patch parts of the version tuple.
49 /// For example version tuple 1.0.3 is serialized as:
50 /// \code
51 /// {
52 /// "major" : 1,
53 /// "minor" : 0,
54 /// "patch" : 3
55 /// }
56 /// \endcode
57 ///
58 /// \returns \c None if the version \p V is empty, or an \c Object containing
59 /// the semantic version representation of \p V.
60 Optional<Object> serializeSemanticVersion(const VersionTuple &V) {
61  if (V.empty())
62  return None;
63 
64  Object Version;
65  Version["major"] = V.getMajor();
66  Version["minor"] = V.getMinor().value_or(0);
67  Version["patch"] = V.getSubminor().value_or(0);
68  return Version;
69 }
70 
71 /// Serialize the OS information in the Symbol Graph platform property.
72 ///
73 /// The OS information in Symbol Graph contains the \c name of the OS, and an
74 /// optional \c minimumVersion semantic version field.
75 Object serializeOperatingSystem(const Triple &T) {
76  Object OS;
77  OS["name"] = T.getOSTypeName(T.getOS());
78  serializeObject(OS, "minimumVersion",
79  serializeSemanticVersion(T.getMinimumSupportedOSVersion()));
80  return OS;
81 }
82 
83 /// Serialize the platform information in the Symbol Graph module section.
84 ///
85 /// The platform object describes a target platform triple in corresponding
86 /// three fields: \c architecture, \c vendor, and \c operatingSystem.
87 Object serializePlatform(const Triple &T) {
88  Object Platform;
89  Platform["architecture"] = T.getArchName();
90  Platform["vendor"] = T.getVendorName();
91  Platform["operatingSystem"] = serializeOperatingSystem(T);
92  return Platform;
93 }
94 
95 /// Serialize a source position.
96 Object serializeSourcePosition(const PresumedLoc &Loc) {
97  assert(Loc.isValid() && "invalid source position");
98 
99  Object SourcePosition;
100  SourcePosition["line"] = Loc.getLine();
101  SourcePosition["character"] = Loc.getColumn();
102 
103  return SourcePosition;
104 }
105 
106 /// Serialize a source location in file.
107 ///
108 /// \param Loc The presumed location to serialize.
109 /// \param IncludeFileURI If true, include the file path of \p Loc as a URI.
110 /// Defaults to false.
111 Object serializeSourceLocation(const PresumedLoc &Loc,
112  bool IncludeFileURI = false) {
114  serializeObject(SourceLocation, "position", serializeSourcePosition(Loc));
115 
116  if (IncludeFileURI) {
117  std::string FileURI = "file://";
118  // Normalize file path to use forward slashes for the URI.
119  FileURI += sys::path::convert_to_slash(Loc.getFilename());
120  SourceLocation["uri"] = FileURI;
121  }
122 
123  return SourceLocation;
124 }
125 
126 /// Serialize a source range with begin and end locations.
127 Object serializeSourceRange(const PresumedLoc &BeginLoc,
128  const PresumedLoc &EndLoc) {
130  serializeObject(SourceRange, "start", serializeSourcePosition(BeginLoc));
131  serializeObject(SourceRange, "end", serializeSourcePosition(EndLoc));
132  return SourceRange;
133 }
134 
135 /// Serialize the availability attributes of a symbol.
136 ///
137 /// Availability information contains the introduced, deprecated, and obsoleted
138 /// versions of the symbol as semantic versions, if not default.
139 /// Availability information also contains flags to indicate if the symbol is
140 /// unconditionally unavailable or deprecated,
141 /// i.e. \c __attribute__((unavailable)) and \c __attribute__((deprecated)).
142 ///
143 /// \returns \c None if the symbol has default availability attributes, or
144 /// an \c Object containing the formatted availability information.
145 Optional<Object> serializeAvailability(const AvailabilityInfo &Avail) {
146  if (Avail.isDefault())
147  return None;
148 
149  Object Availbility;
150  serializeObject(Availbility, "introducedVersion",
151  serializeSemanticVersion(Avail.Introduced));
152  serializeObject(Availbility, "deprecatedVersion",
153  serializeSemanticVersion(Avail.Deprecated));
154  serializeObject(Availbility, "obsoletedVersion",
155  serializeSemanticVersion(Avail.Obsoleted));
156  if (Avail.isUnavailable())
157  Availbility["isUnconditionallyUnavailable"] = true;
158  if (Avail.isUnconditionallyDeprecated())
159  Availbility["isUnconditionallyDeprecated"] = true;
160 
161  return Availbility;
162 }
163 
164 /// Get the language name string for interface language references.
165 StringRef getLanguageName(Language Lang) {
166  switch (Lang) {
167  case Language::C:
168  return "c";
169  case Language::ObjC:
170  return "objective-c";
171 
172  // Unsupported language currently
173  case Language::CXX:
174  case Language::ObjCXX:
175  case Language::OpenCL:
176  case Language::OpenCLCXX:
177  case Language::CUDA:
179  case Language::HIP:
180  case Language::HLSL:
181 
182  // Languages that the frontend cannot parse and compile
183  case Language::Unknown:
184  case Language::Asm:
185  case Language::LLVM_IR:
186  llvm_unreachable("Unsupported language kind");
187  }
188 
189  llvm_unreachable("Unhandled language kind");
190 }
191 
192 /// Serialize the identifier object as specified by the Symbol Graph format.
193 ///
194 /// The identifier property of a symbol contains the USR for precise and unique
195 /// references, and the interface language name.
196 Object serializeIdentifier(const APIRecord &Record, Language Lang) {
198  Identifier["precise"] = Record.USR;
199  Identifier["interfaceLanguage"] = getLanguageName(Lang);
200 
201  return Identifier;
202 }
203 
204 /// Serialize the documentation comments attached to a symbol, as specified by
205 /// the Symbol Graph format.
206 ///
207 /// The Symbol Graph \c docComment object contains an array of lines. Each line
208 /// represents one line of striped documentation comment, with source range
209 /// information.
210 /// e.g.
211 /// \code
212 /// /// This is a documentation comment
213 /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' First line.
214 /// /// with multiple lines.
215 /// ^~~~~~~~~~~~~~~~~~~~~~~' Second line.
216 /// \endcode
217 ///
218 /// \returns \c None if \p Comment is empty, or an \c Object containing the
219 /// formatted lines.
220 Optional<Object> serializeDocComment(const DocComment &Comment) {
221  if (Comment.empty())
222  return None;
223 
225  Array LinesArray;
226  for (const auto &CommentLine : Comment) {
227  Object Line;
228  Line["text"] = CommentLine.Text;
229  serializeObject(Line, "range",
230  serializeSourceRange(CommentLine.Begin, CommentLine.End));
231  LinesArray.emplace_back(std::move(Line));
232  }
233  serializeArray(DocComment, "lines", LinesArray);
234 
235  return DocComment;
236 }
237 
238 /// Serialize the declaration fragments of a symbol.
239 ///
240 /// The Symbol Graph declaration fragments is an array of tagged important
241 /// parts of a symbol's declaration. The fragments sequence can be joined to
242 /// form spans of declaration text, with attached information useful for
243 /// purposes like syntax-highlighting etc. For example:
244 /// \code
245 /// const int pi; -> "declarationFragments" : [
246 /// {
247 /// "kind" : "keyword",
248 /// "spelling" : "const"
249 /// },
250 /// {
251 /// "kind" : "text",
252 /// "spelling" : " "
253 /// },
254 /// {
255 /// "kind" : "typeIdentifier",
256 /// "preciseIdentifier" : "c:I",
257 /// "spelling" : "int"
258 /// },
259 /// {
260 /// "kind" : "text",
261 /// "spelling" : " "
262 /// },
263 /// {
264 /// "kind" : "identifier",
265 /// "spelling" : "pi"
266 /// }
267 /// ]
268 /// \endcode
269 ///
270 /// \returns \c None if \p DF is empty, or an \c Array containing the formatted
271 /// declaration fragments array.
272 Optional<Array> serializeDeclarationFragments(const DeclarationFragments &DF) {
273  if (DF.getFragments().empty())
274  return None;
275 
276  Array Fragments;
277  for (const auto &F : DF.getFragments()) {
278  Object Fragment;
279  Fragment["spelling"] = F.Spelling;
280  Fragment["kind"] = DeclarationFragments::getFragmentKindString(F.Kind);
281  if (!F.PreciseIdentifier.empty())
282  Fragment["preciseIdentifier"] = F.PreciseIdentifier;
283  Fragments.emplace_back(std::move(Fragment));
284  }
285 
286  return Fragments;
287 }
288 
289 /// Serialize the \c names field of a symbol as specified by the Symbol Graph
290 /// format.
291 ///
292 /// The Symbol Graph names field contains multiple representations of a symbol
293 /// that can be used for different applications:
294 /// - \c title : The simple declared name of the symbol;
295 /// - \c subHeading : An array of declaration fragments that provides tags,
296 /// and potentially more tokens (for example the \c +/- symbol for
297 /// Objective-C methods). Can be used as sub-headings for documentation.
298 Object serializeNames(const APIRecord &Record) {
299  Object Names;
300  Names["title"] = Record.Name;
301  serializeArray(Names, "subHeading",
302  serializeDeclarationFragments(Record.SubHeading));
303  DeclarationFragments NavigatorFragments;
304  NavigatorFragments.append(Record.Name,
306  /*PreciseIdentifier*/ "");
307  serializeArray(Names, "navigator",
308  serializeDeclarationFragments(NavigatorFragments));
309 
310  return Names;
311 }
312 
313 /// Serialize the symbol kind information.
314 ///
315 /// The Symbol Graph symbol kind property contains a shorthand \c identifier
316 /// which is prefixed by the source language name, useful for tooling to parse
317 /// the kind, and a \c displayName for rendering human-readable names.
318 Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
319  auto AddLangPrefix = [&Lang](StringRef S) -> std::string {
320  return (getLanguageName(Lang) + "." + S).str();
321  };
322 
323  Object Kind;
324  switch (Record.getKind()) {
326  Kind["identifier"] = AddLangPrefix("func");
327  Kind["displayName"] = "Function";
328  break;
330  Kind["identifier"] = AddLangPrefix("var");
331  Kind["displayName"] = "Global Variable";
332  break;
334  Kind["identifier"] = AddLangPrefix("enum.case");
335  Kind["displayName"] = "Enumeration Case";
336  break;
337  case APIRecord::RK_Enum:
338  Kind["identifier"] = AddLangPrefix("enum");
339  Kind["displayName"] = "Enumeration";
340  break;
342  Kind["identifier"] = AddLangPrefix("property");
343  Kind["displayName"] = "Instance Property";
344  break;
346  Kind["identifier"] = AddLangPrefix("struct");
347  Kind["displayName"] = "Structure";
348  break;
350  Kind["identifier"] = AddLangPrefix("ivar");
351  Kind["displayName"] = "Instance Variable";
352  break;
354  if (dyn_cast<ObjCMethodRecord>(&Record)->IsInstanceMethod) {
355  Kind["identifier"] = AddLangPrefix("method");
356  Kind["displayName"] = "Instance Method";
357  } else {
358  Kind["identifier"] = AddLangPrefix("type.method");
359  Kind["displayName"] = "Type Method";
360  }
361  break;
363  Kind["identifier"] = AddLangPrefix("property");
364  Kind["displayName"] = "Instance Property";
365  break;
367  Kind["identifier"] = AddLangPrefix("class");
368  Kind["displayName"] = "Class";
369  break;
371  // We don't serialize out standalone Objective-C category symbols yet.
372  llvm_unreachable("Serializing standalone Objective-C category symbols is "
373  "not supported.");
374  break;
376  Kind["identifier"] = AddLangPrefix("protocol");
377  Kind["displayName"] = "Protocol";
378  break;
380  Kind["identifier"] = AddLangPrefix("macro");
381  Kind["displayName"] = "Macro";
382  break;
384  Kind["identifier"] = AddLangPrefix("typealias");
385  Kind["displayName"] = "Type Alias";
386  break;
387  }
388 
389  return Kind;
390 }
391 
392 template <typename RecordTy>
393 Optional<Object> serializeFunctionSignatureMixinImpl(const RecordTy &Record,
394  std::true_type) {
395  const auto &FS = Record.Signature;
396  if (FS.empty())
397  return None;
398 
399  Object Signature;
400  serializeArray(Signature, "returns",
401  serializeDeclarationFragments(FS.getReturnType()));
402 
403  Array Parameters;
404  for (const auto &P : FS.getParameters()) {
406  Parameter["name"] = P.Name;
407  serializeArray(Parameter, "declarationFragments",
408  serializeDeclarationFragments(P.Fragments));
409  Parameters.emplace_back(std::move(Parameter));
410  }
411 
412  if (!Parameters.empty())
413  Signature["parameters"] = std::move(Parameters);
414 
415  return Signature;
416 }
417 
418 template <typename RecordTy>
419 Optional<Object> serializeFunctionSignatureMixinImpl(const RecordTy &Record,
420  std::false_type) {
421  return None;
422 }
423 
424 /// Serialize the function signature field, as specified by the
425 /// Symbol Graph format.
426 ///
427 /// The Symbol Graph function signature property contains two arrays.
428 /// - The \c returns array is the declaration fragments of the return type;
429 /// - The \c parameters array contains names and declaration fragments of the
430 /// parameters.
431 ///
432 /// \returns \c None if \p FS is empty, or an \c Object containing the
433 /// formatted function signature.
434 template <typename RecordTy>
435 void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
436  serializeObject(Paren, "functionSignature",
437  serializeFunctionSignatureMixinImpl(
439 }
440 
441 } // namespace
442 
443 void SymbolGraphSerializer::anchor() {}
444 
445 /// Defines the format version emitted by SymbolGraphSerializer.
446 const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
447 
448 Object SymbolGraphSerializer::serializeMetadata() const {
449  Object Metadata;
450  serializeObject(Metadata, "formatVersion",
451  serializeSemanticVersion(FormatVersion));
452  Metadata["generator"] = clang::getClangFullVersion();
453  return Metadata;
454 }
455 
456 Object SymbolGraphSerializer::serializeModule() const {
457  Object Module;
458  // The user is expected to always pass `--product-name=` on the command line
459  // to populate this field.
460  Module["name"] = ProductName;
461  serializeObject(Module, "platform", serializePlatform(API.getTarget()));
462  return Module;
463 }
464 
465 bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
466  // Skip unconditionally unavailable symbols
468  return true;
469 
470  // Filter out symbols prefixed with an underscored as they are understood to
471  // be symbols clients should not use.
472  if (Record.Name.startswith("_"))
473  return true;
474 
475  return false;
476 }
477 
478 template <typename RecordTy>
480 SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
481  if (shouldSkip(Record))
482  return None;
483 
484  Object Obj;
485  serializeObject(Obj, "identifier",
486  serializeIdentifier(Record, API.getLanguage()));
487  serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage()));
488  serializeObject(Obj, "names", serializeNames(Record));
489  serializeObject(
490  Obj, "location",
491  serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
492  serializeObject(Obj, "availbility",
493  serializeAvailability(Record.Availability));
494  serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
495  serializeArray(Obj, "declarationFragments",
496  serializeDeclarationFragments(Record.Declaration));
497  // TODO: Once we keep track of symbol access information serialize it
498  // correctly here.
499  Obj["accessLevel"] = "public";
500  serializeArray(Obj, "pathComponents", Array(PathComponents));
501 
502  serializeFunctionSignatureMixin(Obj, Record);
503 
504  return Obj;
505 }
506 
507 template <typename MemberTy>
508 void SymbolGraphSerializer::serializeMembers(
509  const APIRecord &Record,
510  const SmallVector<std::unique_ptr<MemberTy>> &Members) {
511  for (const auto &Member : Members) {
512  auto MemberPathComponentGuard = makePathComponentGuard(Member->Name);
513  auto MemberRecord = serializeAPIRecord(*Member);
514  if (!MemberRecord)
515  continue;
516 
517  Symbols.emplace_back(std::move(*MemberRecord));
518  serializeRelationship(RelationshipKind::MemberOf, *Member, Record);
519  }
520 }
521 
523  switch (Kind) {
524  case RelationshipKind::MemberOf:
525  return "memberOf";
526  case RelationshipKind::InheritsFrom:
527  return "inheritsFrom";
528  case RelationshipKind::ConformsTo:
529  return "conformsTo";
530  }
531  llvm_unreachable("Unhandled relationship kind");
532 }
533 
534 void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
535  SymbolReference Source,
536  SymbolReference Target) {
537  Object Relationship;
538  Relationship["source"] = Source.USR;
539  Relationship["target"] = Target.USR;
540  Relationship["kind"] = getRelationshipString(Kind);
541 
542  Relationships.emplace_back(std::move(Relationship));
543 }
544 
545 void SymbolGraphSerializer::serializeGlobalFunctionRecord(
546  const GlobalFunctionRecord &Record) {
547  auto GlobalPathComponentGuard = makePathComponentGuard(Record.Name);
548 
549  auto Obj = serializeAPIRecord(Record);
550  if (!Obj)
551  return;
552 
553  Symbols.emplace_back(std::move(*Obj));
554 }
555 
556 void SymbolGraphSerializer::serializeGlobalVariableRecord(
557  const GlobalVariableRecord &Record) {
558  auto GlobalPathComponentGuard = makePathComponentGuard(Record.Name);
559 
560  auto Obj = serializeAPIRecord(Record);
561  if (!Obj)
562  return;
563 
564  Symbols.emplace_back(std::move(*Obj));
565 }
566 
567 void SymbolGraphSerializer::serializeEnumRecord(const EnumRecord &Record) {
568  auto EnumPathComponentGuard = makePathComponentGuard(Record.Name);
569  auto Enum = serializeAPIRecord(Record);
570  if (!Enum)
571  return;
572 
573  Symbols.emplace_back(std::move(*Enum));
574  serializeMembers(Record, Record.Constants);
575 }
576 
577 void SymbolGraphSerializer::serializeStructRecord(const StructRecord &Record) {
578  auto StructPathComponentGuard = makePathComponentGuard(Record.Name);
579  auto Struct = serializeAPIRecord(Record);
580  if (!Struct)
581  return;
582 
583  Symbols.emplace_back(std::move(*Struct));
584  serializeMembers(Record, Record.Fields);
585 }
586 
587 void SymbolGraphSerializer::serializeObjCContainerRecord(
588  const ObjCContainerRecord &Record) {
589  auto ObjCContainerPathComponentGuard = makePathComponentGuard(Record.Name);
590  auto ObjCContainer = serializeAPIRecord(Record);
591  if (!ObjCContainer)
592  return;
593 
594  Symbols.emplace_back(std::move(*ObjCContainer));
595 
596  serializeMembers(Record, Record.Ivars);
597  serializeMembers(Record, Record.Methods);
598  serializeMembers(Record, Record.Properties);
599 
600  for (const auto &Protocol : Record.Protocols)
601  // Record that Record conforms to Protocol.
602  serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
603 
604  if (auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record)) {
605  if (!ObjCInterface->SuperClass.empty())
606  // If Record is an Objective-C interface record and it has a super class,
607  // record that Record is inherited from SuperClass.
608  serializeRelationship(RelationshipKind::InheritsFrom, Record,
609  ObjCInterface->SuperClass);
610 
611  // Members of categories extending an interface are serialized as members of
612  // the interface.
613  for (const auto *Category : ObjCInterface->Categories) {
614  serializeMembers(Record, Category->Ivars);
615  serializeMembers(Record, Category->Methods);
616  serializeMembers(Record, Category->Properties);
617 
618  // Surface the protocols of the the category to the interface.
619  for (const auto &Protocol : Category->Protocols)
620  serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
621  }
622  }
623 }
624 
625 void SymbolGraphSerializer::serializeMacroDefinitionRecord(
626  const MacroDefinitionRecord &Record) {
627  auto MacroPathComponentGuard = makePathComponentGuard(Record.Name);
628  auto Macro = serializeAPIRecord(Record);
629 
630  if (!Macro)
631  return;
632 
633  Symbols.emplace_back(std::move(*Macro));
634 }
635 
636 void SymbolGraphSerializer::serializeTypedefRecord(
637  const TypedefRecord &Record) {
638  // Typedefs of anonymous types have their entries unified with the underlying
639  // type.
640  bool ShouldDrop = Record.UnderlyingType.Name.empty();
641  // enums declared with `NS_OPTION` have a named enum and a named typedef, with
642  // the same name
643  ShouldDrop |= (Record.UnderlyingType.Name == Record.Name);
644  if (ShouldDrop)
645  return;
646 
647  auto TypedefPathComponentGuard = makePathComponentGuard(Record.Name);
648  auto Typedef = serializeAPIRecord(Record);
649  if (!Typedef)
650  return;
651 
652  (*Typedef)["type"] = Record.UnderlyingType.USR;
653 
654  Symbols.emplace_back(std::move(*Typedef));
655 }
656 
657 SymbolGraphSerializer::PathComponentGuard
658 SymbolGraphSerializer::makePathComponentGuard(StringRef Component) {
659  return PathComponentGuard(PathComponents, Component);
660 }
661 
663  Object Root;
664  serializeObject(Root, "metadata", serializeMetadata());
665  serializeObject(Root, "module", serializeModule());
666 
667  // Serialize global variables in the API set.
668  for (const auto &GlobalVar : API.getGlobalVariables())
669  serializeGlobalVariableRecord(*GlobalVar.second);
670 
671  for (const auto &GlobalFunction : API.getGlobalFunctions())
672  serializeGlobalFunctionRecord(*GlobalFunction.second);
673 
674  // Serialize enum records in the API set.
675  for (const auto &Enum : API.getEnums())
676  serializeEnumRecord(*Enum.second);
677 
678  // Serialize struct records in the API set.
679  for (const auto &Struct : API.getStructs())
680  serializeStructRecord(*Struct.second);
681 
682  // Serialize Objective-C interface records in the API set.
683  for (const auto &ObjCInterface : API.getObjCInterfaces())
684  serializeObjCContainerRecord(*ObjCInterface.second);
685 
686  // Serialize Objective-C protocol records in the API set.
687  for (const auto &ObjCProtocol : API.getObjCProtocols())
688  serializeObjCContainerRecord(*ObjCProtocol.second);
689 
690  for (const auto &Macro : API.getMacros())
691  serializeMacroDefinitionRecord(*Macro.second);
692 
693  for (const auto &Typedef : API.getTypedefs())
694  serializeTypedefRecord(*Typedef.second);
695 
696  Root["symbols"] = std::move(Symbols);
697  Root["relationships"] = std::move(Relationships);
698 
699  return Root;
700 }
701 
702 void SymbolGraphSerializer::serialize(raw_ostream &os) {
703  Object root = serialize();
704  if (Options.Compact)
705  os << formatv("{0}", Value(std::move(root))) << "\n";
706  else
707  os << formatv("{0:2}", Value(std::move(root))) << "\n";
708 }
clang::Language::CUDA
@ CUDA
llvm
YAML serialization mapping.
Definition: Dominators.h:30
clang::extractapi::AvailabilityInfo::Introduced
VersionTuple Introduced
Definition: AvailabilityInfo.h:29
clang::extractapi::StructRecord
This holds information associated with structs.
Definition: API.h:210
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:210
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::PresumedLoc::getLine
unsigned getLine() const
Return the presumed line number of this location.
Definition: SourceLocation.h:337
clang::ObjCSubstitutionContext::Parameter
@ Parameter
The parameter type of a method or function.
clang::extractapi::APIRecord::Availability
AvailabilityInfo Availability
Definition: API.h:61
clang::extractapi::APIRecord::Name
StringRef Name
Definition: API.h:59
clang::extractapi::ObjCContainerRecord::Ivars
SmallVector< std::unique_ptr< ObjCInstanceVariableRecord > > Ivars
Definition: API.h:338
llvm::SmallVector
Definition: LLVM.h:38
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
clang::MultiVersionKind::Target
@ Target
clang::extractapi::AvailabilityInfo::isUnconditionallyUnavailable
bool isUnconditionallyUnavailable() const
Check if the symbol is unconditionally unavailable.
Definition: AvailabilityInfo.h:50
clang::extractapi::GlobalVariableRecord
This holds information associated with global functions.
Definition: API.h:139
clang::extractapi::has_function_signature
Check if a record type has a function signature mixin.
Definition: API.h:464
clang::Language::OpenCLCXX
@ OpenCLCXX
clang::extractapi::DeclarationFragments
DeclarationFragments is a vector of tagged important parts of a symbol's declaration.
Definition: DeclarationFragments.h:43
llvm::Optional
Definition: LLVM.h:40
clang::extractapi::APIRecord::RK_ObjCInterface
@ RK_ObjCInterface
Definition: API.h:89
clang::index::SymbolKind::Macro
@ Macro
clang::Language::Asm
@ Asm
Assembly: we accept this only so that we can preprocess it.
Identifier
StringRef Identifier
Definition: Format.cpp:2585
Paren
@ Paren
Definition: PPMacroExpansion.cpp:632
clang::syntax::NodeRole::Object
@ Object
clang::extractapi::GlobalFunctionRecord
This holds information associated with global functions.
Definition: API.h:117
clang::syntax::NodeRole::Parameters
@ Parameters
V
#define V(N, I)
Definition: ASTContext.h:3184
clang::Language::RenderScript
@ RenderScript
clang::Module
Describes a module or submodule.
Definition: Module.h:96
llvm::json
Definition: DarwinSDKInfo.h:20
clang::extractapi::AvailabilityInfo::Deprecated
VersionTuple Deprecated
Definition: AvailabilityInfo.h:30
clang::extractapi::APIRecord::RK_Enum
@ RK_Enum
Definition: API.h:83
DeclarationFragments.h
clang::XRayInstrKind::None
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
clang::PresumedLoc::getFilename
const char * getFilename() const
Return the presumed filename of this location.
Definition: SourceLocation.h:324
clang::extractapi::TypedefRecord
This holds information associated with typedefs.
Definition: API.h:440
Version.h
clang::extractapi
Definition: API.h:36
clang::extractapi::MacroDefinitionRecord
This holds information associated with macro definitions.
Definition: API.h:420
clang::DeclaratorContext::Member
@ Member
clang::extractapi::APIRecord::RK_Typedef
@ RK_Typedef
Definition: API.h:93
clang::extractapi::APIRecord::RK_Struct
@ RK_Struct
Definition: API.h:85
clang::extractapi::SymbolReference::USR
StringRef USR
Definition: API.h:316
clang::extractapi::APIRecord::getKind
RecordKind getKind() const
Definition: API.h:100
clang::Language::C
@ C
Languages that the frontend can parse and compile.
clang::extractapi::DeclarationFragments::getFragments
const std::vector< Fragment > & getFragments() const
Definition: DeclarationFragments.h:95
Category
int Category
Definition: Format.cpp:2580
clang::PresumedLoc::getColumn
unsigned getColumn() const
Return the presumed column number of this location.
Definition: SourceLocation.h:345
clang::extractapi::AvailabilityInfo::Obsoleted
VersionTuple Obsoleted
Definition: AvailabilityInfo.h:31
clang::extractapi::DocComment
std::vector< RawComment::CommentLine > DocComment
DocComment is a vector of RawComment::CommentLine.
Definition: API.h:51
clang::extractapi::StructRecord::Fields
SmallVector< std::unique_ptr< StructFieldRecord > > Fields
Definition: API.h:211
clang::extractapi::APIRecord::RK_ObjCCategory
@ RK_ObjCCategory
Definition: API.h:90
clang::extractapi::APIRecord::RK_ObjCProperty
@ RK_ObjCProperty
Definition: API.h:86
Line
const AnnotatedLine * Line
Definition: UsingDeclarationsSorter.cpp:68
clang::extractapi::SymbolGraphSerializer::RelationshipKind
RelationshipKind
The kind of a relationship between two symbols.
Definition: SymbolGraphSerializer.h:80
clang::extractapi::ObjCContainerRecord::Protocols
SmallVector< SymbolReference > Protocols
Definition: API.h:339
clang::extractapi::APIRecord::RK_GlobalVariable
@ RK_GlobalVariable
Definition: API.h:81
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::Language
Language
The language for the input, used to select and validate the language standard and possible actions.
Definition: LangStandard.h:23
clang::extractapi::ObjCContainerRecord::Properties
SmallVector< std::unique_ptr< ObjCPropertyRecord > > Properties
Definition: API.h:337
clang::extractapi::APIRecord::RK_ObjCIvar
@ RK_ObjCIvar
Definition: API.h:87
clang::extractapi::DeclarationFragments::FragmentKind::Identifier
@ Identifier
clang::Language::CXX
@ CXX
clang::Language::ObjCXX
@ ObjCXX
clang::extractapi::AvailabilityInfo
Stores availability attributes of a symbol.
Definition: AvailabilityInfo.h:28
clang::Language::LLVM_IR
@ LLVM_IR
LLVM IR: we accept this so that we can run the optimizer on it, and compile it to assembly or object ...
Value
Value
Definition: UninitializedValues.cpp:102
clang::extractapi::ObjCContainerRecord
The base representation of an Objective-C container record.
Definition: API.h:335
clang::extractapi::DeclarationFragments::append
DeclarationFragments & append(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier="")
Append a new Fragment to the end of the Fragments.
Definition: DeclarationFragments.h:101
clang::Language::ObjC
@ ObjC
clang::extractapi::SymbolGraphSerializer::serialize
Object serialize()
Serialize the APIs in APISet in the Symbol Graph format.
Definition: SymbolGraphSerializer.cpp:662
clang::extractapi::AvailabilityInfo::isUnavailable
bool isUnavailable() const
Check if the symbol is unavailable.
Definition: AvailabilityInfo.h:40
clang::extractapi::APIRecord::RK_GlobalFunction
@ RK_GlobalFunction
Definition: API.h:80
clang::ObjCPropertyAttribute::Kind
Kind
Definition: DeclObjCCommon.h:22
clang::api_notes::SwiftNewTypeKind::Enum
@ Enum
API.h
clang::extractapi::EnumRecord::Constants
SmallVector< std::unique_ptr< EnumConstantRecord > > Constants
Definition: API.h:176
clang::PresumedLoc::isValid
bool isValid() const
Definition: SourceLocation.h:319
clang::extractapi::EnumRecord
This holds information associated with enums.
Definition: API.h:175
clang::extractapi::APIRecord::USR
StringRef USR
Definition: API.h:58
clang
Definition: CalledOnceCheck.h:17
clang::format::getLanguageName
StringRef getLanguageName(FormatStyle::LanguageKind Language)
Definition: Format.h:4273
clang::extractapi::DeclarationFragments::getFragmentKindString
static StringRef getFragmentKindString(FragmentKind Kind)
Get the string description of a FragmentKind Kind.
Definition: DeclarationFragments.cpp:39
clang::extractapi::ObjCContainerRecord::Methods
SmallVector< std::unique_ptr< ObjCMethodRecord > > Methods
Definition: API.h:336
clang::getClangFullVersion
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number,...
Definition: Version.cpp:88
clang::extractapi::APIRecord::SubHeading
DeclarationFragments SubHeading
SubHeading provides a more detailed representation than the plain declaration name.
Definition: API.h:76
clang::extractapi::APIRecord::RK_EnumConstant
@ RK_EnumConstant
Definition: API.h:82
SymbolGraphSerializer.h
clang::extractapi::AvailabilityInfo::isDefault
bool isDefault() const
Determine if this AvailabilityInfo represents the default availability.
Definition: AvailabilityInfo.h:37
clang::extractapi::APIRecord::RK_ObjCProtocol
@ RK_ObjCProtocol
Definition: API.h:91
clang::extractapi::APIRecord::RK_ObjCMethod
@ RK_ObjCMethod
Definition: API.h:88
clang::Language::Unknown
@ Unknown
clang::PresumedLoc
Represents an unpacked "presumed" location which can be presented to the user.
Definition: SourceLocation.h:302
clang::Language::HIP
@ HIP
clang::HLSL
@ HLSL
Definition: LangStandard.h:63
clang::extractapi::TypedefRecord::UnderlyingType
SymbolReference UnderlyingType
Definition: API.h:441
clang::extractapi::SymbolGraphSerializer::getRelationshipString
static StringRef getRelationshipString(RelationshipKind Kind)
Get the string representation of the relationship kind.
Definition: SymbolGraphSerializer.cpp:522
clang::extractapi::SymbolReference::Name
StringRef Name
Definition: API.h:315
clang::extractapi::APIRecord
The base representation of an API record. Holds common symbol information.
Definition: API.h:57
clang::api_notes::SwiftNewTypeKind::Struct
@ Struct
clang::extractapi::AvailabilityInfo::isUnconditionallyDeprecated
bool isUnconditionallyDeprecated() const
Check if the symbol is unconditionally deprecated.
Definition: AvailabilityInfo.h:45
clang::extractapi::SymbolReference
This represents a reference to another symbol that might come from external sources.
Definition: API.h:314
clang::ento::ObjKind::OS
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
clang::extractapi::APIRecord::RK_StructField
@ RK_StructField
Definition: API.h:84
clang::OpenCL
@ OpenCL
clang::extractapi::APIRecord::RK_MacroDefinition
@ RK_MacroDefinition
Definition: API.h:92