Viewing file: SymbolGraphSerializer.h (11.1 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- ExtractAPI/Serialization/SymbolGraphSerializer.h ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the SymbolGraphSerializer class. /// /// Implement an APISetVisitor to serialize the APISet into the Symbol Graph /// format for ExtractAPI. See https://github.com/apple/swift-docc-symbolkit. /// //===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
#include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/APIIgnoresList.h" #include "clang/ExtractAPI/Serialization/APISetVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <optional>
namespace clang { namespace extractapi {
using namespace llvm::json;
/// Common options to customize the visitor output. struct SymbolGraphSerializerOption { /// Do not include unnecessary whitespaces to save space. bool Compact = true; bool EmitSymbolLabelsForTesting = false; };
/// A representation of the contents of a given module symbol graph struct ExtendedModule { ExtendedModule() = default; ExtendedModule(ExtendedModule &&EM) = default; ExtendedModule &operator=(ExtendedModule &&EM) = default; // Copies are expensive so disable them. ExtendedModule(const ExtendedModule &EM) = delete; ExtendedModule &operator=(const ExtendedModule &EM) = delete;
/// Add a symbol to the module, do not store the resulting pointer or use it /// across insertions. Object *addSymbol(Object &&Symbol);
void addRelationship(Object &&Relationship);
/// A JSON array of formatted symbols from an \c APISet. Array Symbols;
/// A JSON array of formatted symbol relationships from an \c APISet. Array Relationships; };
/// The visitor that organizes API information in the Symbol Graph format. /// /// The Symbol Graph format (https://github.com/apple/swift-docc-symbolkit) /// models an API set as a directed graph, where nodes are symbol declarations, /// and edges are relationships between the connected symbols. class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> { private: using Base = APISetVisitor<SymbolGraphSerializer>; /// The main symbol graph that contains symbols that are either top-level or a /// are related to symbols defined in this product/module. ExtendedModule MainModule;
/// Additional symbol graphs that contain symbols that are related to symbols /// defined in another product/module. The key of this map is the module name /// of the extended module. llvm::StringMap<ExtendedModule> ExtendedModules;
/// The Symbol Graph format version used by this serializer. static const VersionTuple FormatVersion;
/// Indicates whether to take into account the extended module. This is only /// useful for \c serializeSingleSymbolSGF. bool ForceEmitToMainModule;
// Stores the references required to construct path components for the // currently visited APIRecord. llvm::SmallVector<SymbolReference, 8> Hierarchy;
/// The list of symbols to ignore. /// /// Note: This should be consulted before emitting a symbol. const APIIgnoresList &IgnoresList;
const bool EmitSymbolLabelsForTesting = false;
const bool SkipSymbolsInCategoriesToExternalTypes = false;
/// The object instantiated by the last call to serializeAPIRecord. Object *CurrentSymbol = nullptr;
/// The module to which \p CurrentSymbol belongs too. ExtendedModule *ModuleForCurrentSymbol = nullptr;
public: static void serializeMainSymbolGraph(raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList, SymbolGraphSerializerOption Options = {});
static void serializeWithExtensionGraphs( raw_ostream &MainOutput, const APISet &API, const APIIgnoresList &IgnoresList, llvm::function_ref< std::unique_ptr<llvm::raw_pwrite_stream>(llvm::Twine BaseFileName)> CreateOutputStream, SymbolGraphSerializerOption Options = {});
/// Serialize a single symbol SGF. This is primarily used for libclang. /// /// \returns an optional JSON Object representing the payload that libclang /// expects for providing symbol information for a single symbol. If this is /// not a known symbol returns \c std::nullopt. static std::optional<Object> serializeSingleSymbolSGF(StringRef USR, const APISet &API);
private: /// The kind of a relationship between two symbols. enum RelationshipKind { /// The source symbol is a member of the target symbol. /// For example enum constants are members of the enum, class/instance /// methods are members of the class, etc. MemberOf,
/// The source symbol is inherited from the target symbol. InheritsFrom,
/// The source symbol conforms to the target symbol. /// For example Objective-C protocol conformances. ConformsTo,
/// The source symbol is an extension to the target symbol. /// For example Objective-C categories extending an external type. ExtensionTo, };
/// Serialize a single record. void serializeSingleRecord(const APIRecord *Record);
/// Get the string representation of the relationship kind. static StringRef getRelationshipString(RelationshipKind Kind);
void serializeRelationship(RelationshipKind Kind, const SymbolReference &Source, const SymbolReference &Target, ExtendedModule &Into);
enum ConstraintKind { Conformance, ConditionalConformance };
static StringRef getConstraintString(ConstraintKind Kind);
/// Serialize the APIs in \c ExtendedModule. /// /// \returns a JSON object that contains the root of the formatted /// Symbol Graph. Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM);
/// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and /// write them to the provide stream. void serializeGraphToStream(raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName, ExtendedModule &&EM);
/// Synthesize the metadata section of the Symbol Graph format. /// /// The metadata section describes information about the Symbol Graph itself, /// including the format version and the generator information. Object serializeMetadata() const;
/// Synthesize the module section of the Symbol Graph format. /// /// The module section contains information about the product that is defined /// by the given API set. /// Note that "module" here is not to be confused with the Clang/C++ module /// concept. Object serializeModuleObject(StringRef ModuleName) const;
Array serializePathComponents(const APIRecord *Record) const;
/// Determine if the given \p Record should be skipped during serialization. bool shouldSkip(const APIRecord *Record) const;
ExtendedModule &getModuleForCurrentSymbol();
/// Format the common API information for \p Record. /// /// This handles the shared information of all kinds of API records, /// for example identifier, source location and path components. The resulting /// object is then augmented with kind-specific symbol information in /// subsequent visit* methods by accessing the \p State member variable. This /// method also checks if the given \p Record should be skipped during /// serialization. This should be called only once per concrete APIRecord /// instance and the first visit* method to be called is responsible for /// calling this. This is normally visitAPIRecord unless a walkUpFromFoo /// method is implemented along the inheritance hierarchy in which case the /// visitFoo method needs to call this. /// /// \returns \c nullptr if this \p Record should be skipped, or a pointer to /// JSON object containing common symbol information of \p Record. Do not /// store the returned pointer only use it to augment the object with record /// specific information as it directly points to the object in the /// \p ExtendedModule, the pointer won't be valid as soon as another object is /// inserted into the module. void serializeAPIRecord(const APIRecord *Record);
public: // Handle if records should be skipped at this level of the traversal to // ensure that children of skipped records aren't serialized. bool traverseAPIRecord(const APIRecord *Record);
bool visitAPIRecord(const APIRecord *Record);
/// Visit a global function record. bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record);
bool visitCXXClassRecord(const CXXClassRecord *Record);
bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
bool visitClassTemplatePartialSpecializationRecord( const ClassTemplatePartialSpecializationRecord *Record);
bool visitCXXMethodRecord(const CXXMethodRecord *Record);
bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
bool visitConceptRecord(const ConceptRecord *Record);
bool visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
bool visitGlobalVariableTemplatePartialSpecializationRecord( const GlobalVariableTemplatePartialSpecializationRecord *Record);
bool visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record); bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record); bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
bool visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
bool walkUpFromTypedefRecord(const TypedefRecord *Record); bool visitTypedefRecord(const TypedefRecord *Record);
SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, bool EmitSymbolLabelsForTesting = false, bool ForceEmitToMainModule = false, bool SkipSymbolsInCategoriesToExternalTypes = false) : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), IgnoresList(IgnoresList), EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting), SkipSymbolsInCategoriesToExternalTypes( SkipSymbolsInCategoriesToExternalTypes) {} };
} // namespace extractapi } // namespace clang
#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
|