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"
29 #include <type_traits>
31 using namespace clang;
40 void serializeObject(Object &
Paren, StringRef Key,
41 std::optional<Object> &&Obj) {
43 Paren[Key] = std::move(*Obj);
48 void serializeArray(Object &
Paren, StringRef Key,
49 std::optional<Array> &&Array) {
51 Paren[Key] = std::move(*Array);
56 template <
typename ContainerTy>
57 void serializeArray(Object &
Paren, StringRef Key, ContainerTy &&C) {
77 std::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);
92 Object serializeOperatingSystem(
const Triple &
T) {
94 OS[
"name"] =
T.getOSTypeName(
T.getOS());
95 serializeObject(OS,
"minimumVersion",
96 serializeSemanticVersion(
T.getMinimumSupportedOSVersion()));
104 Object 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) {
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";
204 return "objective-c++";
219 llvm_unreachable(
"Unsupported language kind");
222 llvm_unreachable(
"Unhandled language kind");
253 std::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));
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.KindForDisplay,
Lang);
527 template <
typename RecordTy>
528 void 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));
543 Parameters.emplace_back(std::move(Parameter));
547 Signature[
"parameters"] = std::move(Parameters);
549 serializeObject(
Paren,
"functionSignature", std::move(Signature));
552 template <
typename RecordTy>
553 void 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;
594 Elem[
"kind"] = serializeSymbolKind(
Parent.Record->KindForDisplay,
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();
640 Relationships.emplace_back(std::move(Relationship));
644 const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
646 Object SymbolGraphSerializer::serializeMetadata()
const {
648 serializeObject(Metadata,
"formatVersion",
649 serializeSemanticVersion(FormatVersion));
655 SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName)
const {
657 Module[
"name"] = ModuleName;
658 serializeObject(
Module,
"platform", serializePlatform(API.
getTarget()));
662 bool SymbolGraphSerializer::shouldSkip(
const APIRecord *
Record)
const {
667 if (
Record->Availability.isUnconditionallyUnavailable())
673 if (
auto *Tag = dyn_cast<TagRecord>(
Record)) {
674 if (Tag->IsEmbeddedInVarDeclarator)
680 if (
Record->Name.starts_with(
"_"))
684 if (IgnoresList.shouldIgnore(
Record->Name))
690 ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
691 if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
692 return *ModuleForCurrentSymbol;
697 Array SymbolGraphSerializer::serializePathComponents(
699 return Array(map_range(Hierarchy, [](
auto Elt) {
return Elt.Name; }));
702 StringRef 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");
716 void 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)
738 MainModule.addRelationship(std::move(Relationship));
743 StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind
Kind) {
745 case ConstraintKind::Conformance:
746 return "conformance";
747 case ConstraintKind::ConditionalConformance:
748 return "conditionalConformance";
750 llvm_unreachable(
"Unhandled constraint kind");
753 void 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));
793 auto RetVal = Base::traverseAPIRecord(
Record);
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 if (SkipSymbolsInCategoriesToExternalTypes &&
932 auto *CurrentModule = ModuleForCurrentSymbol;
933 if (
Record->isExtendingExternalModule())
934 ModuleForCurrentSymbol = &ExtendedModules[
Record->Interface.Source];
936 if (!walkUpFromObjCCategoryRecord(
Record))
939 bool RetVal = traverseRecordContext(
Record);
940 ModuleForCurrentSymbol = CurrentModule;
946 return visitObjCCategoryRecord(
Record);
954 for (
const auto &Protocol :
Record->Protocols)
955 serializeRelationship(ConformsTo,
Record->Interface, Protocol,
956 getModuleForCurrentSymbol());
966 serializeFunctionSignatureMixin(*CurrentSymbol, *
Record);
981 return visitTypedefRecord(
Record);
987 bool ShouldDrop =
Record->UnderlyingType.Name.empty();
990 ShouldDrop |= (
Record->UnderlyingType.Name ==
Record->Name);
995 serializeAPIRecord(
Record);
999 (*CurrentSymbol)[
"type"] =
Record->UnderlyingType.USR;
1004 void SymbolGraphSerializer::serializeSingleRecord(
const APIRecord *
Record) {
1005 switch (
Record->getKind()) {
1007 #define CONCRETE_RECORD(CLASS, BASE, KIND) \
1008 case APIRecord::KIND: { \
1009 walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
1018 llvm_unreachable(
"API Record with uninstantiable kind");
1022 Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
1025 serializeObject(Root,
"metadata", serializeMetadata());
1026 serializeObject(Root,
"module", serializeModuleObject(ModuleName));
1028 Root[
"symbols"] = std::move(EM.Symbols);
1029 Root[
"relationships"] = std::move(EM.Relationships);
1034 void SymbolGraphSerializer::serializeGraphToStream(
1037 Object Root = serializeGraph(ModuleName, std::move(EM));
1038 if (Options.Compact)
1039 OS << formatv(
"{0}",
Value(std::move(Root))) <<
"\n";
1041 OS << formatv(
"{0:2}",
Value(std::move(Root))) <<
"\n";
1048 API, IgnoresList, Options.EmitSymbolLabelsForTesting,
1053 Serializer.serializeGraphToStream(OS, Options, API.
ProductName,
1054 std::move(Serializer.MainModule));
1059 raw_ostream &MainOutput,
const APISet &API,
1061 llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
1065 Options.EmitSymbolLabelsForTesting);
1068 Serializer.serializeGraphToStream(MainOutput, Options, API.
ProductName,
1069 std::move(Serializer.MainModule));
1071 for (
auto &ExtensionSGF : Serializer.ExtendedModules) {
1072 if (
auto ExtensionOS =
1073 CreateOutputStream(ExtensionSGF.getKey() +
"@" + API.
ProductName))
1074 Serializer.serializeGraphToStream(*ExtensionOS, Options,
1075 ExtensionSGF.getKey(),
1076 std::move(ExtensionSGF.getValue()));
1080 std::optional<Object>
1094 Serializer.Hierarchy = generateHierarchyFromRecord(
Record);
1096 Serializer.serializeSingleRecord(
Record);
1097 serializeObject(Root,
"symbolGraph",
1099 std::move(Serializer.MainModule)));
1102 serializeArray(Root,
"parentContexts",
1103 generateParentContexts(Serializer.Hierarchy,
Lang));
1105 Array RelatedSymbols;
1107 for (
const auto &Fragment :
Record->Declaration.getFragments()) {
1109 if (Fragment.PreciseIdentifier.empty())
1118 Object RelatedSymbol;
1119 RelatedSymbol[
"usr"] = RelatedRecord->
USR;
1126 serializeArray(RelatedSymbol,
"parentContexts",
1127 generateParentContexts(
1128 generateHierarchyFromRecord(RelatedRecord),
Lang));
1130 RelatedSymbols.push_back(std::move(RelatedSymbol));
1133 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.
@ 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.