Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:53

0001 //===- ExtractAPI/Serialization/SymbolGraphSerializer.h ---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the SymbolGraphSerializer class.
0011 ///
0012 /// Implement an APISetVisitor to serialize the APISet into the Symbol Graph
0013 /// format for ExtractAPI. See https://github.com/apple/swift-docc-symbolkit.
0014 ///
0015 //===----------------------------------------------------------------------===//
0016 
0017 #ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
0018 #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
0019 
0020 #include "clang/ExtractAPI/API.h"
0021 #include "clang/ExtractAPI/APIIgnoresList.h"
0022 #include "clang/ExtractAPI/Serialization/APISetVisitor.h"
0023 #include "llvm/ADT/DenseMap.h"
0024 #include "llvm/ADT/SmallString.h"
0025 #include "llvm/ADT/SmallVector.h"
0026 #include "llvm/ADT/StringMap.h"
0027 #include "llvm/ADT/StringRef.h"
0028 #include "llvm/ADT/StringSet.h"
0029 #include "llvm/ADT/Twine.h"
0030 #include "llvm/Support/JSON.h"
0031 #include "llvm/Support/VersionTuple.h"
0032 #include "llvm/Support/raw_ostream.h"
0033 #include <optional>
0034 
0035 namespace clang {
0036 namespace extractapi {
0037 
0038 using namespace llvm::json;
0039 
0040 /// Common options to customize the visitor output.
0041 struct SymbolGraphSerializerOption {
0042   /// Do not include unnecessary whitespaces to save space.
0043   bool Compact = true;
0044   bool EmitSymbolLabelsForTesting = false;
0045 };
0046 
0047 /// A representation of the contents of a given module symbol graph
0048 struct ExtendedModule {
0049   ExtendedModule() = default;
0050   ExtendedModule(ExtendedModule &&EM) = default;
0051   ExtendedModule &operator=(ExtendedModule &&EM) = default;
0052   // Copies are expensive so disable them.
0053   ExtendedModule(const ExtendedModule &EM) = delete;
0054   ExtendedModule &operator=(const ExtendedModule &EM) = delete;
0055 
0056   /// Add a symbol to the module, do not store the resulting pointer or use it
0057   /// across insertions.
0058   Object *addSymbol(Object &&Symbol);
0059 
0060   void addRelationship(Object &&Relationship);
0061 
0062   /// A JSON array of formatted symbols from an \c APISet.
0063   Array Symbols;
0064 
0065   /// A JSON array of formatted symbol relationships from an \c APISet.
0066   Array Relationships;
0067 };
0068 
0069 /// The visitor that organizes API information in the Symbol Graph format.
0070 ///
0071 /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit)
0072 /// models an API set as a directed graph, where nodes are symbol declarations,
0073 /// and edges are relationships between the connected symbols.
0074 class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
0075 private:
0076   using Base = APISetVisitor<SymbolGraphSerializer>;
0077   /// The main symbol graph that contains symbols that are either top-level or a
0078   /// are related to symbols defined in this product/module.
0079   ExtendedModule MainModule;
0080 
0081   /// Additional symbol graphs that contain symbols that are related to symbols
0082   /// defined in another product/module. The key of this map is the module name
0083   /// of the extended module.
0084   llvm::StringMap<ExtendedModule> ExtendedModules;
0085 
0086   /// The Symbol Graph format version used by this serializer.
0087   static const VersionTuple FormatVersion;
0088 
0089   /// Indicates whether to take into account the extended module. This is only
0090   /// useful for \c serializeSingleSymbolSGF.
0091   bool ForceEmitToMainModule;
0092 
0093   // Stores the references required to construct path components for the
0094   // currently visited APIRecord.
0095   llvm::SmallVector<SymbolReference, 8> Hierarchy;
0096 
0097   /// The list of symbols to ignore.
0098   ///
0099   /// Note: This should be consulted before emitting a symbol.
0100   const APIIgnoresList &IgnoresList;
0101 
0102   const bool EmitSymbolLabelsForTesting = false;
0103 
0104   const bool SkipSymbolsInCategoriesToExternalTypes = false;
0105 
0106   /// The object instantiated by the last call to serializeAPIRecord.
0107   Object *CurrentSymbol = nullptr;
0108 
0109   /// The module to which \p CurrentSymbol belongs too.
0110   ExtendedModule *ModuleForCurrentSymbol = nullptr;
0111 
0112 public:
0113   static void
0114   serializeMainSymbolGraph(raw_ostream &OS, const APISet &API,
0115                            const APIIgnoresList &IgnoresList,
0116                            SymbolGraphSerializerOption Options = {});
0117 
0118   static void serializeWithExtensionGraphs(
0119       raw_ostream &MainOutput, const APISet &API,
0120       const APIIgnoresList &IgnoresList,
0121       llvm::function_ref<
0122           std::unique_ptr<llvm::raw_pwrite_stream>(llvm::Twine BaseFileName)>
0123           CreateOutputStream,
0124       SymbolGraphSerializerOption Options = {});
0125 
0126   /// Serialize a single symbol SGF. This is primarily used for libclang.
0127   ///
0128   /// \returns an optional JSON Object representing the payload that libclang
0129   /// expects for providing symbol information for a single symbol. If this is
0130   /// not a known symbol returns \c std::nullopt.
0131   static std::optional<Object> serializeSingleSymbolSGF(StringRef USR,
0132                                                         const APISet &API);
0133 
0134 private:
0135   /// The kind of a relationship between two symbols.
0136   enum RelationshipKind {
0137     /// The source symbol is a member of the target symbol.
0138     /// For example enum constants are members of the enum, class/instance
0139     /// methods are members of the class, etc.
0140     MemberOf,
0141 
0142     /// The source symbol is inherited from the target symbol.
0143     InheritsFrom,
0144 
0145     /// The source symbol conforms to the target symbol.
0146     /// For example Objective-C protocol conformances.
0147     ConformsTo,
0148 
0149     /// The source symbol is an extension to the target symbol.
0150     /// For example Objective-C categories extending an external type.
0151     ExtensionTo,
0152   };
0153 
0154   /// Serialize a single record.
0155   void serializeSingleRecord(const APIRecord *Record);
0156 
0157   /// Get the string representation of the relationship kind.
0158   static StringRef getRelationshipString(RelationshipKind Kind);
0159 
0160   void serializeRelationship(RelationshipKind Kind,
0161                              const SymbolReference &Source,
0162                              const SymbolReference &Target,
0163                              ExtendedModule &Into);
0164 
0165   enum ConstraintKind { Conformance, ConditionalConformance };
0166 
0167   static StringRef getConstraintString(ConstraintKind Kind);
0168 
0169   /// Serialize the APIs in \c ExtendedModule.
0170   ///
0171   /// \returns a JSON object that contains the root of the formatted
0172   /// Symbol Graph.
0173   Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM);
0174 
0175   /// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and
0176   /// write them to the provide stream.
0177   void serializeGraphToStream(raw_ostream &OS,
0178                               SymbolGraphSerializerOption Options,
0179                               StringRef ModuleName, ExtendedModule &&EM);
0180 
0181   /// Synthesize the metadata section of the Symbol Graph format.
0182   ///
0183   /// The metadata section describes information about the Symbol Graph itself,
0184   /// including the format version and the generator information.
0185   Object serializeMetadata() const;
0186 
0187   /// Synthesize the module section of the Symbol Graph format.
0188   ///
0189   /// The module section contains information about the product that is defined
0190   /// by the given API set.
0191   /// Note that "module" here is not to be confused with the Clang/C++ module
0192   /// concept.
0193   Object serializeModuleObject(StringRef ModuleName) const;
0194 
0195   Array serializePathComponents(const APIRecord *Record) const;
0196 
0197   /// Determine if the given \p Record should be skipped during serialization.
0198   bool shouldSkip(const APIRecord *Record) const;
0199 
0200   ExtendedModule &getModuleForCurrentSymbol();
0201 
0202   /// Format the common API information for \p Record.
0203   ///
0204   /// This handles the shared information of all kinds of API records,
0205   /// for example identifier, source location and path components. The resulting
0206   /// object is then augmented with kind-specific symbol information in
0207   /// subsequent visit* methods by accessing the \p State member variable. This
0208   /// method also checks if the given \p Record should be skipped during
0209   /// serialization. This should be called only once per concrete APIRecord
0210   /// instance and the first visit* method to be called is responsible for
0211   /// calling this. This is normally visitAPIRecord unless a walkUpFromFoo
0212   /// method is implemented along the inheritance hierarchy in which case the
0213   /// visitFoo method needs to call this.
0214   ///
0215   /// \returns \c nullptr if this \p Record should be skipped, or a pointer to
0216   /// JSON object containing common symbol information of \p Record. Do not
0217   /// store the returned pointer only use it to augment the object with record
0218   /// specific information as it directly points to the object in the
0219   /// \p ExtendedModule, the pointer won't be valid as soon as another object is
0220   /// inserted into the module.
0221   void serializeAPIRecord(const APIRecord *Record);
0222 
0223 public:
0224   // Handle if records should be skipped at this level of the traversal to
0225   // ensure that children of skipped records aren't serialized.
0226   bool traverseAPIRecord(const APIRecord *Record);
0227 
0228   bool visitAPIRecord(const APIRecord *Record);
0229 
0230   /// Visit a global function record.
0231   bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record);
0232 
0233   bool visitCXXClassRecord(const CXXClassRecord *Record);
0234 
0235   bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
0236 
0237   bool visitClassTemplatePartialSpecializationRecord(
0238       const ClassTemplatePartialSpecializationRecord *Record);
0239 
0240   bool visitCXXMethodRecord(const CXXMethodRecord *Record);
0241 
0242   bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
0243 
0244   bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
0245 
0246   bool visitConceptRecord(const ConceptRecord *Record);
0247 
0248   bool
0249   visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
0250 
0251   bool visitGlobalVariableTemplatePartialSpecializationRecord(
0252       const GlobalVariableTemplatePartialSpecializationRecord *Record);
0253 
0254   bool
0255   visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
0256 
0257   bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
0258 
0259   bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
0260 
0261   bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record);
0262   bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record);
0263   bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
0264 
0265   bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
0266 
0267   bool
0268   visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
0269 
0270   bool walkUpFromTypedefRecord(const TypedefRecord *Record);
0271   bool visitTypedefRecord(const TypedefRecord *Record);
0272 
0273   SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList,
0274                         bool EmitSymbolLabelsForTesting = false,
0275                         bool ForceEmitToMainModule = false,
0276                         bool SkipSymbolsInCategoriesToExternalTypes = false)
0277       : Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
0278         IgnoresList(IgnoresList),
0279         EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting),
0280         SkipSymbolsInCategoriesToExternalTypes(
0281             SkipSymbolsInCategoriesToExternalTypes) {}
0282 };
0283 
0284 } // namespace extractapi
0285 } // namespace clang
0286 
0287 #endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H