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"
37void serializeObject(Object &
Paren, StringRef Key,
38 std::optional<Object> &&Obj) {
40 Paren[Key] = std::move(*Obj);
45void serializeArray(Object &
Paren, StringRef Key,
46 std::optional<Array> &&Array) {
48 Paren[Key] = std::move(*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) {
265 Line[
"text"] = CommentLine.Text;
266 serializeObject(
Line,
"range",
267 serializeSourceRange(CommentLine.Begin, CommentLine.End));
268 LinesArray.emplace_back(std::move(
Line));
271 serializeArray(
DocComment,
"lines", std::move(LinesArray));
318 Fragment[
"spelling"] = F.Spelling;
320 if (!F.PreciseIdentifier.empty())
321 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
322 Fragments.emplace_back(std::move(Fragment));
339 Names[
"title"] =
Record->Name;
341 serializeArray(Names,
"subHeading",
342 serializeDeclarationFragments(
Record->SubHeading));
347 switch (
Record->getKind()) {
363 serializeArray(Names,
"navigator",
364 serializeDeclarationFragments(NavigatorFragments));
370 auto AddLangPrefix = [&Lang](StringRef S) -> std::string {
377 Kind[
"identifier"] = AddLangPrefix(
"unknown");
378 Kind[
"displayName"] =
"Unknown";
381 Kind[
"identifier"] = AddLangPrefix(
"namespace");
382 Kind[
"displayName"] =
"Namespace";
385 Kind[
"identifier"] = AddLangPrefix(
"func");
386 Kind[
"displayName"] =
"Function";
389 Kind[
"identifier"] = AddLangPrefix(
"func");
390 Kind[
"displayName"] =
"Function Template";
393 Kind[
"identifier"] = AddLangPrefix(
"func");
394 Kind[
"displayName"] =
"Function Template Specialization";
397 Kind[
"identifier"] = AddLangPrefix(
"var");
398 Kind[
"displayName"] =
"Global Variable Template";
401 Kind[
"identifier"] = AddLangPrefix(
"var");
402 Kind[
"displayName"] =
"Global Variable Template Specialization";
405 Kind[
"identifier"] = AddLangPrefix(
"var");
406 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
409 Kind[
"identifier"] = AddLangPrefix(
"var");
410 Kind[
"displayName"] =
"Global Variable";
413 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
414 Kind[
"displayName"] =
"Enumeration Case";
417 Kind[
"identifier"] = AddLangPrefix(
"enum");
418 Kind[
"displayName"] =
"Enumeration";
421 Kind[
"identifier"] = AddLangPrefix(
"property");
422 Kind[
"displayName"] =
"Instance Property";
425 Kind[
"identifier"] = AddLangPrefix(
"struct");
426 Kind[
"displayName"] =
"Structure";
429 Kind[
"identifier"] = AddLangPrefix(
"property");
430 Kind[
"displayName"] =
"Instance Property";
433 Kind[
"identifier"] = AddLangPrefix(
"union");
434 Kind[
"displayName"] =
"Union";
437 Kind[
"identifier"] = AddLangPrefix(
"property");
438 Kind[
"displayName"] =
"Instance Property";
441 Kind[
"identifier"] = AddLangPrefix(
"type.property");
442 Kind[
"displayName"] =
"Type Property";
448 Kind[
"identifier"] = AddLangPrefix(
"class");
449 Kind[
"displayName"] =
"Class";
452 Kind[
"identifier"] = AddLangPrefix(
"method");
453 Kind[
"displayName"] =
"Method Template";
456 Kind[
"identifier"] = AddLangPrefix(
"method");
457 Kind[
"displayName"] =
"Method Template Specialization";
460 Kind[
"identifier"] = AddLangPrefix(
"property");
461 Kind[
"displayName"] =
"Template Property";
464 Kind[
"identifier"] = AddLangPrefix(
"concept");
465 Kind[
"displayName"] =
"Concept";
468 Kind[
"identifier"] = AddLangPrefix(
"type.method");
469 Kind[
"displayName"] =
"Static Method";
472 Kind[
"identifier"] = AddLangPrefix(
"method");
473 Kind[
"displayName"] =
"Instance Method";
476 Kind[
"identifier"] = AddLangPrefix(
"method");
477 Kind[
"displayName"] =
"Constructor";
480 Kind[
"identifier"] = AddLangPrefix(
"method");
481 Kind[
"displayName"] =
"Destructor";
484 Kind[
"identifier"] = AddLangPrefix(
"ivar");
485 Kind[
"displayName"] =
"Instance Variable";
488 Kind[
"identifier"] = AddLangPrefix(
"method");
489 Kind[
"displayName"] =
"Instance Method";
492 Kind[
"identifier"] = AddLangPrefix(
"type.method");
493 Kind[
"displayName"] =
"Type Method";
496 Kind[
"identifier"] = AddLangPrefix(
"property");
497 Kind[
"displayName"] =
"Instance Property";
500 Kind[
"identifier"] = AddLangPrefix(
"type.property");
501 Kind[
"displayName"] =
"Type Property";
504 Kind[
"identifier"] = AddLangPrefix(
"class");
505 Kind[
"displayName"] =
"Class";
508 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
509 Kind[
"displayName"] =
"Class Extension";
512 Kind[
"identifier"] = AddLangPrefix(
"protocol");
513 Kind[
"displayName"] =
"Protocol";
516 Kind[
"identifier"] = AddLangPrefix(
"macro");
517 Kind[
"displayName"] =
"Macro";
520 Kind[
"identifier"] = AddLangPrefix(
"typealias");
521 Kind[
"displayName"] =
"Type Alias";
524 llvm_unreachable(
"API Record with uninstantiable kind");
536 return serializeSymbolKind(
Record.KindForDisplay, Lang);
546template <
typename RecordTy>
547void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
548 const auto &FS =
Record.Signature;
553 serializeArray(Signature,
"returns",
554 serializeDeclarationFragments(FS.getReturnType()));
557 for (
const auto &P : FS.getParameters()) {
560 serializeArray(
Parameter,
"declarationFragments",
561 serializeDeclarationFragments(P.Fragments));
566 Signature[
"parameters"] = std::move(Parameters);
568 serializeObject(
Paren,
"functionSignature", std::move(Signature));
571template <
typename RecordTy>
572void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
578 Array GenericParameters;
584 GenericParameters.emplace_back(std::move(
Parameter));
586 if (!GenericParameters.empty())
587 Generics[
"parameters"] = std::move(GenericParameters);
589 Array GenericConstraints;
592 Constraint[
"kind"] = Constr.Kind;
593 Constraint[
"lhs"] = Constr.LHS;
594 Constraint[
"rhs"] = Constr.RHS;
595 GenericConstraints.emplace_back(std::move(Constraint));
598 if (!GenericConstraints.empty())
599 Generics[
"constraints"] = std::move(GenericConstraints);
601 serializeObject(
Paren,
"swiftGenerics", Generics);
606 Array ParentContexts;
608 for (
const auto &Parent : Parents) {
610 Elem[
"usr"] = Parent.USR;
611 Elem[
"name"] = Parent.Name;
613 Elem[
"kind"] = serializeSymbolKind(Parent.Record->KindForDisplay,
618 ParentContexts.emplace_back(std::move(Elem));
621 return ParentContexts;
629 for (
const auto *Current =
Record; Current !=
nullptr;
630 Current = Current->Parent.Record)
631 ReverseHierarchy.emplace_back(Current);
634 std::make_move_iterator(ReverseHierarchy.rbegin()),
635 std::make_move_iterator(ReverseHierarchy.rend()));
642 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
643 return CategoryRecord->Interface;
654 Symbols.emplace_back(std::move(Symbol));
655 return Symbols.back().getAsObject();
663const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
665Object SymbolGraphSerializer::serializeMetadata()
const {
667 serializeObject(Metadata,
"formatVersion",
668 serializeSemanticVersion(FormatVersion));
674SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
676 Module[
"name"] = ModuleName;
686 if (
Record->Availability.isUnconditionallyUnavailable())
691 if (
Record->Name.starts_with(
"_"))
695 if (IgnoresList.shouldIgnore(
Record->Name))
701ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
702 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
703 return *ModuleForCurrentSymbol;
708Array SymbolGraphSerializer::serializePathComponents(
710 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
713StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
715 case RelationshipKind::MemberOf:
717 case RelationshipKind::InheritsFrom:
718 return "inheritsFrom";
719 case RelationshipKind::ConformsTo:
721 case RelationshipKind::ExtensionTo:
722 return "extensionTo";
724 llvm_unreachable(
"Unhandled relationship kind");
727void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
732 SmallString<64> TestRelLabel;
733 if (EmitSymbolLabelsForTesting) {
734 llvm::raw_svector_ostream
OS(TestRelLabel);
735 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
736 << Source.
USR <<
" $ ";
741 Relationship[
"!testRelLabel"] = TestRelLabel;
743 Relationship[
"source"] = Source.
USR;
744 Relationship[
"target"] =
Target.USR;
745 Relationship[
"targetFallback"] =
Target.Name;
746 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
748 if (ForceEmitToMainModule)
749 MainModule.addRelationship(std::move(Relationship));
754StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
756 case ConstraintKind::Conformance:
757 return "conformance";
758 case ConstraintKind::ConditionalConformance:
759 return "conditionalConformance";
761 llvm_unreachable(
"Unhandled constraint kind");
764void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
769 if (EmitSymbolLabelsForTesting)
770 Obj[
"!testLabel"] =
Record->USR;
772 serializeObject(Obj,
"identifier",
773 serializeIdentifier(*
Record,
API.getLanguage()));
774 serializeObject(Obj,
"kind", serializeSymbolKind(*
Record,
API.getLanguage()));
775 serializeObject(Obj,
"names", serializeNames(
Record));
778 serializeSourceLocation(
Record->Location,
true));
779 serializeArray(Obj,
"availability",
780 serializeAvailability(
Record->Availability));
781 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
782 serializeArray(Obj,
"declarationFragments",
783 serializeDeclarationFragments(
Record->Declaration));
785 Obj[
"pathComponents"] = serializePathComponents(
Record);
786 Obj[
"accessLevel"] =
Record->Access.getAccess();
788 ExtendedModule &
Module = getModuleForCurrentSymbol();
790 if (Hierarchy.size() >= 2)
791 serializeRelationship(MemberOf, Hierarchy.back(),
792 Hierarchy[Hierarchy.size() - 2],
Module);
794 CurrentSymbol =
Module.addSymbol(std::move(Obj));
802 Hierarchy.push_back(getHierarchyReference(
Record,
API));
805 Hierarchy.pop_back();
810 serializeAPIRecord(
Record);
819 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
827 for (
const auto &Base :
Record->Bases)
828 serializeRelationship(RelationshipKind::InheritsFrom,
Record, Base,
829 getModuleForCurrentSymbol());
838 serializeTemplateMixin(*CurrentSymbol, *
Record);
847 serializeTemplateMixin(*CurrentSymbol, *
Record);
856 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
865 serializeTemplateMixin(*CurrentSymbol, *
Record);
874 serializeTemplateMixin(*CurrentSymbol, *
Record);
882 serializeTemplateMixin(*CurrentSymbol, *
Record);
891 serializeTemplateMixin(*CurrentSymbol, *
Record);
901 serializeTemplateMixin(*CurrentSymbol, *
Record);
910 serializeTemplateMixin(*CurrentSymbol, *
Record);
919 for (
const auto &Protocol :
Record->Protocols)
920 serializeRelationship(ConformsTo,
Record, Protocol,
921 getModuleForCurrentSymbol());
931 if (!
Record->SuperClass.empty())
932 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
933 getModuleForCurrentSymbol());
939 if (SkipSymbolsInCategoriesToExternalTypes &&
940 !
API.findRecordForUSR(
Record->Interface.USR))
943 auto *CurrentModule = ModuleForCurrentSymbol;
944 if (
auto ModuleExtendedByRecord =
Record->getExtendedExternalModule())
945 ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord];
950 bool RetVal = traverseRecordContext(
Record);
951 ModuleForCurrentSymbol = CurrentModule;
965 for (
const auto &Protocol :
Record->Protocols)
966 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
967 getModuleForCurrentSymbol());
977 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
998 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
1001 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
1006 serializeAPIRecord(
Record);
1010 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1015void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1016 switch (
Record->getKind()) {
1018#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1019 case APIRecord::KIND: { \
1020 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1029 llvm_unreachable(
"API Record with uninstantiable kind");
1033Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1036 serializeObject(Root,
"metadata", serializeMetadata());
1037 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1039 Root[
"symbols"] = std::move(EM.Symbols);
1040 Root[
"relationships"] = std::move(EM.Relationships);
1045void SymbolGraphSerializer::serializeGraphToStream(
1048 Object Root = serializeGraph(ModuleName, std::move(EM));
1050 OS << formatv(
"{0}", json::Value(std::move(Root))) <<
"\n";
1052 OS << formatv(
"{0:2}", json::Value(std::move(Root))) <<
"\n";
1064 Serializer.serializeGraphToStream(OS, Options,
API.ProductName,
1065 std::move(Serializer.MainModule));
1070 raw_ostream &MainOutput,
const APISet &
API,
1072 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1079 Serializer.serializeGraphToStream(MainOutput, Options,
API.ProductName,
1080 std::move(Serializer.MainModule));
1082 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1083 if (
auto ExtensionOS =
1084 CreateOutputStream(
API.ProductName +
"@" + ExtensionSGF.getKey()))
1085 Serializer.serializeGraphToStream(*ExtensionOS, Options,
API.ProductName,
1086 std::move(ExtensionSGF.getValue()));
1090std::optional<Object>
1104 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1106 Serializer.serializeSingleRecord(
Record);
1107 serializeObject(Root,
"symbolGraph",
1108 Serializer.serializeGraph(
API.ProductName,
1109 std::move(Serializer.MainModule)));
1112 serializeArray(Root,
"parentContexts",
1113 generateParentContexts(Serializer.Hierarchy, Lang));
1115 Array RelatedSymbols;
1117 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1119 if (Fragment.PreciseIdentifier.empty())
1122 APIRecord *RelatedRecord =
API.findRecordForUSR(Fragment.PreciseIdentifier);
1128 Object RelatedSymbol;
1129 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1133 RelatedSymbol[
"moduleName"] =
API.ProductName;
1136 serializeArray(RelatedSymbol,
"parentContexts",
1137 generateParentContexts(
1138 generateHierarchyFromRecord(RelatedRecord), Lang));
1140 RelatedSymbols.push_back(std::move(RelatedSymbol));
1143 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,...
The JSON file list parser is used to communicate input to InstallAPI.
@ 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.