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();
107 Platform[
"operatingSystem"] = serializeOperatingSystem(
T);
113 assert(
Loc.
isValid() &&
"invalid source position");
116 SourcePosition[
"line"] =
Loc.getLine() - 1;
117 SourcePosition[
"character"] =
Loc.getColumn() - 1;
119 return SourcePosition;
128 bool IncludeFileURI =
false) {
132 if (IncludeFileURI) {
133 std::string FileURI =
"file://";
135 FileURI += sys::path::convert_to_slash(
Loc.getFilename());
146 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
147 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
166 Array AvailabilityArray;
169 Object UnconditionallyDeprecated;
170 UnconditionallyDeprecated[
"domain"] =
"*";
171 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
172 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
176 Availability[
"domain"] = Avail.
Domain;
179 Availability[
"isUnconditionallyUnavailable"] =
true;
181 serializeObject(Availability,
"introduced",
183 serializeObject(Availability,
"deprecated",
185 serializeObject(Availability,
"obsoleted",
186 serializeSemanticVersion(Avail.
Obsoleted));
189 AvailabilityArray.emplace_back(std::move(Availability));
190 return AvailabilityArray;
199 return "objective-c";
202 case Language::ObjCXX:
203 return "objective-c++";
206 case Language::OpenCL:
207 case Language::OpenCLCXX:
209 case Language::RenderScript:
214 case Language::Unknown:
216 case Language::LLVM_IR:
218 llvm_unreachable(
"Unsupported language kind");
221 llvm_unreachable(
"Unhandled language kind");
252std::optional<Object> serializeDocComment(
const DocComment &Comment) {
259 for (
const auto &CommentLine : Comment) {
261 Line[
"text"] = CommentLine.Text;
262 serializeObject(Line,
"range",
263 serializeSourceRange(CommentLine.Begin, CommentLine.End));
264 LinesArray.emplace_back(std::move(Line));
267 serializeArray(
DocComment,
"lines", std::move(LinesArray));
314 Fragment[
"spelling"] = F.Spelling;
316 if (!F.PreciseIdentifier.empty())
317 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
318 Fragments.emplace_back(std::move(Fragment));
335 Names[
"title"] =
Record->Name;
337 serializeArray(Names,
"subHeading",
338 serializeDeclarationFragments(
Record->SubHeading));
341 DeclarationFragments::FragmentKind::Identifier,
343 serializeArray(Names,
"navigator",
344 serializeDeclarationFragments(NavigatorFragments));
350 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
357 Kind[
"identifier"] = AddLangPrefix(
"unknown");
358 Kind[
"displayName"] =
"Unknown";
361 Kind[
"identifier"] = AddLangPrefix(
"namespace");
362 Kind[
"displayName"] =
"Namespace";
365 Kind[
"identifier"] = AddLangPrefix(
"func");
366 Kind[
"displayName"] =
"Function";
369 Kind[
"identifier"] = AddLangPrefix(
"func");
370 Kind[
"displayName"] =
"Function Template";
373 Kind[
"identifier"] = AddLangPrefix(
"func");
374 Kind[
"displayName"] =
"Function Template Specialization";
377 Kind[
"identifier"] = AddLangPrefix(
"var");
378 Kind[
"displayName"] =
"Global Variable Template";
381 Kind[
"identifier"] = AddLangPrefix(
"var");
382 Kind[
"displayName"] =
"Global Variable Template Specialization";
385 Kind[
"identifier"] = AddLangPrefix(
"var");
386 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
389 Kind[
"identifier"] = AddLangPrefix(
"var");
390 Kind[
"displayName"] =
"Global Variable";
393 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
394 Kind[
"displayName"] =
"Enumeration Case";
397 Kind[
"identifier"] = AddLangPrefix(
"enum");
398 Kind[
"displayName"] =
"Enumeration";
401 Kind[
"identifier"] = AddLangPrefix(
"property");
402 Kind[
"displayName"] =
"Instance Property";
405 Kind[
"identifier"] = AddLangPrefix(
"struct");
406 Kind[
"displayName"] =
"Structure";
409 Kind[
"identifier"] = AddLangPrefix(
"property");
410 Kind[
"displayName"] =
"Instance Property";
413 Kind[
"identifier"] = AddLangPrefix(
"union");
414 Kind[
"displayName"] =
"Union";
417 Kind[
"identifier"] = AddLangPrefix(
"property");
418 Kind[
"displayName"] =
"Instance Property";
421 Kind[
"identifier"] = AddLangPrefix(
"type.property");
422 Kind[
"displayName"] =
"Type Property";
428 Kind[
"identifier"] = AddLangPrefix(
"class");
429 Kind[
"displayName"] =
"Class";
432 Kind[
"identifier"] = AddLangPrefix(
"method");
433 Kind[
"displayName"] =
"Method Template";
436 Kind[
"identifier"] = AddLangPrefix(
"method");
437 Kind[
"displayName"] =
"Method Template Specialization";
440 Kind[
"identifier"] = AddLangPrefix(
"property");
441 Kind[
"displayName"] =
"Template Property";
444 Kind[
"identifier"] = AddLangPrefix(
"concept");
445 Kind[
"displayName"] =
"Concept";
448 Kind[
"identifier"] = AddLangPrefix(
"type.method");
449 Kind[
"displayName"] =
"Static Method";
452 Kind[
"identifier"] = AddLangPrefix(
"method");
453 Kind[
"displayName"] =
"Instance Method";
456 Kind[
"identifier"] = AddLangPrefix(
"method");
457 Kind[
"displayName"] =
"Constructor";
460 Kind[
"identifier"] = AddLangPrefix(
"method");
461 Kind[
"displayName"] =
"Destructor";
464 Kind[
"identifier"] = AddLangPrefix(
"ivar");
465 Kind[
"displayName"] =
"Instance Variable";
468 Kind[
"identifier"] = AddLangPrefix(
"method");
469 Kind[
"displayName"] =
"Instance Method";
472 Kind[
"identifier"] = AddLangPrefix(
"type.method");
473 Kind[
"displayName"] =
"Type Method";
476 Kind[
"identifier"] = AddLangPrefix(
"property");
477 Kind[
"displayName"] =
"Instance Property";
480 Kind[
"identifier"] = AddLangPrefix(
"type.property");
481 Kind[
"displayName"] =
"Type Property";
484 Kind[
"identifier"] = AddLangPrefix(
"class");
485 Kind[
"displayName"] =
"Class";
488 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
489 Kind[
"displayName"] =
"Class Extension";
492 Kind[
"identifier"] = AddLangPrefix(
"protocol");
493 Kind[
"displayName"] =
"Protocol";
496 Kind[
"identifier"] = AddLangPrefix(
"macro");
497 Kind[
"displayName"] =
"Macro";
500 Kind[
"identifier"] = AddLangPrefix(
"typealias");
501 Kind[
"displayName"] =
"Type Alias";
504 llvm_unreachable(
"API Record with uninstantiable kind");
516 return serializeSymbolKind(
Record.KindForDisplay, Lang);
526template <
typename RecordTy>
527void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
528 const auto &FS =
Record.Signature;
533 serializeArray(Signature,
"returns",
534 serializeDeclarationFragments(FS.getReturnType()));
537 for (
const auto &
P : FS.getParameters()) {
540 serializeArray(
Parameter,
"declarationFragments",
541 serializeDeclarationFragments(
P.Fragments));
546 Signature[
"parameters"] = std::move(Parameters);
548 serializeObject(
Paren,
"functionSignature", std::move(Signature));
551template <
typename RecordTy>
552void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
558 Array GenericParameters;
564 GenericParameters.emplace_back(std::move(
Parameter));
566 if (!GenericParameters.empty())
567 Generics[
"parameters"] = std::move(GenericParameters);
569 Array GenericConstraints;
572 Constraint[
"kind"] = Constr.Kind;
573 Constraint[
"lhs"] = Constr.LHS;
574 Constraint[
"rhs"] = Constr.RHS;
575 GenericConstraints.emplace_back(std::move(Constraint));
578 if (!GenericConstraints.empty())
579 Generics[
"constraints"] = std::move(GenericConstraints);
581 serializeObject(
Paren,
"swiftGenerics", Generics);
586 Array ParentContexts;
588 for (
const auto &
Parent : Parents) {
591 Elem[
"name"] =
Parent.Name;
593 Elem[
"kind"] = serializeSymbolKind(
Parent.Record->KindForDisplay,
598 ParentContexts.emplace_back(std::move(Elem));
601 return ParentContexts;
609 for (
const auto *Current =
Record; Current !=
nullptr;
610 Current = Current->Parent.Record)
611 ReverseHierarchy.emplace_back(Current);
614 std::make_move_iterator(ReverseHierarchy.rbegin()),
615 std::make_move_iterator(ReverseHierarchy.rend()));
622 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
623 return CategoryRecord->Interface;
634 Symbols.emplace_back(std::move(Symbol));
635 return Symbols.back().getAsObject();
643const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
645Object SymbolGraphSerializer::serializeMetadata()
const {
647 serializeObject(Metadata,
"formatVersion",
648 serializeSemanticVersion(FormatVersion));
654SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
656 Module[
"name"] = ModuleName;
666 if (
Record->Availability.isUnconditionallyUnavailable())
672 if (
auto *Tag = dyn_cast<TagRecord>(
Record)) {
673 if (
Tag->IsEmbeddedInVarDeclarator)
679 if (
Record->Name.starts_with(
"_"))
689ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
690 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
691 return *ModuleForCurrentSymbol;
696Array SymbolGraphSerializer::serializePathComponents(
698 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
701StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
703 case RelationshipKind::MemberOf:
705 case RelationshipKind::InheritsFrom:
706 return "inheritsFrom";
707 case RelationshipKind::ConformsTo:
709 case RelationshipKind::ExtensionTo:
710 return "extensionTo";
712 llvm_unreachable(
"Unhandled relationship kind");
715void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
721 if (EmitSymbolLabelsForTesting) {
722 llvm::raw_svector_ostream OS(TestRelLabel);
723 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
724 << Source.
USR <<
" $ ";
729 Relationship[
"!testRelLabel"] = TestRelLabel;
731 Relationship[
"source"] = Source.
USR;
732 Relationship[
"target"] =
Target.USR;
733 Relationship[
"targetFallback"] =
Target.Name;
734 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
736 if (ForceEmitToMainModule)
742StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
744 case ConstraintKind::Conformance:
745 return "conformance";
746 case ConstraintKind::ConditionalConformance:
747 return "conditionalConformance";
749 llvm_unreachable(
"Unhandled constraint kind");
752void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
757 if (EmitSymbolLabelsForTesting)
758 Obj[
"!testLabel"] =
Record->USR;
760 serializeObject(Obj,
"identifier",
763 serializeObject(Obj,
"names", serializeNames(
Record));
766 serializeSourceLocation(
Record->Location,
true));
767 serializeArray(Obj,
"availability",
768 serializeAvailability(
Record->Availability));
769 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
770 serializeArray(Obj,
"declarationFragments",
771 serializeDeclarationFragments(
Record->Declaration));
773 Obj[
"pathComponents"] = serializePathComponents(
Record);
774 Obj[
"accessLevel"] =
Record->Access.getAccess();
778 if (Hierarchy.size() >= 2)
779 serializeRelationship(MemberOf, Hierarchy.back(),
780 Hierarchy[Hierarchy.size() - 2],
Module);
782 CurrentSymbol =
Module.addSymbol(std::move(Obj));
790 Hierarchy.push_back(getHierarchyReference(
Record,
API));
793 Hierarchy.pop_back();
798 serializeAPIRecord(
Record);
807 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
816 serializeRelationship(RelationshipKind::InheritsFrom,
Record,
Base,
817 getModuleForCurrentSymbol());
826 serializeTemplateMixin(*CurrentSymbol, *
Record);
835 serializeTemplateMixin(*CurrentSymbol, *
Record);
844 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
853 serializeTemplateMixin(*CurrentSymbol, *
Record);
862 serializeTemplateMixin(*CurrentSymbol, *
Record);
870 serializeTemplateMixin(*CurrentSymbol, *
Record);
879 serializeTemplateMixin(*CurrentSymbol, *
Record);
889 serializeTemplateMixin(*CurrentSymbol, *
Record);
898 serializeTemplateMixin(*CurrentSymbol, *
Record);
907 for (
const auto &Protocol :
Record->Protocols)
908 serializeRelationship(ConformsTo,
Record, Protocol,
909 getModuleForCurrentSymbol());
919 if (!
Record->SuperClass.empty())
920 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
921 getModuleForCurrentSymbol());
927 if (SkipSymbolsInCategoriesToExternalTypes &&
931 auto *CurrentModule = ModuleForCurrentSymbol;
932 if (
Record->isExtendingExternalModule())
933 ModuleForCurrentSymbol = &ExtendedModules[
Record->Interface.Source];
939 ModuleForCurrentSymbol = CurrentModule;
953 for (
const auto &Protocol :
Record->Protocols)
954 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
955 getModuleForCurrentSymbol());
965 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
986 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
989 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
994 serializeAPIRecord(
Record);
998 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1003void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1004 switch (
Record->getKind()) {
1006#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1007 case APIRecord::KIND: { \
1008 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1017 llvm_unreachable(
"API Record with uninstantiable kind");
1021Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1024 serializeObject(Root,
"metadata", serializeMetadata());
1025 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1027 Root[
"symbols"] = std::move(EM.Symbols);
1028 Root[
"relationships"] = std::move(EM.Relationships);
1033void SymbolGraphSerializer::serializeGraphToStream(
1036 Object Root = serializeGraph(ModuleName, std::move(EM));
1037 if (Options.Compact)
1038 OS << formatv(
"{0}", json::Value(std::move(Root))) <<
"\n";
1040 OS << formatv(
"{0:2}", json::Value(std::move(Root))) <<
"\n";
1047 API, IgnoresList, Options.EmitSymbolLabelsForTesting,
1053 std::move(Serializer.MainModule));
1058 raw_ostream &MainOutput,
const APISet &API,
1060 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1064 Options.EmitSymbolLabelsForTesting);
1067 Serializer.serializeGraphToStream(MainOutput, Options,
API.
ProductName,
1068 std::move(Serializer.MainModule));
1070 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1071 if (
auto ExtensionOS =
1072 CreateOutputStream(ExtensionSGF.getKey() +
"@" +
API.
ProductName))
1073 Serializer.serializeGraphToStream(*ExtensionOS, Options,
1074 ExtensionSGF.getKey(),
1075 std::move(ExtensionSGF.getValue()));
1079std::optional<Object>
1093 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1095 Serializer.serializeSingleRecord(
Record);
1096 serializeObject(Root,
"symbolGraph",
1098 std::move(Serializer.MainModule)));
1101 serializeArray(Root,
"parentContexts",
1102 generateParentContexts(Serializer.Hierarchy, Lang));
1104 Array RelatedSymbols;
1106 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1108 if (Fragment.PreciseIdentifier.empty())
1117 Object RelatedSymbol;
1118 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1119 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1125 serializeArray(RelatedSymbol,
"parentContexts",
1126 generateParentContexts(
1127 generateHierarchyFromRecord(RelatedRecord), Lang));
1129 RelatedSymbols.push_back(std::move(RelatedSymbol));
1132 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.