19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/STLFunctionalExtras.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/Compiler.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/VersionTuple.h"
26#include "llvm/Support/raw_ostream.h"
40void serializeObject(Object &
Paren, StringRef Key,
41 std::optional<Object> &&Obj) {
43 Paren[Key] = std::move(*Obj);
48void serializeArray(Object &
Paren, StringRef Key,
49 std::optional<Array> &&Array) {
51 Paren[Key] = std::move(*Array);
56template <
typename ContainerTy>
57void serializeArray(Object &
Paren, StringRef Key, ContainerTy &&
C) {
77std::optional<Object> serializeSemanticVersion(
const VersionTuple &
V) {
82 Version[
"major"] =
V.getMajor();
83 Version[
"minor"] =
V.getMinor().value_or(0);
84 Version[
"patch"] =
V.getSubminor().value_or(0);
92Object serializeOperatingSystem(
const Triple &
T) {
94 OS[
"name"] =
T.getOSTypeName(
T.getOS());
95 serializeObject(OS,
"minimumVersion",
96 serializeSemanticVersion(
T.getMinimumSupportedOSVersion()));
104Object serializePlatform(
const Triple &
T) {
106 Platform[
"architecture"] =
T.getArchName();
107 Platform[
"vendor"] =
T.getVendorName();
108 Platform[
"operatingSystem"] = serializeOperatingSystem(
T);
114 assert(Loc.
isValid() &&
"invalid source position");
117 SourcePosition[
"line"] = Loc.
getLine() - 1;
118 SourcePosition[
"character"] = Loc.
getColumn() - 1;
120 return SourcePosition;
129 bool IncludeFileURI =
false) {
131 serializeObject(
SourceLocation,
"position", serializeSourcePosition(Loc));
133 if (IncludeFileURI) {
134 std::string FileURI =
"file://";
136 FileURI += sys::path::convert_to_slash(Loc.
getFilename());
147 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
148 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
168 Array AvailabilityArray;
169 Availability[
"domain"] = Avail.
Domain;
170 serializeObject(Availability,
"introduced",
172 serializeObject(Availability,
"deprecated",
174 serializeObject(Availability,
"obsoleted",
175 serializeSemanticVersion(Avail.
Obsoleted));
177 Object UnconditionallyDeprecated;
178 UnconditionallyDeprecated[
"domain"] =
"*";
179 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
180 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
183 Object UnconditionallyUnavailable;
184 UnconditionallyUnavailable[
"domain"] =
"*";
185 UnconditionallyUnavailable[
"isUnconditionallyUnavailable"] =
true;
186 AvailabilityArray.emplace_back(std::move(UnconditionallyUnavailable));
188 AvailabilityArray.emplace_back(std::move(Availability));
189 return AvailabilityArray;
198 return "objective-c";
201 case Language::ObjCXX:
202 return "objective-c++";
205 case Language::OpenCL:
206 case Language::OpenCLCXX:
208 case Language::RenderScript:
213 case Language::Unknown:
215 case Language::LLVM_IR:
217 llvm_unreachable(
"Unsupported language kind");
220 llvm_unreachable(
"Unhandled language kind");
251std::optional<Object> serializeDocComment(
const DocComment &Comment) {
258 for (
const auto &CommentLine : Comment) {
260 Line[
"text"] = CommentLine.Text;
261 serializeObject(Line,
"range",
262 serializeSourceRange(CommentLine.Begin, CommentLine.End));
263 LinesArray.emplace_back(std::move(Line));
266 serializeArray(
DocComment,
"lines", std::move(LinesArray));
313 Fragment[
"spelling"] = F.Spelling;
315 if (!F.PreciseIdentifier.empty())
316 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
317 Fragments.emplace_back(std::move(Fragment));
334 Names[
"title"] =
Record->Name;
336 serializeArray(Names,
"subHeading",
337 serializeDeclarationFragments(
Record->SubHeading));
340 DeclarationFragments::FragmentKind::Identifier,
342 serializeArray(Names,
"navigator",
343 serializeDeclarationFragments(NavigatorFragments));
349 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
356 Kind[
"identifier"] = AddLangPrefix(
"unknown");
357 Kind[
"displayName"] =
"Unknown";
360 Kind[
"identifier"] = AddLangPrefix(
"namespace");
361 Kind[
"displayName"] =
"Namespace";
364 Kind[
"identifier"] = AddLangPrefix(
"func");
365 Kind[
"displayName"] =
"Function";
368 Kind[
"identifier"] = AddLangPrefix(
"func");
369 Kind[
"displayName"] =
"Function Template";
372 Kind[
"identifier"] = AddLangPrefix(
"func");
373 Kind[
"displayName"] =
"Function Template Specialization";
376 Kind[
"identifier"] = AddLangPrefix(
"var");
377 Kind[
"displayName"] =
"Global Variable Template";
380 Kind[
"identifier"] = AddLangPrefix(
"var");
381 Kind[
"displayName"] =
"Global Variable Template Specialization";
384 Kind[
"identifier"] = AddLangPrefix(
"var");
385 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
388 Kind[
"identifier"] = AddLangPrefix(
"var");
389 Kind[
"displayName"] =
"Global Variable";
392 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
393 Kind[
"displayName"] =
"Enumeration Case";
396 Kind[
"identifier"] = AddLangPrefix(
"enum");
397 Kind[
"displayName"] =
"Enumeration";
400 Kind[
"identifier"] = AddLangPrefix(
"property");
401 Kind[
"displayName"] =
"Instance Property";
404 Kind[
"identifier"] = AddLangPrefix(
"struct");
405 Kind[
"displayName"] =
"Structure";
408 Kind[
"identifier"] = AddLangPrefix(
"property");
409 Kind[
"displayName"] =
"Instance Property";
412 Kind[
"identifier"] = AddLangPrefix(
"union");
413 Kind[
"displayName"] =
"Union";
416 Kind[
"identifier"] = AddLangPrefix(
"property");
417 Kind[
"displayName"] =
"Instance Property";
420 Kind[
"identifier"] = AddLangPrefix(
"type.property");
421 Kind[
"displayName"] =
"Type Property";
427 Kind[
"identifier"] = AddLangPrefix(
"class");
428 Kind[
"displayName"] =
"Class";
431 Kind[
"identifier"] = AddLangPrefix(
"method");
432 Kind[
"displayName"] =
"Method Template";
435 Kind[
"identifier"] = AddLangPrefix(
"method");
436 Kind[
"displayName"] =
"Method Template Specialization";
439 Kind[
"identifier"] = AddLangPrefix(
"property");
440 Kind[
"displayName"] =
"Template Property";
443 Kind[
"identifier"] = AddLangPrefix(
"concept");
444 Kind[
"displayName"] =
"Concept";
447 Kind[
"identifier"] = AddLangPrefix(
"type.method");
448 Kind[
"displayName"] =
"Static Method";
451 Kind[
"identifier"] = AddLangPrefix(
"method");
452 Kind[
"displayName"] =
"Instance Method";
455 Kind[
"identifier"] = AddLangPrefix(
"method");
456 Kind[
"displayName"] =
"Constructor";
459 Kind[
"identifier"] = AddLangPrefix(
"method");
460 Kind[
"displayName"] =
"Destructor";
463 Kind[
"identifier"] = AddLangPrefix(
"ivar");
464 Kind[
"displayName"] =
"Instance Variable";
467 Kind[
"identifier"] = AddLangPrefix(
"method");
468 Kind[
"displayName"] =
"Instance Method";
471 Kind[
"identifier"] = AddLangPrefix(
"type.method");
472 Kind[
"displayName"] =
"Type Method";
475 Kind[
"identifier"] = AddLangPrefix(
"property");
476 Kind[
"displayName"] =
"Instance Property";
479 Kind[
"identifier"] = AddLangPrefix(
"type.property");
480 Kind[
"displayName"] =
"Type Property";
483 Kind[
"identifier"] = AddLangPrefix(
"class");
484 Kind[
"displayName"] =
"Class";
487 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
488 Kind[
"displayName"] =
"Class Extension";
491 Kind[
"identifier"] = AddLangPrefix(
"protocol");
492 Kind[
"displayName"] =
"Protocol";
495 Kind[
"identifier"] = AddLangPrefix(
"macro");
496 Kind[
"displayName"] =
"Macro";
499 Kind[
"identifier"] = AddLangPrefix(
"typealias");
500 Kind[
"displayName"] =
"Type Alias";
503 llvm_unreachable(
"API Record with uninstantiable kind");
515 return serializeSymbolKind(
Record.getKind(), Lang);
525template <
typename RecordTy>
526void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
527 const auto &FS =
Record.Signature;
532 serializeArray(Signature,
"returns",
533 serializeDeclarationFragments(FS.getReturnType()));
536 for (
const auto &
P : FS.getParameters()) {
539 serializeArray(
Parameter,
"declarationFragments",
540 serializeDeclarationFragments(
P.Fragments));
545 Signature[
"parameters"] = std::move(Parameters);
547 serializeObject(
Paren,
"functionSignature", std::move(Signature));
550template <
typename RecordTy>
551void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
557 Array GenericParameters;
563 GenericParameters.emplace_back(std::move(
Parameter));
565 if (!GenericParameters.empty())
566 Generics[
"parameters"] = std::move(GenericParameters);
568 Array GenericConstraints;
571 Constraint[
"kind"] = Constr.Kind;
572 Constraint[
"lhs"] = Constr.LHS;
573 Constraint[
"rhs"] = Constr.RHS;
574 GenericConstraints.emplace_back(std::move(Constraint));
577 if (!GenericConstraints.empty())
578 Generics[
"constraints"] = std::move(GenericConstraints);
580 serializeObject(
Paren,
"swiftGenerics", Generics);
585 Array ParentContexts;
587 for (
const auto &
Parent : Parents) {
590 Elem[
"name"] =
Parent.Name;
593 serializeSymbolKind(
Parent.Record->getKind(), Lang)[
"identifier"];
597 ParentContexts.emplace_back(std::move(Elem));
600 return ParentContexts;
608 for (
const auto *Current =
Record; Current !=
nullptr;
609 Current = Current->Parent.Record)
610 ReverseHierarchy.emplace_back(Current);
613 std::make_move_iterator(ReverseHierarchy.rbegin()),
614 std::make_move_iterator(ReverseHierarchy.rend()));
621 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
622 return CategoryRecord->Interface;
633 Symbols.emplace_back(std::move(Symbol));
634 return Symbols.back().getAsObject();
642const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
644Object SymbolGraphSerializer::serializeMetadata()
const {
646 serializeObject(Metadata,
"formatVersion",
647 serializeSemanticVersion(FormatVersion));
653SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
655 Module[
"name"] = ModuleName;
665 if (
Record->Availability.isUnconditionallyUnavailable())
670 if (
Record->Name.starts_with(
"_"))
680ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
681 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
682 return *ModuleForCurrentSymbol;
687Array SymbolGraphSerializer::serializePathComponents(
689 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
692StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
694 case RelationshipKind::MemberOf:
696 case RelationshipKind::InheritsFrom:
697 return "inheritsFrom";
698 case RelationshipKind::ConformsTo:
700 case RelationshipKind::ExtensionTo:
701 return "extensionTo";
703 llvm_unreachable(
"Unhandled relationship kind");
706void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
712 if (EmitSymbolLabelsForTesting) {
713 llvm::raw_svector_ostream OS(TestRelLabel);
714 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
715 << Source.
USR <<
" $ ";
720 Relationship[
"!testRelLabel"] = TestRelLabel;
722 Relationship[
"source"] = Source.
USR;
723 Relationship[
"target"] =
Target.USR;
724 Relationship[
"targetFallback"] =
Target.Name;
725 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
727 if (ForceEmitToMainModule)
733StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
735 case ConstraintKind::Conformance:
736 return "conformance";
737 case ConstraintKind::ConditionalConformance:
738 return "conditionalConformance";
740 llvm_unreachable(
"Unhandled constraint kind");
743void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
748 if (EmitSymbolLabelsForTesting)
749 Obj[
"!testLabel"] =
Record->USR;
751 serializeObject(Obj,
"identifier",
754 serializeObject(Obj,
"names", serializeNames(
Record));
757 serializeSourceLocation(
Record->Location,
true));
758 serializeArray(Obj,
"availability",
759 serializeAvailability(
Record->Availability));
760 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
761 serializeArray(Obj,
"declarationFragments",
762 serializeDeclarationFragments(
Record->Declaration));
764 Obj[
"pathComponents"] = serializePathComponents(
Record);
765 Obj[
"accessLevel"] =
Record->Access.getAccess();
769 if (Hierarchy.size() >= 2)
770 serializeRelationship(MemberOf, Hierarchy.back(),
771 Hierarchy[Hierarchy.size() - 2],
Module);
773 CurrentSymbol =
Module.addSymbol(std::move(Obj));
781 Hierarchy.push_back(getHierarchyReference(
Record,
API));
784 Hierarchy.pop_back();
789 serializeAPIRecord(
Record);
798 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
807 serializeRelationship(RelationshipKind::InheritsFrom,
Record,
Base,
808 getModuleForCurrentSymbol());
817 serializeTemplateMixin(*CurrentSymbol, *
Record);
826 serializeTemplateMixin(*CurrentSymbol, *
Record);
835 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
844 serializeTemplateMixin(*CurrentSymbol, *
Record);
853 serializeTemplateMixin(*CurrentSymbol, *
Record);
861 serializeTemplateMixin(*CurrentSymbol, *
Record);
870 serializeTemplateMixin(*CurrentSymbol, *
Record);
880 serializeTemplateMixin(*CurrentSymbol, *
Record);
889 serializeTemplateMixin(*CurrentSymbol, *
Record);
898 for (
const auto &Protocol :
Record->Protocols)
899 serializeRelationship(ConformsTo,
Record, Protocol,
900 getModuleForCurrentSymbol());
910 if (!
Record->SuperClass.empty())
911 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
912 getModuleForCurrentSymbol());
918 auto *CurrentModule = ModuleForCurrentSymbol;
919 if (
Record->isExtendingExternalModule())
920 ModuleForCurrentSymbol = &ExtendedModules[
Record->Interface.Source];
926 ModuleForCurrentSymbol = CurrentModule;
940 for (
const auto &Protocol :
Record->Protocols)
941 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
942 getModuleForCurrentSymbol());
952 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
973 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
976 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
981 serializeAPIRecord(
Record);
985 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
990void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
991 switch (
Record->getKind()) {
993#define CONCRETE_RECORD(CLASS, BASE, KIND) \
994 case APIRecord::KIND: { \
995 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1004 llvm_unreachable(
"API Record with uninstantiable kind");
1008Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1011 serializeObject(Root,
"metadata", serializeMetadata());
1012 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1014 Root[
"symbols"] = std::move(EM.Symbols);
1015 Root[
"relationships"] = std::move(EM.Relationships);
1020void SymbolGraphSerializer::serializeGraphToStream(
1023 Object Root = serializeGraph(ModuleName, std::move(EM));
1024 if (Options.Compact)
1025 OS << formatv(
"{0}",
Value(std::move(Root))) <<
"\n";
1027 OS << formatv(
"{0:2}",
Value(std::move(Root))) <<
"\n";
1034 Options.EmitSymbolLabelsForTesting);
1037 std::move(Serializer.MainModule));
1042 raw_ostream &MainOutput,
const APISet &API,
1044 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1048 Options.EmitSymbolLabelsForTesting);
1051 Serializer.serializeGraphToStream(MainOutput, Options,
API.
ProductName,
1052 std::move(Serializer.MainModule));
1054 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1055 if (
auto ExtensionOS =
1056 CreateOutputStream(ExtensionSGF.getKey() +
"@" +
API.
ProductName))
1057 Serializer.serializeGraphToStream(*ExtensionOS, Options,
1058 ExtensionSGF.getKey(),
1059 std::move(ExtensionSGF.getValue()));
1063std::optional<Object>
1077 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1079 Serializer.serializeSingleRecord(
Record);
1080 serializeObject(Root,
"symbolGraph",
1082 std::move(Serializer.MainModule)));
1085 serializeArray(Root,
"parentContexts",
1086 generateParentContexts(Serializer.Hierarchy, Lang));
1088 Array RelatedSymbols;
1090 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1092 if (Fragment.PreciseIdentifier.empty())
1101 Object RelatedSymbol;
1102 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1103 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1109 serializeArray(RelatedSymbol,
"parentContexts",
1110 generateParentContexts(
1111 generateHierarchyFromRecord(RelatedRecord), Lang));
1113 RelatedSymbols.push_back(std::move(RelatedSymbol));
1116 serializeArray(Root,
"relatedSymbols", RelatedSymbols);
This file defines the APIRecord-based structs and the APISet class.
This file defines the Declaration Fragments related classes.
llvm::MachO::Target Target
llvm::MachO::Record Record
Defines the clang::SourceLocation class and associated facilities.
This file defines the SymbolGraphSerializer class.
Defines version macros and version-related utility functions for Clang.
Describes a module or submodule.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
A trivial tuple used to represent a source range.
The JSON file list parser is used to communicate input to InstallAPI.
Language
The language for the input, used to select and validate the language standard and possible actions.
@ Parameter
The parameter type of a method or function.
const FunctionProtoType * T
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number,...
Diagnostic wrappers for TextAPI types for error reporting.
Storage of availability attributes for a declaration.
bool isUnconditionallyDeprecated() const
Check if the symbol is unconditionally deprecated.
llvm::SmallString< 32 > Domain
The domain is the platform for which this availability info applies to.
bool isDefault() const
Determine if this AvailabilityInfo represents the default availability.
bool isUnconditionallyUnavailable() const
Check if the symbol is unconditionally unavailable.