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:
216 case Language::RenderScript:
221 case Language::Unknown:
223 case Language::LLVM_IR:
225 llvm_unreachable(
"Unsupported language kind");
228 llvm_unreachable(
"Unhandled language kind");
259std::optional<Object> serializeDocComment(
const DocComment &Comment) {
266 for (
const auto &CommentLine : Comment) {
268 Line[
"text"] = CommentLine.Text;
269 serializeObject(Line,
"range",
270 serializeSourceRange(CommentLine.Begin, CommentLine.End));
271 LinesArray.emplace_back(std::move(Line));
274 serializeArray(
DocComment,
"lines", std::move(LinesArray));
321 Fragment[
"spelling"] = F.Spelling;
323 if (!F.PreciseIdentifier.empty())
324 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
325 Fragments.emplace_back(std::move(Fragment));
342 Names[
"title"] =
Record->Name;
344 serializeArray(Names,
"subHeading",
345 serializeDeclarationFragments(
Record->SubHeading));
348 DeclarationFragments::FragmentKind::Identifier,
350 serializeArray(Names,
"navigator",
351 serializeDeclarationFragments(NavigatorFragments));
357 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
364 Kind[
"identifier"] = AddLangPrefix(
"unknown");
365 Kind[
"displayName"] =
"Unknown";
368 Kind[
"identifier"] = AddLangPrefix(
"namespace");
369 Kind[
"displayName"] =
"Namespace";
372 Kind[
"identifier"] = AddLangPrefix(
"func");
373 Kind[
"displayName"] =
"Function";
376 Kind[
"identifier"] = AddLangPrefix(
"func");
377 Kind[
"displayName"] =
"Function Template";
380 Kind[
"identifier"] = AddLangPrefix(
"func");
381 Kind[
"displayName"] =
"Function Template Specialization";
384 Kind[
"identifier"] = AddLangPrefix(
"var");
385 Kind[
"displayName"] =
"Global Variable Template";
388 Kind[
"identifier"] = AddLangPrefix(
"var");
389 Kind[
"displayName"] =
"Global Variable Template Specialization";
392 Kind[
"identifier"] = AddLangPrefix(
"var");
393 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
396 Kind[
"identifier"] = AddLangPrefix(
"var");
397 Kind[
"displayName"] =
"Global Variable";
400 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
401 Kind[
"displayName"] =
"Enumeration Case";
404 Kind[
"identifier"] = AddLangPrefix(
"enum");
405 Kind[
"displayName"] =
"Enumeration";
408 Kind[
"identifier"] = AddLangPrefix(
"property");
409 Kind[
"displayName"] =
"Instance Property";
412 Kind[
"identifier"] = AddLangPrefix(
"struct");
413 Kind[
"displayName"] =
"Structure";
416 Kind[
"identifier"] = AddLangPrefix(
"property");
417 Kind[
"displayName"] =
"Instance Property";
420 Kind[
"identifier"] = AddLangPrefix(
"union");
421 Kind[
"displayName"] =
"Union";
424 Kind[
"identifier"] = AddLangPrefix(
"property");
425 Kind[
"displayName"] =
"Instance Property";
428 Kind[
"identifier"] = AddLangPrefix(
"type.property");
429 Kind[
"displayName"] =
"Type Property";
435 Kind[
"identifier"] = AddLangPrefix(
"class");
436 Kind[
"displayName"] =
"Class";
439 Kind[
"identifier"] = AddLangPrefix(
"method");
440 Kind[
"displayName"] =
"Method Template";
443 Kind[
"identifier"] = AddLangPrefix(
"method");
444 Kind[
"displayName"] =
"Method Template Specialization";
447 Kind[
"identifier"] = AddLangPrefix(
"property");
448 Kind[
"displayName"] =
"Template Property";
451 Kind[
"identifier"] = AddLangPrefix(
"concept");
452 Kind[
"displayName"] =
"Concept";
455 Kind[
"identifier"] = AddLangPrefix(
"type.method");
456 Kind[
"displayName"] =
"Static Method";
459 Kind[
"identifier"] = AddLangPrefix(
"method");
460 Kind[
"displayName"] =
"Instance Method";
463 Kind[
"identifier"] = AddLangPrefix(
"method");
464 Kind[
"displayName"] =
"Constructor";
467 Kind[
"identifier"] = AddLangPrefix(
"method");
468 Kind[
"displayName"] =
"Destructor";
471 Kind[
"identifier"] = AddLangPrefix(
"ivar");
472 Kind[
"displayName"] =
"Instance Variable";
475 Kind[
"identifier"] = AddLangPrefix(
"method");
476 Kind[
"displayName"] =
"Instance Method";
479 Kind[
"identifier"] = AddLangPrefix(
"type.method");
480 Kind[
"displayName"] =
"Type Method";
483 Kind[
"identifier"] = AddLangPrefix(
"property");
484 Kind[
"displayName"] =
"Instance Property";
487 Kind[
"identifier"] = AddLangPrefix(
"type.property");
488 Kind[
"displayName"] =
"Type Property";
491 Kind[
"identifier"] = AddLangPrefix(
"class");
492 Kind[
"displayName"] =
"Class";
495 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
496 Kind[
"displayName"] =
"Class Extension";
499 Kind[
"identifier"] = AddLangPrefix(
"protocol");
500 Kind[
"displayName"] =
"Protocol";
503 Kind[
"identifier"] = AddLangPrefix(
"macro");
504 Kind[
"displayName"] =
"Macro";
507 Kind[
"identifier"] = AddLangPrefix(
"typealias");
508 Kind[
"displayName"] =
"Type Alias";
511 llvm_unreachable(
"API Record with uninstantiable kind");
523 return serializeSymbolKind(
Record.KindForDisplay, Lang);
533template <
typename RecordTy>
534void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
535 const auto &FS =
Record.Signature;
540 serializeArray(Signature,
"returns",
541 serializeDeclarationFragments(FS.getReturnType()));
544 for (
const auto &
P : FS.getParameters()) {
547 serializeArray(
Parameter,
"declarationFragments",
548 serializeDeclarationFragments(
P.Fragments));
553 Signature[
"parameters"] = std::move(Parameters);
555 serializeObject(
Paren,
"functionSignature", std::move(Signature));
558template <
typename RecordTy>
559void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
565 Array GenericParameters;
571 GenericParameters.emplace_back(std::move(
Parameter));
573 if (!GenericParameters.empty())
574 Generics[
"parameters"] = std::move(GenericParameters);
576 Array GenericConstraints;
579 Constraint[
"kind"] = Constr.Kind;
580 Constraint[
"lhs"] = Constr.LHS;
581 Constraint[
"rhs"] = Constr.RHS;
582 GenericConstraints.emplace_back(std::move(Constraint));
585 if (!GenericConstraints.empty())
586 Generics[
"constraints"] = std::move(GenericConstraints);
588 serializeObject(
Paren,
"swiftGenerics", Generics);
593 Array ParentContexts;
595 for (
const auto &
Parent : Parents) {
598 Elem[
"name"] =
Parent.Name;
600 Elem[
"kind"] = serializeSymbolKind(
Parent.Record->KindForDisplay,
605 ParentContexts.emplace_back(std::move(Elem));
608 return ParentContexts;
616 for (
const auto *Current =
Record; Current !=
nullptr;
617 Current = Current->Parent.Record)
618 ReverseHierarchy.emplace_back(Current);
621 std::make_move_iterator(ReverseHierarchy.rbegin()),
622 std::make_move_iterator(ReverseHierarchy.rend()));
629 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
630 return CategoryRecord->Interface;
641 Symbols.emplace_back(std::move(Symbol));
642 return Symbols.back().getAsObject();
650const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
652Object SymbolGraphSerializer::serializeMetadata()
const {
654 serializeObject(Metadata,
"formatVersion",
655 serializeSemanticVersion(FormatVersion));
661SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
663 Module[
"name"] = ModuleName;
673 if (
Record->Availability.isUnconditionallyUnavailable())
678 if (
Record->Name.starts_with(
"_"))
688ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
689 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
690 return *ModuleForCurrentSymbol;
695Array SymbolGraphSerializer::serializePathComponents(
697 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
700StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
702 case RelationshipKind::MemberOf:
704 case RelationshipKind::InheritsFrom:
705 return "inheritsFrom";
706 case RelationshipKind::ConformsTo:
708 case RelationshipKind::ExtensionTo:
709 return "extensionTo";
711 llvm_unreachable(
"Unhandled relationship kind");
714void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
720 if (EmitSymbolLabelsForTesting) {
721 llvm::raw_svector_ostream OS(TestRelLabel);
722 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
723 << Source.
USR <<
" $ ";
728 Relationship[
"!testRelLabel"] = TestRelLabel;
730 Relationship[
"source"] = Source.
USR;
731 Relationship[
"target"] =
Target.USR;
732 Relationship[
"targetFallback"] =
Target.Name;
733 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
735 if (ForceEmitToMainModule)
741StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
743 case ConstraintKind::Conformance:
744 return "conformance";
745 case ConstraintKind::ConditionalConformance:
746 return "conditionalConformance";
748 llvm_unreachable(
"Unhandled constraint kind");
751void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
756 if (EmitSymbolLabelsForTesting)
757 Obj[
"!testLabel"] =
Record->USR;
759 serializeObject(Obj,
"identifier",
762 serializeObject(Obj,
"names", serializeNames(
Record));
765 serializeSourceLocation(
Record->Location,
true));
766 serializeArray(Obj,
"availability",
767 serializeAvailability(
Record->Availability));
768 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
769 serializeArray(Obj,
"declarationFragments",
770 serializeDeclarationFragments(
Record->Declaration));
772 Obj[
"pathComponents"] = serializePathComponents(
Record);
773 Obj[
"accessLevel"] =
Record->Access.getAccess();
777 if (Hierarchy.size() >= 2)
778 serializeRelationship(MemberOf, Hierarchy.back(),
779 Hierarchy[Hierarchy.size() - 2],
Module);
781 CurrentSymbol =
Module.addSymbol(std::move(Obj));
789 Hierarchy.push_back(getHierarchyReference(
Record,
API));
792 Hierarchy.pop_back();
797 serializeAPIRecord(
Record);
806 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
815 serializeRelationship(RelationshipKind::InheritsFrom,
Record,
Base,
816 getModuleForCurrentSymbol());
825 serializeTemplateMixin(*CurrentSymbol, *
Record);
834 serializeTemplateMixin(*CurrentSymbol, *
Record);
843 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
852 serializeTemplateMixin(*CurrentSymbol, *
Record);
861 serializeTemplateMixin(*CurrentSymbol, *
Record);
869 serializeTemplateMixin(*CurrentSymbol, *
Record);
878 serializeTemplateMixin(*CurrentSymbol, *
Record);
888 serializeTemplateMixin(*CurrentSymbol, *
Record);
897 serializeTemplateMixin(*CurrentSymbol, *
Record);
906 for (
const auto &Protocol :
Record->Protocols)
907 serializeRelationship(ConformsTo,
Record, Protocol,
908 getModuleForCurrentSymbol());
918 if (!
Record->SuperClass.empty())
919 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
920 getModuleForCurrentSymbol());
926 if (SkipSymbolsInCategoriesToExternalTypes &&
930 auto *CurrentModule = ModuleForCurrentSymbol;
931 if (
Record->isExtendingExternalModule())
932 ModuleForCurrentSymbol = &ExtendedModules[
Record->Interface.Source];
938 ModuleForCurrentSymbol = CurrentModule;
952 for (
const auto &Protocol :
Record->Protocols)
953 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
954 getModuleForCurrentSymbol());
964 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
985 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
988 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
993 serializeAPIRecord(
Record);
997 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1002void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1003 switch (
Record->getKind()) {
1005#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1006 case APIRecord::KIND: { \
1007 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1016 llvm_unreachable(
"API Record with uninstantiable kind");
1020Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1023 serializeObject(Root,
"metadata", serializeMetadata());
1024 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1026 Root[
"symbols"] = std::move(EM.Symbols);
1027 Root[
"relationships"] = std::move(EM.Relationships);
1032void SymbolGraphSerializer::serializeGraphToStream(
1035 Object Root = serializeGraph(ModuleName, std::move(EM));
1036 if (Options.Compact)
1037 OS << formatv(
"{0}", json::Value(std::move(Root))) <<
"\n";
1039 OS << formatv(
"{0:2}", json::Value(std::move(Root))) <<
"\n";
1046 API, IgnoresList, Options.EmitSymbolLabelsForTesting,
1052 std::move(Serializer.MainModule));
1057 raw_ostream &MainOutput,
const APISet &API,
1059 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1063 Options.EmitSymbolLabelsForTesting);
1066 Serializer.serializeGraphToStream(MainOutput, Options,
API.
ProductName,
1067 std::move(Serializer.MainModule));
1069 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1070 if (
auto ExtensionOS =
1071 CreateOutputStream(ExtensionSGF.getKey() +
"@" +
API.
ProductName))
1072 Serializer.serializeGraphToStream(*ExtensionOS, Options,
1073 ExtensionSGF.getKey(),
1074 std::move(ExtensionSGF.getValue()));
1078std::optional<Object>
1092 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1094 Serializer.serializeSingleRecord(
Record);
1095 serializeObject(Root,
"symbolGraph",
1097 std::move(Serializer.MainModule)));
1100 serializeArray(Root,
"parentContexts",
1101 generateParentContexts(Serializer.Hierarchy, Lang));
1103 Array RelatedSymbols;
1105 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1107 if (Fragment.PreciseIdentifier.empty())
1116 Object RelatedSymbol;
1117 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1118 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1124 serializeArray(RelatedSymbol,
"parentContexts",
1125 generateParentContexts(
1126 generateHierarchyFromRecord(RelatedRecord), Lang));
1128 RelatedSymbols.push_back(std::move(RelatedSymbol));
1131 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.