19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/STLFunctionalExtras.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/Compiler.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/VersionTuple.h"
25#include "llvm/Support/raw_ostream.h"
38 std::optional<Object> &&Obj) {
40 Paren[Key] = std::move(*Obj);
46 std::optional<Array> &&
Array) {
53template <
typename ContainerTy>
54void serializeArray(
Object &
Paren, StringRef Key, ContainerTy &&
C) {
74std::optional<Object> serializeSemanticVersion(
const VersionTuple &
V) {
79 Version[
"major"] =
V.getMajor();
80 Version[
"minor"] =
V.getMinor().value_or(0);
81 Version[
"patch"] =
V.getSubminor().value_or(0);
89Object serializeOperatingSystem(
const Triple &
T) {
91 OS[
"name"] =
T.getOSTypeName(
T.getOS());
92 serializeObject(OS,
"minimumVersion",
93 serializeSemanticVersion(
T.getMinimumSupportedOSVersion()));
101Object serializePlatform(
const Triple &
T) {
103 Platform[
"architecture"] =
T.getArchName();
104 Platform[
"vendor"] =
T.getVendorName();
106 if (!
T.getEnvironmentName().empty())
107 Platform[
"environment"] =
T.getEnvironmentName();
109 Platform[
"operatingSystem"] = serializeOperatingSystem(
T);
115 assert(Loc.
isValid() &&
"invalid source position");
118 SourcePosition[
"line"] = Loc.
getLine() - 1;
119 SourcePosition[
"character"] = Loc.
getColumn() - 1;
121 return SourcePosition;
130 bool IncludeFileURI =
false) {
132 serializeObject(
SourceLocation,
"position", serializeSourcePosition(Loc));
134 if (IncludeFileURI) {
135 std::string FileURI =
"file://";
137 FileURI += sys::path::convert_to_slash(Loc.
getFilename());
148 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
149 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
168 Array AvailabilityArray;
171 Object UnconditionallyDeprecated;
172 UnconditionallyDeprecated[
"domain"] =
"*";
173 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
174 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
177 if (Avail.
Domain.str() !=
"") {
179 Availability[
"domain"] = Avail.
Domain;
182 Availability[
"isUnconditionallyUnavailable"] =
true;
184 serializeObject(Availability,
"introduced",
186 serializeObject(Availability,
"deprecated",
188 serializeObject(Availability,
"obsoleted",
189 serializeSemanticVersion(Avail.
Obsoleted));
192 AvailabilityArray.emplace_back(std::move(Availability));
195 return AvailabilityArray;
204 return "objective-c";
208 return "objective-c++";
222 llvm_unreachable(
"Unsupported language kind");
225 llvm_unreachable(
"Unhandled language kind");
234 Identifier[
"precise"] =
Record.USR;
256std::optional<Object> serializeDocComment(
const DocComment &Comment) {
263 for (
const auto &CommentLine : Comment) {
267 Line[
"text"] = json::isUTF8(CommentLine.Text)
269 : json::fixUTF8(CommentLine.Text);
270 serializeObject(
Line,
"range",
271 serializeSourceRange(CommentLine.Begin, CommentLine.End));
272 LinesArray.emplace_back(std::move(
Line));
275 serializeArray(
DocComment,
"lines", std::move(LinesArray));
322 Fragment[
"spelling"] = F.Spelling;
324 if (!F.PreciseIdentifier.empty())
325 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
326 Fragments.emplace_back(std::move(Fragment));
343 Names[
"title"] =
Record->Name;
345 serializeArray(Names,
"subHeading",
346 serializeDeclarationFragments(
Record->SubHeading));
351 switch (
Record->getKind()) {
367 serializeArray(Names,
"navigator",
368 serializeDeclarationFragments(NavigatorFragments));
374 auto AddLangPrefix = [&Lang](StringRef S) -> std::string {
381 Kind[
"identifier"] = AddLangPrefix(
"unknown");
382 Kind[
"displayName"] =
"Unknown";
385 Kind[
"identifier"] = AddLangPrefix(
"namespace");
386 Kind[
"displayName"] =
"Namespace";
389 Kind[
"identifier"] = AddLangPrefix(
"func");
390 Kind[
"displayName"] =
"Function";
393 Kind[
"identifier"] = AddLangPrefix(
"func");
394 Kind[
"displayName"] =
"Function Template";
397 Kind[
"identifier"] = AddLangPrefix(
"func");
398 Kind[
"displayName"] =
"Function Template Specialization";
401 Kind[
"identifier"] = AddLangPrefix(
"var");
402 Kind[
"displayName"] =
"Global Variable Template";
405 Kind[
"identifier"] = AddLangPrefix(
"var");
406 Kind[
"displayName"] =
"Global Variable Template Specialization";
409 Kind[
"identifier"] = AddLangPrefix(
"var");
410 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
413 Kind[
"identifier"] = AddLangPrefix(
"var");
414 Kind[
"displayName"] =
"Global Variable";
417 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
418 Kind[
"displayName"] =
"Enumeration Case";
421 Kind[
"identifier"] = AddLangPrefix(
"enum");
422 Kind[
"displayName"] =
"Enumeration";
425 Kind[
"identifier"] = AddLangPrefix(
"property");
426 Kind[
"displayName"] =
"Instance Property";
429 Kind[
"identifier"] = AddLangPrefix(
"struct");
430 Kind[
"displayName"] =
"Structure";
433 Kind[
"identifier"] = AddLangPrefix(
"property");
434 Kind[
"displayName"] =
"Instance Property";
437 Kind[
"identifier"] = AddLangPrefix(
"union");
438 Kind[
"displayName"] =
"Union";
441 Kind[
"identifier"] = AddLangPrefix(
"property");
442 Kind[
"displayName"] =
"Instance Property";
445 Kind[
"identifier"] = AddLangPrefix(
"type.property");
446 Kind[
"displayName"] =
"Type Property";
452 Kind[
"identifier"] = AddLangPrefix(
"class");
453 Kind[
"displayName"] =
"Class";
456 Kind[
"identifier"] = AddLangPrefix(
"method");
457 Kind[
"displayName"] =
"Method Template";
460 Kind[
"identifier"] = AddLangPrefix(
"method");
461 Kind[
"displayName"] =
"Method Template Specialization";
464 Kind[
"identifier"] = AddLangPrefix(
"property");
465 Kind[
"displayName"] =
"Template Property";
468 Kind[
"identifier"] = AddLangPrefix(
"concept");
469 Kind[
"displayName"] =
"Concept";
472 Kind[
"identifier"] = AddLangPrefix(
"type.method");
473 Kind[
"displayName"] =
"Static Method";
476 Kind[
"identifier"] = AddLangPrefix(
"method");
477 Kind[
"displayName"] =
"Instance Method";
480 Kind[
"identifier"] = AddLangPrefix(
"method");
481 Kind[
"displayName"] =
"Constructor";
484 Kind[
"identifier"] = AddLangPrefix(
"method");
485 Kind[
"displayName"] =
"Destructor";
488 Kind[
"identifier"] = AddLangPrefix(
"ivar");
489 Kind[
"displayName"] =
"Instance Variable";
492 Kind[
"identifier"] = AddLangPrefix(
"method");
493 Kind[
"displayName"] =
"Instance Method";
496 Kind[
"identifier"] = AddLangPrefix(
"type.method");
497 Kind[
"displayName"] =
"Type Method";
500 Kind[
"identifier"] = AddLangPrefix(
"property");
501 Kind[
"displayName"] =
"Instance Property";
504 Kind[
"identifier"] = AddLangPrefix(
"type.property");
505 Kind[
"displayName"] =
"Type Property";
508 Kind[
"identifier"] = AddLangPrefix(
"class");
509 Kind[
"displayName"] =
"Class";
512 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
513 Kind[
"displayName"] =
"Class Extension";
516 Kind[
"identifier"] = AddLangPrefix(
"protocol");
517 Kind[
"displayName"] =
"Protocol";
520 Kind[
"identifier"] = AddLangPrefix(
"macro");
521 Kind[
"displayName"] =
"Macro";
524 Kind[
"identifier"] = AddLangPrefix(
"typealias");
525 Kind[
"displayName"] =
"Type Alias";
528 llvm_unreachable(
"API Record with uninstantiable kind");
540 return serializeSymbolKind(
Record.KindForDisplay, Lang);
550template <
typename RecordTy>
552 const auto &FS =
Record.Signature;
557 serializeArray(Signature,
"returns",
558 serializeDeclarationFragments(FS.getReturnType()));
561 for (
const auto &P : FS.getParameters()) {
564 serializeArray(
Parameter,
"declarationFragments",
565 serializeDeclarationFragments(P.Fragments));
570 Signature[
"parameters"] = std::move(Parameters);
572 serializeObject(
Paren,
"functionSignature", std::move(Signature));
575template <
typename RecordTy>
582 Array GenericParameters;
588 GenericParameters.emplace_back(std::move(
Parameter));
590 if (!GenericParameters.empty())
591 Generics[
"parameters"] = std::move(GenericParameters);
593 Array GenericConstraints;
596 Constraint[
"kind"] = Constr.Kind;
597 Constraint[
"lhs"] = Constr.LHS;
598 Constraint[
"rhs"] = Constr.RHS;
599 GenericConstraints.emplace_back(std::move(Constraint));
602 if (!GenericConstraints.empty())
603 Generics[
"constraints"] = std::move(GenericConstraints);
605 serializeObject(
Paren,
"swiftGenerics", Generics);
610 Array ParentContexts;
612 for (
const auto &Parent : Parents) {
614 Elem[
"usr"] = Parent.USR;
615 Elem[
"name"] = Parent.Name;
617 Elem[
"kind"] = serializeSymbolKind(Parent.Record->KindForDisplay,
622 ParentContexts.emplace_back(std::move(Elem));
625 return ParentContexts;
633 for (
const auto *Current =
Record; Current !=
nullptr;
634 Current = Current->Parent.Record)
635 ReverseHierarchy.emplace_back(Current);
638 std::make_move_iterator(ReverseHierarchy.rbegin()),
639 std::make_move_iterator(ReverseHierarchy.rend()));
646 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
647 return CategoryRecord->Interface;
658 Symbols.emplace_back(std::move(Symbol));
659 return Symbols.back().getAsObject();
667const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
669Object SymbolGraphSerializer::serializeMetadata()
const {
671 serializeObject(Metadata,
"formatVersion",
672 serializeSemanticVersion(FormatVersion));
678SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
680 Module[
"name"] = ModuleName;
690 if (
Record->Availability.isUnconditionallyUnavailable())
695 if (
Record->Name.starts_with(
"_"))
699 if (IgnoresList.shouldIgnore(
Record->Name))
705ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
706 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
707 return *ModuleForCurrentSymbol;
712Array SymbolGraphSerializer::serializePathComponents(
714 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
717StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
719 case RelationshipKind::MemberOf:
721 case RelationshipKind::InheritsFrom:
722 return "inheritsFrom";
723 case RelationshipKind::ConformsTo:
725 case RelationshipKind::ExtensionTo:
726 return "extensionTo";
728 llvm_unreachable(
"Unhandled relationship kind");
731void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
736 SmallString<64> TestRelLabel;
737 if (EmitSymbolLabelsForTesting) {
738 llvm::raw_svector_ostream
OS(TestRelLabel);
739 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
740 << Source.
USR <<
" $ ";
745 Relationship[
"!testRelLabel"] = TestRelLabel;
747 Relationship[
"source"] = Source.
USR;
748 Relationship[
"target"] =
Target.USR;
749 Relationship[
"targetFallback"] =
Target.Name;
750 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
752 if (ForceEmitToMainModule)
753 MainModule.addRelationship(std::move(Relationship));
758StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
760 case ConstraintKind::Conformance:
761 return "conformance";
762 case ConstraintKind::ConditionalConformance:
763 return "conditionalConformance";
765 llvm_unreachable(
"Unhandled constraint kind");
768void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
773 if (EmitSymbolLabelsForTesting)
774 Obj[
"!testLabel"] =
Record->USR;
776 serializeObject(Obj,
"identifier",
777 serializeIdentifier(*
Record,
API.getLanguage()));
778 serializeObject(Obj,
"kind", serializeSymbolKind(*
Record,
API.getLanguage()));
779 serializeObject(Obj,
"names", serializeNames(
Record));
782 serializeSourceLocation(
Record->Location,
true));
783 serializeArray(Obj,
"availability",
784 serializeAvailability(
Record->Availability));
785 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
786 serializeArray(Obj,
"declarationFragments",
787 serializeDeclarationFragments(
Record->Declaration));
789 Obj[
"pathComponents"] = serializePathComponents(
Record);
790 Obj[
"accessLevel"] =
Record->Access.getAccess();
792 ExtendedModule &
Module = getModuleForCurrentSymbol();
794 if (Hierarchy.size() >= 2)
795 serializeRelationship(MemberOf, Hierarchy.back(),
796 Hierarchy[Hierarchy.size() - 2],
Module);
798 CurrentSymbol =
Module.addSymbol(std::move(Obj));
806 Hierarchy.push_back(getHierarchyReference(
Record,
API));
809 Hierarchy.pop_back();
814 serializeAPIRecord(
Record);
823 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
831 for (
const auto &Base :
Record->Bases)
832 serializeRelationship(RelationshipKind::InheritsFrom,
Record, Base,
833 getModuleForCurrentSymbol());
842 serializeTemplateMixin(*CurrentSymbol, *
Record);
851 serializeTemplateMixin(*CurrentSymbol, *
Record);
860 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
869 serializeTemplateMixin(*CurrentSymbol, *
Record);
878 serializeTemplateMixin(*CurrentSymbol, *
Record);
886 serializeTemplateMixin(*CurrentSymbol, *
Record);
895 serializeTemplateMixin(*CurrentSymbol, *
Record);
905 serializeTemplateMixin(*CurrentSymbol, *
Record);
914 serializeTemplateMixin(*CurrentSymbol, *
Record);
923 for (
const auto &Protocol :
Record->Protocols)
924 serializeRelationship(ConformsTo,
Record, Protocol,
925 getModuleForCurrentSymbol());
935 if (!
Record->SuperClass.empty())
936 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
937 getModuleForCurrentSymbol());
943 if (SkipSymbolsInCategoriesToExternalTypes &&
944 !
API.findRecordForUSR(
Record->Interface.USR))
947 auto *CurrentModule = ModuleForCurrentSymbol;
948 if (
auto ModuleExtendedByRecord =
Record->getExtendedExternalModule())
949 ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord];
954 bool RetVal = traverseRecordContext(
Record);
955 ModuleForCurrentSymbol = CurrentModule;
969 for (
const auto &Protocol :
Record->Protocols)
970 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
971 getModuleForCurrentSymbol());
981 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
1002 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
1005 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
1010 serializeAPIRecord(
Record);
1014 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1019void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1020 switch (
Record->getKind()) {
1022#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1023 case APIRecord::KIND: { \
1024 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1033 llvm_unreachable(
"API Record with uninstantiable kind");
1037Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1040 serializeObject(Root,
"metadata", serializeMetadata());
1041 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1043 Root[
"symbols"] = std::move(EM.Symbols);
1044 Root[
"relationships"] = std::move(EM.Relationships);
1049void SymbolGraphSerializer::serializeGraphToStream(
1052 Object Root = serializeGraph(ModuleName, std::move(EM));
1054 OS << formatv(
"{0}", json::Value(std::move(Root))) <<
"\n";
1056 OS << formatv(
"{0:2}", json::Value(std::move(Root))) <<
"\n";
1068 Serializer.serializeGraphToStream(OS, Options,
API.ProductName,
1069 std::move(Serializer.MainModule));
1074 raw_ostream &MainOutput,
const APISet &
API,
1076 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1083 Serializer.serializeGraphToStream(MainOutput, Options,
API.ProductName,
1084 std::move(Serializer.MainModule));
1086 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1087 if (
auto ExtensionOS =
1088 CreateOutputStream(
API.ProductName +
"@" + ExtensionSGF.getKey()))
1089 Serializer.serializeGraphToStream(*ExtensionOS, Options,
API.ProductName,
1090 std::move(ExtensionSGF.getValue()));
1094std::optional<Object>
1108 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1110 Serializer.serializeSingleRecord(
Record);
1111 serializeObject(Root,
"symbolGraph",
1112 Serializer.serializeGraph(
API.ProductName,
1113 std::move(Serializer.MainModule)));
1116 serializeArray(Root,
"parentContexts",
1117 generateParentContexts(Serializer.Hierarchy, Lang));
1119 Array RelatedSymbols;
1121 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1123 if (Fragment.PreciseIdentifier.empty())
1126 APIRecord *RelatedRecord =
API.findRecordForUSR(Fragment.PreciseIdentifier);
1133 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1134 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1137 RelatedSymbol[
"moduleName"] =
API.ProductName;
1140 serializeArray(RelatedSymbol,
"parentContexts",
1141 generateParentContexts(
1142 generateHierarchyFromRecord(RelatedRecord), Lang));
1144 RelatedSymbols.push_back(std::move(RelatedSymbol));
1147 serializeArray(Root,
"relatedSymbols", RelatedSymbols);
This file defines the classes defined from ExtractAPI's APIRecord.
This file defines the APIRecord-based structs and the APISet class.
This file defines the Declaration Fragments related classes.
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.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
Top level wrappers for InstallAPI frontend operations.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Language
The language for the input, used to select and validate the language standard and possible actions.
@ C
Languages that the frontend can parse and compile.
@ CIR
LLVM IR & CIR: we accept these so that we can run the optimizer on them, and compile them to assembly...
@ Asm
Assembly: we accept this only so that we can preprocess it.
@ 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 isUnavailable() const
Check if the symbol is unavailable unconditionally or on the active platform and os version.