Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-tools-extra][ExtractAPI] create clang-symbolgraph-merger #65894

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
[clang-tools-extra][ExtractAPI] create clang-symbolgraph-merger
Create a clang tool to merge all the JSON symbolgraph emited by --emit-symbol-graph or -extract-api options into one unified JSON symbolgraph file.

Differential Revision: https://reviews.llvm.org/D158646
  • Loading branch information
Arsenic-ATG committed Sep 10, 2023
commit a24e832827a376d803c03405eff474fa996d8228
1 change: 1 addition & 0 deletions clang-tools-extra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if(CLANG_INCLUDE_TESTS)
endif()
endif()

add_subdirectory(clang-symbolgraph-merger)
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-symbolgraph-merger/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_directories(include)
add_subdirectory(lib)
add_subdirectory(tool)
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef SYMBOLGRAPH_H
#define SYMBOLGRAPH_H

#include "clang/Basic/LangStandard.h"
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/AvailabilityInfo.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include <memory>
#include <vector>

namespace sgmerger {

// see https://github.com/apple/swift-docc-symbolkit/bdob/main/openapi.yaml
struct SymbolGraph {

struct Symbol {
Symbol(const llvm::json::Object &SymbolObj);

llvm::json::Object SymbolObj;
std::string AccessLevel;
clang::extractapi::APIRecord::RecordKind Kind;
clang::extractapi::DeclarationFragments DeclFragments;
clang::extractapi::FunctionSignature FunctionSign;
std::string Name;
std::string USR;
clang::extractapi::AvailabilitySet Availabilities;
clang::extractapi::DocComment Comments;
clang::extractapi::RecordLocation Location;
clang::extractapi::DeclarationFragments SubHeadings;

// underlying type in case of Typedef
clang::extractapi::SymbolReference UnderLyingType;
};

SymbolGraph(const llvm::StringRef JSON);
llvm::json::Object SymbolGraphObject;
llvm::json::Object Metadata;
llvm::json::Object Module;
std::vector<Symbol> Symbols;
llvm::json::Array Relationships;
};

} // namespace sgmerger

#endif /* SYMBOLGRAPH_H */
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef SYMBOLGRAPHMERGER_H
#define SYMBOLGRAPHMERGER_H

#include "clang-symbolgraph-merger/SymbolGraph.h"
#include "clang-symbolgraph-merger/SymbolGraphVisitor.h"
#include "clang/Basic/LangStandard.h"
#include "clang/ExtractAPI/API.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TargetParser/Triple.h"
#include <memory>

namespace sgmerger {

using SymbolMap = llvm::DenseMap<llvm::StringRef, const SymbolGraph::Symbol *>;

class SymbolGraphMerger : public SymbolGraphVisitor<SymbolGraphMerger> {
public:
SymbolGraphMerger(const clang::SmallVector<SymbolGraph> &SymbolGraphs,
const std::string &ProductName = "")
: ProductName(ProductName), Lang(clang::Language::Unknown),
SymbolGraphs(SymbolGraphs) {}
bool merge();
bool visitMetadata(const llvm::json::Object &Metadata);
bool visitModule(const llvm::json::Object &Module);
bool visitSymbol(const SymbolGraph::Symbol &Symbol);
bool visitRelationship(const llvm::json::Object &Relationship);

private:
std::string Generator;

// stuff required to construct the APISet
std::string ProductName;
llvm::Triple Target;
clang::Language Lang;

SymbolMap PendingSymbols;
SymbolMap VisitedSymbols;

const clang::SmallVector<SymbolGraph> &SymbolGraphs;
};

} // namespace sgmerger

#endif /* SYMBOLGRAPHMERGER_H */
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#ifndef SYMBOLGRAPHVISITOR_H
#define SYMBOLGRAPHVISITOR_H

#include "clang-symbolgraph-merger/SymbolGraph.h"
#include "clang/ExtractAPI/API.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include <memory>

namespace sgmerger {

// Visits a symbol graph obbect and record the extracted info to API
template <typename Derived> class SymbolGraphVisitor {
public:
bool traverseSymbolGraph(const SymbolGraph &SG) {
bool Success = true;
Success = (getDerived()->visitMetadata(SG.Metadata) &&
getDerived()->visitModule(SG.Module) &&
getDerived()->traverseSymbols(SG.Symbols) &&
getDerived()->traverseRelationships(SG.Relationships));

return Success;
}

bool traverseSymbols(const std::vector<SymbolGraph::Symbol> &Symbols) {
bool Success = true;
for (const auto &Symbol : Symbols)
Success = getDerived()->visitSymbol(Symbol);
return Success;
}

bool traverseRelationships(const llvm::json::Array &Relationships) {
bool Success = true;
for (const auto &RelValue : Relationships) {
if (const auto *RelObj = RelValue.getAsObject())
Success = getDerived()->visitRelationship(*RelObj);
}
return Success;
}

bool visitMetadata(const llvm::json::Object &Metadata);
bool visitModule(const llvm::json::Object &Module);
bool visitSymbol(const SymbolGraph::Symbol &Symbol);
bool visitRelationship(const llvm::json::Object &Relationship);

std::unique_ptr<clang::extractapi::APISet> getAPISet() {
return std::move(API);
}

protected:
std::unique_ptr<clang::extractapi::APISet> API;

public:
SymbolGraphVisitor(const SymbolGraphVisitor &) = delete;
SymbolGraphVisitor(SymbolGraphVisitor &&) = delete;
SymbolGraphVisitor &operator=(const SymbolGraphVisitor &) = delete;
SymbolGraphVisitor &operator=(SymbolGraphVisitor &&) = delete;

protected:
SymbolGraphVisitor() : API(nullptr) {}
~SymbolGraphVisitor() = default;

Derived *getDerived() { return static_cast<Derived *>(this); };
};

} // namespace sgmerger

#endif /* SYMBOLGRAPHVISITOR_H */
14 changes: 14 additions & 0 deletions clang-tools-extra/clang-symbolgraph-merger/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set(LLVM_LINK_COMPONENTS Support)

add_clang_library(clangSymbolGraphMerger
SymbolGraphMerger.cpp
SymbolGraph.cpp
)

clang_target_link_libraries(clangSymbolGraphMerger
PRIVATE
clangBasic
clangToolingCore
clangToolingInclusions
clangExtractAPI
)
Loading