[clang] 89f6b26 - [clang][extract-api] Refactor ExtractAPI and improve docs
Zixu Wang via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 22 13:22:07 PDT 2022
Author: Zixu Wang
Date: 2022-03-22T13:21:57-07:00
New Revision: 89f6b26f1beb2c1344f5cfeb34e405128544c76b
URL: https://github.com/llvm/llvm-project/commit/89f6b26f1beb2c1344f5cfeb34e405128544c76b
DIFF: https://github.com/llvm/llvm-project/commit/89f6b26f1beb2c1344f5cfeb34e405128544c76b.diff
LOG: [clang][extract-api] Refactor ExtractAPI and improve docs
- The name SymbolGraph is inappropriate and confusing for the new library
for clang-extract-api. Refactor and rename things to make it clear that
ExtractAPI is the core functionality and SymbolGraph is one serializer
for the API information.
- Add documentation comments to ExtractAPI classes and methods to improve
readability and clearness of the ExtractAPI work.
Differential Revision: https://reviews.llvm.org/D122160
Added:
clang/include/clang/ExtractAPI/API.h
clang/include/clang/ExtractAPI/AvailabilityInfo.h
clang/include/clang/ExtractAPI/DeclarationFragments.h
clang/include/clang/ExtractAPI/FrontendActions.h
clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
clang/lib/ExtractAPI/API.cpp
clang/lib/ExtractAPI/CMakeLists.txt
clang/lib/ExtractAPI/DeclarationFragments.cpp
clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
clang/lib/ExtractAPI/Serialization/SerializerBase.cpp
clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
clang/test/ExtractAPI/global_record.c
Modified:
clang/lib/CMakeLists.txt
clang/lib/FrontendTool/CMakeLists.txt
clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Removed:
clang/include/clang/SymbolGraph/API.h
clang/include/clang/SymbolGraph/AvailabilityInfo.h
clang/include/clang/SymbolGraph/DeclarationFragments.h
clang/include/clang/SymbolGraph/FrontendActions.h
clang/include/clang/SymbolGraph/Serialization.h
clang/lib/SymbolGraph/API.cpp
clang/lib/SymbolGraph/CMakeLists.txt
clang/lib/SymbolGraph/DeclarationFragments.cpp
clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
clang/lib/SymbolGraph/Serialization.cpp
clang/test/SymbolGraph/global_record.c
################################################################################
diff --git a/clang/include/clang/SymbolGraph/API.h b/clang/include/clang/ExtractAPI/API.h
similarity index 57%
rename from clang/include/clang/SymbolGraph/API.h
rename to clang/include/clang/ExtractAPI/API.h
index ffcc03758f4d2..5ba3cf7268d88 100644
--- a/clang/include/clang/SymbolGraph/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -1,4 +1,4 @@
-//===- SymbolGraph/API.h ----------------------------------------*- C++ -*-===//
+//===- ExtractAPI/API.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.
@@ -7,18 +7,22 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines SymbolGraph API records.
+/// This file defines the APIRecord-based structs and the APISet class.
+///
+/// Clang ExtractAPI is a tool to collect API information from a given set of
+/// header files. The structures in this file describe data representations of
+/// the API information collected for various kinds of symbols.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SYMBOLGRAPH_API_H
-#define LLVM_CLANG_SYMBOLGRAPH_API_H
+#ifndef LLVM_CLANG_EXTRACTAPI_API_H
+#define LLVM_CLANG_EXTRACTAPI_API_H
#include "clang/AST/Decl.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/SymbolGraph/AvailabilityInfo.h"
-#include "clang/SymbolGraph/DeclarationFragments.h"
+#include "clang/ExtractAPI/AvailabilityInfo.h"
+#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
@@ -27,18 +31,43 @@
#include <memory>
namespace clang {
-namespace symbolgraph {
+namespace extractapi {
+/// DocComment is a vector of RawComment::CommentLine.
+///
+/// Each line represents one line of striped documentation comment,
+/// with source range information. This simplifies calculating the source
+/// location of a character in the doc comment for pointing back to the source
+/// file.
+/// e.g.
+/// \code
+/// /// This is a documentation comment
+/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' First line.
+/// /// with multiple lines.
+/// ^~~~~~~~~~~~~~~~~~~~~~~' Second line.
+/// \endcode
using DocComment = std::vector<RawComment::CommentLine>;
+/// The base representation of an API record. Holds common symbol information.
struct APIRecord {
StringRef Name;
StringRef USR;
PresumedLoc Location;
AvailabilityInfo Availability;
LinkageInfo Linkage;
+
+ /// Documentation comment lines attached to this symbol declaration.
DocComment Comment;
+
+ /// Declaration fragments of this symbol declaration.
DeclarationFragments Declaration;
+
+ /// SubHeading provides a more detailed representation than the plain
+ /// declaration name.
+ ///
+ /// SubHeading is an array of declaration fragments of tagged declaration
+ /// name, with potentially more tokens (for example the \c +/- symbol for
+ /// Objective-C class/instance methods).
DeclarationFragments SubHeading;
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
@@ -66,14 +95,18 @@ struct APIRecord {
virtual ~APIRecord() = 0;
};
+/// The kind of a global record.
enum class GVKind : uint8_t {
Unknown = 0,
Variable = 1,
Function = 2,
};
+/// This holds information associated with global variables or functions.
struct GlobalRecord : APIRecord {
GVKind GlobalKind;
+
+ /// The function signature of the record if it is a function.
FunctionSignature Signature;
GlobalRecord(GVKind Kind, StringRef Name, StringRef USR, PresumedLoc Loc,
@@ -87,16 +120,20 @@ struct GlobalRecord : APIRecord {
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_Global;
}
+
+private:
+ virtual void anchor();
};
+/// APISet holds the set of API records collected from given inputs.
class APISet {
public:
- APISet(const llvm::Triple &Target, const LangOptions &LangOpts)
- : Target(Target), LangOpts(LangOpts) {}
-
- const llvm::Triple &getTarget() const { return Target; }
- const LangOptions &getLangOpts() const { return LangOpts; }
-
+ /// Create and add a GlobalRecord of kind \p Kind into the API set.
+ ///
+ /// Note: the caller is responsible for keeping the StringRef \p Name and
+ /// \p USR alive. APISet::copyString provides a way to copy strings into
+ /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
+ /// to generate the USR for \c D and keep it alive in APISet.
GlobalRecord *addGlobal(GVKind Kind, StringRef Name, StringRef USR,
PresumedLoc Loc, const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
@@ -104,12 +141,24 @@ class APISet {
DeclarationFragments SubHeading,
FunctionSignature Signature);
+ /// Create and add a global variable record into the API set.
+ ///
+ /// Note: the caller is responsible for keeping the StringRef \p Name and
+ /// \p USR alive. APISet::copyString provides a way to copy strings into
+ /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
+ /// to generate the USR for \c D and keep it alive in APISet.
GlobalRecord *addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
+ /// Create and add a function record into the API set.
+ ///
+ /// Note: the caller is responsible for keeping the StringRef \p Name and
+ /// \p USR alive. APISet::copyString provides a way to copy strings into
+ /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
+ /// to generate the USR for \c D and keep it alive in APISet.
GlobalRecord *addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
@@ -117,10 +166,6 @@ class APISet {
DeclarationFragments SubHeading,
FunctionSignature Signature);
- StringRef recordUSR(const Decl *D);
- StringRef copyString(StringRef String, llvm::BumpPtrAllocator &Allocator);
- StringRef copyString(StringRef String);
-
private:
/// \brief A custom deleter used for ``std::unique_ptr`` to APIRecords stored
/// in the BumpPtrAllocator.
@@ -138,20 +183,45 @@ class APISet {
using APIRecordUniquePtr =
std::unique_ptr<T, UniquePtrBumpPtrAllocatorDeleter<T>>;
+ /// A map to store the set of GlobalRecord%s with the declaration name as the
+ /// key.
using GlobalRecordMap =
llvm::MapVector<StringRef, APIRecordUniquePtr<GlobalRecord>>;
+ /// Get the target triple for the ExtractAPI invocation.
+ const llvm::Triple &getTarget() const { return Target; }
+
+ /// Get the language options used to parse the APIs.
+ const LangOptions &getLangOpts() const { return LangOpts; }
+
const GlobalRecordMap &getGlobals() const { return Globals; }
+ /// Generate and store the USR of declaration \p D.
+ ///
+ /// Note: The USR string is stored in and owned by Allocator.
+ ///
+ /// \returns a StringRef of the generated USR string.
+ StringRef recordUSR(const Decl *D);
+
+ /// Copy \p String into the Allocator in this APISet.
+ ///
+ /// \returns a StringRef of the copied string in APISet::Allocator.
+ StringRef copyString(StringRef String);
+
+ APISet(const llvm::Triple &Target, const LangOptions &LangOpts)
+ : Target(Target), LangOpts(LangOpts) {}
+
private:
+ /// BumpPtrAllocator to store APIRecord%s and generated/copied strings.
llvm::BumpPtrAllocator Allocator;
+
const llvm::Triple Target;
const LangOptions LangOpts;
GlobalRecordMap Globals;
};
-} // namespace symbolgraph
+} // namespace extractapi
} // namespace clang
-#endif // LLVM_CLANG_SYMBOLGRAPH_API_H
+#endif // LLVM_CLANG_EXTRACTAPI_API_H
diff --git a/clang/include/clang/SymbolGraph/AvailabilityInfo.h b/clang/include/clang/ExtractAPI/AvailabilityInfo.h
similarity index 70%
rename from clang/include/clang/SymbolGraph/AvailabilityInfo.h
rename to clang/include/clang/ExtractAPI/AvailabilityInfo.h
index 5a5e4253b11d5..f5f85bd576120 100644
--- a/clang/include/clang/SymbolGraph/AvailabilityInfo.h
+++ b/clang/include/clang/ExtractAPI/AvailabilityInfo.h
@@ -1,4 +1,4 @@
-//===- SymbolGraph/AvailabilityInfo.h - Availability Info -------*- C++ -*-===//
+//===- ExtractAPI/AvailabilityInfo.h - Availability Info --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,12 +7,13 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the Availability Info for a declaration.
+/// This file defines the AvailabilityInfo struct that collects availability
+/// attributes of a symbol.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SYMBOLGRAPH_AVAILABILITY_INFO_H
-#define LLVM_CLANG_SYMBOLGRAPH_AVAILABILITY_INFO_H
+#ifndef LLVM_CLANG_EXTRACTAPI_AVAILABILITY_INFO_H
+#define LLVM_CLANG_EXTRACTAPI_AVAILABILITY_INFO_H
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
@@ -21,8 +22,9 @@
using llvm::VersionTuple;
namespace clang {
-namespace symbolgraph {
+namespace extractapi {
+/// Stores availability attributes of a symbol.
struct AvailabilityInfo {
VersionTuple Introduced;
VersionTuple Deprecated;
@@ -31,21 +33,31 @@ struct AvailabilityInfo {
bool UnconditionallyDeprecated{false};
bool UnconditionallyUnavailable{false};
- explicit AvailabilityInfo(bool Unavailable = false)
- : Unavailable(Unavailable) {}
-
- AvailabilityInfo(VersionTuple I, VersionTuple D, VersionTuple O, bool U,
- bool UD, bool UU)
- : Introduced(I), Deprecated(D), Obsoleted(O), Unavailable(U),
- UnconditionallyDeprecated(UD), UnconditionallyUnavailable(UU) {}
-
+ /// Determine if this AvailabilityInfo represents the default availability.
bool isDefault() const { return *this == AvailabilityInfo(); }
+
+ /// Check if the symbol is unavailable.
bool isUnavailable() const { return Unavailable; }
+
+ /// Check if the symbol is unconditionally deprecated.
+ ///
+ /// i.e. \code __attribute__((deprecated)) \endcode
bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; }
+
+ /// Check if the symbol is unconditionally unavailable.
+ ///
+ /// i.e. \code __attribute__((unavailable)) \endcode
bool isUnconditionallyUnavailable() const {
return UnconditionallyUnavailable;
}
+ AvailabilityInfo() = default;
+
+ AvailabilityInfo(VersionTuple I, VersionTuple D, VersionTuple O, bool U,
+ bool UD, bool UU)
+ : Introduced(I), Deprecated(D), Obsoleted(O), Unavailable(U),
+ UnconditionallyDeprecated(UD), UnconditionallyUnavailable(UU) {}
+
friend bool operator==(const AvailabilityInfo &Lhs,
const AvailabilityInfo &Rhs);
};
@@ -60,7 +72,7 @@ inline bool operator==(const AvailabilityInfo &Lhs,
Rhs.UnconditionallyUnavailable);
}
-} // namespace symbolgraph
+} // namespace extractapi
} // namespace clang
-#endif // LLVM_CLANG_SYMBOLGRAPH_AVAILABILITY_INFO_H
+#endif // LLVM_CLANG_EXTRACTAPI_AVAILABILITY_INFO_H
diff --git a/clang/include/clang/SymbolGraph/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
similarity index 53%
rename from clang/include/clang/SymbolGraph/DeclarationFragments.h
rename to clang/include/clang/ExtractAPI/DeclarationFragments.h
index a1cd7b52b25b1..17375efd12c77 100644
--- a/clang/include/clang/SymbolGraph/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -1,4 +1,4 @@
-//===- SymbolGraph/DeclarationFragments.h -----------------------*- C++ -*-===//
+//===- ExtractAPI/DeclarationFragments.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.
@@ -7,12 +7,16 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines SymbolGraph Declaration Fragments related classes.
+/// This file defines the Declaration Fragments related classes.
+///
+/// Declaration Fragments represent parts of a symbol declaration tagged with
+/// syntactic/semantic information.
+/// See https://github.com/apple/swift-docc-symbolkit
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SYMBOLGRAPH_DECLARATION_FRAGMENTS_H
-#define LLVM_CLANG_SYMBOLGRAPH_DECLARATION_FRAGMENTS_H
+#ifndef LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
+#define LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -21,29 +25,64 @@
#include <vector>
namespace clang {
-namespace symbolgraph {
+namespace extractapi {
+/// DeclarationFragments is a vector of tagged important parts of a symbol's
+/// declaration.
+///
+/// The fragments sequence can be joined to form spans of declaration text, with
+/// attached information useful for purposes like syntax-highlighting etc.
+/// For example:
+/// \code
+/// const -> keyword "const"
+/// int -> type "int"
+/// pi; -> identifier "pi"
+/// \endcode
class DeclarationFragments {
public:
DeclarationFragments() = default;
+ /// The kind of a fragment.
enum class FragmentKind {
+ /// Unknown fragment kind.
None,
+
Keyword,
Attribute,
NumberLiteral,
StringLiteral,
Identifier,
+
+ /// Identifier that refers to a type in the context.
TypeIdentifier,
+
+ /// Parameter that's used as generics in the context. For example template
+ /// parameters.
GenericParameter,
+
+ /// External parameters in Objective-C methods.
+ /// For example, \c forKey in
+ /// \code{.m}
+ /// - (void) setValue:(Value)value forKey(Key)key
+ /// \endcode
ExternalParam,
+
+ /// Internal/local parameters in Objective-C methods.
+ /// For example, \c key in
+ /// \code{.m}
+ /// - (void) setValue:(Value)value forKey(Key)key
+ /// \endcode
InternalParam,
+
Text,
};
+ /// Fragment holds information of a single fragment.
struct Fragment {
std::string Spelling;
FragmentKind Kind;
+
+ /// The USR of the fragment symbol, if applicable.
std::string PreciseIdentifier;
Fragment(StringRef Spelling, FragmentKind Kind, StringRef PreciseIdentifier)
@@ -53,10 +92,16 @@ class DeclarationFragments {
const std::vector<Fragment> &getFragments() const { return Fragments; }
+ /// Append a new Fragment to the end of the Fragments.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// appending to chain up consecutive appends.
DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
StringRef PreciseIdentifier = "") {
if (Kind == FragmentKind::Text && !Fragments.empty() &&
Fragments.back().Kind == FragmentKind::Text) {
+ // If appending a text fragment, and the last fragment is also text,
+ // merge into the last fragment.
Fragments.back().Spelling.append(Spelling.data(), Spelling.size());
} else {
Fragments.emplace_back(Spelling, Kind, PreciseIdentifier);
@@ -64,6 +109,13 @@ class DeclarationFragments {
return *this;
}
+ /// Append another DeclarationFragments to the end.
+ ///
+ /// Note: \p Other is moved from and cannot be used after a call to this
+ /// method.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// appending to chain up consecutive appends.
DeclarationFragments &append(DeclarationFragments &&Other) {
Fragments.insert(Fragments.end(),
std::make_move_iterator(Other.Fragments.begin()),
@@ -72,19 +124,29 @@ class DeclarationFragments {
return *this;
}
+ /// Append a text Fragment of a space character.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// appending to chain up consecutive appends.
DeclarationFragments &appendSpace();
+ /// Get the string description of a FragmentKind \p Kind.
static StringRef getFragmentKindString(FragmentKind Kind);
+
+ /// Get the corresponding FragmentKind from string \p S.
static FragmentKind parseFragmentKindFromString(StringRef S);
private:
std::vector<Fragment> Fragments;
};
+/// Store function signature information with DeclarationFragments of the
+/// return type and parameters.
class FunctionSignature {
public:
FunctionSignature() = default;
+ /// Parameter holds the name and DeclarationFragments of a single parameter.
struct Parameter {
std::string Name;
DeclarationFragments Fragments;
@@ -104,6 +166,10 @@ class FunctionSignature {
void setReturnType(DeclarationFragments RT) { ReturnType = RT; }
+ /// Determine if the FunctionSignature is empty.
+ ///
+ /// \returns true if the return type DeclarationFragments is empty and there
+ /// is no parameter, otherwise false.
bool empty() const {
return Parameters.empty() && ReturnType.getFragments().empty();
}
@@ -113,28 +179,46 @@ class FunctionSignature {
DeclarationFragments ReturnType;
};
+/// A factory class to build DeclarationFragments for
diff erent kinds of Decl.
class DeclarationFragmentsBuilder {
public:
+ /// Build DeclarationFragments for a variable declaration VarDecl.
static DeclarationFragments getFragmentsForVar(const VarDecl *);
+
+ /// Build DeclarationFragments for a function declaration FunctionDecl.
static DeclarationFragments getFragmentsForFunction(const FunctionDecl *);
+
+ /// Build sub-heading fragments for a NamedDecl.
static DeclarationFragments getSubHeading(const NamedDecl *);
+
+ /// Build FunctionSignature for a function declaration FunctionDecl.
static FunctionSignature getFunctionSignature(const FunctionDecl *);
private:
DeclarationFragmentsBuilder() = delete;
+ /// Build DeclarationFragments for a QualType.
static DeclarationFragments getFragmentsForType(const QualType, ASTContext &,
DeclarationFragments &);
+
+ /// Build DeclarationFragments for a Type.
static DeclarationFragments getFragmentsForType(const Type *, ASTContext &,
DeclarationFragments &);
+
+ /// Build DeclarationFragments for a NestedNameSpecifier.
static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *,
ASTContext &,
DeclarationFragments &);
+
+ /// Build DeclarationFragments for Qualifiers.
static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals);
+
+ /// Build DeclarationFragments for a parameter variable declaration
+ /// ParmVarDecl.
static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
};
-} // namespace symbolgraph
+} // namespace extractapi
} // namespace clang
-#endif // LLVM_CLANG_SYMBOLGRAPH_DECLARATION_FRAGMENTS_H
+#endif // LLVM_CLANG_EXTRACTAPI_DECLARATION_FRAGMENTS_H
diff --git a/clang/include/clang/SymbolGraph/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h
similarity index 68%
rename from clang/include/clang/SymbolGraph/FrontendActions.h
rename to clang/include/clang/ExtractAPI/FrontendActions.h
index 47e973b39f554..e43b6cf9212d6 100644
--- a/clang/include/clang/SymbolGraph/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -1,4 +1,4 @@
-//===- SymbolGraph/FrontendActions.h -----------------------*- C++ -*-===//
+//===- ExtractAPI/FrontendActions.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.
@@ -7,17 +7,18 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines SymbolGraph frontend actions.
+/// This file defines the ExtractAPIAction frontend action.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SYMBOLGRAPH_FRONTEND_ACTIONS_H
-#define LLVM_CLANG_SYMBOLGRAPH_FRONTEND_ACTIONS_H
+#ifndef LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H
+#define LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H
#include "clang/Frontend/FrontendAction.h"
namespace clang {
+/// ExtractAPIAction sets up the output file and creates the ExtractAPIVisitor.
class ExtractAPIAction : public ASTFrontendAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
@@ -30,4 +31,4 @@ class ExtractAPIAction : public ASTFrontendAction {
} // namespace clang
-#endif // LLVM_CLANG_SYMBOLGRAPH_FRONTEND_ACTIONS_H
+#endif // LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H
diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
new file mode 100644
index 0000000000000..cec35987813f9
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
@@ -0,0 +1,56 @@
+//===- ExtractAPI/Serialization/SerializerBase.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 ExtractAPI APISerializer interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+
+#include "clang/ExtractAPI/API.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace extractapi {
+
+/// Common options to customize the serializer output.
+struct APISerializerOption {
+ /// Do not include unnecessary whitespaces to save space.
+ bool Compact;
+};
+
+/// The base interface of serializers for API information.
+class APISerializer {
+public:
+ /// Serialize the API information to \p os.
+ virtual void serialize(raw_ostream &os) = 0;
+
+protected:
+ const APISet &API;
+ APISerializerOption Options;
+
+public:
+ APISerializer() = delete;
+ APISerializer(const APISerializer &) = delete;
+ APISerializer(APISerializer &&) = delete;
+ APISerializer &operator=(const APISerializer &) = delete;
+ APISerializer &operator=(APISerializer &&) = delete;
+
+protected:
+ APISerializer(const APISet &API, APISerializerOption Options = {})
+ : API(API), Options(Options) {}
+
+ virtual ~APISerializer() = default;
+};
+
+} // namespace extractapi
+} // namespace clang
+
+#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
new file mode 100644
index 0000000000000..8fe5a34e5113d
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -0,0 +1,100 @@
+//===- 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 APISerializer for 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/Serialization/SerializerBase.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace extractapi {
+
+using namespace llvm::json;
+
+/// The serializer 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 APISerializer {
+ virtual void anchor();
+
+ /// A JSON array of formatted symbols in \c APISet.
+ Array Symbols;
+
+ /// A JSON array of formatted symbol relationships in \c APISet.
+ Array Relationships;
+
+ /// The Symbol Graph format version used by this serializer.
+ static const VersionTuple FormatVersion;
+
+public:
+ /// Serialize the APIs in \c APISet in the Symbol Graph format.
+ ///
+ /// \returns a JSON object that contains the root of the formatted
+ /// Symbol Graph.
+ Object serialize();
+
+ /// Implement the APISerializer::serialize interface. Wrap serialize(void) and
+ /// write out the serialized JSON object to \p os.
+ void serialize(raw_ostream &os) override;
+
+private:
+ /// 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 serializeModule() const;
+
+ /// Determine if the given \p Record should be skipped during serialization.
+ bool shouldSkip(const APIRecord &Record) const;
+
+ /// Format the common API information for \p Record.
+ ///
+ /// This handles the shared information of all kinds of API records,
+ /// for example identifier and source location. The resulting object is then
+ /// augmented with kind-specific symbol information by the caller.
+ /// This method also checks if the given \p Record should be skipped during
+ /// serialization.
+ ///
+ /// \returns \c None if this \p Record should be skipped, or a JSON object
+ /// containing common symbol information of \p Record.
+ Optional<Object> serializeAPIRecord(const APIRecord &Record) const;
+
+ /// Serialize a global record.
+ void serializeGlobalRecord(const GlobalRecord &Record);
+
+public:
+ SymbolGraphSerializer(const APISet &API, APISerializerOption Options = {})
+ : APISerializer(API, Options) {}
+};
+
+} // namespace extractapi
+} // namespace clang
+
+#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
diff --git a/clang/include/clang/SymbolGraph/Serialization.h b/clang/include/clang/SymbolGraph/Serialization.h
deleted file mode 100644
index 6452f6e93750b..0000000000000
--- a/clang/include/clang/SymbolGraph/Serialization.h
+++ /dev/null
@@ -1,58 +0,0 @@
-//===- SymbolGraph/Serialization.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
-/// \brief Defines the SymbolGraph serializer and parser.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SYMBOLGRAPH_SERIALIZATION_H
-#define LLVM_CLANG_SYMBOLGRAPH_SERIALIZATION_H
-
-#include "clang/SymbolGraph/API.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/VersionTuple.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang {
-namespace symbolgraph {
-
-using namespace llvm::json;
-
-struct SerializerOption {
- bool Compact;
-};
-
-class Serializer {
-public:
- Serializer(const APISet &API, SerializerOption Options = {})
- : API(API), Options(Options) {}
-
- Object serialize();
- void serialize(raw_ostream &os);
-
-private:
- Object serializeMetadata() const;
- Object serializeModule() const;
- Optional<Object> serializeAPIRecord(const APIRecord &Record) const;
- void serializeGlobalRecord(const GlobalRecord &Record);
-
- bool shouldSkip(const APIRecord &Record) const;
-
- const APISet &API;
- SerializerOption Options;
- Array Symbols;
- Array Relationships;
-
- static const VersionTuple FormatVersion;
-};
-
-} // namespace symbolgraph
-} // namespace clang
-
-#endif // LLVM_CLANG_SYMBOLGRAPH_SERIALIZATION_H
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index 6bee9a881ea66..cc98efcf433a3 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -10,6 +10,7 @@ add_subdirectory(Sema)
add_subdirectory(CodeGen)
add_subdirectory(Analysis)
add_subdirectory(Edit)
+add_subdirectory(ExtractAPI)
add_subdirectory(Rewrite)
if(CLANG_ENABLE_ARCMT)
add_subdirectory(ARCMigrate)
@@ -23,7 +24,6 @@ add_subdirectory(DirectoryWatcher)
add_subdirectory(Index)
add_subdirectory(IndexSerialization)
add_subdirectory(StaticAnalyzer)
-add_subdirectory(SymbolGraph)
add_subdirectory(Format)
add_subdirectory(Testing)
add_subdirectory(Interpreter)
diff --git a/clang/lib/SymbolGraph/API.cpp b/clang/lib/ExtractAPI/API.cpp
similarity index 87%
rename from clang/lib/SymbolGraph/API.cpp
rename to clang/lib/ExtractAPI/API.cpp
index 69e7469425c98..45eef3d1e9529 100644
--- a/clang/lib/SymbolGraph/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -1,4 +1,4 @@
-//===- SymbolGraph/API.cpp --------------------------------------*- C++ -*-===//
+//===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,21 +7,20 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines SymbolGraph API records.
+/// This file implements the APIRecord and derived record structs,
+/// and the APISet class.
///
//===----------------------------------------------------------------------===//
-#include "clang/SymbolGraph/API.h"
+#include "clang/ExtractAPI/API.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentLexer.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/Support/Allocator.h"
-namespace clang {
-namespace symbolgraph {
-
-APIRecord::~APIRecord() {}
+using namespace clang::extractapi;
+using namespace llvm;
GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
PresumedLoc Loc,
@@ -32,6 +31,7 @@ GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
FunctionSignature Signature) {
auto Result = Globals.insert({Name, nullptr});
if (Result.second) {
+ // Create the record if it does not already exist.
auto Record = APIRecordUniquePtr<GlobalRecord>(new (Allocator) GlobalRecord{
Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments,
SubHeading, Signature});
@@ -65,11 +65,11 @@ StringRef APISet::recordUSR(const Decl *D) {
return copyString(USR);
}
-StringRef APISet::copyString(StringRef String,
- llvm::BumpPtrAllocator &Allocator) {
+StringRef APISet::copyString(StringRef String) {
if (String.empty())
return {};
+ // No need to allocate memory and copy if the string has already been stored.
if (Allocator.identifyObject(String.data()))
return String;
@@ -78,9 +78,6 @@ StringRef APISet::copyString(StringRef String,
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}
-StringRef APISet::copyString(StringRef String) {
- return copyString(String, Allocator);
-}
+APIRecord::~APIRecord() {}
-} // namespace symbolgraph
-} // namespace clang
+void GlobalRecord::anchor() {}
diff --git a/clang/lib/SymbolGraph/CMakeLists.txt b/clang/lib/ExtractAPI/CMakeLists.txt
similarity index 60%
rename from clang/lib/SymbolGraph/CMakeLists.txt
rename to clang/lib/ExtractAPI/CMakeLists.txt
index 715937f89ddfb..044caa0922483 100644
--- a/clang/lib/SymbolGraph/CMakeLists.txt
+++ b/clang/lib/ExtractAPI/CMakeLists.txt
@@ -2,11 +2,12 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_library(clangSymbolGraph
+add_clang_library(clangExtractAPI
API.cpp
ExtractAPIConsumer.cpp
DeclarationFragments.cpp
- Serialization.cpp
+ Serialization/SerializerBase.cpp
+ Serialization/SymbolGraphSerializer.cpp
LINK_LIBS
clangAST
diff --git a/clang/lib/SymbolGraph/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
similarity index 97%
rename from clang/lib/SymbolGraph/DeclarationFragments.cpp
rename to clang/lib/ExtractAPI/DeclarationFragments.cpp
index 4a00629ae9150..d5e03832f80e1 100644
--- a/clang/lib/SymbolGraph/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -1,4 +1,4 @@
-//===- SymbolGraph/DeclarationFragments.cpp ---------------------*- C++ -*-===//
+//===- ExtractAPI/DeclarationFragments.cpp ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,22 +7,24 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines SymbolGraph Declaration Fragments related classes.
+/// This file implements Declaration Fragments related classes.
///
//===----------------------------------------------------------------------===//
-#include "clang/SymbolGraph/DeclarationFragments.h"
+#include "clang/ExtractAPI/DeclarationFragments.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringSwitch.h"
-namespace clang {
-namespace symbolgraph {
+using namespace clang::extractapi;
+using namespace llvm;
DeclarationFragments &DeclarationFragments::appendSpace() {
if (!Fragments.empty()) {
Fragment Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
- if (Last.Spelling.back() != ' ') {
+ // Merge the extra space into the last fragment if the last fragment is
+ // also text.
+ if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
Last.Spelling.push_back(' ');
}
} else {
@@ -429,6 +431,3 @@ DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
DeclarationFragments::FragmentKind::Identifier);
return Fragments;
}
-
-} // namespace symbolgraph
-} // namespace clang
diff --git a/clang/lib/SymbolGraph/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
similarity index 84%
rename from clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
rename to clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 1675045400692..c469f565afd40 100644
--- a/clang/lib/SymbolGraph/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -1,4 +1,4 @@
-//===- ExtractAPIConsumer.cpp -----------------------------------*- C++ -*-===//
+//===- ExtractAPI/ExtractAPIConsumer.cpp ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief Defines the ExtractAPI AST visitor to collect API information.
+/// This file implements the ExtractAPIAction, and ASTVisitor/Consumer to
+/// collect API information.
///
//===----------------------------------------------------------------------===//
-//
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -20,19 +20,22 @@
#include "clang/AST/RawCommentList.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/ExtractAPI/API.h"
+#include "clang/ExtractAPI/AvailabilityInfo.h"
+#include "clang/ExtractAPI/DeclarationFragments.h"
+#include "clang/ExtractAPI/FrontendActions.h"
+#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/CompilerInstance.h"
-#include "clang/SymbolGraph/API.h"
-#include "clang/SymbolGraph/AvailabilityInfo.h"
-#include "clang/SymbolGraph/DeclarationFragments.h"
-#include "clang/SymbolGraph/FrontendActions.h"
-#include "clang/SymbolGraph/Serialization.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
-using namespace symbolgraph;
+using namespace extractapi;
namespace {
+
+/// The RecursiveASTVisitor to traverse symbol declarations and collect API
+/// information.
class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
public:
explicit ExtractAPIVisitor(ASTContext &Context)
@@ -59,6 +62,7 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
Decl->getTemplateSpecializationKind() == TSK_Undeclared)
return true;
+ // Collect symbol information.
StringRef Name = Decl->getName();
StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
@@ -69,11 +73,14 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
Context.getDiagnostics());
+
+ // Build declaration fragments and sub-heading for the variable.
DeclarationFragments Declaration =
DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
+ // Add the global variable record to the API set.
API.addGlobalVar(Name, USR, Loc, Availability, Linkage, Comment,
Declaration, SubHeading);
return true;
@@ -112,6 +119,7 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
return true;
}
+ // Collect symbol information.
StringRef Name = Decl->getName();
StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
@@ -122,6 +130,8 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
Context.getDiagnostics());
+
+ // Build declaration fragments, sub-heading, and signature of the function.
DeclarationFragments Declaration =
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
DeclarationFragments SubHeading =
@@ -129,16 +139,19 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
+ // Add the function record to the API set.
API.addFunction(Name, USR, Loc, Availability, Linkage, Comment, Declaration,
SubHeading, Signature);
return true;
}
private:
+ /// Get availability information of the declaration \p D.
AvailabilityInfo getAvailability(const Decl *D) const {
StringRef PlatformName = Context.getTargetInfo().getPlatformName();
AvailabilityInfo Availability;
+ // Collect availability attributes from all redeclarations.
for (const auto *RD : D->redecls()) {
for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) {
if (A->getPlatform()->getName() != PlatformName)
@@ -174,15 +187,21 @@ class ExtractAPIConsumer : public ASTConsumer {
: Visitor(Context), OS(std::move(OS)) {}
void HandleTranslationUnit(ASTContext &Context) override {
+ // Use ExtractAPIVisitor to traverse symbol declarations in the context.
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
- Serializer Serializer(Visitor.getAPI());
- Serializer.serialize(*OS);
+
+ // Setup a SymbolGraphSerializer to write out collected API information in
+ // the Symbol Graph format.
+ // FIXME: Make the kind of APISerializer configurable.
+ SymbolGraphSerializer SGSerializer(Visitor.getAPI());
+ SGSerializer.serialize(*OS);
}
private:
ExtractAPIVisitor Visitor;
std::unique_ptr<raw_pwrite_stream> OS;
};
+
} // namespace
std::unique_ptr<ASTConsumer>
diff --git a/clang/lib/ExtractAPI/Serialization/SerializerBase.cpp b/clang/lib/ExtractAPI/Serialization/SerializerBase.cpp
new file mode 100644
index 0000000000000..71fd25b2b2abb
--- /dev/null
+++ b/clang/lib/ExtractAPI/Serialization/SerializerBase.cpp
@@ -0,0 +1,19 @@
+//===- ExtractAPI/Serialization/SerializerBase.cpp --------------*- 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 implements the APISerializer interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ExtractAPI/Serialization/SerializerBase.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::extractapi;
+
+void APISerializer::serialize(llvm::raw_ostream &os) {}
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
new file mode 100644
index 0000000000000..b0bc2034fe970
--- /dev/null
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -0,0 +1,450 @@
+//===- ExtractAPI/Serialization/SymbolGraphSerializer.cpp -------*- 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 implements the SymbolGraphSerializer.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
+#include "clang/Basic/Version.h"
+#include "clang/ExtractAPI/API.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VersionTuple.h"
+
+using namespace clang;
+using namespace clang::extractapi;
+using namespace llvm;
+using namespace llvm::json;
+
+namespace {
+
+/// Helper function to inject a JSON object \p Obj into another object \p Paren
+/// at position \p Key.
+void serializeObject(Object &Paren, StringRef Key, Optional<Object> Obj) {
+ if (Obj)
+ Paren[Key] = std::move(Obj.getValue());
+}
+
+/// Helper function to inject a JSON array \p Array into object \p Paren at
+/// position \p Key.
+void serializeArray(Object &Paren, StringRef Key, Optional<Array> Array) {
+ if (Array)
+ Paren[Key] = std::move(Array.getValue());
+}
+
+/// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version
+/// format.
+///
+/// A semantic version object contains three numeric fields, representing the
+/// \c major, \c minor, and \c patch parts of the version tuple.
+/// For example version tuple 1.0.3 is serialized as:
+/// \code
+/// {
+/// "major" : 1,
+/// "minor" : 0,
+/// "patch" : 3
+/// }
+/// \endcode
+///
+/// \returns \c None if the version \p V is empty, or an \c Object containing
+/// the semantic version representation of \p V.
+Optional<Object> serializeSemanticVersion(const VersionTuple &V) {
+ if (V.empty())
+ return None;
+
+ Object Version;
+ Version["major"] = V.getMajor();
+ Version["minor"] = V.getMinor().getValueOr(0);
+ Version["patch"] = V.getSubminor().getValueOr(0);
+ return Version;
+}
+
+/// Serialize the OS information in the Symbol Graph platform property.
+///
+/// The OS information in Symbol Graph contains the \c name of the OS, and an
+/// optional \c minimumVersion semantic version field.
+Object serializeOperatingSystem(const Triple &T) {
+ Object OS;
+ OS["name"] = T.getOSTypeName(T.getOS());
+ serializeObject(OS, "minimumVersion",
+ serializeSemanticVersion(T.getMinimumSupportedOSVersion()));
+ return OS;
+}
+
+/// Serialize the platform information in the Symbol Graph module section.
+///
+/// The platform object describes a target platform triple in corresponding
+/// three fields: \c architecture, \c vendor, and \c operatingSystem.
+Object serializePlatform(const Triple &T) {
+ Object Platform;
+ Platform["architecture"] = T.getArchName();
+ Platform["vendor"] = T.getVendorName();
+ Platform["operatingSystem"] = serializeOperatingSystem(T);
+ return Platform;
+}
+
+/// Serialize a source location in file.
+///
+/// \param Loc The presumed location to serialize.
+/// \param IncludeFileURI If true, include the file path of \p Loc as a URI.
+/// Defaults to false.
+Object serializeSourcePosition(const PresumedLoc &Loc,
+ bool IncludeFileURI = false) {
+ assert(Loc.isValid() && "invalid source position");
+
+ Object SourcePosition;
+ SourcePosition["line"] = Loc.getLine();
+ SourcePosition["character"] = Loc.getColumn();
+
+ if (IncludeFileURI) {
+ std::string FileURI = "file://";
+ // Normalize file path to use forward slashes for the URI.
+ FileURI += sys::path::convert_to_slash(Loc.getFilename());
+ SourcePosition["uri"] = FileURI;
+ }
+
+ return SourcePosition;
+}
+
+/// Serialize a source range with begin and end locations.
+Object serializeSourceRange(const PresumedLoc &BeginLoc,
+ const PresumedLoc &EndLoc) {
+ Object SourceRange;
+ serializeObject(SourceRange, "start", serializeSourcePosition(BeginLoc));
+ serializeObject(SourceRange, "end", serializeSourcePosition(EndLoc));
+ return SourceRange;
+}
+
+/// Serialize the availability attributes of a symbol.
+///
+/// Availability information contains the introduced, deprecated, and obsoleted
+/// versions of the symbol as semantic versions, if not default.
+/// Availability information also contains flags to indicate if the symbol is
+/// unconditionally unavailable or deprecated,
+/// i.e. \c __attribute__((unavailable)) and \c __attribute__((deprecated)).
+///
+/// \returns \c None if the symbol has default availability attributes, or
+/// an \c Object containing the formatted availability information.
+Optional<Object> serializeAvailability(const AvailabilityInfo &Avail) {
+ if (Avail.isDefault())
+ return None;
+
+ Object Availbility;
+ serializeObject(Availbility, "introducedVersion",
+ serializeSemanticVersion(Avail.Introduced));
+ serializeObject(Availbility, "deprecatedVersion",
+ serializeSemanticVersion(Avail.Deprecated));
+ serializeObject(Availbility, "obsoletedVersion",
+ serializeSemanticVersion(Avail.Obsoleted));
+ if (Avail.isUnavailable())
+ Availbility["isUnconditionallyUnavailable"] = true;
+ if (Avail.isUnconditionallyDeprecated())
+ Availbility["isUnconditionallyDeprecated"] = true;
+
+ return Availbility;
+}
+
+/// Get the short language name string for interface language references.
+StringRef getLanguageName(const LangOptions &LangOpts) {
+ auto Language =
+ LangStandard::getLangStandardForKind(LangOpts.LangStd).getLanguage();
+ switch (Language) {
+ case Language::C:
+ return "c";
+ case Language::ObjC:
+ return "objc";
+
+ // Unsupported language currently
+ case Language::CXX:
+ case Language::ObjCXX:
+ case Language::OpenCL:
+ case Language::OpenCLCXX:
+ case Language::CUDA:
+ case Language::RenderScript:
+ case Language::HIP:
+
+ // Languages that the frontend cannot parse and compile
+ case Language::Unknown:
+ case Language::Asm:
+ case Language::LLVM_IR:
+ llvm_unreachable("Unsupported language kind");
+ }
+
+ llvm_unreachable("Unhandled language kind");
+}
+
+/// Serialize the identifier object as specified by the Symbol Graph format.
+///
+/// The identifier property of a symbol contains the USR for precise and unique
+/// references, and the interface language name.
+Object serializeIdentifier(const APIRecord &Record,
+ const LangOptions &LangOpts) {
+ Object Identifier;
+ Identifier["precise"] = Record.USR;
+ Identifier["interfaceLanguage"] = getLanguageName(LangOpts);
+
+ return Identifier;
+}
+
+/// Serialize the documentation comments attached to a symbol, as specified by
+/// the Symbol Graph format.
+///
+/// The Symbol Graph \c docComment object contains an array of lines. Each line
+/// represents one line of striped documentation comment, with source range
+/// information.
+/// e.g.
+/// \code
+/// /// This is a documentation comment
+/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' First line.
+/// /// with multiple lines.
+/// ^~~~~~~~~~~~~~~~~~~~~~~' Second line.
+/// \endcode
+///
+/// \returns \c None if \p Comment is empty, or an \c Object containing the
+/// formatted lines.
+Optional<Object> serializeDocComment(const DocComment &Comment) {
+ if (Comment.empty())
+ return None;
+
+ Object DocComment;
+ Array LinesArray;
+ for (const auto &CommentLine : Comment) {
+ Object Line;
+ Line["text"] = CommentLine.Text;
+ serializeObject(Line, "range",
+ serializeSourceRange(CommentLine.Begin, CommentLine.End));
+ LinesArray.emplace_back(std::move(Line));
+ }
+ serializeArray(DocComment, "lines", LinesArray);
+
+ return DocComment;
+}
+
+/// Serialize the declaration fragments of a symbol.
+///
+/// The Symbol Graph declaration fragments is an array of tagged important
+/// parts of a symbol's declaration. The fragments sequence can be joined to
+/// form spans of declaration text, with attached information useful for
+/// purposes like syntax-highlighting etc. For example:
+/// \code
+/// const int pi; -> "declarationFragments" : [
+/// {
+/// "kind" : "keyword",
+/// "spelling" : "const"
+/// },
+/// {
+/// "kind" : "text",
+/// "spelling" : " "
+/// },
+/// {
+/// "kind" : "typeIdentifier",
+/// "preciseIdentifier" : "c:I",
+/// "spelling" : "int"
+/// },
+/// {
+/// "kind" : "text",
+/// "spelling" : " "
+/// },
+/// {
+/// "kind" : "identifier",
+/// "spelling" : "pi"
+/// }
+/// ]
+/// \endcode
+///
+/// \returns \c None if \p DF is empty, or an \c Array containing the formatted
+/// declaration fragments array.
+Optional<Array> serializeDeclarationFragments(const DeclarationFragments &DF) {
+ if (DF.getFragments().empty())
+ return None;
+
+ Array Fragments;
+ for (const auto &F : DF.getFragments()) {
+ Object Fragment;
+ Fragment["spelling"] = F.Spelling;
+ Fragment["kind"] = DeclarationFragments::getFragmentKindString(F.Kind);
+ if (!F.PreciseIdentifier.empty())
+ Fragment["preciseIdentifier"] = F.PreciseIdentifier;
+ Fragments.emplace_back(std::move(Fragment));
+ }
+
+ return Fragments;
+}
+
+/// Serialize the function signature field of a function, as specified by the
+/// Symbol Graph format.
+///
+/// The Symbol Graph function signature property contains two arrays.
+/// - The \c returns array is the declaration fragments of the return type;
+/// - The \c parameters array contains names and declaration fragments of the
+/// parameters.
+///
+/// \returns \c None if \p FS is empty, or an \c Object containing the
+/// formatted function signature.
+Optional<Object> serializeFunctionSignature(const FunctionSignature &FS) {
+ if (FS.empty())
+ return None;
+
+ Object Signature;
+ serializeArray(Signature, "returns",
+ serializeDeclarationFragments(FS.getReturnType()));
+
+ Array Parameters;
+ for (const auto &P : FS.getParameters()) {
+ Object Parameter;
+ Parameter["name"] = P.Name;
+ serializeArray(Parameter, "declarationFragments",
+ serializeDeclarationFragments(P.Fragments));
+ Parameters.emplace_back(std::move(Parameter));
+ }
+
+ if (!Parameters.empty())
+ Signature["parameters"] = std::move(Parameters);
+
+ return Signature;
+}
+
+/// Serialize the \c names field of a symbol as specified by the Symbol Graph
+/// format.
+///
+/// The Symbol Graph names field contains multiple representations of a symbol
+/// that can be used for
diff erent applications:
+/// - \c title : The simple declared name of the symbol;
+/// - \c subHeading : An array of declaration fragments that provides tags,
+/// and potentially more tokens (for example the \c +/- symbol for
+/// Objective-C methods). Can be used as sub-headings for documentation.
+Object serializeNames(const APIRecord &Record) {
+ Object Names;
+ Names["title"] = Record.Name;
+ serializeArray(Names, "subHeading",
+ serializeDeclarationFragments(Record.SubHeading));
+
+ return Names;
+}
+
+/// Serialize the symbol kind information.
+///
+/// The Symbol Graph symbol kind property contains a shorthand \c identifier
+/// which is prefixed by the source language name, useful for tooling to parse
+/// the kind, and a \c displayName for rendering human-readable names.
+Object serializeSymbolKind(const APIRecord &Record,
+ const LangOptions &LangOpts) {
+ Object Kind;
+ switch (Record.getKind()) {
+ case APIRecord::RK_Global:
+ auto *GR = dyn_cast<GlobalRecord>(&Record);
+ switch (GR->GlobalKind) {
+ case GVKind::Function:
+ Kind["identifier"] = (getLanguageName(LangOpts) + ".func").str();
+ Kind["displayName"] = "Function";
+ break;
+ case GVKind::Variable:
+ Kind["identifier"] = (getLanguageName(LangOpts) + ".var").str();
+ Kind["displayName"] = "Global Variable";
+ break;
+ case GVKind::Unknown:
+ // Unknown global kind
+ break;
+ }
+ break;
+ }
+
+ return Kind;
+}
+
+} // namespace
+
+void SymbolGraphSerializer::anchor() {}
+
+/// Defines the format version emitted by SymbolGraphSerializer.
+const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
+
+Object SymbolGraphSerializer::serializeMetadata() const {
+ Object Metadata;
+ serializeObject(Metadata, "formatVersion",
+ serializeSemanticVersion(FormatVersion));
+ Metadata["generator"] = clang::getClangFullVersion();
+ return Metadata;
+}
+
+Object SymbolGraphSerializer::serializeModule() const {
+ Object Module;
+ // FIXME: We might not be building a module, some Clang-based languages might
+ // not have a "module" concept. Figure out a way to provide a name to
+ // describe the API set.
+ Module["name"] = "";
+ serializeObject(Module, "platform", serializePlatform(API.getTarget()));
+ return Module;
+}
+
+bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
+ // Skip unconditionally unavailable symbols
+ if (Record.Availability.isUnconditionallyUnavailable())
+ return true;
+
+ return false;
+}
+
+Optional<Object>
+SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const {
+ if (shouldSkip(Record))
+ return None;
+
+ Object Obj;
+ serializeObject(Obj, "identifier",
+ serializeIdentifier(Record, API.getLangOpts()));
+ serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLangOpts()));
+ serializeObject(Obj, "names", serializeNames(Record));
+ serializeObject(
+ Obj, "location",
+ serializeSourcePosition(Record.Location, /*IncludeFileURI=*/true));
+ serializeObject(Obj, "availbility",
+ serializeAvailability(Record.Availability));
+ serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
+ serializeArray(Obj, "declarationFragments",
+ serializeDeclarationFragments(Record.Declaration));
+
+ return Obj;
+}
+
+void SymbolGraphSerializer::serializeGlobalRecord(const GlobalRecord &Record) {
+ auto Obj = serializeAPIRecord(Record);
+ if (!Obj)
+ return;
+
+ if (Record.GlobalKind == GVKind::Function)
+ serializeObject(*Obj, "parameters",
+ serializeFunctionSignature(Record.Signature));
+
+ Symbols.emplace_back(std::move(*Obj));
+}
+
+Object SymbolGraphSerializer::serialize() {
+ Object Root;
+ serializeObject(Root, "metadata", serializeMetadata());
+ serializeObject(Root, "module", serializeModule());
+
+ // Serialize global records in the API set.
+ for (const auto &Global : API.getGlobals())
+ serializeGlobalRecord(*Global.second);
+
+ Root["symbols"] = std::move(Symbols);
+ Root["relationhips"] = std::move(Relationships);
+
+ return Root;
+}
+
+void SymbolGraphSerializer::serialize(raw_ostream &os) {
+ Object root = serialize();
+ if (Options.Compact)
+ os << formatv("{0}", Value(std::move(root))) << "\n";
+ else
+ os << formatv("{0:2}", Value(std::move(root))) << "\n";
+}
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 38033dea4f06f..51c379ade2704 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -7,9 +7,9 @@ set(link_libs
clangBasic
clangCodeGen
clangDriver
+ clangExtractAPI
clangFrontend
clangRewriteFrontend
- clangSymbolGraph
)
if(CLANG_ENABLE_ARCMT)
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index dcc20a5bb5cc3..4525a2c977853 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -15,6 +15,7 @@
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Config/config.h"
#include "clang/Driver/Options.h"
+#include "clang/ExtractAPI/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -25,7 +26,6 @@
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
-#include "clang/SymbolGraph/FrontendActions.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/BuryPointer.h"
diff --git a/clang/lib/SymbolGraph/Serialization.cpp b/clang/lib/SymbolGraph/Serialization.cpp
deleted file mode 100644
index b07b19a93ac6c..0000000000000
--- a/clang/lib/SymbolGraph/Serialization.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-//===- SymbolGraph/Serialization.cpp ----------------------------*- 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
-/// \brief Defines the SymbolGraph serializer and parser.
-///
-//===----------------------------------------------------------------------===//
-
-#include "clang/SymbolGraph/Serialization.h"
-#include "clang/Basic/Version.h"
-#include "clang/SymbolGraph/API.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/VersionTuple.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace clang;
-using namespace clang::symbolgraph;
-using namespace llvm;
-using namespace llvm::json;
-
-namespace {
-
-static void serializeObject(Object &Paren, StringRef Key,
- Optional<Object> Obj) {
- if (Obj)
- Paren[Key] = std::move(Obj.getValue());
-}
-
-static void serializeArray(Object &Paren, StringRef Key,
- Optional<Array> Array) {
- if (Array)
- Paren[Key] = std::move(Array.getValue());
-}
-
-// SymbolGraph: SemanticVersion
-static Optional<Object> serializeSemanticVersion(const VersionTuple &V) {
- if (V.empty())
- return None;
-
- Object Version;
- Version["major"] = V.getMajor();
- Version["minor"] = V.getMinor().getValueOr(0);
- Version["patch"] = V.getSubminor().getValueOr(0);
- return Version;
-}
-
-static Object serializeOperatingSystem(const Triple &T) {
- Object OS;
- OS["name"] = T.getOSTypeName(T.getOS());
- serializeObject(OS, "minimumVersion",
- serializeSemanticVersion(T.getMinimumSupportedOSVersion()));
- return OS;
-}
-
-// SymbolGraph: Platform
-static Object serializePlatform(const Triple &T) {
- Object Platform;
- Platform["architecture"] = T.getArchName();
- Platform["vendor"] = T.getVendorName();
- Platform["operatingSystem"] = serializeOperatingSystem(T);
- return Platform;
-}
-
-// SymbolGraph: SourcePosition
-static Object serializeSourcePosition(const PresumedLoc &Loc,
- bool IncludeFileURI = false) {
- assert(Loc.isValid() && "invalid source position");
-
- Object SourcePosition;
- SourcePosition["line"] = Loc.getLine();
- SourcePosition["character"] = Loc.getColumn();
-
- if (IncludeFileURI) {
- std::string FileURI = "file://";
- FileURI += sys::path::convert_to_slash(Loc.getFilename());
- SourcePosition["uri"] = FileURI;
- }
-
- return SourcePosition;
-}
-
-// SymbolGraph: SourceRange
-static Object serializeSourceRange(const PresumedLoc &BeginLoc,
- const PresumedLoc &EndLoc) {
- Object SourceRange;
- serializeObject(SourceRange, "start", serializeSourcePosition(BeginLoc));
- serializeObject(SourceRange, "end", serializeSourcePosition(EndLoc));
- return SourceRange;
-}
-
-// SymbolGraph: AvailabilityItem
-static Optional<Object> serializeAvailability(const AvailabilityInfo &Avail) {
- if (Avail.isDefault())
- return None;
-
- Object Availbility;
- serializeObject(Availbility, "introducedVersion",
- serializeSemanticVersion(Avail.Introduced));
- serializeObject(Availbility, "deprecatedVersion",
- serializeSemanticVersion(Avail.Deprecated));
- serializeObject(Availbility, "obsoletedVersion",
- serializeSemanticVersion(Avail.Obsoleted));
- if (Avail.isUnavailable())
- Availbility["isUnconditionallyUnavailable"] = true;
- if (Avail.isUnconditionallyDeprecated())
- Availbility["isUnconditionallyDeprecated"] = true;
-
- return Availbility;
-}
-
-static StringRef getLanguageName(const LangOptions &LangOpts) {
- auto Language =
- LangStandard::getLangStandardForKind(LangOpts.LangStd).getLanguage();
- switch (Language) {
- case Language::C:
- return "c";
- case Language::ObjC:
- return "objc";
-
- // Unsupported language currently
- case Language::CXX:
- case Language::ObjCXX:
- case Language::OpenCL:
- case Language::OpenCLCXX:
- case Language::CUDA:
- case Language::RenderScript:
- case Language::HIP:
-
- // Languages that the frontend cannot parse and compile
- case Language::Unknown:
- case Language::Asm:
- case Language::LLVM_IR:
- llvm_unreachable("Unsupported language kind");
- }
-
- llvm_unreachable("Unhandled language kind");
-}
-
-// SymbolGraph: Symbol::identifier
-static Object serializeIdentifier(const APIRecord &Record,
- const LangOptions &LangOpts) {
- Object Identifier;
- Identifier["precise"] = Record.USR;
- Identifier["interfaceLanguage"] = getLanguageName(LangOpts);
-
- return Identifier;
-}
-
-// SymbolGraph: DocComment
-static Optional<Object> serializeDocComment(const DocComment &Comment) {
- if (Comment.empty())
- return None;
-
- Object DocComment;
- Array LinesArray;
- for (const auto &CommentLine : Comment) {
- Object Line;
- Line["text"] = CommentLine.Text;
- serializeObject(Line, "range",
- serializeSourceRange(CommentLine.Begin, CommentLine.End));
- LinesArray.emplace_back(std::move(Line));
- }
- serializeArray(DocComment, "lines", LinesArray);
-
- return DocComment;
-}
-
-static Optional<Array>
-serializeDeclarationFragments(const DeclarationFragments &DF) {
- if (DF.getFragments().empty())
- return None;
-
- Array Fragments;
- for (const auto &F : DF.getFragments()) {
- Object Fragment;
- Fragment["spelling"] = F.Spelling;
- Fragment["kind"] = DeclarationFragments::getFragmentKindString(F.Kind);
- if (!F.PreciseIdentifier.empty())
- Fragment["preciseIdentifier"] = F.PreciseIdentifier;
- Fragments.emplace_back(std::move(Fragment));
- }
-
- return Fragments;
-}
-
-static Optional<Object>
-serializeFunctionSignature(const FunctionSignature &FS) {
- if (FS.empty())
- return None;
-
- Object Signature;
- serializeArray(Signature, "returns",
- serializeDeclarationFragments(FS.getReturnType()));
-
- Array Parameters;
- for (const auto &P : FS.getParameters()) {
- Object Parameter;
- Parameter["name"] = P.Name;
- serializeArray(Parameter, "declarationFragments",
- serializeDeclarationFragments(P.Fragments));
- Parameters.emplace_back(std::move(Parameter));
- }
-
- if (!Parameters.empty())
- Signature["parameters"] = std::move(Parameters);
-
- return Signature;
-}
-
-static Object serializeNames(const APIRecord &Record) {
- Object Names;
- Names["title"] = Record.Name;
- serializeArray(Names, "subHeading",
- serializeDeclarationFragments(Record.SubHeading));
-
- return Names;
-}
-
-// SymbolGraph: Symbol::kind
-static Object serializeSymbolKind(const APIRecord &Record,
- const LangOptions &LangOpts) {
- Object Kind;
- switch (Record.getKind()) {
- case APIRecord::RK_Global:
- auto *GR = dyn_cast<GlobalRecord>(&Record);
- switch (GR->GlobalKind) {
- case GVKind::Function:
- Kind["identifier"] = (getLanguageName(LangOpts) + ".func").str();
- Kind["displayName"] = "Function";
- break;
- case GVKind::Variable:
- Kind["identifier"] = (getLanguageName(LangOpts) + ".var").str();
- Kind["displayName"] = "Global Variable";
- break;
- case GVKind::Unknown:
- // Unknown global kind
- break;
- }
- break;
- }
-
- return Kind;
-}
-
-} // namespace
-
-const VersionTuple Serializer::FormatVersion{0, 5, 3};
-
-Object Serializer::serializeMetadata() const {
- Object Metadata;
- serializeObject(Metadata, "formatVersion",
- serializeSemanticVersion(FormatVersion));
- Metadata["generator"] = clang::getClangFullVersion();
- return Metadata;
-}
-
-Object Serializer::serializeModule() const {
- Object Module;
- // FIXME: What to put in here?
- Module["name"] = "";
- serializeObject(Module, "platform", serializePlatform(API.getTarget()));
- return Module;
-}
-
-bool Serializer::shouldSkip(const APIRecord &Record) const {
- // Skip unconditionally unavailable symbols
- if (Record.Availability.isUnconditionallyUnavailable())
- return true;
-
- return false;
-}
-
-Optional<Object> Serializer::serializeAPIRecord(const APIRecord &Record) const {
- if (shouldSkip(Record))
- return None;
-
- Object Obj;
- serializeObject(Obj, "identifier",
- serializeIdentifier(Record, API.getLangOpts()));
- serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLangOpts()));
- serializeObject(Obj, "names", serializeNames(Record));
- serializeObject(
- Obj, "location",
- serializeSourcePosition(Record.Location, /*IncludeFileURI=*/true));
- serializeObject(Obj, "availbility",
- serializeAvailability(Record.Availability));
- serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
- serializeArray(Obj, "declarationFragments",
- serializeDeclarationFragments(Record.Declaration));
-
- return Obj;
-}
-
-void Serializer::serializeGlobalRecord(const GlobalRecord &Record) {
- auto Obj = serializeAPIRecord(Record);
- if (!Obj)
- return;
-
- if (Record.GlobalKind == GVKind::Function)
- serializeObject(*Obj, "parameters",
- serializeFunctionSignature(Record.Signature));
-
- Symbols.emplace_back(std::move(*Obj));
-}
-
-Object Serializer::serialize() {
- Object Root;
- serializeObject(Root, "metadata", serializeMetadata());
- serializeObject(Root, "module", serializeModule());
-
- for (const auto &Global : API.getGlobals())
- serializeGlobalRecord(*Global.second);
-
- Root["symbols"] = std::move(Symbols);
- Root["relationhips"] = std::move(Relationships);
-
- return Root;
-}
-
-void Serializer::serialize(raw_ostream &os) {
- Object root = serialize();
- if (Options.Compact)
- os << formatv("{0}", Value(std::move(root))) << "\n";
- else
- os << formatv("{0:2}", Value(std::move(root))) << "\n";
-}
diff --git a/clang/test/SymbolGraph/global_record.c b/clang/test/ExtractAPI/global_record.c
similarity index 100%
rename from clang/test/SymbolGraph/global_record.c
rename to clang/test/ExtractAPI/global_record.c
More information about the cfe-commits
mailing list