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"
39void serializeObject(Object &
Paren, StringRef Key,
40 std::optional<Object> &&Obj) {
42 Paren[Key] = std::move(*Obj);
47void serializeArray(Object &
Paren, StringRef Key,
48 std::optional<Array> &&Array) {
50 Paren[Key] = std::move(*Array);
55template <
typename ContainerTy>
56void serializeArray(Object &
Paren, StringRef Key, ContainerTy &&
C) {
76std::optional<Object> serializeSemanticVersion(
const VersionTuple &
V) {
81 Version[
"major"] =
V.getMajor();
82 Version[
"minor"] =
V.getMinor().value_or(0);
83 Version[
"patch"] =
V.getSubminor().value_or(0);
91Object serializeOperatingSystem(
const Triple &
T) {
93 OS[
"name"] =
T.getOSTypeName(
T.getOS());
94 serializeObject(OS,
"minimumVersion",
95 serializeSemanticVersion(
T.getMinimumSupportedOSVersion()));
103Object serializePlatform(
const Triple &
T) {
105 Platform[
"architecture"] =
T.getArchName();
106 Platform[
"vendor"] =
T.getVendorName();
108 if (!
T.getEnvironmentName().empty())
109 Platform[
"environment"] =
T.getEnvironmentName();
111 Platform[
"operatingSystem"] = serializeOperatingSystem(
T);
117 assert(
Loc.
isValid() &&
"invalid source position");
120 SourcePosition[
"line"] =
Loc.getLine() - 1;
121 SourcePosition[
"character"] =
Loc.getColumn() - 1;
123 return SourcePosition;
132 bool IncludeFileURI =
false) {
136 if (IncludeFileURI) {
137 std::string FileURI =
"file://";
139 FileURI += sys::path::convert_to_slash(
Loc.getFilename());
150 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
151 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
170 Array AvailabilityArray;
173 Object UnconditionallyDeprecated;
174 UnconditionallyDeprecated[
"domain"] =
"*";
175 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
176 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
179 if (Avail.
Domain.str() !=
"") {
181 Availability[
"domain"] = Avail.
Domain;
184 Availability[
"isUnconditionallyUnavailable"] =
true;
186 serializeObject(Availability,
"introduced",
188 serializeObject(Availability,
"deprecated",
190 serializeObject(Availability,
"obsoleted",
191 serializeSemanticVersion(Avail.
Obsoleted));
194 AvailabilityArray.emplace_back(std::move(Availability));
197 return AvailabilityArray;
206 return "objective-c";
209 case Language::ObjCXX:
210 return "objective-c++";
213 case Language::OpenCL:
214 case Language::OpenCLCXX:
220 case Language::Unknown:
222 case Language::LLVM_IR:
224 llvm_unreachable(
"Unsupported language kind");
227 llvm_unreachable(
"Unhandled language kind");
258std::optional<Object> serializeDocComment(
const DocComment &Comment) {
265 for (
const auto &CommentLine : Comment) {
267 Line[
"text"] = CommentLine.Text;
268 serializeObject(Line,
"range",
269 serializeSourceRange(CommentLine.Begin, CommentLine.End));
270 LinesArray.emplace_back(std::move(Line));
273 serializeArray(
DocComment,
"lines", std::move(LinesArray));
320 Fragment[
"spelling"] = F.Spelling;
322 if (!F.PreciseIdentifier.empty())
323 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
324 Fragments.emplace_back(std::move(Fragment));
341 Names[
"title"] =
Record->Name;
343 serializeArray(Names,
"subHeading",
344 serializeDeclarationFragments(
Record->SubHeading));
347 DeclarationFragments::FragmentKind::Identifier,
349 serializeArray(Names,
"navigator",
350 serializeDeclarationFragments(NavigatorFragments));
356 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
363 Kind[
"identifier"] = AddLangPrefix(
"unknown");
364 Kind[
"displayName"] =
"Unknown";
367 Kind[
"identifier"] = AddLangPrefix(
"namespace");
368 Kind[
"displayName"] =
"Namespace";
371 Kind[
"identifier"] = AddLangPrefix(
"func");
372 Kind[
"displayName"] =
"Function";
375 Kind[
"identifier"] = AddLangPrefix(
"func");
376 Kind[
"displayName"] =
"Function Template";
379 Kind[
"identifier"] = AddLangPrefix(
"func");
380 Kind[
"displayName"] =
"Function Template Specialization";
383 Kind[
"identifier"] = AddLangPrefix(
"var");
384 Kind[
"displayName"] =
"Global Variable Template";
387 Kind[
"identifier"] = AddLangPrefix(
"var");
388 Kind[
"displayName"] =
"Global Variable Template Specialization";
391 Kind[
"identifier"] = AddLangPrefix(
"var");
392 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
395 Kind[
"identifier"] = AddLangPrefix(
"var");
396 Kind[
"displayName"] =
"Global Variable";
399 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
400 Kind[
"displayName"] =
"Enumeration Case";
403 Kind[
"identifier"] = AddLangPrefix(
"enum");
404 Kind[
"displayName"] =
"Enumeration";
407 Kind[
"identifier"] = AddLangPrefix(
"property");
408 Kind[
"displayName"] =
"Instance Property";
411 Kind[
"identifier"] = AddLangPrefix(
"struct");
412 Kind[
"displayName"] =
"Structure";
415 Kind[
"identifier"] = AddLangPrefix(
"property");
416 Kind[
"displayName"] =
"Instance Property";
419 Kind[
"identifier"] = AddLangPrefix(
"union");
420 Kind[
"displayName"] =
"Union";
423 Kind[
"identifier"] = AddLangPrefix(
"property");
424 Kind[
"displayName"] =
"Instance Property";
427 Kind[
"identifier"] = AddLangPrefix(
"type.property");
428 Kind[
"displayName"] =
"Type Property";
434 Kind[
"identifier"] = AddLangPrefix(
"class");
435 Kind[
"displayName"] =
"Class";
438 Kind[
"identifier"] = AddLangPrefix(
"method");
439 Kind[
"displayName"] =
"Method Template";
442 Kind[
"identifier"] = AddLangPrefix(
"method");
443 Kind[
"displayName"] =
"Method Template Specialization";
446 Kind[
"identifier"] = AddLangPrefix(
"property");
447 Kind[
"displayName"] =
"Template Property";
450 Kind[
"identifier"] = AddLangPrefix(
"concept");
451 Kind[
"displayName"] =
"Concept";
454 Kind[
"identifier"] = AddLangPrefix(
"type.method");
455 Kind[
"displayName"] =
"Static Method";
458 Kind[
"identifier"] = AddLangPrefix(
"method");
459 Kind[
"displayName"] =
"Instance Method";
462 Kind[
"identifier"] = AddLangPrefix(
"method");
463 Kind[
"displayName"] =
"Constructor";
466 Kind[
"identifier"] = AddLangPrefix(
"method");
467 Kind[
"displayName"] =
"Destructor";
470 Kind[
"identifier"] = AddLangPrefix(
"ivar");
471 Kind[
"displayName"] =
"Instance Variable";
474 Kind[
"identifier"] = AddLangPrefix(
"method");
475 Kind[
"displayName"] =
"Instance Method";
478 Kind[
"identifier"] = AddLangPrefix(
"type.method");
479 Kind[
"displayName"] =
"Type Method";
482 Kind[
"identifier"] = AddLangPrefix(
"property");
483 Kind[
"displayName"] =
"Instance Property";
486 Kind[
"identifier"] = AddLangPrefix(
"type.property");
487 Kind[
"displayName"] =
"Type Property";
490 Kind[
"identifier"] = AddLangPrefix(
"class");
491 Kind[
"displayName"] =
"Class";
494 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
495 Kind[
"displayName"] =
"Class Extension";
498 Kind[
"identifier"] = AddLangPrefix(
"protocol");
499 Kind[
"displayName"] =
"Protocol";
502 Kind[
"identifier"] = AddLangPrefix(
"macro");
503 Kind[
"displayName"] =
"Macro";
506 Kind[
"identifier"] = AddLangPrefix(
"typealias");
507 Kind[
"displayName"] =
"Type Alias";
510 llvm_unreachable(
"API Record with uninstantiable kind");
522 return serializeSymbolKind(
Record.KindForDisplay, Lang);
532template <
typename RecordTy>
533void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
534 const auto &FS =
Record.Signature;
539 serializeArray(Signature,
"returns",
540 serializeDeclarationFragments(FS.getReturnType()));
543 for (
const auto &
P : FS.getParameters()) {
546 serializeArray(
Parameter,
"declarationFragments",
547 serializeDeclarationFragments(
P.Fragments));
552 Signature[
"parameters"] = std::move(Parameters);
554 serializeObject(
Paren,
"functionSignature", std::move(Signature));
557template <
typename RecordTy>
558void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
564 Array GenericParameters;
570 GenericParameters.emplace_back(std::move(
Parameter));
572 if (!GenericParameters.empty())
573 Generics[
"parameters"] = std::move(GenericParameters);
575 Array GenericConstraints;
578 Constraint[
"kind"] = Constr.Kind;
579 Constraint[
"lhs"] = Constr.LHS;
580 Constraint[
"rhs"] = Constr.RHS;
581 GenericConstraints.emplace_back(std::move(Constraint));
584 if (!GenericConstraints.empty())
585 Generics[
"constraints"] = std::move(GenericConstraints);
587 serializeObject(
Paren,
"swiftGenerics", Generics);
592 Array ParentContexts;
594 for (
const auto &
Parent : Parents) {
597 Elem[
"name"] =
Parent.Name;
599 Elem[
"kind"] = serializeSymbolKind(
Parent.Record->KindForDisplay,
604 ParentContexts.emplace_back(std::move(Elem));
607 return ParentContexts;
615 for (
const auto *Current =
Record; Current !=
nullptr;
616 Current = Current->Parent.Record)
617 ReverseHierarchy.emplace_back(Current);
620 std::make_move_iterator(ReverseHierarchy.rbegin()),
621 std::make_move_iterator(ReverseHierarchy.rend()));
628 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
629 return CategoryRecord->Interface;
640 Symbols.emplace_back(std::move(Symbol));
641 return Symbols.back().getAsObject();
649const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
651Object SymbolGraphSerializer::serializeMetadata()
const {
653 serializeObject(Metadata,
"formatVersion",
654 serializeSemanticVersion(FormatVersion));
660SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
662 Module[
"name"] = ModuleName;
672 if (
Record->Availability.isUnconditionallyUnavailable())
677 if (
Record->Name.starts_with(
"_"))
687ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
688 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
689 return *ModuleForCurrentSymbol;
694Array SymbolGraphSerializer::serializePathComponents(
696 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
699StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
701 case RelationshipKind::MemberOf:
703 case RelationshipKind::InheritsFrom:
704 return "inheritsFrom";
705 case RelationshipKind::ConformsTo:
707 case RelationshipKind::ExtensionTo:
708 return "extensionTo";
710 llvm_unreachable(
"Unhandled relationship kind");
713void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
719 if (EmitSymbolLabelsForTesting) {
720 llvm::raw_svector_ostream OS(TestRelLabel);
721 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
722 << Source.
USR <<
" $ ";
727 Relationship[
"!testRelLabel"] = TestRelLabel;
729 Relationship[
"source"] = Source.
USR;
730 Relationship[
"target"] =
Target.USR;
731 Relationship[
"targetFallback"] =
Target.Name;
732 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
734 if (ForceEmitToMainModule)
740StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
742 case ConstraintKind::Conformance:
743 return "conformance";
744 case ConstraintKind::ConditionalConformance:
745 return "conditionalConformance";
747 llvm_unreachable(
"Unhandled constraint kind");
750void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
755 if (EmitSymbolLabelsForTesting)
756 Obj[
"!testLabel"] =
Record->USR;
758 serializeObject(Obj,
"identifier",
761 serializeObject(Obj,
"names", serializeNames(
Record));
764 serializeSourceLocation(
Record->Location,
true));
765 serializeArray(Obj,
"availability",
766 serializeAvailability(
Record->Availability));
767 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
768 serializeArray(Obj,
"declarationFragments",
769 serializeDeclarationFragments(
Record->Declaration));
771 Obj[
"pathComponents"] = serializePathComponents(
Record);
772 Obj[
"accessLevel"] =
Record->Access.getAccess();
776 if (Hierarchy.size() >= 2)
777 serializeRelationship(MemberOf, Hierarchy.back(),
778 Hierarchy[Hierarchy.size() - 2],
Module);
780 CurrentSymbol =
Module.addSymbol(std::move(Obj));
788 Hierarchy.push_back(getHierarchyReference(
Record,
API));
791 Hierarchy.pop_back();
796 serializeAPIRecord(
Record);
805 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
814 serializeRelationship(RelationshipKind::InheritsFrom,
Record,
Base,
815 getModuleForCurrentSymbol());
824 serializeTemplateMixin(*CurrentSymbol, *
Record);
833 serializeTemplateMixin(*CurrentSymbol, *
Record);
842 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
851 serializeTemplateMixin(*CurrentSymbol, *
Record);
860 serializeTemplateMixin(*CurrentSymbol, *
Record);
868 serializeTemplateMixin(*CurrentSymbol, *
Record);
877 serializeTemplateMixin(*CurrentSymbol, *
Record);
887 serializeTemplateMixin(*CurrentSymbol, *
Record);
896 serializeTemplateMixin(*CurrentSymbol, *
Record);
905 for (
const auto &Protocol :
Record->Protocols)
906 serializeRelationship(ConformsTo,
Record, Protocol,
907 getModuleForCurrentSymbol());
917 if (!
Record->SuperClass.empty())
918 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
919 getModuleForCurrentSymbol());
925 if (SkipSymbolsInCategoriesToExternalTypes &&
929 auto *CurrentModule = ModuleForCurrentSymbol;
930 if (
auto ModuleExtendedByRecord =
Record->getExtendedExternalModule())
931 ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord];
937 ModuleForCurrentSymbol = CurrentModule;
951 for (
const auto &Protocol :
Record->Protocols)
952 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
953 getModuleForCurrentSymbol());
963 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
984 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
987 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
992 serializeAPIRecord(
Record);
996 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1001void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1002 switch (
Record->getKind()) {
1004#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1005 case APIRecord::KIND: { \
1006 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1015 llvm_unreachable(
"API Record with uninstantiable kind");
1019Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1022 serializeObject(Root,
"metadata", serializeMetadata());
1023 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1025 Root[
"symbols"] = std::move(EM.Symbols);
1026 Root[
"relationships"] = std::move(EM.Relationships);
1031void SymbolGraphSerializer::serializeGraphToStream(
1034 Object Root = serializeGraph(ModuleName, std::move(EM));
1035 if (Options.Compact)
1036 OS << formatv(
"{0}", json::Value(std::move(Root))) <<
"\n";
1038 OS << formatv(
"{0:2}", json::Value(std::move(Root))) <<
"\n";
1045 API, IgnoresList, Options.EmitSymbolLabelsForTesting,
1051 std::move(Serializer.MainModule));
1056 raw_ostream &MainOutput,
const APISet &API,
1058 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1062 Options.EmitSymbolLabelsForTesting);
1065 Serializer.serializeGraphToStream(MainOutput, Options,
API.
ProductName,
1066 std::move(Serializer.MainModule));
1068 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1069 if (
auto ExtensionOS =
1070 CreateOutputStream(
API.
ProductName +
"@" + ExtensionSGF.getKey()))
1071 Serializer.serializeGraphToStream(*ExtensionOS, Options,
API.
ProductName,
1072 std::move(ExtensionSGF.getValue()));
1076std::optional<Object>
1090 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1092 Serializer.serializeSingleRecord(
Record);
1093 serializeObject(Root,
"symbolGraph",
1095 std::move(Serializer.MainModule)));
1098 serializeArray(Root,
"parentContexts",
1099 generateParentContexts(Serializer.Hierarchy, Lang));
1101 Array RelatedSymbols;
1103 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1105 if (Fragment.PreciseIdentifier.empty())
1114 Object RelatedSymbol;
1115 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1116 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1122 serializeArray(RelatedSymbol,
"parentContexts",
1123 generateParentContexts(
1124 generateHierarchyFromRecord(RelatedRecord), Lang));
1126 RelatedSymbols.push_back(std::move(RelatedSymbol));
1129 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.
const char * getFilename() const
Return the presumed filename of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
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 isUnavailable() const
Check if the symbol is unavailable unconditionally or on the active platform and os version.