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"
40void serializeObject(Object &
Paren, StringRef Key,
41 std::optional<Object> &&Obj) {
43 Paren[Key] = std::move(*Obj);
48void serializeArray(Object &
Paren, StringRef Key,
49 std::optional<Array> &&Array) {
51 Paren[Key] = std::move(*Array);
56template <
typename ContainerTy>
57void serializeArray(Object &
Paren, StringRef Key, ContainerTy &&
C) {
77std::optional<Object> serializeSemanticVersion(
const VersionTuple &
V) {
82 Version[
"major"] =
V.getMajor();
83 Version[
"minor"] =
V.getMinor().value_or(0);
84 Version[
"patch"] =
V.getSubminor().value_or(0);
92Object serializeOperatingSystem(
const Triple &
T) {
94 OS[
"name"] =
T.getOSTypeName(
T.getOS());
95 serializeObject(OS,
"minimumVersion",
96 serializeSemanticVersion(
T.getMinimumSupportedOSVersion()));
104Object serializePlatform(
const Triple &
T) {
106 Platform[
"architecture"] =
T.getArchName();
107 Platform[
"vendor"] =
T.getVendorName();
108 Platform[
"operatingSystem"] = serializeOperatingSystem(
T);
114 assert(Loc.
isValid() &&
"invalid source position");
117 SourcePosition[
"line"] = Loc.
getLine() - 1;
118 SourcePosition[
"character"] = Loc.
getColumn() - 1;
120 return SourcePosition;
129 bool IncludeFileURI =
false) {
131 serializeObject(
SourceLocation,
"position", serializeSourcePosition(Loc));
133 if (IncludeFileURI) {
134 std::string FileURI =
"file://";
136 FileURI += sys::path::convert_to_slash(Loc.
getFilename());
147 serializeObject(
SourceRange,
"start", serializeSourcePosition(BeginLoc));
148 serializeObject(
SourceRange,
"end", serializeSourcePosition(EndLoc));
167 Array AvailabilityArray;
170 Object UnconditionallyDeprecated;
171 UnconditionallyDeprecated[
"domain"] =
"*";
172 UnconditionallyDeprecated[
"isUnconditionallyDeprecated"] =
true;
173 AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
177 Availability[
"domain"] = Avail.
Domain;
180 Availability[
"isUnconditionallyUnavailable"] =
true;
182 serializeObject(Availability,
"introduced",
184 serializeObject(Availability,
"deprecated",
186 serializeObject(Availability,
"obsoleted",
187 serializeSemanticVersion(Avail.
Obsoleted));
190 AvailabilityArray.emplace_back(std::move(Availability));
191 return AvailabilityArray;
200 return "objective-c";
203 case Language::ObjCXX:
204 return "objective-c++";
207 case Language::OpenCL:
208 case Language::OpenCLCXX:
210 case Language::RenderScript:
215 case Language::Unknown:
217 case Language::LLVM_IR:
219 llvm_unreachable(
"Unsupported language kind");
222 llvm_unreachable(
"Unhandled language kind");
253std::optional<Object> serializeDocComment(
const DocComment &Comment) {
260 for (
const auto &CommentLine : Comment) {
262 Line[
"text"] = CommentLine.Text;
263 serializeObject(Line,
"range",
264 serializeSourceRange(CommentLine.Begin, CommentLine.End));
265 LinesArray.emplace_back(std::move(Line));
268 serializeArray(
DocComment,
"lines", std::move(LinesArray));
315 Fragment[
"spelling"] = F.Spelling;
317 if (!F.PreciseIdentifier.empty())
318 Fragment[
"preciseIdentifier"] = F.PreciseIdentifier;
319 Fragments.emplace_back(std::move(Fragment));
336 Names[
"title"] =
Record->Name;
338 serializeArray(Names,
"subHeading",
339 serializeDeclarationFragments(
Record->SubHeading));
342 DeclarationFragments::FragmentKind::Identifier,
344 serializeArray(Names,
"navigator",
345 serializeDeclarationFragments(NavigatorFragments));
351 auto AddLangPrefix = [&
Lang](StringRef S) -> std::string {
358 Kind[
"identifier"] = AddLangPrefix(
"unknown");
359 Kind[
"displayName"] =
"Unknown";
362 Kind[
"identifier"] = AddLangPrefix(
"namespace");
363 Kind[
"displayName"] =
"Namespace";
366 Kind[
"identifier"] = AddLangPrefix(
"func");
367 Kind[
"displayName"] =
"Function";
370 Kind[
"identifier"] = AddLangPrefix(
"func");
371 Kind[
"displayName"] =
"Function Template";
374 Kind[
"identifier"] = AddLangPrefix(
"func");
375 Kind[
"displayName"] =
"Function Template Specialization";
378 Kind[
"identifier"] = AddLangPrefix(
"var");
379 Kind[
"displayName"] =
"Global Variable Template";
382 Kind[
"identifier"] = AddLangPrefix(
"var");
383 Kind[
"displayName"] =
"Global Variable Template Specialization";
386 Kind[
"identifier"] = AddLangPrefix(
"var");
387 Kind[
"displayName"] =
"Global Variable Template Partial Specialization";
390 Kind[
"identifier"] = AddLangPrefix(
"var");
391 Kind[
"displayName"] =
"Global Variable";
394 Kind[
"identifier"] = AddLangPrefix(
"enum.case");
395 Kind[
"displayName"] =
"Enumeration Case";
398 Kind[
"identifier"] = AddLangPrefix(
"enum");
399 Kind[
"displayName"] =
"Enumeration";
402 Kind[
"identifier"] = AddLangPrefix(
"property");
403 Kind[
"displayName"] =
"Instance Property";
406 Kind[
"identifier"] = AddLangPrefix(
"struct");
407 Kind[
"displayName"] =
"Structure";
410 Kind[
"identifier"] = AddLangPrefix(
"property");
411 Kind[
"displayName"] =
"Instance Property";
414 Kind[
"identifier"] = AddLangPrefix(
"union");
415 Kind[
"displayName"] =
"Union";
418 Kind[
"identifier"] = AddLangPrefix(
"property");
419 Kind[
"displayName"] =
"Instance Property";
422 Kind[
"identifier"] = AddLangPrefix(
"type.property");
423 Kind[
"displayName"] =
"Type Property";
429 Kind[
"identifier"] = AddLangPrefix(
"class");
430 Kind[
"displayName"] =
"Class";
433 Kind[
"identifier"] = AddLangPrefix(
"method");
434 Kind[
"displayName"] =
"Method Template";
437 Kind[
"identifier"] = AddLangPrefix(
"method");
438 Kind[
"displayName"] =
"Method Template Specialization";
441 Kind[
"identifier"] = AddLangPrefix(
"property");
442 Kind[
"displayName"] =
"Template Property";
445 Kind[
"identifier"] = AddLangPrefix(
"concept");
446 Kind[
"displayName"] =
"Concept";
449 Kind[
"identifier"] = AddLangPrefix(
"type.method");
450 Kind[
"displayName"] =
"Static Method";
453 Kind[
"identifier"] = AddLangPrefix(
"method");
454 Kind[
"displayName"] =
"Instance Method";
457 Kind[
"identifier"] = AddLangPrefix(
"method");
458 Kind[
"displayName"] =
"Constructor";
461 Kind[
"identifier"] = AddLangPrefix(
"method");
462 Kind[
"displayName"] =
"Destructor";
465 Kind[
"identifier"] = AddLangPrefix(
"ivar");
466 Kind[
"displayName"] =
"Instance Variable";
469 Kind[
"identifier"] = AddLangPrefix(
"method");
470 Kind[
"displayName"] =
"Instance Method";
473 Kind[
"identifier"] = AddLangPrefix(
"type.method");
474 Kind[
"displayName"] =
"Type Method";
477 Kind[
"identifier"] = AddLangPrefix(
"property");
478 Kind[
"displayName"] =
"Instance Property";
481 Kind[
"identifier"] = AddLangPrefix(
"type.property");
482 Kind[
"displayName"] =
"Type Property";
485 Kind[
"identifier"] = AddLangPrefix(
"class");
486 Kind[
"displayName"] =
"Class";
489 Kind[
"identifier"] = AddLangPrefix(
"class.extension");
490 Kind[
"displayName"] =
"Class Extension";
493 Kind[
"identifier"] = AddLangPrefix(
"protocol");
494 Kind[
"displayName"] =
"Protocol";
497 Kind[
"identifier"] = AddLangPrefix(
"macro");
498 Kind[
"displayName"] =
"Macro";
501 Kind[
"identifier"] = AddLangPrefix(
"typealias");
502 Kind[
"displayName"] =
"Type Alias";
505 llvm_unreachable(
"API Record with uninstantiable kind");
517 return serializeSymbolKind(
Record.getKind(), Lang);
527template <
typename RecordTy>
528void serializeFunctionSignatureMixin(Object &
Paren,
const RecordTy &
Record) {
529 const auto &FS =
Record.Signature;
534 serializeArray(Signature,
"returns",
535 serializeDeclarationFragments(FS.getReturnType()));
538 for (
const auto &
P : FS.getParameters()) {
541 serializeArray(
Parameter,
"declarationFragments",
542 serializeDeclarationFragments(
P.Fragments));
547 Signature[
"parameters"] = std::move(Parameters);
549 serializeObject(
Paren,
"functionSignature", std::move(Signature));
552template <
typename RecordTy>
553void serializeTemplateMixin(Object &
Paren,
const RecordTy &
Record) {
559 Array GenericParameters;
565 GenericParameters.emplace_back(std::move(
Parameter));
567 if (!GenericParameters.empty())
568 Generics[
"parameters"] = std::move(GenericParameters);
570 Array GenericConstraints;
573 Constraint[
"kind"] = Constr.Kind;
574 Constraint[
"lhs"] = Constr.LHS;
575 Constraint[
"rhs"] = Constr.RHS;
576 GenericConstraints.emplace_back(std::move(Constraint));
579 if (!GenericConstraints.empty())
580 Generics[
"constraints"] = std::move(GenericConstraints);
582 serializeObject(
Paren,
"swiftGenerics", Generics);
587 Array ParentContexts;
589 for (
const auto &
Parent : Parents) {
592 Elem[
"name"] =
Parent.Name;
595 serializeSymbolKind(
Parent.Record->getKind(), Lang)[
"identifier"];
599 ParentContexts.emplace_back(std::move(Elem));
602 return ParentContexts;
610 for (
const auto *Current =
Record; Current !=
nullptr;
611 Current = Current->Parent.Record)
612 ReverseHierarchy.emplace_back(Current);
615 std::make_move_iterator(ReverseHierarchy.rbegin()),
616 std::make_move_iterator(ReverseHierarchy.rend()));
623 if (
auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(
Record)) {
624 return CategoryRecord->Interface;
635 Symbols.emplace_back(std::move(Symbol));
636 return Symbols.back().getAsObject();
644const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
646Object SymbolGraphSerializer::serializeMetadata()
const {
648 serializeObject(Metadata,
"formatVersion",
649 serializeSemanticVersion(FormatVersion));
655SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
657 Module[
"name"] = ModuleName;
667 if (
Record->Availability.isUnconditionallyUnavailable())
673 if (
auto *Tag = dyn_cast<TagRecord>(
Record)) {
674 if (Tag->IsEmbeddedInVarDeclarator)
680 if (
Record->Name.starts_with(
"_"))
690ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
691 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
692 return *ModuleForCurrentSymbol;
697Array SymbolGraphSerializer::serializePathComponents(
699 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
702StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
704 case RelationshipKind::MemberOf:
706 case RelationshipKind::InheritsFrom:
707 return "inheritsFrom";
708 case RelationshipKind::ConformsTo:
710 case RelationshipKind::ExtensionTo:
711 return "extensionTo";
713 llvm_unreachable(
"Unhandled relationship kind");
716void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
722 if (EmitSymbolLabelsForTesting) {
723 llvm::raw_svector_ostream OS(TestRelLabel);
724 OS << SymbolGraphSerializer::getRelationshipString(Kind) <<
" $ "
725 << Source.
USR <<
" $ ";
730 Relationship[
"!testRelLabel"] = TestRelLabel;
732 Relationship[
"source"] = Source.
USR;
733 Relationship[
"target"] =
Target.USR;
734 Relationship[
"targetFallback"] =
Target.Name;
735 Relationship[
"kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
737 if (ForceEmitToMainModule)
743StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
745 case ConstraintKind::Conformance:
746 return "conformance";
747 case ConstraintKind::ConditionalConformance:
748 return "conditionalConformance";
750 llvm_unreachable(
"Unhandled constraint kind");
753void SymbolGraphSerializer::serializeAPIRecord(
const APIRecord *
Record) {
758 if (EmitSymbolLabelsForTesting)
759 Obj[
"!testLabel"] =
Record->USR;
761 serializeObject(Obj,
"identifier",
764 serializeObject(Obj,
"names", serializeNames(
Record));
767 serializeSourceLocation(
Record->Location,
true));
768 serializeArray(Obj,
"availability",
769 serializeAvailability(
Record->Availability));
770 serializeObject(Obj,
"docComment", serializeDocComment(
Record->Comment));
771 serializeArray(Obj,
"declarationFragments",
772 serializeDeclarationFragments(
Record->Declaration));
774 Obj[
"pathComponents"] = serializePathComponents(
Record);
775 Obj[
"accessLevel"] =
Record->Access.getAccess();
779 if (Hierarchy.size() >= 2)
780 serializeRelationship(MemberOf, Hierarchy.back(),
781 Hierarchy[Hierarchy.size() - 2],
Module);
783 CurrentSymbol =
Module.addSymbol(std::move(Obj));
791 Hierarchy.push_back(getHierarchyReference(
Record,
API));
794 Hierarchy.pop_back();
799 serializeAPIRecord(
Record);
808 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
817 serializeRelationship(RelationshipKind::InheritsFrom,
Record,
Base,
818 getModuleForCurrentSymbol());
827 serializeTemplateMixin(*CurrentSymbol, *
Record);
836 serializeTemplateMixin(*CurrentSymbol, *
Record);
845 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
854 serializeTemplateMixin(*CurrentSymbol, *
Record);
863 serializeTemplateMixin(*CurrentSymbol, *
Record);
871 serializeTemplateMixin(*CurrentSymbol, *
Record);
880 serializeTemplateMixin(*CurrentSymbol, *
Record);
890 serializeTemplateMixin(*CurrentSymbol, *
Record);
899 serializeTemplateMixin(*CurrentSymbol, *
Record);
908 for (
const auto &Protocol :
Record->Protocols)
909 serializeRelationship(ConformsTo,
Record, Protocol,
910 getModuleForCurrentSymbol());
920 if (!
Record->SuperClass.empty())
921 serializeRelationship(InheritsFrom,
Record,
Record->SuperClass,
922 getModuleForCurrentSymbol());
928 auto *CurrentModule = ModuleForCurrentSymbol;
929 if (
Record->isExtendingExternalModule())
930 ModuleForCurrentSymbol = &ExtendedModules[
Record->Interface.Source];
936 ModuleForCurrentSymbol = CurrentModule;
950 for (
const auto &Protocol :
Record->Protocols)
951 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
952 getModuleForCurrentSymbol());
962 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
983 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
986 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
991 serializeAPIRecord(
Record);
995 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1000void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1001 switch (
Record->getKind()) {
1003#define CONCRETE_RECORD(CLASS, BASE, KIND) \
1004 case APIRecord::KIND: { \
1005 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1014 llvm_unreachable(
"API Record with uninstantiable kind");
1018Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1021 serializeObject(Root,
"metadata", serializeMetadata());
1022 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1024 Root[
"symbols"] = std::move(EM.Symbols);
1025 Root[
"relationships"] = std::move(EM.Relationships);
1030void SymbolGraphSerializer::serializeGraphToStream(
1033 Object Root = serializeGraph(ModuleName, std::move(EM));
1034 if (Options.Compact)
1035 OS << formatv(
"{0}",
Value(std::move(Root))) <<
"\n";
1037 OS << formatv(
"{0:2}",
Value(std::move(Root))) <<
"\n";
1044 Options.EmitSymbolLabelsForTesting);
1047 std::move(Serializer.MainModule));
1052 raw_ostream &MainOutput,
const APISet &API,
1054 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1058 Options.EmitSymbolLabelsForTesting);
1061 Serializer.serializeGraphToStream(MainOutput, Options,
API.
ProductName,
1062 std::move(Serializer.MainModule));
1064 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1065 if (
auto ExtensionOS =
1066 CreateOutputStream(ExtensionSGF.getKey() +
"@" +
API.
ProductName))
1067 Serializer.serializeGraphToStream(*ExtensionOS, Options,
1068 ExtensionSGF.getKey(),
1069 std::move(ExtensionSGF.getValue()));
1073std::optional<Object>
1087 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1089 Serializer.serializeSingleRecord(
Record);
1090 serializeObject(Root,
"symbolGraph",
1092 std::move(Serializer.MainModule)));
1095 serializeArray(Root,
"parentContexts",
1096 generateParentContexts(Serializer.Hierarchy, Lang));
1098 Array RelatedSymbols;
1100 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1102 if (Fragment.PreciseIdentifier.empty())
1111 Object RelatedSymbol;
1112 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1113 RelatedSymbol[
"declarationLanguage"] = getLanguageName(Lang);
1119 serializeArray(RelatedSymbol,
"parentContexts",
1120 generateParentContexts(
1121 generateHierarchyFromRecord(RelatedRecord), Lang));
1123 RelatedSymbols.push_back(std::move(RelatedSymbol));
1126 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.
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.
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.