[clang] Reenable external categories (PR #87357)
Daniel Grumberg via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 2 08:21:06 PDT 2024
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/87357
Reenables b31414bf4f9898f7817a9fcf8a91f62ec26f3eaf.
Also adds a new warning for missing `--symbol-graph-dir` arg when `--emit-extension-symbol-graphs` is provided. This also reverts the commit that removed.
>From a2e9febec367d9680da9bd38baf2f6c3a7bc63a3 Mon Sep 17 00:00:00 2001
From: Daniel Grumberg <dgrumberg at apple.com>
Date: Tue, 2 Apr 2024 15:36:02 +0100
Subject: [PATCH 1/2] Revert "Revert "[clang][ExtractAPI] Add ability to create
multiple symbol graphs (#86676)""
This reverts commit 209a1e8dfdf1c104dd53b50eb196d6bc0dd01659.
---
.../clang/Basic/DiagnosticDriverKinds.td | 6 +
.../clang/Basic/DiagnosticFrontendKinds.td | 2 +
clang/include/clang/Driver/Options.td | 21 +-
clang/include/clang/ExtractAPI/API.h | 1547 ++++++++--------
clang/include/clang/ExtractAPI/APIRecords.inc | 103 ++
.../clang/ExtractAPI/DeclarationFragments.h | 14 +
.../clang/ExtractAPI/ExtractAPIActionBase.h | 8 +-
.../clang/ExtractAPI/ExtractAPIVisitor.h | 674 +++----
.../clang/ExtractAPI/FrontendActions.h | 6 -
.../ExtractAPI/Serialization/APISetVisitor.h | 172 ++
.../ExtractAPI/Serialization/SerializerBase.h | 314 ----
.../Serialization/SymbolGraphSerializer.h | 254 +--
.../include/clang/Frontend/FrontendOptions.h | 21 +-
clang/lib/Driver/Driver.cpp | 7 +
clang/lib/Driver/ToolChains/Clang.cpp | 15 +
clang/lib/ExtractAPI/API.cpp | 544 +-----
clang/lib/ExtractAPI/DeclarationFragments.cpp | 71 +-
clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 112 +-
.../Serialization/SymbolGraphSerializer.cpp | 943 ++++------
.../TypedefUnderlyingTypeResolver.cpp | 6 +-
.../ExecuteCompilerInvocation.cpp | 10 +-
.../ExtractAPI/anonymous_record_no_typedef.c | 3 +-
clang/test/ExtractAPI/availability.c | 2 +-
clang/test/ExtractAPI/bool.c | 2 +-
clang/test/ExtractAPI/bool.cpp | 2 +-
clang/test/ExtractAPI/class.cpp | 2 +-
clang/test/ExtractAPI/class_template.cpp | 2 +-
.../class_template_param_inheritance.cpp | 2 +-
.../class_template_partial_spec.cpp | 4 +-
clang/test/ExtractAPI/class_template_spec.cpp | 2 +-
clang/test/ExtractAPI/concept.cpp | 2 +-
.../ExtractAPI/constructor_destructor.cpp | 6 +-
clang/test/ExtractAPI/conversions.cpp | 2 +-
.../ExtractAPI/emit-symbol-graph/multi_file.c | 7 +-
.../emit-symbol-graph/single_file.c | 5 +-
clang/test/ExtractAPI/enum.c | 2 +-
clang/test/ExtractAPI/field_template.cpp | 2 +-
clang/test/ExtractAPI/function_noexcepts.cpp | 2 +-
.../test/ExtractAPI/global_func_template.cpp | 2 +-
.../ExtractAPI/global_func_template_spec.cpp | 2 +-
clang/test/ExtractAPI/global_record.c | 2 +-
.../test/ExtractAPI/global_record_multifile.c | 2 +-
clang/test/ExtractAPI/global_var_template.cpp | 2 +-
.../global_var_template_partial_spec.cpp | 2 +-
.../ExtractAPI/global_var_template_spec.cpp | 2 +-
clang/test/ExtractAPI/known_files_only.c | 101 +-
clang/test/ExtractAPI/language.c | 6 +-
clang/test/ExtractAPI/macro_undefined.c | 2 +-
clang/test/ExtractAPI/macros.c | 2 +-
clang/test/ExtractAPI/metadata_and_module.c | 32 +
clang/test/ExtractAPI/method_template.cpp | 2 +-
.../test/ExtractAPI/method_template_spec.cpp | 2 +-
clang/test/ExtractAPI/methods.cpp | 660 +++----
.../test/ExtractAPI/multiple_inheritance.cpp | 2 +-
clang/test/ExtractAPI/namespace.cpp | 2 +-
clang/test/ExtractAPI/nested_namespaces.cpp | 2 +-
clang/test/ExtractAPI/objc_block.m | 1567 +++++++----------
clang/test/ExtractAPI/objc_category.m | 338 +---
.../test/ExtractAPI/objc_external_category.m | 49 +
clang/test/ExtractAPI/objc_id_protocol.m | 357 +---
clang/test/ExtractAPI/objc_instancetype.m | 4 +-
clang/test/ExtractAPI/objc_interface.m | 1033 ++++-------
clang/test/ExtractAPI/objc_module_category.m | 404 -----
clang/test/ExtractAPI/objc_property.m | 600 +------
clang/test/ExtractAPI/objc_protocol.m | 2 +-
.../test/ExtractAPI/objc_various_categories.m | 507 ------
clang/test/ExtractAPI/operator_overload.cpp | 2 +-
clang/test/ExtractAPI/relative_include.m | 2 +-
clang/test/ExtractAPI/simple_inheritance.cpp | 2 +-
clang/test/ExtractAPI/struct.c | 2 +-
clang/test/ExtractAPI/typedef.c | 464 +----
.../ExtractAPI/typedef_anonymous_record.c | 612 ++-----
clang/test/ExtractAPI/typedef_chain.c | 2 +-
clang/test/ExtractAPI/typedef_struct_enum.c | 561 ++----
clang/test/ExtractAPI/underscored.c | 411 +----
clang/test/ExtractAPI/union.c | 4 +-
.../test/ExtractAPI/vfs_redirected_include.m | 2 +-
clang/test/Index/extract-api-cursor.m | 9 +
clang/tools/libclang/CXExtractAPI.cpp | 73 +-
79 files changed, 3888 insertions(+), 8845 deletions(-)
create mode 100644 clang/include/clang/ExtractAPI/APIRecords.inc
create mode 100644 clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
delete mode 100644 clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
create mode 100644 clang/test/ExtractAPI/metadata_and_module.c
create mode 100644 clang/test/ExtractAPI/objc_external_category.m
delete mode 100644 clang/test/ExtractAPI/objc_module_category.m
delete mode 100644 clang/test/ExtractAPI/objc_various_categories.m
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 592ed3bda51506..3d86f7510bde20 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -548,6 +548,12 @@ def err_drv_extract_api_wrong_kind : Error<
"header file '%0' input '%1' does not match the type of prior input "
"in api extraction; use '-x %2' to override">;
+def err_drv_missing_symbol_graph_dir: Error<
+ "Must provide a symbol graph output directory using --symbol-graph-dir=<directory>">;
+
+def err_drv_unexpected_symbol_graph_output : Error<
+ "Unexpected output symbol graph '%1'; please provide --symbol-graph-dir=<directory> instead">;
+
def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
InGroup<DiagGroup<"slash-u-filename">>;
def note_use_dashdash : Note<
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ba23cf84c5e343..241544b2b8c6fa 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -366,4 +366,6 @@ def warn_profile_data_misexpect : Warning<
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
+def warn_missing_symbol_graph_dir : Warning<"Missing symbol graph output directory, defaulting to working directory">;
+
}
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f5289fb00c895e..c3e90a70925b78 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1507,14 +1507,29 @@ def extract_api : Flag<["-"], "extract-api">,
def product_name_EQ: Joined<["--"], "product-name=">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<FrontendOpts<"ProductName">>;
-def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">,
+def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">,
Visibility<[ClangOption, CC1Option]>,
- HelpText<"Generate Extract API information as a side effect of compilation.">,
- MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
+ HelpText<"Generate Extract API information as a side effect of compilation.">,
+ MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraph">>;
+def emit_extension_symbol_graphs: Flag<["--"], "emit-extension-symbol-graphs">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Generate additional symbol graphs for extended modules.">,
+ MarshallingInfoFlag<FrontendOpts<"EmitExtensionSymbolGraphs">>;
def extract_api_ignores_EQ: CommaJoined<["--"], "extract-api-ignores=">,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Comma separated list of files containing a new line separated list of API symbols to ignore when extracting API information.">,
MarshallingInfoStringVector<FrontendOpts<"ExtractAPIIgnoresFileList">>;
+def symbol_graph_dir_EQ: Joined<["--"], "symbol-graph-dir=">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Directory in which to emit symbol graphs.">,
+ MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
+def emit_pretty_sgf: Flag<["--"], "pretty-sgf">,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Emit pretty printed symbol graphs">,
+ MarshallingInfoFlag<FrontendOpts<"EmitPrettySymbolGraphs">>;
+def emit_sgf_symbol_labels_for_testing: Flag<["--"], "emit-sgf-symbol-labels-for-testing">,
+ Visibility<[CC1Option]>,
+ MarshallingInfoFlag<FrontendOpts<"EmitSymbolGraphSymbolLabelsForTesting">>;
def e : Separate<["-"], "e">, Flags<[LinkerInput]>, Group<Link_Group>;
def fmax_tokens_EQ : Joined<["-"], "fmax-tokens=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index b220db294101d8..92cacf65c7d64e 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -20,17 +20,25 @@
#include "clang/AST/Availability.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
+#include <cstddef>
+#include <iterator>
#include <memory>
+#include <optional>
#include <type_traits>
namespace clang {
@@ -149,15 +157,58 @@ class Template {
/// \endcode
using DocComment = std::vector<RawComment::CommentLine>;
-// Classes deriving from APIRecord need to have USR be the first constructor
-// argument. This is so that they are compatible with `addTopLevelRecord`
-// defined in API.cpp
+struct APIRecord;
+
+// This represents a reference to another symbol that might come from external
+/// sources.
+struct SymbolReference {
+ StringRef Name;
+ StringRef USR;
+
+ /// The source project/module/product of the referred symbol.
+ StringRef Source;
+
+ // A Pointer to the APIRecord for this reference if known
+ const APIRecord *Record = nullptr;
+
+ SymbolReference() = default;
+ SymbolReference(StringRef Name, StringRef USR, StringRef Source = "")
+ : Name(Name), USR(USR), Source(Source) {}
+ SymbolReference(const APIRecord *R);
+
+ /// Determine if this SymbolReference is empty.
+ ///
+ /// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
+ bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
+};
+
+class RecordContext;
+
+// Concrete classes deriving from APIRecord need to have a construct with first
+// arguments USR, and Name, in that order. This is so that they
+// are compatible with `APISet::createRecord`.
+// When adding a new kind of record don't forget to update APIRecords.inc!
/// The base representation of an API record. Holds common symbol information.
struct APIRecord {
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum RecordKind {
RK_Unknown,
+ // If adding a record context record kind here make sure to update
+ // RecordContext::classof if needed and add a RECORD_CONTEXT entry to
+ // APIRecords.inc
+ RK_FirstRecordContext,
RK_Namespace,
+ RK_Enum,
+ RK_Struct,
+ RK_Union,
+ RK_ObjCInterface,
+ RK_ObjCCategory,
+ RK_ObjCProtocol,
+ RK_CXXClass,
+ RK_ClassTemplate,
+ RK_ClassTemplateSpecialization,
+ RK_ClassTemplatePartialSpecialization,
+ RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
@@ -166,18 +217,11 @@ struct APIRecord {
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_EnumConstant,
- RK_Enum,
RK_StructField,
- RK_Struct,
RK_UnionField,
- RK_Union,
RK_StaticField,
RK_CXXField,
RK_CXXFieldTemplate,
- RK_CXXClass,
- RK_ClassTemplate,
- RK_ClassTemplateSpecialization,
- RK_ClassTemplatePartialSpecialization,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
@@ -190,40 +234,15 @@ struct APIRecord {
RK_ObjCIvar,
RK_ObjCClassMethod,
RK_ObjCInstanceMethod,
- RK_ObjCInterface,
- RK_ObjCCategory,
- RK_ObjCCategoryModule,
- RK_ObjCProtocol,
RK_MacroDefinition,
RK_Typedef,
};
- /// Stores information about the context of the declaration of this API.
- /// This is roughly analogous to the DeclContext hierarchy for an AST Node.
- struct HierarchyInformation {
- /// The USR of the parent API.
- StringRef ParentUSR;
- /// The name of the parent API.
- StringRef ParentName;
- /// The record kind of the parent API.
- RecordKind ParentKind = RK_Unknown;
- /// A pointer to the parent APIRecord if known.
- APIRecord *ParentRecord = nullptr;
-
- HierarchyInformation() = default;
- HierarchyInformation(StringRef ParentUSR, StringRef ParentName,
- RecordKind Kind, APIRecord *ParentRecord = nullptr)
- : ParentUSR(ParentUSR), ParentName(ParentName), ParentKind(Kind),
- ParentRecord(ParentRecord) {}
-
- bool empty() const {
- return ParentUSR.empty() && ParentName.empty() &&
- ParentKind == RK_Unknown && ParentRecord == nullptr;
- }
- };
-
StringRef USR;
StringRef Name;
+
+ SymbolReference Parent;
+
PresumedLoc Location;
AvailabilityInfo Availability;
LinkageInfo Linkage;
@@ -242,79 +261,169 @@ struct APIRecord {
/// Objective-C class/instance methods).
DeclarationFragments SubHeading;
- /// Information about the parent record of this record.
- HierarchyInformation ParentInformation;
-
/// Whether the symbol was defined in a system header.
bool IsFromSystemHeader;
+ AccessControl Access;
+
private:
const RecordKind Kind;
+ friend class RecordContext;
+ // Used to store the next child record in RecordContext. This works because
+ // APIRecords semantically only have one parent.
+ mutable APIRecord *NextInContext = nullptr;
public:
+ APIRecord *getNextInContext() const { return NextInContext; }
+
RecordKind getKind() const { return Kind; }
+ static APIRecord *castFromRecordContext(const RecordContext *Ctx);
+ static RecordContext *castToRecordContext(const APIRecord *Record);
+
APIRecord() = delete;
APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Location, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- bool IsFromSystemHeader)
- : USR(USR), Name(Name), Location(Location),
+ SymbolReference Parent, PresumedLoc Location,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader,
+ AccessControl Access = AccessControl())
+ : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location),
Availability(std::move(Availability)), Linkage(Linkage),
Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
- IsFromSystemHeader(IsFromSystemHeader), Kind(Kind) {}
+ IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
+ Kind(Kind) {}
APIRecord(RecordKind Kind, StringRef USR, StringRef Name)
: USR(USR), Name(Name), Kind(Kind) {}
// Pure virtual destructor to make APIRecord abstract
virtual ~APIRecord() = 0;
+ static bool classof(const APIRecord *Record) { return true; }
+ static bool classofKind(RecordKind K) { return true; }
+ static bool classof(const RecordContext *Ctx) { return true; }
+};
+
+/// Base class used for specific record types that have children records this is
+/// analogous to the DeclContext for the AST
+class RecordContext {
+public:
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(APIRecord::RecordKind K) {
+ return K > APIRecord::RK_FirstRecordContext &&
+ K < APIRecord::RK_LastRecordContext;
+ }
+
+ static bool classof(const RecordContext *Context) { return true; }
+
+ RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
+
+ APIRecord::RecordKind getKind() const { return Kind; }
+
+ struct record_iterator {
+ private:
+ APIRecord *Current = nullptr;
+
+ public:
+ using value_type = APIRecord *;
+ using reference = const value_type &;
+ using pointer = const value_type *;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ record_iterator() = default;
+ explicit record_iterator(value_type R) : Current(R) {}
+ reference operator*() const { return Current; }
+ // This doesn't strictly meet the iterator requirements, but it's the
+ // behavior we want here.
+ value_type operator->() const { return Current; }
+ record_iterator &operator++() {
+ Current = Current->getNextInContext();
+ return *this;
+ }
+ record_iterator operator++(int) {
+ record_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(record_iterator x, record_iterator y) {
+ return x.Current == y.Current;
+ }
+ friend bool operator!=(record_iterator x, record_iterator y) {
+ return x.Current != y.Current;
+ }
+ };
+
+ using record_range = llvm::iterator_range<record_iterator>;
+ record_range records() const {
+ return record_range(records_begin(), records_end());
+ }
+ record_iterator records_begin() const { return record_iterator(First); };
+ record_iterator records_end() const { return record_iterator(); }
+ bool records_empty() const { return First == nullptr; };
+
+private:
+ APIRecord::RecordKind Kind;
+ mutable APIRecord *First = nullptr;
+ mutable APIRecord *Last = nullptr;
+
+protected:
+ friend class APISet;
+ void addToRecordChain(APIRecord *) const;
};
-struct NamespaceRecord : APIRecord {
- NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
+struct NamespaceRecord : APIRecord, RecordContext {
+ NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(RK_Namespace) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Namespace;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Namespace; }
};
/// This holds information associated with global functions.
struct GlobalFunctionRecord : APIRecord {
FunctionSignature Signature;
- GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader),
+ : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
+ std::move(Availability), Linkage, Comment, Declaration,
+ SubHeading, IsFromSystemHeader),
Signature(Signature) {}
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader),
Signature(Signature) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunction;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
private:
virtual void anchor();
@@ -323,63 +432,74 @@ struct GlobalFunctionRecord : APIRecord {
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
Template Templ;
- GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, Template Template,
bool IsFromSystemHeader)
- : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
+ : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunctionTemplate;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalFunctionTemplate;
}
};
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Signature,
+ Parent, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading, Signature,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalFunctionTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalFunctionTemplateSpecialization;
}
};
/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
- GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalVariable, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
+ std::move(Availability), Linkage, Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent,
+
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariable;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
private:
virtual void anchor();
@@ -388,34 +508,42 @@ struct GlobalVariableRecord : APIRecord {
struct GlobalVariableTemplateRecord : GlobalVariableRecord {
Template Templ;
- GlobalVariableTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
class Template Template, bool IsFromSystemHeader)
- : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Loc,
+ : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplate;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplate;
}
};
struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, IsFromSystemHeader) {}
+ Parent, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplateSpecialization;
}
};
@@ -424,126 +552,203 @@ struct GlobalVariableTemplatePartialSpecializationRecord
Template Templ;
GlobalVariableTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, class Template Template,
bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
- USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading,
+ USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_GlobalVariableTemplatePartialSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_GlobalVariableTemplatePartialSpecialization;
}
};
/// This holds information associated with enum constants.
struct EnumConstantRecord : APIRecord {
- EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availability),
- LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
+ std::move(Availability), LinkageInfo::none(), Comment,
+ Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_EnumConstant;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
private:
virtual void anchor();
};
/// This holds information associated with enums.
-struct EnumRecord : APIRecord {
- SmallVector<std::unique_ptr<EnumConstantRecord>> Constants;
-
- EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- bool IsFromSystemHeader)
- : APIRecord(RK_Enum, USR, Name, Loc, std::move(Availability),
+struct EnumRecord : APIRecord, RecordContext {
+ EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(RK_Enum) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Enum;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Enum; }
private:
virtual void anchor();
};
-/// This holds information associated with struct fields.
+/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord {
- RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
- DeclarationFragments SubHeading, RecordKind Kind,
- bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_StructField ||
- Record->getKind() == RK_UnionField;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_StructField || K == RK_UnionField;
}
-private:
- virtual void anchor();
+ virtual ~RecordFieldRecord() = 0;
};
-/// This holds information associated with structs.
-struct RecordRecord : APIRecord {
- SmallVector<std::unique_ptr<RecordFieldRecord>> Fields;
-
- RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+/// This holds information associated with structs and unions.
+struct RecordRecord : APIRecord, RecordContext {
+ RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
- DeclarationFragments SubHeading, RecordKind Kind,
- bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Struct || Record->getKind() == RK_Union;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_Struct || K == RK_Union;
}
+ virtual ~RecordRecord() = 0;
+};
+
+struct StructFieldRecord : RecordFieldRecord {
+ StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_StructField; }
+
private:
virtual void anchor();
};
-struct CXXFieldRecord : APIRecord {
- AccessControl Access;
+struct StructRecord : RecordRecord {
+ StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
- CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Struct; }
+
+private:
+ virtual void anchor();
+};
+
+struct UnionFieldRecord : RecordFieldRecord {
+ UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_UnionField; }
+
+private:
+ virtual void anchor();
+};
+
+struct UnionRecord : RecordRecord {
+ UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader)
+ : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Union; }
+
+private:
+ virtual void anchor();
+};
+
+struct CXXFieldRecord : APIRecord {
+ CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)) {}
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXField;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
}
private:
@@ -553,111 +758,122 @@ struct CXXFieldRecord : APIRecord {
struct CXXFieldTemplateRecord : CXXFieldRecord {
Template Templ;
- CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc,
+ : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Access, IsFromSystemHeader),
+ SubHeading, std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXFieldTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
};
struct CXXMethodRecord : APIRecord {
FunctionSignature Signature;
- AccessControl Access;
CXXMethodRecord() = delete;
CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Signature(Signature), Access(Access) {}
+ IsFromSystemHeader, std::move(Access)),
+ Signature(Signature) {}
virtual ~CXXMethodRecord() = 0;
};
struct CXXConstructorRecord : CXXMethodRecord {
- CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXConstructorMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
private:
virtual void anchor();
};
struct CXXDestructorRecord : CXXMethodRecord {
- CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXDestructorMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
private:
virtual void anchor();
};
struct CXXStaticMethodRecord : CXXMethodRecord {
- CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXStaticMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
private:
virtual void anchor();
};
struct CXXInstanceMethodRecord : CXXMethodRecord {
- CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXInstanceMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
private:
virtual void anchor();
@@ -666,36 +882,42 @@ struct CXXInstanceMethodRecord : CXXMethodRecord {
struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;
- CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
+ : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader),
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXMethodTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
};
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader) {}
+ : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
+ Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, std::move(Access),
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_CXXMethodTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXMethodTemplateSpecialization;
}
};
@@ -714,13 +936,13 @@ struct ObjCPropertyRecord : APIRecord {
bool IsOptional;
ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AttributeKind Attributes,
StringRef GetterName, StringRef SetterName,
bool IsOptional, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
@@ -733,44 +955,44 @@ struct ObjCPropertyRecord : APIRecord {
};
struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
- ObjCInstancePropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- AttributeKind Attributes, StringRef GetterName,
- StringRef SetterName, bool IsOptional,
- bool IsFromSystemHeader)
- : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Loc,
+ ObjCInstancePropertyRecord(
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ AttributeKind Attributes, StringRef GetterName, StringRef SetterName,
+ bool IsOptional, bool IsFromSystemHeader)
+ : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInstanceProperty;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
private:
virtual void anchor();
};
struct ObjCClassPropertyRecord : ObjCPropertyRecord {
- ObjCClassPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
AttributeKind Attributes, StringRef GetterName,
StringRef SetterName, bool IsOptional,
bool IsFromSystemHeader)
- : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Loc,
+ : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCClassProperty;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
private:
virtual void anchor();
@@ -778,23 +1000,21 @@ struct ObjCClassPropertyRecord : ObjCPropertyRecord {
/// This holds information associated with Objective-C instance variables.
struct ObjCInstanceVariableRecord : APIRecord {
- using AccessControl = ObjCIvarDecl::AccessControl;
- AccessControl Access;
-
- ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availability),
+ bool IsFromSystemHeader)
+ : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCIvar;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
private:
virtual void anchor();
@@ -807,11 +1027,12 @@ struct ObjCMethodRecord : APIRecord {
ObjCMethodRecord() = delete;
ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
@@ -820,122 +1041,103 @@ struct ObjCMethodRecord : APIRecord {
};
struct ObjCInstanceMethodRecord : ObjCMethodRecord {
- ObjCInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
+ SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Loc,
+ : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInstanceMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
private:
virtual void anchor();
};
struct ObjCClassMethodRecord : ObjCMethodRecord {
- ObjCClassMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability,
+ ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Loc,
+ : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCClassMethod;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
private:
virtual void anchor();
};
-/// This represents a reference to another symbol that might come from external
-/// sources.
-struct SymbolReference {
- StringRef Name;
- StringRef USR;
-
- /// The source project/module/product of the referred symbol.
- StringRef Source;
-
- SymbolReference() = default;
- SymbolReference(StringRef Name, StringRef USR = "", StringRef Source = "")
- : Name(Name), USR(USR), Source(Source) {}
- SymbolReference(const APIRecord &Record)
- : Name(Record.Name), USR(Record.USR) {}
- SymbolReference(const APIRecord *Record)
- : Name(Record->Name), USR(Record->USR) {}
-
- /// Determine if this SymbolReference is empty.
- ///
- /// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
- bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
-};
-
struct StaticFieldRecord : CXXFieldRecord {
- SymbolReference Context;
-
- StaticFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeader)
- : CXXFieldRecord(RK_StaticField, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Access,
- IsFromSystemHeader),
- Context(Context) {}
+ StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, AccessControl Access,
+ bool IsFromSystemHeader)
+ : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, std::move(Access), IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_StaticField;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_StaticField; }
};
/// The base representation of an Objective-C container record. Holds common
/// information associated with Objective-C containers.
-struct ObjCContainerRecord : APIRecord {
- SmallVector<std::unique_ptr<ObjCMethodRecord>> Methods;
- SmallVector<std::unique_ptr<ObjCPropertyRecord>> Properties;
- SmallVector<std::unique_ptr<ObjCInstanceVariableRecord>> Ivars;
+struct ObjCContainerRecord : APIRecord, RecordContext {
SmallVector<SymbolReference> Protocols;
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ SymbolReference Parent, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, IsFromSystemHeader) {}
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader),
+ RecordContext(Kind) {}
virtual ~ObjCContainerRecord() = 0;
};
-struct CXXClassRecord : APIRecord {
- SmallVector<std::unique_ptr<CXXFieldRecord>> Fields;
- SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
+struct CXXClassRecord : APIRecord, RecordContext {
SmallVector<SymbolReference> Bases;
- AccessControl Access;
- CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- Access(Access) {}
+ IsFromSystemHeader, std::move(Access)),
+ RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
- return (Record->getKind() == RK_CXXClass);
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_CXXClass || K == RK_ClassTemplate ||
+ K == RK_ClassTemplateSpecialization ||
+ K == RK_ClassTemplatePartialSpecialization;
}
private:
@@ -945,86 +1147,108 @@ struct CXXClassRecord : APIRecord {
struct ClassTemplateRecord : CXXClassRecord {
Template Templ;
- ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, RK_ClassTemplate, Access,
- IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, RK_ClassTemplate,
+ std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplate;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
};
struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplateSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_ClassTemplateSpecialization;
}
};
struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
Template Templ;
ClassTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, PresumedLoc Loc,
+ StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, RK_ClassTemplateSpecialization,
- Access, IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading,
+ RK_ClassTemplatePartialSpecialization, Access,
+ IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ClassTemplatePartialSpecialization;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) {
+ return K == RK_ClassTemplatePartialSpecialization;
}
};
struct ConceptRecord : APIRecord {
Template Templ;
- ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader)
- : APIRecord(RK_Concept, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
+
+ static bool classof(const APIRecord *Record) {
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_Concept; }
};
/// This holds information associated with Objective-C categories.
struct ObjCCategoryRecord : ObjCContainerRecord {
SymbolReference Interface;
- /// Determine whether the Category is derived from external class interface.
- bool IsFromExternalModule = false;
- ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Interface(Interface) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCCategory;
+ return classofKind(Record->getKind());
+ }
+ static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
+
+ bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
+
+ std::optional<StringRef> getExtendedExternalModule() const {
+ if (!isExtendingExternalModule())
+ return {};
+ return Interface.Source;
}
private:
@@ -1034,23 +1258,22 @@ struct ObjCCategoryRecord : ObjCContainerRecord {
/// This holds information associated with Objective-C interfaces/classes.
struct ObjCInterfaceRecord : ObjCContainerRecord {
SymbolReference SuperClass;
- // ObjCCategoryRecord%s are stored in and owned by APISet.
- SmallVector<ObjCCategoryRecord *> Categories;
- ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
SuperClass(SuperClass) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCInterface;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
private:
virtual void anchor();
@@ -1058,18 +1281,20 @@ struct ObjCInterfaceRecord : ObjCContainerRecord {
/// This holds information associated with Objective-C protocols.
struct ObjCProtocolRecord : ObjCContainerRecord {
- ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc,
+ : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_ObjCProtocol;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
private:
virtual void anchor();
@@ -1077,17 +1302,18 @@ struct ObjCProtocolRecord : ObjCContainerRecord {
/// This holds information associated with macro definitions.
struct MacroDefinitionRecord : APIRecord {
- MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- DeclarationFragments Declaration,
+ MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
- : APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(),
- LinkageInfo(), {}, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
+ AvailabilityInfo(), LinkageInfo(), {}, Declaration,
+ SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_MacroDefinition;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
private:
virtual void anchor();
@@ -1101,575 +1327,228 @@ struct MacroDefinitionRecord : APIRecord {
struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
- TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType,
bool IsFromSystemHeader)
- : APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availability),
+ : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
UnderlyingType(UnderlyingType) {}
static bool classof(const APIRecord *Record) {
- return Record->getKind() == RK_Typedef;
+ return classofKind(Record->getKind());
}
+ static bool classofKind(RecordKind K) { return K == RK_Typedef; }
private:
virtual void anchor();
};
-/// Check if a record type has a function signature mixin.
-///
-/// This is denoted by the record type having a ``Signature`` field of type
-/// FunctionSignature.
-template <typename RecordTy>
-struct has_function_signature : public std::false_type {};
-template <>
-struct has_function_signature<GlobalFunctionRecord> : public std::true_type {};
-template <>
-struct has_function_signature<ObjCMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<ObjCInstanceMethodRecord>
- : public std::true_type {};
-template <>
-struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXInstanceMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXStaticMethodRecord> : public std::true_type {};
-template <>
-struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
-};
-template <>
-struct has_function_signature<CXXMethodTemplateSpecializationRecord>
- : public std::true_type {};
-
-template <typename RecordTy> struct has_access : public std::false_type {};
-template <> struct has_access<CXXInstanceMethodRecord> : public std::true_type {};
-template <> struct has_access<CXXStaticMethodRecord> : public std::true_type {};
-template <> struct has_access<CXXFieldRecord> : public std::true_type {};
-template <>
-struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
-template <>
-struct has_access<CXXMethodTemplateSpecializationRecord>
- : public std::true_type {};
-template <>
-struct has_access<CXXFieldTemplateRecord> : public std::true_type {};
-template <> struct has_access<CXXClassRecord> : public std::true_type {};
-template <> struct has_access<ClassTemplateRecord> : public std::true_type {};
-template <>
-struct has_access<ClassTemplateSpecializationRecord> : public std::true_type {};
-template <>
-struct has_access<ClassTemplatePartialSpecializationRecord>
- : public std::true_type {};
-
-template <typename RecordTy> struct has_template : public std::false_type {};
-template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<ClassTemplatePartialSpecializationRecord>
- : public std::true_type {};
-template <> struct has_template<ConceptRecord> : public std::true_type {};
-template <>
-struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
- : public std::true_type {};
-template <>
-struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
-template <>
-struct has_template<CXXFieldTemplateRecord> : public std::true_type {};
-
-template <>
-struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
-template <>
-struct has_function_signature<GlobalFunctionTemplateRecord>
- : public std::true_type {};
-template <>
-struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
- : public std::true_type {};
-
/// APISet holds the set of API records collected from given inputs.
class APISet {
public:
- NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeaderg);
- /// 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.
- GlobalVariableRecord *
- addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeadin, bool IsFromSystemHeaderg);
+ /// Get the target triple for the ExtractAPI invocation.
+ const llvm::Triple &getTarget() const { return Target; }
- GlobalVariableTemplateRecord *
- addGlobalVariableTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
+ /// Get the language used by the APIs.
+ Language getLanguage() const { return Lang; }
- /// Create and add a function record into the API set.
+ /// Finds the APIRecord for a given USR.
///
- /// 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.
- GlobalFunctionRecord *
- addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsFromSystemHeader);
-
- GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- Template Template, bool IsFromSystemHeader);
-
- GlobalFunctionTemplateSpecializationRecord *
- addGlobalFunctionTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader);
+ /// \returns a pointer to the APIRecord associated with that USR or nullptr.
+ APIRecord *findRecordForUSR(StringRef USR) const;
- /// Create and add an enum constant record into the API set.
+ /// Copy \p String into the Allocator in this APISet.
///
- /// 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.
- EnumConstantRecord *
- addEnumConstant(EnumRecord *Enum, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+ /// \returns a StringRef of the copied string in APISet::Allocator.
+ StringRef copyString(StringRef String);
- /// Create and add an enum 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.
- EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+ SymbolReference createSymbolReference(StringRef Name, StringRef USR,
+ StringRef Source = "");
- /// Create and add a record field record into the API set.
+ /// Create a subclass of \p APIRecord and store it in the APISet.
///
- /// 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.
- RecordFieldRecord *
- addRecordField(RecordRecord *Record, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
- bool IsFromSystemHeader);
-
- /// Create and add a record 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.
- RecordRecord *addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, bool IsFromSystemHeader);
-
- StaticFieldRecord *
- addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeaderg);
-
- CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader);
-
- CXXFieldTemplateRecord *addCXXFieldTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, Template Template, bool IsFromSystemHeader);
-
- CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, AccessControl Access,
- bool IsFromSystemHeader);
-
- ClassTemplateRecord *
- addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- AccessControl Access, bool IsFromSystemHeader);
-
- ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader);
-
- ClassTemplatePartialSpecializationRecord *
- addClassTemplatePartialSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader);
-
- GlobalVariableTemplateSpecializationRecord *
- addGlobalVariableTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
-
- GlobalVariableTemplatePartialSpecializationRecord *
- addGlobalVariableTemplatePartialSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXInstanceMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXStaticMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodRecord *addCXXSpecialMethod(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
-
- CXXMethodTemplateRecord *addCXXMethodTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access, Template Template,
- bool IsFromSystemHeader);
+ /// \returns A pointer to the created record or the already existing record
+ /// matching this USR.
+ template <typename RecordTy, typename... CtorArgsContTy>
+ typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
+ createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
+
+ ArrayRef<const APIRecord *> getTopLevelRecords() const {
+ return TopLevelRecords;
+ }
- CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader);
+ APISet(const llvm::Triple &Target, Language Lang,
+ const std::string &ProductName)
+ : Target(Target), Lang(Lang), ProductName(ProductName) {}
- ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader);
+ // Prevent moves and copies
+ APISet(const APISet &Other) = delete;
+ APISet &operator=(const APISet &Other) = delete;
+ APISet(APISet &&Other) = delete;
+ APISet &operator=(APISet &&Other) = delete;
- /// Create and add an Objective-C category 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.
- ObjCCategoryRecord *
- addObjCCategory(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Interface,
- bool IsFromSystemHeader, bool IsFromExternalModule);
+private:
+ /// BumpPtrAllocator that serves as the memory arena for the allocated objects
+ llvm::BumpPtrAllocator Allocator;
- /// Create and add an Objective-C interface 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.
- ObjCInterfaceRecord *
- addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference SuperClass,
- bool IsFromSystemHeader);
+ const llvm::Triple Target;
+ const Language Lang;
- /// Create and add an Objective-C method 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.
- ObjCMethodRecord *
- addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsInstanceMethod, bool IsFromSystemHeader);
+ struct APIRecordDeleter {
+ void operator()(APIRecord *Record) { Record->~APIRecord(); }
+ };
- /// Create and add an Objective-C property 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.
- ObjCPropertyRecord *
- addObjCProperty(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- ObjCPropertyRecord::AttributeKind Attributes,
- StringRef GetterName, StringRef SetterName, bool IsOptional,
- bool IsInstanceProperty, bool IsFromSystemHeader);
+ // Ensure that the destructor of each record is called when the LookupTable is
+ // destroyed without calling delete operator as the memory for the record
+ // lives in the BumpPtrAllocator.
+ using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>;
+ llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
+ std::vector<const APIRecord *> TopLevelRecords;
- /// Create and add an Objective-C instance 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.
- ObjCInstanceVariableRecord *addObjCInstanceVariable(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCInstanceVariableRecord::AccessControl Access,
- bool IsFromSystemHeader);
+public:
+ const std::string ProductName;
+};
- /// Create and add an Objective-C protocol 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.
- ObjCProtocolRecord *
- addObjCProtocol(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader);
+template <typename RecordTy, typename... CtorArgsContTy>
+typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
+APISet::createRecord(StringRef USR, StringRef Name,
+ CtorArgsContTy &&...CtorArgs) {
+ // Ensure USR refers to a String stored in the allocator.
+ auto USRString = copyString(USR);
+ auto Result = USRBasedLookupTable.insert({USRString, nullptr});
+ RecordTy *Record;
+
+ // Create the record if it does not already exist
+ if (Result.second) {
+ Record = new (Allocator) RecordTy(
+ USRString, copyString(Name), std::forward<CtorArgsContTy>(CtorArgs)...);
+ // Store the record in the record lookup map
+ Result.first->second = APIRecordStoredPtr(Record);
+
+ if (auto *ParentContext =
+ dyn_cast_if_present<RecordContext>(Record->Parent.Record))
+ ParentContext->addToRecordChain(Record);
+ else
+ TopLevelRecords.push_back(Record);
+ } else {
+ Record = dyn_cast<RecordTy>(Result.first->second.get());
+ }
- /// Create a macro definition 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::recordUSRForMacro(StringRef Name,
- /// SourceLocation SL, const SourceManager &SM) is a helper method to generate
- /// the USR for the macro and keep it alive in APISet.
- MacroDefinitionRecord *addMacroDefinition(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader);
-
- /// Create a typedef 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.
- TypedefRecord *
- addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- SymbolReference UnderlyingType, bool IsFromSystemHeader);
-
- /// A mapping type to store a set of APIRecord%s with the USR as the key.
- template <typename RecordTy,
- typename =
- std::enable_if_t<std::is_base_of<APIRecord, RecordTy>::value>>
- using RecordMap = llvm::MapVector<StringRef, std::unique_ptr<RecordTy>>;
+ return Record;
+}
- /// Get the target triple for the ExtractAPI invocation.
- const llvm::Triple &getTarget() const { return Target; }
+// Helper type for implementing casting to RecordContext pointers.
+// Selected when FromTy not a known subclass of RecordContext.
+template <typename FromTy,
+ bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
+struct ToRecordContextCastInfoWrapper {
+ static_assert(std::is_base_of_v<APIRecord, FromTy>,
+ "Can only cast APIRecord and derived classes to RecordContext");
- /// Get the language used by the APIs.
- Language getLanguage() const { return Lang; }
+ static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
- const RecordMap<NamespaceRecord> &getNamespaces() const { return Namespaces; }
- const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
- return GlobalFunctions;
- }
- const RecordMap<GlobalFunctionTemplateRecord> &
- getGlobalFunctionTemplates() const {
- return GlobalFunctionTemplates;
- }
- const RecordMap<GlobalFunctionTemplateSpecializationRecord> &
- getGlobalFunctionTemplateSpecializations() const {
- return GlobalFunctionTemplateSpecializations;
- }
- const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
- return GlobalVariables;
- }
- const RecordMap<GlobalVariableTemplateRecord> &
- getGlobalVariableTemplates() const {
- return GlobalVariableTemplates;
+ static RecordContext *doCast(FromTy *From) {
+ return APIRecord::castToRecordContext(From);
}
- const RecordMap<StaticFieldRecord> &getStaticFields() const {
- return StaticFields;
- }
- const RecordMap<GlobalVariableTemplateSpecializationRecord> &
- getGlobalVariableTemplateSpecializations() const {
- return GlobalVariableTemplateSpecializations;
- }
- const RecordMap<GlobalVariableTemplatePartialSpecializationRecord> &
- getGlobalVariableTemplatePartialSpecializations() const {
- return GlobalVariableTemplatePartialSpecializations;
- }
- const RecordMap<EnumRecord> &getEnums() const { return Enums; }
- const RecordMap<RecordRecord> &getRecords() const { return Records; }
- const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
- const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
- return CXXMethodTemplates;
- }
- const RecordMap<CXXInstanceMethodRecord> &getCXXInstanceMethods() const {
- return CXXInstanceMethods;
- }
- const RecordMap<CXXStaticMethodRecord> &getCXXStaticMethods() const {
- return CXXStaticMethods;
- }
- const RecordMap<CXXFieldRecord> &getCXXFields() const { return CXXFields; }
- const RecordMap<CXXMethodTemplateSpecializationRecord> &
- getCXXMethodTemplateSpecializations() const {
- return CXXMethodTemplateSpecializations;
- }
- const RecordMap<CXXFieldTemplateRecord> &getCXXFieldTemplates() const {
- return CXXFieldTemplates;
- }
- const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
- return ClassTemplates;
- }
- const RecordMap<ClassTemplateSpecializationRecord> &
- getClassTemplateSpecializations() const {
- return ClassTemplateSpecializations;
+};
+
+// Selected when FromTy is a known subclass of RecordContext.
+template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> {
+ static_assert(std::is_base_of_v<APIRecord, FromTy>,
+ "Can only cast APIRecord and derived classes to RecordContext");
+ static bool isPossible(const FromTy *From) { return true; }
+ static RecordContext *doCast(FromTy *From) {
+ return static_cast<RecordContext *>(From);
}
- const RecordMap<ClassTemplatePartialSpecializationRecord> &
- getClassTemplatePartialSpecializations() const {
- return ClassTemplatePartialSpecializations;
+};
+
+// Helper type for implementing casting to RecordContext pointers.
+// Selected when ToTy isn't a known subclass of RecordContext
+template <typename ToTy,
+ bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
+struct FromRecordContextCastInfoWrapper {
+ static_assert(
+ std::is_base_of_v<APIRecord, ToTy>,
+ "Can only class RecordContext to APIRecord and derived classes");
+
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classofKind(Ctx->getKind());
}
- const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
- const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
- return ObjCCategories;
+
+ static ToTy *doCast(RecordContext *Ctx) {
+ return APIRecord::castFromRecordContext(Ctx);
}
- const RecordMap<ObjCInterfaceRecord> &getObjCInterfaces() const {
- return ObjCInterfaces;
+};
+
+// Selected when ToTy is a known subclass of RecordContext.
+template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> {
+ static_assert(
+ std::is_base_of_v<APIRecord, ToTy>,
+ "Can only class RecordContext to APIRecord and derived classes");
+ static bool isPossible(RecordContext *Ctx) {
+ return ToTy::classof(Ctx->getKind());
}
- const RecordMap<ObjCProtocolRecord> &getObjCProtocols() const {
- return ObjCProtocols;
+ static RecordContext *doCast(RecordContext *Ctx) {
+ return static_cast<ToTy *>(Ctx);
}
- const RecordMap<MacroDefinitionRecord> &getMacros() const { return Macros; }
- const RecordMap<TypedefRecord> &getTypedefs() const { return Typedefs; }
-
- /// Finds the APIRecord for a given USR.
- ///
- /// \returns a pointer to the APIRecord associated with that USR or nullptr.
- APIRecord *findRecordForUSR(StringRef USR) const;
-
- /// 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);
-
- /// Generate and store the USR for a macro \p Name.
- ///
- /// Note: The USR string is stored in and owned by Allocator.
- ///
- /// \returns a StringRef to the generate USR string.
- StringRef recordUSRForMacro(StringRef Name, SourceLocation SL,
- const SourceManager &SM);
-
- /// 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, Language Lang,
- const std::string &ProductName)
- : Target(Target), Lang(Lang), ProductName(ProductName) {}
+} // namespace extractapi
+} // namespace clang
-private:
- /// BumpPtrAllocator to store generated/copied strings.
- ///
- /// Note: The main use for this is being able to deduplicate strings.
- llvm::BumpPtrAllocator StringAllocator;
+// Implement APIRecord (and derived classes) to and from RecordContext
+// conversions
+namespace llvm {
+
+template <typename FromTy>
+struct CastInfo<::clang::extractapi::RecordContext, FromTy *>
+ : public NullableValueCastFailed<::clang::extractapi::RecordContext *>,
+ public DefaultDoCastIfPossible<
+ ::clang::extractapi::RecordContext *, FromTy *,
+ CastInfo<::clang::extractapi::RecordContext, FromTy *>> {
+ static inline bool isPossible(FromTy *From) {
+ return ::clang::extractapi::ToRecordContextCastInfoWrapper<
+ FromTy>::isPossible(From);
+ }
- const llvm::Triple Target;
- const Language Lang;
+ static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
+ return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast(
+ From);
+ }
+};
- llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
- RecordMap<NamespaceRecord> Namespaces;
- RecordMap<GlobalFunctionRecord> GlobalFunctions;
- RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
- RecordMap<GlobalFunctionTemplateSpecializationRecord>
- GlobalFunctionTemplateSpecializations;
- RecordMap<GlobalVariableRecord> GlobalVariables;
- RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
- RecordMap<GlobalVariableTemplateSpecializationRecord>
- GlobalVariableTemplateSpecializations;
- RecordMap<GlobalVariableTemplatePartialSpecializationRecord>
- GlobalVariableTemplatePartialSpecializations;
- RecordMap<ConceptRecord> Concepts;
- RecordMap<StaticFieldRecord> StaticFields;
- RecordMap<EnumRecord> Enums;
- RecordMap<RecordRecord> Records;
- RecordMap<CXXClassRecord> CXXClasses;
- RecordMap<CXXFieldRecord> CXXFields;
- RecordMap<CXXMethodRecord> CXXMethods;
- RecordMap<CXXInstanceMethodRecord> CXXInstanceMethods;
- RecordMap<CXXStaticMethodRecord> CXXStaticMethods;
- RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
- RecordMap<CXXMethodTemplateSpecializationRecord>
- CXXMethodTemplateSpecializations;
- RecordMap<CXXFieldTemplateRecord> CXXFieldTemplates;
- RecordMap<ClassTemplateRecord> ClassTemplates;
- RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
- RecordMap<ClassTemplatePartialSpecializationRecord>
- ClassTemplatePartialSpecializations;
- RecordMap<ObjCCategoryRecord> ObjCCategories;
- RecordMap<ObjCInterfaceRecord> ObjCInterfaces;
- RecordMap<ObjCProtocolRecord> ObjCProtocols;
- RecordMap<MacroDefinitionRecord> Macros;
- RecordMap<TypedefRecord> Typedefs;
+template <typename FromTy>
+struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
+ : public ConstStrippingForwardingCast<
+ ::clang::extractapi::RecordContext, const FromTy *,
+ CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
+
+template <typename ToTy>
+struct CastInfo<ToTy, ::clang::extractapi::RecordContext *>
+ : public NullableValueCastFailed<ToTy *>,
+ public DefaultDoCastIfPossible<
+ ToTy *, ::clang::extractapi::RecordContext *,
+ CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {
+ static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) {
+ return ::clang::extractapi::FromRecordContextCastInfoWrapper<
+ ToTy>::isPossible(Ctx);
+ }
-public:
- const std::string ProductName;
+ static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
+ return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast(
+ Ctx);
+ }
};
-} // namespace extractapi
-} // namespace clang
+template <typename ToTy>
+struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
+ : public ConstStrippingForwardingCast<
+ ToTy, const ::clang::extractapi::RecordContext *,
+ CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
+
+} // namespace llvm
#endif // LLVM_CLANG_EXTRACTAPI_API_H
diff --git a/clang/include/clang/ExtractAPI/APIRecords.inc b/clang/include/clang/ExtractAPI/APIRecords.inc
new file mode 100644
index 00000000000000..15fee809656d9a
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/APIRecords.inc
@@ -0,0 +1,103 @@
+//===- ExtractAPI/APIRecords.inc --------------------------------*- 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 classes defined from ExtractAPI's APIRecord
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ABSTRACT_RECORD
+#define ABSTRACT_RECORD(CLASS, BASE) RECORD(CLASS, BASE)
+#endif
+#ifndef CONCRETE_RECORD
+#define CONCRETE_RECORD(CLASS, BASE, KIND) RECORD(CLASS, BASE)
+#endif
+#ifndef RECORD
+#define RECORD(CLASS, BASE)
+#endif
+
+CONCRETE_RECORD(NamespaceRecord, APIRecord, RK_Namespace)
+CONCRETE_RECORD(GlobalFunctionRecord, APIRecord, RK_GlobalFunction)
+CONCRETE_RECORD(GlobalFunctionTemplateRecord, GlobalFunctionRecord,
+ RK_GlobalFunctionTemplate)
+CONCRETE_RECORD(GlobalFunctionTemplateSpecializationRecord,
+ GlobalFunctionRecord, RK_GlobalFunctionTemplateSpecialization)
+CONCRETE_RECORD(GlobalVariableRecord, APIRecord, RK_GlobalVariable)
+CONCRETE_RECORD(GlobalVariableTemplateRecord, GlobalVariableRecord,
+ RK_GlobalVariableTemplate)
+CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
+ GlobalVariableRecord, RK_GlobalVariableTemplateSpecialization)
+CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
+ GlobalVariableRecord,
+ RK_GlobalVariableTemplatePartialSpecialization)
+CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
+CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
+ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
+ABSTRACT_RECORD(RecordRecord, APIRecord)
+CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
+CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
+CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
+CONCRETE_RECORD(UnionRecord, APIRecord, RK_Union)
+CONCRETE_RECORD(CXXFieldRecord, APIRecord, RK_CXXField)
+CONCRETE_RECORD(CXXFieldTemplateRecord, CXXFieldRecord, RK_CXXFieldTemplate)
+ABSTRACT_RECORD(CXXMethodRecord, APIRecord)
+CONCRETE_RECORD(CXXConstructorRecord, CXXMethodRecord, RK_CXXConstructorMethod)
+CONCRETE_RECORD(CXXDestructorRecord, CXXMethodRecord, RK_CXXDestructorMethod)
+CONCRETE_RECORD(CXXStaticMethodRecord, CXXMethodRecord, RK_CXXStaticMethod)
+CONCRETE_RECORD(CXXInstanceMethodRecord, CXXMethodRecord, RK_CXXInstanceMethod)
+CONCRETE_RECORD(CXXMethodTemplateRecord, CXXMethodRecord, RK_CXXMethodTemplate)
+CONCRETE_RECORD(CXXMethodTemplateSpecializationRecord, CXXMethodRecord,
+ RK_CXXMethodTemplateSpecialization)
+ABSTRACT_RECORD(ObjCPropertyRecord, APIRecord)
+CONCRETE_RECORD(ObjCInstancePropertyRecord, ObjCPropertyRecord,
+ RK_ObjCInstanceProperty)
+CONCRETE_RECORD(ObjCClassPropertyRecord, ObjCPropertyRecord,
+ RK_ObjCClassProperty)
+CONCRETE_RECORD(ObjCInstanceVariableRecord, APIRecord, RK_ObjCIvar)
+ABSTRACT_RECORD(ObjCMethodRecord, APIRecord)
+CONCRETE_RECORD(ObjCInstanceMethodRecord, ObjCMethodRecord,
+ RK_ObjCInstanceMethod)
+CONCRETE_RECORD(ObjCClassMethodRecord, ObjCMethodRecord, RK_ObjCClassMethod)
+CONCRETE_RECORD(StaticFieldRecord, CXXFieldRecord, RK_StaticField)
+ABSTRACT_RECORD(ObjCContainerRecord, APIRecord)
+CONCRETE_RECORD(CXXClassRecord, APIRecord, RK_CXXClass)
+CONCRETE_RECORD(ClassTemplateRecord, CXXClassRecord, RK_ClassTemplate)
+CONCRETE_RECORD(ClassTemplateSpecializationRecord, CXXClassRecord,
+ RK_ClassTemplateSpecialization)
+CONCRETE_RECORD(ClassTemplatePartialSpecializationRecord, CXXClassRecord,
+ RK_ClassTemplatePartialSpecialization)
+CONCRETE_RECORD(ConceptRecord, APIRecord, RK_Concept)
+CONCRETE_RECORD(ObjCCategoryRecord, ObjCContainerRecord, RK_ObjCCategory)
+CONCRETE_RECORD(ObjCInterfaceRecord, ObjCContainerRecord, RK_ObjCInterface)
+CONCRETE_RECORD(ObjCProtocolRecord, ObjCContainerRecord, RK_ObjCProtocol)
+CONCRETE_RECORD(MacroDefinitionRecord, APIRecord, RK_MacroDefinition)
+CONCRETE_RECORD(TypedefRecord, APIRecord, RK_Typedef)
+
+#undef CONCRETE_RECORD
+#undef ABSTRACT_RECORD
+#undef RECORD
+
+#ifndef RECORD_CONTEXT
+#define RECORD_CONTEXT(CLASS, KIND)
+#endif
+
+RECORD_CONTEXT(NamespaceRecord, RK_Namespace)
+RECORD_CONTEXT(EnumRecord, RK_Enum)
+RECORD_CONTEXT(StructRecord, RK_Struct)
+RECORD_CONTEXT(UnionRecord, RK_Union)
+RECORD_CONTEXT(ObjCCategoryRecord, RK_ObjCCategory)
+RECORD_CONTEXT(ObjCInterfaceRecord, RK_ObjCInterface)
+RECORD_CONTEXT(ObjCProtocolRecord, RK_ObjCProtocol)
+RECORD_CONTEXT(CXXClassRecord, RK_CXXClass)
+RECORD_CONTEXT(ClassTemplateRecord, RK_ClassTemplate)
+RECORD_CONTEXT(ClassTemplateSpecializationRecord,
+ RK_ClassTemplateSpecialization)
+RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
+ RK_ClassTemplatePartialSpecialization)
+
+#undef RECORD_CONTEXT
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index b85a5d21d61217..ec97c2e3e254c2 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -182,6 +182,18 @@ class DeclarationFragments {
/// appending to chain up consecutive appends.
DeclarationFragments &appendSpace();
+ /// Append a text Fragment of a semicolon character.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// appending to chain up consecutive appends.
+ DeclarationFragments &appendSemicolon();
+
+ /// Removes a trailing semicolon character if present.
+ ///
+ /// \returns a reference to the DeclarationFragments object itself after
+ /// removing to chain up consecutive operations.
+ DeclarationFragments &removeTrailingSemicolon();
+
/// Get the string description of a FragmentKind \p Kind.
static StringRef getFragmentKindString(FragmentKind Kind);
@@ -194,12 +206,14 @@ class DeclarationFragments {
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
private:
+ DeclarationFragments &appendUnduplicatedTextCharacter(char Character);
std::vector<Fragment> Fragments;
};
class AccessControl {
public:
AccessControl(std::string Access) : Access(Access) {}
+ AccessControl() : Access("public") {}
const std::string &getAccess() const { return Access; }
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
index ac4f391db5f14a..08210a7ee05954 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
@@ -17,6 +17,8 @@
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -29,8 +31,8 @@ class ExtractAPIActionBase {
/// A representation of the APIs this action extracts.
std::unique_ptr<extractapi::APISet> API;
- /// A stream to the output file of this action.
- std::unique_ptr<raw_pwrite_stream> OS;
+ /// A stream to the main output file of this action.
+ std::unique_ptr<llvm::raw_pwrite_stream> OS;
/// The product this action is extracting API information for.
std::string ProductName;
@@ -46,7 +48,7 @@ class ExtractAPIActionBase {
///
/// Use the serializer to generate output symbol graph files from
/// the information gathered during the execution of Action.
- void ImplEndSourceFileAction();
+ void ImplEndSourceFileAction(CompilerInstance &CI);
};
} // namespace clang
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
index e1c3e41c750d40..4cb866892b5d00 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -14,23 +14,23 @@
#ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
#define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
-#include "clang/AST/Availability.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/OperatorKinds.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/ExtractAPI/DeclarationFragments.h"
-#include "llvm/ADT/FunctionExtras.h"
-
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/API.h"
+#include "clang/ExtractAPI/DeclarationFragments.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include <type_traits>
namespace clang {
@@ -130,12 +130,6 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
void recordEnumConstants(EnumRecord *EnumRecord,
const EnumDecl::enumerator_range Constants);
- /// Collect API information for the record fields and associate with the
- /// parent struct.
- void recordRecordFields(RecordRecord *RecordRecord,
- APIRecord::RecordKind FieldKind,
- const RecordDecl::field_range Fields);
-
/// Collect API information for the Objective-C methods and associate with the
/// parent container.
void recordObjCMethods(ObjCContainerRecord *Container,
@@ -172,6 +166,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
return *static_cast<Derived *>(this);
}
+protected:
SmallVector<SymbolReference> getBases(const CXXRecordDecl *Decl) {
// FIXME: store AccessSpecifier given by inheritance
SmallVector<SymbolReference> Bases;
@@ -182,49 +177,54 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
SymbolReference BaseClass;
if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) {
BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString());
- BaseClass.USR = API.recordUSR(
- BaseSpecifier.getType()->getAs<TemplateTypeParmType>()->getDecl());
+ if (auto *TTPTD = BaseSpecifier.getType()
+ ->getAs<TemplateTypeParmType>()
+ ->getDecl()) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(TTPTD, USR);
+ BaseClass.USR = API.copyString(USR);
+ BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD));
+ }
} else {
- CXXRecordDecl *BaseClassDecl =
- BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl();
- BaseClass.Name = BaseClassDecl->getName();
- BaseClass.USR = API.recordUSR(BaseClassDecl);
+ BaseClass = createSymbolReferenceForDecl(
+ *BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl());
}
Bases.emplace_back(BaseClass);
}
return Bases;
}
- APIRecord *determineParentRecord(const DeclContext *Context) {
- SmallString<128> ParentUSR;
- if (Context->getDeclKind() == Decl::TranslationUnit)
- return nullptr;
+ StringRef getOwningModuleName(const Decl &D) {
+ if (auto *OwningModule = D.getImportedOwningModule())
+ return OwningModule->Name;
- index::generateUSRForDecl(dyn_cast<Decl>(Context), ParentUSR);
+ return {};
+ }
- APIRecord *Parent = API.findRecordForUSR(ParentUSR);
- return Parent;
+ SymbolReference createHierarchyInformationForDecl(const Decl &D) {
+ const auto *Context = cast_if_present<Decl>(D.getDeclContext());
+
+ if (!Context || isa<TranslationUnitDecl>(Context))
+ return {};
+
+ return createSymbolReferenceForDecl(*Context);
}
-};
-template <typename T>
-static void modifyRecords(const T &Records, const StringRef &Name) {
- for (const auto &Record : Records) {
- if (Name == Record.second.get()->Name) {
- auto &DeclFragment = Record.second->Declaration;
- DeclFragment.insert(DeclFragment.begin(), " ",
- DeclarationFragments::FragmentKind::Text);
- DeclFragment.insert(DeclFragment.begin(), "typedef",
- DeclarationFragments::FragmentKind::Keyword, "",
- nullptr);
- DeclFragment.insert(--DeclFragment.end(), " { ... } ",
- DeclarationFragments::FragmentKind::Text);
- DeclFragment.insert(--DeclFragment.end(), Name,
- DeclarationFragments::FragmentKind::Identifier);
- break;
- }
+ SymbolReference createSymbolReferenceForDecl(const Decl &D) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(&D, USR);
+
+ APIRecord *Record = API.findRecordForUSR(USR);
+ if (Record)
+ return SymbolReference(Record);
+
+ StringRef Name;
+ if (auto *ND = dyn_cast<NamedDecl>(&D))
+ Name = ND->getName();
+
+ return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}
-}
+};
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
@@ -251,7 +251,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -267,21 +268,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
if (Decl->isStaticDataMember()) {
- SymbolReference Context;
- // getDeclContext() should return a RecordDecl since we
- // are currently handling a static data member.
- auto *Record = cast<RecordDecl>(Decl->getDeclContext());
- Context.Name = Record->getName();
- Context.USR = API.recordUSR(Record);
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- API.addStaticField(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading, Context,
- Access, isInSystemHeader(Decl));
+ API.createRecord<StaticFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Access, isInSystemHeader(Decl));
} else
// Add the global variable record to the API set.
- API.addGlobalVar(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading,
- isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -304,7 +301,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
return true;
}
- // Skip templated functions.
+ // Skip templated functions that aren't processed here.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
@@ -321,7 +318,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -337,18 +335,19 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
if (Decl->getTemplateSpecializationInfo())
- API.addGlobalFunctionTemplateSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment,
+ API.createRecord<GlobalFunctionTemplateSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, isInSystemHeader(Decl));
else
// Add the function record to the API set.
- API.addGlobalFunction(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment, DeclarationFragmentsBuilder::getFragmentsForFunction(Decl),
- SubHeading, Signature, isInSystemHeader(Decl));
+ API.createRecord<GlobalFunctionRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
+ Signature, isInSystemHeader(Decl));
return true;
}
@@ -368,7 +367,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
Name = QualifiedNameBuffer.str();
}
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -382,13 +382,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- EnumRecord *EnumRecord = API.addEnum(
- API.copyString(Name), USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, isInSystemHeader(Decl));
+ auto *ER = API.createRecord<EnumRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ isInSystemHeader(Decl));
// Now collect information about the enumerators in this enum.
- getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord,
- Decl->enumerators());
+ getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
return true;
}
@@ -476,13 +476,13 @@ bool ExtractAPIVisitorBase<Derived>::WalkUpFromNamespaceDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
const NamespaceDecl *Decl) {
-
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
if (Decl->isAnonymousNamespace())
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
@@ -497,10 +497,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- API.addNamespace(Parent, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ API.createRecord<NamespaceRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -509,14 +509,20 @@ template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
+
+ SmallString<128> QualifiedNameBuffer;
// Collect symbol information.
StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);
- if (Name.empty())
- return true;
+ if (Name.empty()) {
+ llvm::raw_svector_ostream OS(QualifiedNameBuffer);
+ Decl->printQualifiedName(OS);
+ Name = QualifiedNameBuffer.str();
+ }
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -531,21 +537,16 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- auto RecordKind = APIRecord::RK_Struct;
- auto FieldRecordKind = APIRecord::RK_StructField;
-
- if (Decl->isUnion()) {
- RecordKind = APIRecord::RK_Union;
- FieldRecordKind = APIRecord::RK_UnionField;
- }
-
- RecordRecord *RecordRecord = API.addRecord(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, RecordKind, isInSystemHeader(Decl));
-
- // Now collect information about the fields in this struct.
- getDerivedExtractAPIVisitor().recordRecordFields(
- RecordRecord, FieldRecordKind, Decl->fields());
+ if (Decl->isUnion())
+ API.createRecord<UnionRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ else
+ API.createRecord<StructRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -558,7 +559,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -580,24 +582,25 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
Kind = APIRecord::RecordKind::RK_CXXClass;
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- CXXClassRecord *CXXClassRecord;
+ CXXClassRecord *Record;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
- CXXClassRecord = API.addClassTemplate(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()),
- Access, isInSystemHeader(Decl));
+ Record = API.createRecord<ClassTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
+ isInSystemHeader(Decl));
} else
- CXXClassRecord = API.addCXXClass(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Kind, Access, isInSystemHeader(Decl));
+ Record = API.createRecord<CXXClassRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Kind, Access, isInSystemHeader(Decl));
- CXXClassRecord->Bases = getBases(Decl);
+ Record->Bases = getBases(Decl);
return true;
}
@@ -614,7 +617,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
return true;
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -627,14 +631,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- auto *Parent = API.findRecordForUSR(ParentUSR);
- if (Decl->isTemplated()) {
- FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
- API.addCXXMethodTemplate(
- API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc,
+ if (FunctionTemplateDecl *TemplateDecl =
+ Decl->getDescribedFunctionTemplate()) {
+ API.createRecord<CXXMethodTemplateRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
@@ -642,27 +642,27 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
- API.addCXXMethodTemplateSpec(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord<CXXMethodTemplateSpecializationRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isOverloadedOperator())
- API.addCXXInstanceMethod(
- Parent, API.copyString(Decl->getNameAsString()), USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
+ API.createRecord<CXXInstanceMethodRecord>(
+ USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
+ Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isStatic())
- API.addCXXStaticMethod(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord<CXXStaticMethodRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
else
- API.addCXXInstanceMethod(
- Parent, Decl->getName(), USR, Loc,
+ API.createRecord<CXXInstanceMethodRecord>(
+ USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
@@ -673,9 +673,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
const CXXConstructorDecl *Decl) {
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -692,22 +696,24 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+
+ API.createRecord<CXXConstructorRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
const CXXDestructorDecl *Decl) {
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -724,13 +730,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXDestructorRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
return true;
}
@@ -740,7 +743,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -752,9 +756,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForConcept(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addConcept(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, Template(Decl),
- isInSystemHeader(Decl));
+ API.createRecord<ConceptRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -765,7 +770,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -779,14 +785,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading,
+ auto *CTSR = API.createRecord<ClassTemplateSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
- ClassTemplateSpecializationRecord->Bases = getBases(Decl);
+ CTSR->Bases = getBases(Decl);
return true;
}
@@ -799,7 +804,8 @@ bool ExtractAPIVisitorBase<Derived>::
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -811,15 +817,13 @@ bool ExtractAPIVisitorBase<Derived>::
getFragmentsForClassTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
- auto *ClassTemplatePartialSpecRecord =
- API.addClassTemplatePartialSpecialization(
- Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment, Declaration, SubHeading, Template(Decl),
- DeclarationFragmentsBuilder::getAccessControl(Decl),
- isInSystemHeader(Decl));
+ auto *CTPSR = API.createRecord<ClassTemplatePartialSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl),
+ isInSystemHeader(Decl));
- ClassTemplatePartialSpecRecord->Bases = getBases(Decl);
+ CTPSR->Bases = getBases(Decl);
return true;
}
@@ -832,7 +836,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -853,20 +858,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord)
- API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading,
- DeclarationFragmentsBuilder::getAccessControl(Decl),
- Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<CXXFieldTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
+ Template(Decl), isInSystemHeader(Decl));
else
- API.addGlobalVariableTemplate(Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl),
- Linkage, Comment, Declaration, SubHeading,
- Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -878,7 +880,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -894,9 +897,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addGlobalVariableTemplateSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplateSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -908,7 +912,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -923,9 +928,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
getFragmentsForVarTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.addGlobalVariableTemplatePartialSpecialization(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, Template(Decl), isInSystemHeader(Decl));
+ API.createRecord<GlobalVariableTemplatePartialSpecializationRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -939,7 +945,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -954,8 +961,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(
Decl->getTemplatedDecl());
- API.addGlobalFunctionTemplate(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ API.createRecord<GlobalFunctionTemplateRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
@@ -970,7 +978,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -988,24 +997,23 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// Collect super class information.
SymbolReference SuperClass;
- if (const auto *SuperClassDecl = Decl->getSuperClass()) {
- SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
- SuperClass.USR = API.recordUSR(SuperClassDecl);
- }
+ if (const auto *SuperClassDecl = Decl->getSuperClass())
+ SuperClass = createSymbolReferenceForDecl(*SuperClassDecl);
- ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
+ auto *InterfaceRecord = API.createRecord<ObjCInterfaceRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
+ SubHeading, SuperClass, isInSystemHeader(Decl));
// Record all methods (selectors). This doesn't include automatically
// synthesized property methods.
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(InterfaceRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord,
Decl->protocols());
return true;
@@ -1019,7 +1027,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1034,15 +1043,15 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, isInSystemHeader(Decl));
+ auto *ProtoRecord = API.createRecord<ObjCProtocolRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ isInSystemHeader(Decl));
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord,
- Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods());
+ getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord,
Decl->protocols());
return true;
@@ -1061,25 +1070,36 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
- // Add the notion of typedef for tag type (struct or enum) of the same name.
- if (const ElaboratedType *ET =
- dyn_cast<ElaboratedType>(Decl->getUnderlyingType())) {
- if (const TagType *TagTy = dyn_cast<TagType>(ET->desugar())) {
- if (Decl->getName() == TagTy->getDecl()->getName()) {
- if (isa<RecordDecl>(TagTy->getDecl())) {
- modifyRecords(API.getRecords(), Decl->getName());
- }
- if (TagTy->getDecl()->isEnum()) {
- modifyRecords(API.getEnums(), Decl->getName());
- }
+ StringRef Name = Decl->getName();
+
+ // If the underlying type was defined as part of the typedef modify it's
+ // fragments directly and pretend the typedef doesn't exist.
+ if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
+ if (TagDecl->getName() == Decl->getName() &&
+ TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) {
+ SmallString<128> TagUSR;
+ index::generateUSRForDecl(TagDecl, TagUSR);
+ if (auto *Record = API.findRecordForUSR(TagUSR)) {
+ DeclarationFragments LeadingFragments;
+ LeadingFragments.append("typedef",
+ DeclarationFragments::FragmentKind::Keyword, "",
+ nullptr);
+ LeadingFragments.appendSpace();
+ Record->Declaration.removeTrailingSemicolon()
+ .insert(Record->Declaration.begin(), std::move(LeadingFragments))
+ .append(" { ... } ", DeclarationFragments::FragmentKind::Text)
+ .append(Name, DeclarationFragments::FragmentKind::Identifier)
+ .appendSemicolon();
+
+ return true;
}
}
}
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
- StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
DocComment Comment;
if (auto *RawComment =
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
@@ -1091,11 +1111,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
API);
- API.addTypedef(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
- Comment,
- DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
- DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
- isInSystemHeader(Decl));
+ API.createRecord<TypedefRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
+ DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
+ DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
+ isInSystemHeader(Decl));
return true;
}
@@ -1107,7 +1128,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
return true;
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1122,29 +1144,20 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
DeclarationFragmentsBuilder::getSubHeading(Decl);
const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
- SymbolReference Interface(InterfaceDecl->getName(),
- API.recordUSR(InterfaceDecl));
-
- bool IsFromExternalModule = true;
- for (const auto &Interface : API.getObjCInterfaces()) {
- if (InterfaceDecl->getName() == Interface.second.get()->Name) {
- IsFromExternalModule = false;
- break;
- }
- }
+ SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl);
- ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Interface, isInSystemHeader(Decl),
- IsFromExternalModule);
+ auto *CategoryRecord = API.createRecord<ObjCCategoryRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ Interface, isInSystemHeader(Decl));
- getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord,
Decl->protocols());
return true;
@@ -1158,7 +1171,8 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
for (const auto *Constant : Constants) {
// Collect symbol information.
StringRef Name = Constant->getName();
- StringRef USR = API.recordUSR(Constant);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Constant, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Constant->getLocation());
DocComment Comment;
@@ -1173,51 +1187,26 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Constant);
- API.addEnumConstant(EnumRecord, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Constant), Comment,
- Declaration, SubHeading, isInSystemHeader(Constant));
- }
-}
-
-/// Collect API information for the struct fields and associate with the
-/// parent struct.
-template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordRecordFields(
- RecordRecord *RecordRecord, APIRecord::RecordKind FieldKind,
- const RecordDecl::field_range Fields) {
- for (const auto *Field : Fields) {
- // Collect symbol information.
- StringRef Name = Field->getName();
- StringRef USR = API.recordUSR(Field);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Field->getLocation());
- DocComment Comment;
- if (auto *RawComment =
- getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments and sub-heading for the struct field.
- DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForField(Field);
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Field);
-
- API.addRecordField(
- RecordRecord, Name, USR, Loc, AvailabilityInfo::createFromDecl(Field),
- Comment, Declaration, SubHeading, FieldKind, isInSystemHeader(Field));
+ API.createRecord<EnumConstantRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Constant), Loc,
+ AvailabilityInfo::createFromDecl(Constant), Comment, Declaration,
+ SubHeading, isInSystemHeader(Constant));
}
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
- if (Decl->getDeclContext()->getDeclKind() == Decl::Record)
+ // ObjCIvars are handled separately
+ if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl))
return true;
- if (isa<ObjCIvarDecl>(Decl))
+
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
+
// Collect symbol information.
StringRef Name = Decl->getName();
- StringRef USR = API.recordUSR(Decl);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1231,22 +1220,40 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForField(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
- API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Access, isInSystemHeader(Decl));
+ if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+
+ API.createRecord<CXXFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Access, isInSystemHeader(Decl));
+ } else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
+ if (RD->isUnion())
+ API.createRecord<UnionFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ else
+ API.createRecord<StructFieldRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, isInSystemHeader(Decl));
+ }
+
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
const CXXConversionDecl *Decl) {
- StringRef Name = API.copyString(Decl->getNameAsString());
- StringRef USR = API.recordUSR(Decl);
+ if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
+ Decl->isImplicit())
+ return true;
+
+ auto Name = Decl->getNameAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1264,19 +1271,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- SmallString<128> ParentUSR;
- index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
- ParentUSR);
if (Decl->isStatic())
- API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXStaticMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
else
- API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- Declaration, SubHeading, Signature, Access,
- isInSystemHeader(Decl));
+ API.createRecord<CXXInstanceMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
+
return true;
}
@@ -1291,8 +1296,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
if (Method->isPropertyAccessor())
continue;
- StringRef Name = API.copyString(Method->getSelector().getAsString());
- StringRef USR = API.recordUSR(Method);
+ auto Name = Method->getSelector().getAsString();
+ SmallString<128> USR;
+ index::generateUSRForDecl(Method, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Method->getLocation());
DocComment Comment;
@@ -1309,10 +1315,16 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Method);
- API.addObjCMethod(Container, Name, USR, Loc,
- AvailabilityInfo::createFromDecl(Method), Comment,
- Declaration, SubHeading, Signature,
- Method->isInstanceMethod(), isInSystemHeader(Method));
+ if (Method->isInstanceMethod())
+ API.createRecord<ObjCInstanceMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Method), Loc,
+ AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
+ SubHeading, Signature, isInSystemHeader(Method));
+ else
+ API.createRecord<ObjCClassMethodRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Method), Loc,
+ AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
+ SubHeading, Signature, isInSystemHeader(Method));
}
}
@@ -1322,7 +1334,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
const ObjCContainerDecl::prop_range Properties) {
for (const auto *Property : Properties) {
StringRef Name = Property->getName();
- StringRef USR = API.recordUSR(Property);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Property, USR);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Property->getLocation());
DocComment Comment;
@@ -1337,10 +1350,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Property);
- StringRef GetterName =
- API.copyString(Property->getGetterName().getAsString());
- StringRef SetterName =
- API.copyString(Property->getSetterName().getAsString());
+ auto GetterName = Property->getGetterName().getAsString();
+ auto SetterName = Property->getSetterName().getAsString();
// Get the attributes for property.
unsigned Attributes = ObjCPropertyRecord::NoAttr;
@@ -1348,14 +1359,22 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
ObjCPropertyAttribute::kind_readonly)
Attributes |= ObjCPropertyRecord::ReadOnly;
- API.addObjCProperty(
- Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Property),
- Comment, Declaration, SubHeading,
- static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), GetterName,
- SetterName, Property->isOptional(),
- !(Property->getPropertyAttributes() &
- ObjCPropertyAttribute::kind_class),
- isInSystemHeader(Property));
+ if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class)
+ API.createRecord<ObjCClassPropertyRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Property), Loc,
+ AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
+ SubHeading,
+ static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
+ GetterName, SetterName, Property->isOptional(),
+ isInSystemHeader(Property));
+ else
+ API.createRecord<ObjCInstancePropertyRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Property), Loc,
+ AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
+ SubHeading,
+ static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
+ GetterName, SetterName, Property->isOptional(),
+ isInSystemHeader(Property));
}
}
@@ -1367,7 +1386,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
Ivars) {
for (const auto *Ivar : Ivars) {
StringRef Name = Ivar->getName();
- StringRef USR = API.recordUSR(Ivar);
+ SmallString<128> USR;
+ index::generateUSRForDecl(Ivar, USR);
+
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
DocComment Comment;
@@ -1382,12 +1403,10 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Ivar);
- ObjCInstanceVariableRecord::AccessControl Access =
- Ivar->getCanonicalAccessControl();
-
- API.addObjCInstanceVariable(
- Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Ivar),
- Comment, Declaration, SubHeading, Access, isInSystemHeader(Ivar));
+ API.createRecord<ObjCInstanceVariableRecord>(
+ USR, Name, createHierarchyInformationForDecl(*Ivar), Loc,
+ AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration,
+ SubHeading, isInSystemHeader(Ivar));
}
}
@@ -1396,8 +1415,7 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProtocols(
ObjCContainerRecord *Container,
ObjCInterfaceDecl::protocol_range Protocols) {
for (const auto *Protocol : Protocols)
- Container->Protocols.emplace_back(Protocol->getName(),
- API.recordUSR(Protocol));
+ Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol));
}
} // namespace impl
diff --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h
index c67864aac9af9c..08045a30823db8 100644
--- a/clang/include/clang/ExtractAPI/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -49,9 +49,6 @@ class ExtractAPIAction : public ASTFrontendAction,
void EndSourceFileAction() override;
static StringRef getInputBufferName() { return "<extract-api-includes>"; }
-
- static std::unique_ptr<llvm::raw_pwrite_stream>
- CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
/// Wrap ExtractAPIAction on top of a pre-existing action
@@ -85,9 +82,6 @@ class WrappingExtractAPIAction : public WrapperFrontendAction,
/// actions. This is the place where all the gathered symbol graph
/// information is emited.
void EndSourceFileAction() override;
-
- static std::unique_ptr<llvm::raw_pwrite_stream>
- CreateOutputFile(CompilerInstance &CI, StringRef InFile);
};
} // namespace clang
diff --git a/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
new file mode 100644
index 00000000000000..07f14f349f3dd7
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
@@ -0,0 +1,172 @@
+//===- ExtractAPI/Serialization/APISetVisitor.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 APISetVisitor interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
+
+#include "clang/ExtractAPI/API.h"
+
+namespace clang {
+namespace extractapi {
+
+// A helper macro to implement short-circuiting when recursing. It
+// invokes CALL_EXPR, which must be a method call, on the derived
+// object (s.t. a user of RecursiveASTVisitor can override the method
+// in CALL_EXPR).
+#define TRY_TO(CALL_EXPR) \
+ do { \
+ if (!getDerived()->CALL_EXPR) \
+ return false; \
+ } while (false)
+
+/// The base interface of visitors for API information, the interface and usage
+/// is almost identical to RecurisveASTVistor. This class performs three
+/// distinct tasks:
+/// 1. traverse the APISet (i.e. go to every record);
+/// 2. at a given record, walk up the class hierarchy starting from the record's
+/// dynamic type until APIRecord is reached.
+/// 3. given a (record, class) combination where 'class' is some base class of
+/// the dynamic type of 'record', call a user-overridable function to actually
+/// visit the record.
+///
+/// These tasks are done by three groups of methods, respectively:
+/// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for
+/// traversing the records starting from x. This method simply forwards to
+/// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls
+/// walkUpFromFoo(x) and then recursively visits the child records of x.
+/// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of
+/// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent
+/// class of Foo (unless Foo has no parent) and then calls visitFoo(x).
+/// 3. visitFoo(Foo *x) does task #3.
+///
+/// These three method groups are tiered (traverse* > walkUpFrom* >
+/// visit*). A method (e.g. traverse*) may call methods from the same
+/// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*).
+/// It may not call methods from a higher tier.
+///
+/// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar
+/// is Foo's super class) before calling visitFoo(), the result is
+/// that the visit*() methods for a given record are called in the
+/// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the
+/// order will be visitRecord(), visitObjCPropertyRecord(), and then
+/// visitObjCInstancePropertyRecord()).
+///
+/// This scheme guarantees that all visit*() calls for the same record
+/// are grouped together. In other words, visit*() methods for different
+/// records are never interleaved.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the traverse*, walkUpFrom*,
+/// and visit* methods for records where the visitor should customize
+/// behavior. Most users only need to override visit*. Advanced
+/// users may override traverse* and walkUpFrom* to implement custom
+/// traversal strategies. Returning false from one of these overridden
+/// functions will abort the entire traversal.
+template <typename Derived> class APISetVisitor {
+public:
+ bool traverseAPISet() {
+ for (const APIRecord *TLR : API.getTopLevelRecords()) {
+ TRY_TO(traverseAPIRecord(TLR));
+ }
+ return true;
+ }
+
+ bool traverseAPIRecord(const APIRecord *Record);
+ bool walkUpFromAPIRecord(const APIRecord *Record) {
+ TRY_TO(visitAPIRecord(Record));
+ return true;
+ }
+ bool visitAPIRecord(const APIRecord *Record) { return true; }
+
+#define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
+ bool traverse##CLASS(const CLASS *Record) { \
+ TRY_TO(walkUpFrom##CLASS(Record)); \
+ TRY_TO(traverseRecordContext(dyn_cast<RecordContext>(Record))); \
+ return true; \
+ }
+
+#define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \
+ bool walkUpFrom##CLASS(const CLASS *Record) { \
+ TRY_TO(walkUpFrom##BASE(Record)); \
+ TRY_TO(visit##CLASS(Record)); \
+ return true; \
+ } \
+ bool visit##CLASS(const CLASS *Record) { return true; }
+
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
+ GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
+
+#define ABSTRACT_RECORD(CLASS, BASE) \
+ GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
+
+#include "../APIRecords.inc"
+
+#undef GENERATE_WALKUP_AND_VISIT_METHODS
+#undef GENERATE_TRAVERSE_METHOD
+
+ bool traverseRecordContext(const RecordContext *);
+
+protected:
+ const APISet &API;
+
+public:
+ APISetVisitor() = delete;
+ APISetVisitor(const APISetVisitor &) = delete;
+ APISetVisitor(APISetVisitor &&) = delete;
+ APISetVisitor &operator=(const APISetVisitor &) = delete;
+ APISetVisitor &operator=(APISetVisitor &&) = delete;
+
+protected:
+ APISetVisitor(const APISet &API) : API(API) {}
+ ~APISetVisitor() = default;
+
+ Derived *getDerived() { return static_cast<Derived *>(this); };
+};
+
+template <typename Derived>
+bool APISetVisitor<Derived>::traverseRecordContext(
+ const RecordContext *Context) {
+ if (!Context)
+ return true;
+
+ for (auto *Child : Context->records())
+ TRY_TO(traverseAPIRecord(Child));
+
+ return true;
+}
+
+template <typename Derived>
+bool APISetVisitor<Derived>::traverseAPIRecord(const APIRecord *Record) {
+ switch (Record->getKind()) {
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ case APIRecord::KIND: { \
+ TRY_TO(traverse##CLASS(static_cast<const CLASS *>(Record))); \
+ break; \
+ }
+#include "../APIRecords.inc"
+ case APIRecord::RK_Unknown: {
+ TRY_TO(walkUpFromAPIRecord(static_cast<const APIRecord *>(Record)));
+ break;
+ }
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
+ }
+ return true;
+}
+
+} // namespace extractapi
+} // namespace clang
+
+#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
deleted file mode 100644
index f0629a9ad56b03..00000000000000
--- a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
+++ /dev/null
@@ -1,314 +0,0 @@
-//===- 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 APISetVisitor interface.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
-#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
-
-#include "clang/ExtractAPI/API.h"
-
-namespace clang {
-namespace extractapi {
-
-/// The base interface of visitors for API information.
-template <typename Derived> class APISetVisitor {
-public:
- void traverseAPISet() {
- getDerived()->traverseNamespaces();
-
- getDerived()->traverseGlobalVariableRecords();
-
- getDerived()->traverseGlobalFunctionRecords();
-
- getDerived()->traverseEnumRecords();
-
- getDerived()->traverseStaticFieldRecords();
-
- getDerived()->traverseCXXClassRecords();
-
- getDerived()->traverseClassTemplateRecords();
-
- getDerived()->traverseClassTemplateSpecializationRecords();
-
- getDerived()->traverseClassTemplatePartialSpecializationRecords();
-
- getDerived()->traverseCXXInstanceMethods();
-
- getDerived()->traverseCXXStaticMethods();
-
- getDerived()->traverseCXXMethodTemplates();
-
- getDerived()->traverseCXXMethodTemplateSpecializations();
-
- getDerived()->traverseCXXFields();
-
- getDerived()->traverseCXXFieldTemplates();
-
- getDerived()->traverseConcepts();
-
- getDerived()->traverseGlobalVariableTemplateRecords();
-
- getDerived()->traverseGlobalVariableTemplateSpecializationRecords();
-
- getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords();
-
- getDerived()->traverseGlobalFunctionTemplateRecords();
-
- getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
-
- getDerived()->traverseRecordRecords();
-
- getDerived()->traverseObjCInterfaces();
-
- getDerived()->traverseObjCProtocols();
-
- getDerived()->traverseObjCCategories();
-
- getDerived()->traverseMacroDefinitionRecords();
-
- getDerived()->traverseTypedefRecords();
- }
-
- void traverseNamespaces() {
- for (const auto &Namespace : API.getNamespaces())
- getDerived()->visitNamespaceRecord(*Namespace.second);
- }
-
- void traverseGlobalFunctionRecords() {
- for (const auto &GlobalFunction : API.getGlobalFunctions())
- getDerived()->visitGlobalFunctionRecord(*GlobalFunction.second);
- }
-
- void traverseGlobalVariableRecords() {
- for (const auto &GlobalVariable : API.getGlobalVariables())
- getDerived()->visitGlobalVariableRecord(*GlobalVariable.second);
- }
-
- void traverseEnumRecords() {
- for (const auto &Enum : API.getEnums())
- getDerived()->visitEnumRecord(*Enum.second);
- }
-
- void traverseRecordRecords() {
- for (const auto &Record : API.getRecords())
- getDerived()->visitRecordRecord(*Record.second);
- }
-
- void traverseStaticFieldRecords() {
- for (const auto &StaticField : API.getStaticFields())
- getDerived()->visitStaticFieldRecord(*StaticField.second);
- }
-
- void traverseCXXClassRecords() {
- for (const auto &Class : API.getCXXClasses())
- getDerived()->visitCXXClassRecord(*Class.second);
- }
-
- void traverseCXXMethodTemplates() {
- for (const auto &MethodTemplate : API.getCXXMethodTemplates())
- getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
- }
-
- void traverseCXXMethodTemplateSpecializations() {
- for (const auto &MethodTemplateSpecialization :
- API.getCXXMethodTemplateSpecializations())
- getDerived()->visitMethodTemplateSpecializationRecord(
- *MethodTemplateSpecialization.second);
- }
-
- void traverseClassTemplateRecords() {
- for (const auto &ClassTemplate : API.getClassTemplates())
- getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
- }
-
- void traverseClassTemplateSpecializationRecords() {
- for (const auto &ClassTemplateSpecialization :
- API.getClassTemplateSpecializations())
- getDerived()->visitClassTemplateSpecializationRecord(
- *ClassTemplateSpecialization.second);
- }
-
- void traverseClassTemplatePartialSpecializationRecords() {
- for (const auto &ClassTemplatePartialSpecialization :
- API.getClassTemplatePartialSpecializations())
- getDerived()->visitClassTemplatePartialSpecializationRecord(
- *ClassTemplatePartialSpecialization.second);
- }
-
- void traverseCXXInstanceMethods() {
- for (const auto &InstanceMethod : API.getCXXInstanceMethods())
- getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second);
- }
-
- void traverseCXXStaticMethods() {
- for (const auto &InstanceMethod : API.getCXXStaticMethods())
- getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second);
- }
-
- void traverseCXXFields() {
- for (const auto &CXXField : API.getCXXFields())
- getDerived()->visitCXXFieldRecord(*CXXField.second);
- }
-
- void traverseCXXFieldTemplates() {
- for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates())
- getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second);
- }
-
- void traverseGlobalVariableTemplateRecords() {
- for (const auto &GlobalVariableTemplate : API.getGlobalVariableTemplates())
- getDerived()->visitGlobalVariableTemplateRecord(
- *GlobalVariableTemplate.second);
- }
-
- void traverseGlobalVariableTemplateSpecializationRecords() {
- for (const auto &GlobalVariableTemplateSpecialization :
- API.getGlobalVariableTemplateSpecializations())
- getDerived()->visitGlobalVariableTemplateSpecializationRecord(
- *GlobalVariableTemplateSpecialization.second);
- }
-
- void traverseGlobalVariableTemplatePartialSpecializationRecords() {
- for (const auto &GlobalVariableTemplatePartialSpecialization :
- API.getGlobalVariableTemplatePartialSpecializations())
- getDerived()->visitGlobalVariableTemplatePartialSpecializationRecord(
- *GlobalVariableTemplatePartialSpecialization.second);
- }
-
- void traverseGlobalFunctionTemplateRecords() {
- for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
- getDerived()->visitGlobalFunctionTemplateRecord(
- *GlobalFunctionTemplate.second);
- }
-
- void traverseGlobalFunctionTemplateSpecializationRecords() {
- for (const auto &GlobalFunctionTemplateSpecialization :
- API.getGlobalFunctionTemplateSpecializations())
- getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
- *GlobalFunctionTemplateSpecialization.second);
- }
-
- void traverseConcepts() {
- for (const auto &Concept : API.getConcepts())
- getDerived()->visitConceptRecord(*Concept.second);
- }
-
- void traverseObjCInterfaces() {
- for (const auto &Interface : API.getObjCInterfaces())
- getDerived()->visitObjCContainerRecord(*Interface.second);
- }
-
- void traverseObjCProtocols() {
- for (const auto &Protocol : API.getObjCProtocols())
- getDerived()->visitObjCContainerRecord(*Protocol.second);
- }
-
- void traverseObjCCategories() {
- for (const auto &Category : API.getObjCCategories())
- getDerived()->visitObjCCategoryRecord(*Category.second);
- }
-
- void traverseMacroDefinitionRecords() {
- for (const auto &Macro : API.getMacros())
- getDerived()->visitMacroDefinitionRecord(*Macro.second);
- }
-
- void traverseTypedefRecords() {
- for (const auto &Typedef : API.getTypedefs())
- getDerived()->visitTypedefRecord(*Typedef.second);
- }
-
- void visitNamespaceRecord(const NamespaceRecord &Record){};
-
- /// Visit a global function record.
- void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record){};
-
- /// Visit a global variable record.
- void visitGlobalVariableRecord(const GlobalVariableRecord &Record){};
-
- /// Visit an enum record.
- void visitEnumRecord(const EnumRecord &Record){};
-
- /// Visit a record record.
- void visitRecordRecord(const RecordRecord &Record){};
-
- void visitStaticFieldRecord(const StaticFieldRecord &Record){};
-
- void visitCXXClassRecord(const CXXClassRecord &Record){};
-
- void visitClassTemplateRecord(const ClassTemplateRecord &Record){};
-
- void visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record){};
-
- void visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record){};
-
- void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){};
-
- void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){};
-
- void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
-
- void visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record){};
-
- void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record){};
-
- void visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord &Record) {}
-
- void visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record){};
-
- void visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record){};
-
- void visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord &Record){};
-
- void visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record){};
-
- /// Visit an Objective-C container record.
- void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
-
- /// Visit an Objective-C category record.
- void visitObjCCategoryRecord(const ObjCCategoryRecord &Record){};
-
- /// Visit a macro definition record.
- void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record){};
-
- /// Visit a typedef record.
- void visitTypedefRecord(const TypedefRecord &Record){};
-
-protected:
- const APISet &API;
-
-public:
- APISetVisitor() = delete;
- APISetVisitor(const APISetVisitor &) = delete;
- APISetVisitor(APISetVisitor &&) = delete;
- APISetVisitor &operator=(const APISetVisitor &) = delete;
- APISetVisitor &operator=(APISetVisitor &&) = delete;
-
-protected:
- APISetVisitor(const APISet &API) : API(API) {}
- ~APISetVisitor() = default;
-
- Derived *getDerived() { return static_cast<Derived *>(this); };
-};
-
-} // 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
index 4249ac405fd262..724b087f7aea98 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -17,11 +17,17 @@
#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SYMBOLGRAPHSERIALIZER_H
+#include "clang/Basic/Module.h"
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
-#include "clang/ExtractAPI/Serialization/SerializerBase.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"
@@ -35,7 +41,30 @@ using namespace llvm::json;
/// Common options to customize the visitor output.
struct SymbolGraphSerializerOption {
/// Do not include unnecessary whitespaces to save space.
- bool Compact;
+ 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.
@@ -44,28 +73,54 @@ struct SymbolGraphSerializerOption {
/// 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> {
- /// A JSON array of formatted symbols in \c APISet.
- Array Symbols;
+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;
- /// A JSON array of formatted symbol relationships in \c APISet.
- Array Relationships;
+ /// 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 child symbols should be visited. This is mainly
+ /// Indicates whether to take into account the extended module. This is only
/// useful for \c serializeSingleSymbolSGF.
- bool ShouldRecurse;
+ bool ForceEmitToMainModule;
-public:
- /// Serialize the APIs in \c APISet in the Symbol Graph format.
+ // Stores the references required to construct path components for the
+ // currently visited APIRecord.
+ llvm::SmallVector<SymbolReference, 8> Hierarchy;
+
+ /// The list of symbols to ignore.
///
- /// \returns a JSON object that contains the root of the formatted
- /// Symbol Graph.
- Object serialize();
+ /// Note: This should be consulted before emitting a symbol.
+ const APIIgnoresList &IgnoresList;
- /// Wrap serialize(void) and write out the serialized JSON object to \p os.
- void serialize(raw_ostream &os);
+ const bool EmitSymbolLabelsForTesting = 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.
///
@@ -75,6 +130,7 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
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.
@@ -94,16 +150,32 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
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);
-private:
- /// Just serialize the currently recorded objects in Symbol Graph format.
- Object serializeCurrentGraph();
+ /// 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.
///
@@ -117,124 +189,92 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
/// by the given API set.
/// Note that "module" here is not to be confused with the Clang/C++ module
/// concept.
- Object serializeModule() const;
+ 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;
+ 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 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.
+ /// 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 std::nullopt if this \p Record should be skipped, or a JSON
- /// object containing common symbol information of \p Record.
- template <typename RecordTy>
- std::optional<Object> serializeAPIRecord(const RecordTy &Record) const;
-
- /// Helper method to serialize second-level member records of \p Record and
- /// the member-of relationships.
- template <typename MemberTy>
- void serializeMembers(const APIRecord &Record,
- const SmallVector<std::unique_ptr<MemberTy>> &Members);
-
- /// Serialize the \p Kind relationship between \p Source and \p Target.
- ///
- /// Record the relationship between the two symbols in
- /// SymbolGraphSerializer::Relationships.
- void serializeRelationship(RelationshipKind Kind, SymbolReference Source,
- SymbolReference Target);
-
-protected:
- /// The list of symbols to ignore.
- ///
- /// Note: This should be consulted before emitting a symbol.
- const APIIgnoresList &IgnoresList;
-
- SymbolGraphSerializerOption Options;
-
- llvm::StringSet<> visitedCategories;
+ /// \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:
- void visitNamespaceRecord(const NamespaceRecord &Record);
-
- /// Visit a global function record.
- void visitGlobalFunctionRecord(const GlobalFunctionRecord &Record);
-
- /// Visit a global variable record.
- void visitGlobalVariableRecord(const GlobalVariableRecord &Record);
-
- /// Visit an enum record.
- void visitEnumRecord(const EnumRecord &Record);
-
- /// Visit a record record.
- void visitRecordRecord(const RecordRecord &Record);
-
- void visitStaticFieldRecord(const StaticFieldRecord &Record);
+ // 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);
- void visitCXXClassRecord(const CXXClassRecord &Record);
+ bool visitAPIRecord(const APIRecord *Record);
- void visitClassTemplateRecord(const ClassTemplateRecord &Record);
-
- void visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record);
-
- void visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record);
-
- void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
+ /// Visit a global function record.
+ bool visitGlobalFunctionRecord(const GlobalFunctionRecord *Record);
- void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
+ bool visitCXXClassRecord(const CXXClassRecord *Record);
- void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
+ bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
- void visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record);
+ bool visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord *Record);
- void visitCXXFieldRecord(const CXXFieldRecord &Record);
+ bool visitCXXMethodRecord(const CXXMethodRecord *Record);
- void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
+ bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
- void visitConceptRecord(const ConceptRecord &Record);
+ bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
- void
- visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record);
+ bool visitConceptRecord(const ConceptRecord *Record);
- void visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record);
+ bool
+ visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
- void visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record);
+ bool visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord *Record);
- void
- visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
+ bool
+ visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
- void visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record);
+ bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
- /// Visit an Objective-C container record.
- void visitObjCContainerRecord(const ObjCContainerRecord &Record);
+ bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
- /// Visit an Objective-C category record.
- void visitObjCCategoryRecord(const ObjCCategoryRecord &Record);
+ bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record);
+ bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record);
+ bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
- /// Visit a macro definition record.
- void visitMacroDefinitionRecord(const MacroDefinitionRecord &Record);
+ bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
- /// Visit a typedef record.
- void visitTypedefRecord(const TypedefRecord &Record);
+ bool
+ visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
- /// Serialize a single record.
- void serializeSingleRecord(const APIRecord *Record);
+ bool walkUpFromTypedefRecord(const TypedefRecord *Record);
+ bool visitTypedefRecord(const TypedefRecord *Record);
SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList,
- SymbolGraphSerializerOption Options = {},
- bool ShouldRecurse = true)
- : APISetVisitor(API), ShouldRecurse(ShouldRecurse),
- IgnoresList(IgnoresList), Options(Options) {}
+ bool EmitSymbolLabelsForTesting = false,
+ bool ForceEmitToMainModule = false)
+ : Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
+ IgnoresList(IgnoresList),
+ EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {}
};
} // namespace extractapi
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 8085dbcbf671a6..864af66b337069 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -15,6 +15,7 @@
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
#include <map>
@@ -387,6 +388,22 @@ class FrontendOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesShareFileManager : 1;
+ /// Whether to emit symbol graph files as a side effect of compilation.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitSymbolGraph : 1;
+
+ /// Whether to emit additional symbol graphs for extended modules.
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitExtensionSymbolGraphs : 1;
+
+ /// Whether to emit symbol labels for testing in generated symbol graphs
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitSymbolGraphSymbolLabelsForTesting : 1;
+
+ /// Whether to emit symbol labels for testing in generated symbol graphs
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned EmitPrettySymbolGraphs : 1;
+
CodeCompleteOptions CodeCompleteOpts;
/// Specifies the output format of the AST.
@@ -496,10 +513,8 @@ class FrontendOptions {
// ignore when extracting documentation.
std::vector<std::string> ExtractAPIIgnoresFileList;
- // Currently this is only used as part of the `-emit-symbol-graph`
- // action.
// Location of output directory where symbol graph information would
- // be dumped
+ // be dumped. This overrides regular -o output file specification
std::string SymbolGraphOutputDir;
/// Args to pass to the plugins
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 1a0f5f27eda2fc..e6c1767a0082dd 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -49,6 +49,7 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
+#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -5889,6 +5890,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
&JA);
}
+ if (JA.getType() == types::TY_API_INFO &&
+ C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
+ C.getArgs().hasArg(options::OPT_o))
+ Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
+ << C.getArgs().getLastArgValue(options::OPT_o);
+
// DXC defaults to standard out when generating assembly. We check this after
// any DXC flags that might specify a file.
if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b03ac6018d2b80..33f0b05a37696b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5037,11 +5037,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getType() == types::TY_API_INFO &&
"Extract API actions must generate a API information.");
CmdArgs.push_back("-extract-api");
+
+ if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf))
+ PrettySGFArg->render(Args, CmdArgs);
+
+ Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ);
+
if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
ProductNameArg->render(Args, CmdArgs);
if (Arg *ExtractAPIIgnoresFileArg =
Args.getLastArg(options::OPT_extract_api_ignores_EQ))
ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
+ if (Arg *EmitExtensionSymbolGraphs =
+ Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) {
+ if (!SymbolGraphDirArg)
+ D.Diag(diag::err_drv_missing_symbol_graph_dir);
+
+ EmitExtensionSymbolGraphs->render(Args, CmdArgs);
+ }
+ if (SymbolGraphDirArg)
+ SymbolGraphDirArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index aa7a1e9360f474..5a62c5deb24083 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -13,514 +13,67 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/API.h"
-#include "clang/AST/CommentCommandTraits.h"
-#include "clang/AST/CommentLexer.h"
#include "clang/AST/RawCommentList.h"
+#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
#include <memory>
using namespace clang::extractapi;
using namespace llvm;
-namespace {
+SymbolReference::SymbolReference(const APIRecord *R)
+ : Name(R->Name), USR(R->USR), Record(R) {}
-template <typename RecordTy, typename... CtorArgsTy>
-RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
- APISet::RecordMap<RecordTy> &RecordMap,
- StringRef USR, CtorArgsTy &&...CtorArgs) {
- auto Result = RecordMap.insert({USR, nullptr});
-
- // Create the record if it does not already exist
- if (Result.second)
- Result.first->second =
- std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
-
- auto *Record = Result.first->second.get();
- USRLookupTable.insert({USR, Record});
- return Record;
-}
-
-} // namespace
-
-NamespaceRecord *
-APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader);
-
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-GlobalVariableRecord *
-APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
- std::move(Availability), Linkage, Comment, Fragments,
- SubHeading, IsFromSystemHeader);
-}
-
-GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR,
- Name, Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Template,
- IsFromSystemHeader);
-}
-
-GlobalFunctionRecord *APISet::addGlobalFunction(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
- std::move(Availability), Linkage, Comment, Fragments,
- SubHeading, Signature, IsFromSystemHeader);
-}
-
-GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- Template Template, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
- Name, Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Signature, Template,
- IsFromSystemHeader);
-}
-
-GlobalFunctionTemplateSpecializationRecord *
-APISet::addGlobalFunctionTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(
- USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
- Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
- Signature, IsFromSystemHeader);
-}
-
-EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- auto Record = std::make_unique<EnumConstantRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Enum->USR, Enum->Name, Enum->getKind(), Enum);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Enum->Constants.emplace_back(std::move(Record)).get();
-}
-
-EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
-}
-
-RecordFieldRecord *APISet::addRecordField(
- RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind, bool IsFromSystemHeader) {
- auto RecordField = std::make_unique<RecordFieldRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- Kind, IsFromSystemHeader);
- RecordField->ParentInformation = APIRecord::HierarchyInformation(
- Record->USR, Record->Name, Record->getKind(), Record);
- USRBasedLookupTable.insert({USR, RecordField.get()});
- return Record->Fields.emplace_back(std::move(RecordField)).get();
-}
-
-RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- APIRecord::RecordKind Kind,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Kind, IsFromSystemHeader);
-}
-
-StaticFieldRecord *
-APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading, SymbolReference Context,
- AccessControl Access, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
- std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, Context, Access,
- IsFromSystemHeader);
-}
-
-CXXFieldRecord *
-APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, AccessControl Access,
- bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
- return Record;
-}
-
-CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, Template Template, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Access, Template, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-CXXClassRecord *
-APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
- AccessControl Access, bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability),
- Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplateRecord *APISet::addClassTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Template, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- AccessControl Access, bool IsFromSystemHeader) {
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR,
- Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-ClassTemplatePartialSpecializationRecord *
-APISet::addClassTemplatePartialSpecialization(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- Template Template, AccessControl Access, bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc,
- std::move(Availability), Comment, Declaration, SubHeading, Template,
- Access, IsFromSystemHeader);
- if (Parent)
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
- return Record;
-}
-
-GlobalVariableTemplateSpecializationRecord *
-APISet::addGlobalVariableTemplateSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable,
- GlobalVariableTemplateSpecializations, USR, Name,
- Loc, std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, IsFromSystemHeader);
-}
-
-GlobalVariableTemplatePartialSpecializationRecord *
-APISet::addGlobalVariableTemplatePartialSpecialization(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, Template Template,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(
- USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR,
- Name, Loc, std::move(Availability), Linkage, Comment, Declaration,
- SubHeading, Template, IsFromSystemHeader);
-}
-
-ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- Template Template, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Template, IsFromSystemHeader);
-}
-
-CXXMethodRecord *APISet::addCXXInstanceMethod(
- APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
- CXXMethodRecord *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
- CXXClassRecord);
- return Record;
-}
-
-CXXMethodRecord *APISet::addCXXStaticMethod(
- APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
- CXXMethodRecord *Record =
- addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
- CXXClassRecord);
- return Record;
-}
-
-CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access, Template Template,
- bool IsFromSystemHeader) {
- auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
- Name, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, Signature, Access,
- Template, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
- APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, AccessControl Access,
- bool IsFromSystemHeader) {
-
- auto *Record = addTopLevelRecord(
- USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
- std::move(Availability), Comment, Declaration, SubHeading, Signature,
- Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Parent->USR, Parent->Name, Parent->getKind(), Parent);
-
- return Record;
-}
-
-ObjCCategoryRecord *APISet::addObjCCategory(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- SymbolReference Interface, bool IsFromSystemHeader,
- bool IsFromExternalModule) {
- // Create the category record.
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, Interface, IsFromSystemHeader);
-
- Record->IsFromExternalModule = IsFromExternalModule;
-
- auto It = ObjCInterfaces.find(Interface.USR);
- if (It != ObjCInterfaces.end())
- It->second->Categories.push_back(Record);
-
- return Record;
-}
-
-ObjCInterfaceRecord *
-APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference SuperClass, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
- std::move(Availability), Linkage, Comment,
- Declaration, SubHeading, SuperClass,
- IsFromSystemHeader);
-}
-
-ObjCMethodRecord *APISet::addObjCMethod(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsInstanceMethod,
- bool IsFromSystemHeader) {
- std::unique_ptr<ObjCMethodRecord> Record;
- if (IsInstanceMethod)
- Record = std::make_unique<ObjCInstanceMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
-
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Methods.emplace_back(std::move(Record)).get();
-}
-
-ObjCPropertyRecord *APISet::addObjCProperty(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
- StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
- bool IsFromSystemHeader) {
- std::unique_ptr<ObjCPropertyRecord> Record;
- if (IsInstanceProperty)
- Record = std::make_unique<ObjCInstancePropertyRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassPropertyRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Properties.emplace_back(std::move(Record)).get();
-}
-
-ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
- auto Record = std::make_unique<ObjCInstanceVariableRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
- Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Ivars.emplace_back(std::move(Record)).get();
+APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
+ switch (Ctx->getKind()) {
+#define RECORD_CONTEXT(CLASS, KIND) \
+ case KIND: \
+ return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
+#include "clang/ExtractAPI/APIRecords.inc"
+ default:
+ return nullptr;
+ // llvm_unreachable("RecordContext derived class isn't propertly
+ // implemented");
+ }
}
-ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- AvailabilityInfo Availability,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
+RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
+ if (!Record)
+ return nullptr;
+ switch (Record->getKind()) {
+#define RECORD_CONTEXT(CLASS, KIND) \
+ case KIND: \
+ return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
+#include "clang/ExtractAPI/APIRecords.inc"
+ default:
+ return nullptr;
+ // llvm_unreachable("RecordContext derived class isn't propertly
+ // implemented");
+ }
}
-MacroDefinitionRecord *
-APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
- Declaration, SubHeading, IsFromSystemHeader);
-}
+void RecordContext::addToRecordChain(APIRecord *Record) const {
+ if (!First) {
+ First = Record;
+ Last = Record;
+ return;
+ }
-TypedefRecord *
-APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference UnderlyingType, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
- std::move(Availability), Comment, Declaration,
- SubHeading, UnderlyingType, IsFromSystemHeader);
+ Last->NextInContext = Record;
+ Last = Record;
}
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
if (USR.empty())
return nullptr;
- return USRBasedLookupTable.lookup(USR);
-}
-
-StringRef APISet::recordUSR(const Decl *D) {
- SmallString<128> USR;
- index::generateUSRForDecl(D, USR);
- return copyString(USR);
-}
+ auto FindIt = USRBasedLookupTable.find(USR);
+ if (FindIt != USRBasedLookupTable.end())
+ return FindIt->getSecond().get();
-StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
- const SourceManager &SM) {
- SmallString<128> USR;
- index::generateUSRForMacro(Name, SL, SM, USR);
- return copyString(USR);
+ return nullptr;
}
StringRef APISet::copyString(StringRef String) {
@@ -528,15 +81,22 @@ StringRef APISet::copyString(StringRef String) {
return {};
// No need to allocate memory and copy if the string has already been stored.
- if (StringAllocator.identifyObject(String.data()))
+ if (Allocator.identifyObject(String.data()))
return String;
- void *Ptr = StringAllocator.Allocate(String.size(), 1);
+ void *Ptr = Allocator.Allocate(String.size(), 1);
memcpy(Ptr, String.data(), String.size());
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}
+SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
+ StringRef Source) {
+ return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
+}
+
APIRecord::~APIRecord() {}
+RecordRecord::~RecordRecord() {}
+RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
ObjCMethodRecord::~ObjCMethodRecord() {}
ObjCPropertyRecord::~ObjCPropertyRecord() {}
@@ -546,8 +106,10 @@ void GlobalFunctionRecord::anchor() {}
void GlobalVariableRecord::anchor() {}
void EnumConstantRecord::anchor() {}
void EnumRecord::anchor() {}
-void RecordFieldRecord::anchor() {}
-void RecordRecord::anchor() {}
+void StructFieldRecord::anchor() {}
+void StructRecord::anchor() {}
+void UnionFieldRecord::anchor() {}
+void UnionRecord::anchor() {}
void CXXFieldRecord::anchor() {}
void CXXClassRecord::anchor() {}
void CXXConstructorRecord::anchor() {}
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 80a0a498dc4001..0f9e1eb22a1d96 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -60,23 +60,44 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
} // namespace
-DeclarationFragments &DeclarationFragments::appendSpace() {
+DeclarationFragments &
+DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
if (!Fragments.empty()) {
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
// 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(' ');
+ if (Last.Spelling.back() != Character) { // avoid duplicates at end
+ Last.Spelling.push_back(Character);
}
} else {
- append(" ", FragmentKind::Text);
+ append("", FragmentKind::Text);
+ Fragments.back().Spelling.push_back(Character);
}
}
return *this;
}
+DeclarationFragments &DeclarationFragments::appendSpace() {
+ return appendUnduplicatedTextCharacter(' ');
+}
+
+DeclarationFragments &DeclarationFragments::appendSemicolon() {
+ return appendUnduplicatedTextCharacter(';');
+}
+
+DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
+ if (Fragments.empty())
+ return *this;
+
+ Fragment &Last = Fragments.back();
+ if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
+ Last.Spelling.pop_back();
+
+ return *this;
+}
+
StringRef DeclarationFragments::getFragmentKindString(
DeclarationFragments::FragmentKind Kind) {
switch (Kind) {
@@ -469,7 +490,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -511,7 +532,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -543,7 +564,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
return Fragments;
}
@@ -712,7 +733,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
@@ -741,7 +762,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -757,7 +778,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
@@ -775,7 +796,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
@@ -790,7 +811,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -820,7 +841,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
@@ -860,7 +881,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -891,7 +912,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments
@@ -923,7 +944,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
@@ -1028,7 +1049,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1069,7 +1090,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1091,7 +1112,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1110,7 +1131,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1132,7 +1153,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments
@@ -1203,7 +1224,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
- .append(Category->getClassInterface()->getName(),
+ .append(Interface->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
@@ -1277,7 +1298,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
@@ -1378,7 +1399,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .append(";", DeclarationFragments::FragmentKind::Text);
+ .appendSemicolon();
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
@@ -1422,7 +1443,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+ return Fragments.appendSemicolon();
}
// Instantiate template for FunctionDecl.
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 275f49be22e15a..d6335854cbf262 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -30,6 +30,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Index/USRGeneration.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
@@ -39,6 +40,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -327,11 +329,12 @@ class MacroCallback : public PPCallbacks {
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
- StringRef USR =
- API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
+ SmallString<128> USR;
+ index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
+ USR);
- API.addMacroDefinition(
- Name, USR, Loc,
+ API.createRecord<extractapi::MacroDefinitionRecord>(
+ USR, Name, SymbolReference(), Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
@@ -372,40 +375,57 @@ class APIMacroCallback : public MacroCallback {
LocationFileChecker &LCF;
};
+std::unique_ptr<llvm::raw_pwrite_stream>
+createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) {
+ auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir;
+
+ SmallString<256> FileName;
+ llvm::sys::path::append(FileName, OutputDirectory,
+ BaseName + ".symbols.json");
+ return CI.createOutputFile(
+ FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false,
+ /*UseTemporary*/ true, /*CreateMissingDirectories*/ true);
+}
+
} // namespace
-void ExtractAPIActionBase::ImplEndSourceFileAction() {
- if (!OS)
- return;
+void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) {
+ SymbolGraphSerializerOption SerializationOptions;
+ SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs;
+ SerializationOptions.EmitSymbolLabelsForTesting =
+ CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting;
+
+ if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) {
+ auto ConstructOutputFile = [&CI](Twine BaseName) {
+ return createAdditionalSymbolGraphFile(CI, BaseName);
+ };
+
+ SymbolGraphSerializer::serializeWithExtensionGraphs(
+ *OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions);
+ } else {
+ SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList,
+ SerializationOptions);
+ }
- // Setup a SymbolGraphSerializer to write out collected API information in
- // the Symbol Graph format.
- // FIXME: Make the kind of APISerializer configurable.
- SymbolGraphSerializer SGSerializer(*API, IgnoresList);
- SGSerializer.serialize(*OS);
+ // Flush the stream and close the main output stream.
OS.reset();
}
-std::unique_ptr<raw_pwrite_stream>
-ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
- std::unique_ptr<raw_pwrite_stream> OS;
- OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile,
- /*Extension=*/"json",
- /*RemoveFileOnSignal=*/false);
- if (!OS)
- return nullptr;
- return OS;
-}
-
std::unique_ptr<ASTConsumer>
ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- OS = CreateOutputFile(CI, InFile);
+ auto ProductName = CI.getFrontendOpts().ProductName;
+
+ if (CI.getFrontendOpts().SymbolGraphOutputDir.empty())
+ OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile,
+ /*Extension*/ "symbols.json",
+ /*RemoveFileOnSignal*/ false,
+ /*CreateMissingDirectories*/ true);
+ else
+ OS = createAdditionalSymbolGraphFile(CI, ProductName);
if (!OS)
return nullptr;
- auto ProductName = CI.getFrontendOpts().ProductName;
-
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
API = std::make_unique<APISet>(
@@ -495,7 +515,9 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}
-void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
+void ExtractAPIAction::EndSourceFileAction() {
+ ImplEndSourceFileAction(getCompilerInstance());
+}
std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
@@ -506,11 +528,9 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
CreatedASTConsumer = true;
- OS = CreateOutputFile(CI, InFile);
- if (!OS)
- return nullptr;
-
- auto ProductName = CI.getFrontendOpts().ProductName;
+ ProductName = CI.getFrontendOpts().ProductName;
+ auto InputFilename = llvm::sys::path::filename(InFile);
+ OS = createAdditionalSymbolGraphFile(CI, InputFilename);
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
@@ -552,32 +572,6 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();
if (CreatedASTConsumer) {
- ImplEndSourceFileAction();
+ ImplEndSourceFileAction(getCompilerInstance());
}
}
-
-std::unique_ptr<raw_pwrite_stream>
-WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI,
- StringRef InFile) {
- std::unique_ptr<raw_pwrite_stream> OS;
- std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir;
-
- // The symbol graphs need to be generated as a side effect of regular
- // compilation so the output should be dumped in the directory provided with
- // the command line option.
- llvm::SmallString<128> OutFilePath(OutputDir);
- auto Seperator = llvm::sys::path::get_separator();
- auto Infilename = llvm::sys::path::filename(InFile);
- OutFilePath.append({Seperator, Infilename});
- llvm::sys::path::replace_extension(OutFilePath, "json");
- // StringRef outputFilePathref = *OutFilePath;
-
- // don't use the default output file
- OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false,
- /*RemoveFileOnSignal=*/true,
- /*UseTemporary=*/true,
- /*CreateMissingDirectories=*/true);
- if (!OS)
- return nullptr;
- return OS;
-}
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 545860acb7db80..57f966c8b2be35 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -14,13 +14,17 @@
#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Version.h"
+#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/raw_ostream.h"
+#include <iterator>
#include <optional>
#include <type_traits>
@@ -33,26 +37,27 @@ 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, std::optional<Object> Obj) {
+void serializeObject(Object &Paren, StringRef Key,
+ std::optional<Object> &&Obj) {
if (Obj)
Paren[Key] = std::move(*Obj);
}
-/// Helper function to inject a StringRef \p String into an object \p Paren at
-/// position \p Key
-void serializeString(Object &Paren, StringRef Key,
- std::optional<std::string> String) {
- if (String)
- Paren[Key] = std::move(*String);
-}
-
/// Helper function to inject a JSON array \p Array into object \p Paren at
/// position \p Key.
-void serializeArray(Object &Paren, StringRef Key, std::optional<Array> Array) {
+void serializeArray(Object &Paren, StringRef Key,
+ std::optional<Array> &&Array) {
if (Array)
Paren[Key] = std::move(*Array);
}
+/// Helper function to inject a JSON array composed of the values in \p C into
+/// object \p Paren at position \p Key.
+template <typename ContainerTy>
+void serializeArray(Object &Paren, StringRef Key, ContainerTy &&C) {
+ Paren[Key] = Array(C);
+}
+
/// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version
/// format.
///
@@ -248,6 +253,7 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
return std::nullopt;
Object DocComment;
+
Array LinesArray;
for (const auto &CommentLine : Comment) {
Object Line;
@@ -256,7 +262,8 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
serializeSourceRange(CommentLine.Begin, CommentLine.End));
LinesArray.emplace_back(std::move(Line));
}
- serializeArray(DocComment, "lines", LinesArray);
+
+ serializeArray(DocComment, "lines", std::move(LinesArray));
return DocComment;
}
@@ -322,19 +329,14 @@ serializeDeclarationFragments(const DeclarationFragments &DF) {
/// - \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 serializeNames(const APIRecord *Record) {
Object Names;
- if (auto *CategoryRecord =
- dyn_cast_or_null<const ObjCCategoryRecord>(&Record))
- Names["title"] =
- (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str();
- else
- Names["title"] = Record.Name;
+ Names["title"] = Record->Name;
serializeArray(Names, "subHeading",
- serializeDeclarationFragments(Record.SubHeading));
+ serializeDeclarationFragments(Record->SubHeading));
DeclarationFragments NavigatorFragments;
- NavigatorFragments.append(Record.Name,
+ NavigatorFragments.append(Record->Name,
DeclarationFragments::FragmentKind::Identifier,
/*PreciseIdentifier*/ "");
serializeArray(Names, "navigator",
@@ -351,7 +353,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Object Kind;
switch (RK) {
case APIRecord::RK_Unknown:
- llvm_unreachable("Records should have an explicit kind");
+ Kind["identifier"] = AddLangPrefix("unknown");
+ Kind["displayName"] = "Unknown";
break;
case APIRecord::RK_Namespace:
Kind["identifier"] = AddLangPrefix("namespace");
@@ -484,10 +487,6 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("class.extension");
Kind["displayName"] = "Class Extension";
break;
- case APIRecord::RK_ObjCCategoryModule:
- Kind["identifier"] = AddLangPrefix("module.extension");
- Kind["displayName"] = "Module Extension";
- break;
case APIRecord::RK_ObjCProtocol:
Kind["identifier"] = AddLangPrefix("protocol");
Kind["displayName"] = "Protocol";
@@ -500,6 +499,8 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("typealias");
Kind["displayName"] = "Type Alias";
break;
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
}
return Kind;
@@ -514,12 +515,18 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
return serializeSymbolKind(Record.getKind(), Lang);
}
+/// Serialize the function signature field, 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.
template <typename RecordTy>
-std::optional<Object>
-serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
+void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
const auto &FS = Record.Signature;
if (FS.empty())
- return std::nullopt;
+ return;
Object Signature;
serializeArray(Signature, "returns",
@@ -537,63 +544,14 @@ serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
if (!Parameters.empty())
Signature["parameters"] = std::move(Parameters);
- return Signature;
+ serializeObject(Paren, "functionSignature", std::move(Signature));
}
template <typename RecordTy>
-std::optional<Object>
-serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::false_type) {
- return std::nullopt;
-}
-
-/// Serialize the function signature field, 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 std::nullopt if \p FS is empty, or an \c Object containing the
-/// formatted function signature.
-template <typename RecordTy>
-void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
- serializeObject(Paren, "functionSignature",
- serializeFunctionSignatureMixinImpl(
- Record, has_function_signature<RecordTy>()));
-}
-
-template <typename RecordTy>
-std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
- std::true_type) {
- const auto &AccessControl = Record.Access;
- std::string Access;
- if (AccessControl.empty())
- return std::nullopt;
- Access = AccessControl.getAccess();
- return Access;
-}
-
-template <typename RecordTy>
-std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
- std::false_type) {
- return std::nullopt;
-}
-
-template <typename RecordTy>
-void serializeAccessMixin(Object &Paren, const RecordTy &Record) {
- auto accessLevel = serializeAccessMixinImpl(Record, has_access<RecordTy>());
- if (!accessLevel.has_value())
- accessLevel = "public";
- serializeString(Paren, "accessLevel", accessLevel);
-}
-
-template <typename RecordTy>
-std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
- std::true_type) {
+void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
const auto &Template = Record.Templ;
if (Template.empty())
- return std::nullopt;
+ return;
Object Generics;
Array GenericParameters;
@@ -619,97 +577,66 @@ std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
if (!GenericConstraints.empty())
Generics["constraints"] = std::move(GenericConstraints);
- return Generics;
-}
-
-template <typename RecordTy>
-std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
- std::false_type) {
- return std::nullopt;
+ serializeObject(Paren, "swiftGenerics", Generics);
}
-template <typename RecordTy>
-void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
- serializeObject(Paren, "swiftGenerics",
- serializeTemplateMixinImpl(Record, has_template<RecordTy>()));
-}
+Array generateParentContexts(const SmallVectorImpl<SymbolReference> &Parents,
+ Language Lang) {
+ Array ParentContexts;
-struct PathComponent {
- StringRef USR;
- StringRef Name;
- APIRecord::RecordKind Kind;
+ for (const auto &Parent : Parents) {
+ Object Elem;
+ Elem["usr"] = Parent.USR;
+ Elem["name"] = Parent.Name;
+ if (Parent.Record)
+ Elem["kind"] =
+ serializeSymbolKind(Parent.Record->getKind(), Lang)["identifier"];
+ else
+ Elem["kind"] =
+ serializeSymbolKind(APIRecord::RK_Unknown, Lang)["identifier"];
+ ParentContexts.emplace_back(std::move(Elem));
+ }
- PathComponent(StringRef USR, StringRef Name, APIRecord::RecordKind Kind)
- : USR(USR), Name(Name), Kind(Kind) {}
-};
+ return ParentContexts;
+}
-template <typename RecordTy>
-bool generatePathComponents(
- const RecordTy &Record, const APISet &API,
- function_ref<void(const PathComponent &)> ComponentTransformer) {
- SmallVector<PathComponent, 4> ReverseComponenents;
- ReverseComponenents.emplace_back(Record.USR, Record.Name, Record.getKind());
- const auto *CurrentParent = &Record.ParentInformation;
- bool FailedToFindParent = false;
- while (CurrentParent && !CurrentParent->empty()) {
- PathComponent CurrentParentComponent(CurrentParent->ParentUSR,
- CurrentParent->ParentName,
- CurrentParent->ParentKind);
-
- auto *ParentRecord = CurrentParent->ParentRecord;
- // Slow path if we don't have a direct reference to the ParentRecord
- if (!ParentRecord)
- ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR);
-
- // If the parent is a category extended from internal module then we need to
- // pretend this belongs to the associated interface.
- if (auto *CategoryRecord =
- dyn_cast_or_null<ObjCCategoryRecord>(ParentRecord)) {
- if (!CategoryRecord->IsFromExternalModule) {
- ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR);
- CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR,
- CategoryRecord->Interface.Name,
- APIRecord::RK_ObjCInterface);
- }
- }
-
- // The parent record doesn't exist which means the symbol shouldn't be
- // treated as part of the current product.
- if (!ParentRecord) {
- FailedToFindParent = true;
- break;
- }
-
- ReverseComponenents.push_back(std::move(CurrentParentComponent));
- CurrentParent = &ParentRecord->ParentInformation;
+/// Walk the records parent information in reverse to generate a hierarchy
+/// suitable for serialization.
+SmallVector<SymbolReference, 8>
+generateHierarchyFromRecord(const APIRecord *Record) {
+ SmallVector<SymbolReference, 8> ReverseHierarchy;
+ for (const auto *Current = Record; Current != nullptr;
+ Current = Current->Parent.Record)
+ ReverseHierarchy.emplace_back(Current);
+
+ return SmallVector<SymbolReference, 8>(
+ std::make_move_iterator(ReverseHierarchy.rbegin()),
+ std::make_move_iterator(ReverseHierarchy.rend()));
+}
+
+SymbolReference getHierarchyReference(const APIRecord *Record,
+ const APISet &API) {
+ // If the parent is a category extended from internal module then we need to
+ // pretend this belongs to the associated interface.
+ if (auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(Record)) {
+ return CategoryRecord->Interface;
+ // FIXME: TODO generate path components correctly for categories extending
+ // an external module.
}
- for (const auto &PC : reverse(ReverseComponenents))
- ComponentTransformer(PC);
-
- return FailedToFindParent;
+ return SymbolReference(Record);
}
-Object serializeParentContext(const PathComponent &PC, Language Lang) {
- Object ParentContextElem;
- ParentContextElem["usr"] = PC.USR;
- ParentContextElem["name"] = PC.Name;
- ParentContextElem["kind"] = serializeSymbolKind(PC.Kind, Lang)["identifier"];
- return ParentContextElem;
-}
+} // namespace
-template <typename RecordTy>
-Array generateParentContexts(const RecordTy &Record, const APISet &API,
- Language Lang) {
- Array ParentContexts;
- generatePathComponents(
- Record, API, [Lang, &ParentContexts](const PathComponent &PC) {
- ParentContexts.push_back(serializeParentContext(PC, Lang));
- });
+Object *ExtendedModule::addSymbol(Object &&Symbol) {
+ Symbols.emplace_back(std::move(Symbol));
+ return Symbols.back().getAsObject();
+}
- return ParentContexts;
+void ExtendedModule::addRelationship(Object &&Relationship) {
+ Relationships.emplace_back(std::move(Relationship));
}
-} // namespace
/// Defines the format version emitted by SymbolGraphSerializer.
const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
@@ -722,84 +649,44 @@ Object SymbolGraphSerializer::serializeMetadata() const {
return Metadata;
}
-Object SymbolGraphSerializer::serializeModule() const {
+Object
+SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName) const {
Object Module;
- // The user is expected to always pass `--product-name=` on the command line
- // to populate this field.
- Module["name"] = API.ProductName;
+ Module["name"] = ModuleName;
serializeObject(Module, "platform", serializePlatform(API.getTarget()));
return Module;
}
-bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
- // Skip explicitly ignored symbols.
- if (IgnoresList.shouldIgnore(Record.Name))
+bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
+ if (!Record)
return true;
// Skip unconditionally unavailable symbols
- if (Record.Availability.isUnconditionallyUnavailable())
+ if (Record->Availability.isUnconditionallyUnavailable())
return true;
// Filter out symbols prefixed with an underscored as they are understood to
// be symbols clients should not use.
- if (Record.Name.starts_with("_"))
+ if (Record->Name.starts_with("_"))
+ return true;
+
+ // Skip explicitly ignored symbols.
+ if (IgnoresList.shouldIgnore(Record->Name))
return true;
return false;
}
-template <typename RecordTy>
-std::optional<Object>
-SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
- if (shouldSkip(Record))
- return std::nullopt;
-
- Object Obj;
- serializeObject(Obj, "identifier",
- serializeIdentifier(Record, API.getLanguage()));
- serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage()));
- serializeObject(Obj, "names", serializeNames(Record));
- serializeObject(
- Obj, "location",
- serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
- serializeArray(Obj, "availability",
- serializeAvailability(Record.Availability));
- serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
- serializeArray(Obj, "declarationFragments",
- serializeDeclarationFragments(Record.Declaration));
- SmallVector<StringRef, 4> PathComponentsNames;
- // If this returns true it indicates that we couldn't find a symbol in the
- // hierarchy.
- if (generatePathComponents(Record, API,
- [&PathComponentsNames](const PathComponent &PC) {
- PathComponentsNames.push_back(PC.Name);
- }))
- return {};
-
- serializeArray(Obj, "pathComponents", Array(PathComponentsNames));
+ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
+ if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
+ return *ModuleForCurrentSymbol;
- serializeFunctionSignatureMixin(Obj, Record);
- serializeAccessMixin(Obj, Record);
- serializeTemplateMixin(Obj, Record);
-
- return Obj;
+ return MainModule;
}
-template <typename MemberTy>
-void SymbolGraphSerializer::serializeMembers(
- const APIRecord &Record,
- const SmallVector<std::unique_ptr<MemberTy>> &Members) {
- // Members should not be serialized if we aren't recursing.
- if (!ShouldRecurse)
- return;
- for (const auto &Member : Members) {
- auto MemberRecord = serializeAPIRecord(*Member);
- if (!MemberRecord)
- continue;
-
- Symbols.emplace_back(std::move(*MemberRecord));
- serializeRelationship(RelationshipKind::MemberOf, *Member, Record);
- }
+Array SymbolGraphSerializer::serializePathComponents(
+ const APIRecord *Record) const {
+ return Array(map_range(Hierarchy, [](auto Elt) { return Elt.Name; }));
}
StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
@@ -816,6 +703,33 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
llvm_unreachable("Unhandled relationship kind");
}
+void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
+ const SymbolReference &Source,
+ const SymbolReference &Target,
+ ExtendedModule &Into) {
+ Object Relationship;
+ SmallString<64> TestRelLabel;
+ if (EmitSymbolLabelsForTesting) {
+ llvm::raw_svector_ostream OS(TestRelLabel);
+ OS << SymbolGraphSerializer::getRelationshipString(Kind) << " $ "
+ << Source.USR << " $ ";
+ if (Target.USR.empty())
+ OS << Target.Name;
+ else
+ OS << Target.USR;
+ Relationship["!testRelLabel"] = TestRelLabel;
+ }
+ Relationship["source"] = Source.USR;
+ Relationship["target"] = Target.USR;
+ Relationship["targetFallback"] = Target.Name;
+ Relationship["kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
+
+ if (ForceEmitToMainModule)
+ MainModule.addRelationship(std::move(Relationship));
+ else
+ Into.addRelationship(std::move(Relationship));
+}
+
StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
switch (Kind) {
case ConstraintKind::Conformance:
@@ -826,430 +740,324 @@ StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
llvm_unreachable("Unhandled constraint kind");
}
-void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
- SymbolReference Source,
- SymbolReference Target) {
- Object Relationship;
- Relationship["source"] = Source.USR;
- Relationship["target"] = Target.USR;
- Relationship["targetFallback"] = Target.Name;
- Relationship["kind"] = getRelationshipString(Kind);
-
- Relationships.emplace_back(std::move(Relationship));
-}
+void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) {
+ Object Obj;
-void SymbolGraphSerializer::visitNamespaceRecord(
- const NamespaceRecord &Record) {
- auto Namespace = serializeAPIRecord(Record);
- if (!Namespace)
- return;
- Symbols.emplace_back(std::move(*Namespace));
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+ // If we need symbol labels for testing emit the USR as the value and the key
+ // starts with '!'' to ensure it ends up at the top of the object.
+ if (EmitSymbolLabelsForTesting)
+ Obj["!testLabel"] = Record->USR;
-void SymbolGraphSerializer::visitGlobalFunctionRecord(
- const GlobalFunctionRecord &Record) {
- auto Obj = serializeAPIRecord(Record);
- if (!Obj)
- return;
+ serializeObject(Obj, "identifier",
+ serializeIdentifier(*Record, API.getLanguage()));
+ serializeObject(Obj, "kind", serializeSymbolKind(*Record, API.getLanguage()));
+ serializeObject(Obj, "names", serializeNames(Record));
+ serializeObject(
+ Obj, "location",
+ serializeSourceLocation(Record->Location, /*IncludeFileURI=*/true));
+ serializeArray(Obj, "availability",
+ serializeAvailability(Record->Availability));
+ serializeObject(Obj, "docComment", serializeDocComment(Record->Comment));
+ serializeArray(Obj, "declarationFragments",
+ serializeDeclarationFragments(Record->Declaration));
- Symbols.emplace_back(std::move(*Obj));
-}
+ Obj["pathComponents"] = serializePathComponents(Record);
+ Obj["accessLevel"] = Record->Access.getAccess();
-void SymbolGraphSerializer::visitGlobalVariableRecord(
- const GlobalVariableRecord &Record) {
- auto Obj = serializeAPIRecord(Record);
- if (!Obj)
- return;
+ ExtendedModule &Module = getModuleForCurrentSymbol();
+ // If the hierarchy has at least one parent and child.
+ if (Hierarchy.size() >= 2)
+ serializeRelationship(MemberOf, Hierarchy.back(),
+ Hierarchy[Hierarchy.size() - 2], Module);
- Symbols.emplace_back(std::move(*Obj));
+ CurrentSymbol = Module.addSymbol(std::move(Obj));
}
-void SymbolGraphSerializer::visitEnumRecord(const EnumRecord &Record) {
- auto Enum = serializeAPIRecord(Record);
- if (!Enum)
- return;
-
- Symbols.emplace_back(std::move(*Enum));
- serializeMembers(Record, Record.Constants);
+bool SymbolGraphSerializer::traverseAPIRecord(const APIRecord *Record) {
+ if (!Record)
+ return true;
+ if (shouldSkip(Record))
+ return true;
+ Hierarchy.push_back(getHierarchyReference(Record, API));
+ // Defer traversal mechanics to APISetVisitor base implementation
+ auto RetVal = Base::traverseAPIRecord(Record);
+ Hierarchy.pop_back();
+ return RetVal;
}
-void SymbolGraphSerializer::visitRecordRecord(const RecordRecord &Record) {
- auto SerializedRecord = serializeAPIRecord(Record);
- if (!SerializedRecord)
- return;
-
- Symbols.emplace_back(std::move(*SerializedRecord));
- serializeMembers(Record, Record.Fields);
+bool SymbolGraphSerializer::visitAPIRecord(const APIRecord *Record) {
+ serializeAPIRecord(Record);
+ return true;
}
-void SymbolGraphSerializer::visitStaticFieldRecord(
- const StaticFieldRecord &Record) {
- auto StaticField = serializeAPIRecord(Record);
- if (!StaticField)
- return;
- Symbols.emplace_back(std::move(*StaticField));
- serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context);
+bool SymbolGraphSerializer::visitGlobalFunctionRecord(
+ const GlobalFunctionRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
+
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
+bool SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Class));
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ for (const auto &Base : Record->Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base,
+ getModuleForCurrentSymbol());
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplateRecord(
- const ClassTemplateRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
+bool SymbolGraphSerializer::visitClassTemplateRecord(
+ const ClassTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Class));
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplateSpecializationRecord(
- const ClassTemplateSpecializationRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
-
- Symbols.emplace_back(std::move(*Class));
+bool SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord &Record) {
- auto Class = serializeAPIRecord(Record);
- if (!Class)
- return;
-
- Symbols.emplace_back(std::move(*Class));
+bool SymbolGraphSerializer::visitCXXMethodRecord(
+ const CXXMethodRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- for (const auto &Base : Record.Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
- if (!Record.ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXInstanceMethodRecord(
- const CXXInstanceMethodRecord &Record) {
- auto InstanceMethod = serializeAPIRecord(Record);
- if (!InstanceMethod)
- return;
+bool SymbolGraphSerializer::visitCXXMethodTemplateRecord(
+ const CXXMethodTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*InstanceMethod));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXStaticMethodRecord(
- const CXXStaticMethodRecord &Record) {
- auto StaticMethod = serializeAPIRecord(Record);
- if (!StaticMethod)
- return;
+bool SymbolGraphSerializer::visitCXXFieldTemplateRecord(
+ const CXXFieldTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*StaticMethod));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitMethodTemplateRecord(
- const CXXMethodTemplateRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto MethodTemplate = serializeAPIRecord(Record);
- if (!MethodTemplate)
- return;
- Symbols.emplace_back(std::move(*MethodTemplate));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+bool SymbolGraphSerializer::visitConceptRecord(const ConceptRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
- const CXXMethodTemplateSpecializationRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto MethodTemplateSpecialization = serializeAPIRecord(Record);
- if (!MethodTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*MethodTemplateSpecialization));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) {
- if (!ShouldRecurse)
- return;
- auto CXXField = serializeAPIRecord(Record);
- if (!CXXField)
- return;
- Symbols.emplace_back(std::move(*CXXField));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
-}
+bool SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
+ const GlobalVariableTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitCXXFieldTemplateRecord(
- const CXXFieldTemplateRecord &Record) {
- if (!ShouldRecurse)
- // Ignore child symbols
- return;
- auto CXXFieldTemplate = serializeAPIRecord(Record);
- if (!CXXFieldTemplate)
- return;
- Symbols.emplace_back(std::move(*CXXFieldTemplate));
- serializeRelationship(RelationshipKind::MemberOf, Record,
- Record.ParentInformation.ParentRecord);
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
- auto Concept = serializeAPIRecord(Record);
- if (!Concept)
- return;
+bool SymbolGraphSerializer::
+ visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*Concept));
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord &Record) {
- auto GlobalVariableTemplate = serializeAPIRecord(Record);
- if (!GlobalVariableTemplate)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplate));
-}
+bool SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord(
- const GlobalVariableTemplateSpecializationRecord &Record) {
- auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record);
- if (!GlobalVariableTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization));
+ serializeTemplateMixin(*CurrentSymbol, *Record);
+ return true;
}
-void SymbolGraphSerializer::
- visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord &Record) {
- auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record);
- if (!GlobalVariableTemplatePartialSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
-}
+bool SymbolGraphSerializer::visitObjCContainerRecord(
+ const ObjCContainerRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
-void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord &Record) {
- auto GlobalFunctionTemplate = serializeAPIRecord(Record);
- if (!GlobalFunctionTemplate)
- return;
- Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
-}
+ for (const auto &Protocol : Record->Protocols)
+ serializeRelationship(ConformsTo, Record, Protocol,
+ getModuleForCurrentSymbol());
-void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord(
- const GlobalFunctionTemplateSpecializationRecord &Record) {
- auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
- if (!GlobalFunctionTemplateSpecialization)
- return;
- Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
+ return true;
}
-void SymbolGraphSerializer::visitObjCContainerRecord(
- const ObjCContainerRecord &Record) {
- auto ObjCContainer = serializeAPIRecord(Record);
- if (!ObjCContainer)
- return;
+bool SymbolGraphSerializer::visitObjCInterfaceRecord(
+ const ObjCInterfaceRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- Symbols.emplace_back(std::move(*ObjCContainer));
-
- serializeMembers(Record, Record.Ivars);
- serializeMembers(Record, Record.Methods);
- serializeMembers(Record, Record.Properties);
-
- for (const auto &Protocol : Record.Protocols)
- // Record that Record conforms to Protocol.
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
-
- if (auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record)) {
- if (!ObjCInterface->SuperClass.empty())
- // If Record is an Objective-C interface record and it has a super class,
- // record that Record is inherited from SuperClass.
- serializeRelationship(RelationshipKind::InheritsFrom, Record,
- ObjCInterface->SuperClass);
-
- // Members of categories extending an interface are serialized as members of
- // the interface.
- for (const auto *Category : ObjCInterface->Categories) {
- serializeMembers(Record, Category->Ivars);
- serializeMembers(Record, Category->Methods);
- serializeMembers(Record, Category->Properties);
-
- // Surface the protocols of the category to the interface.
- for (const auto &Protocol : Category->Protocols)
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
- }
- }
+ if (!Record->SuperClass.empty())
+ serializeRelationship(InheritsFrom, Record, Record->SuperClass,
+ getModuleForCurrentSymbol());
+ return true;
}
-void SymbolGraphSerializer::visitObjCCategoryRecord(
- const ObjCCategoryRecord &Record) {
- if (!Record.IsFromExternalModule)
- return;
-
- // Check if the current Category' parent has been visited before, if so skip.
- if (!visitedCategories.contains(Record.Interface.Name)) {
- visitedCategories.insert(Record.Interface.Name);
- Object Obj;
- serializeObject(Obj, "identifier",
- serializeIdentifier(Record, API.getLanguage()));
- serializeObject(Obj, "kind",
- serializeSymbolKind(APIRecord::RK_ObjCCategoryModule,
- API.getLanguage()));
- Obj["accessLevel"] = "public";
- Symbols.emplace_back(std::move(Obj));
- }
+bool SymbolGraphSerializer::traverseObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ auto *CurrentModule = ModuleForCurrentSymbol;
+ if (Record->isExtendingExternalModule())
+ ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source];
- Object Relationship;
- Relationship["source"] = Record.USR;
- Relationship["target"] = Record.Interface.USR;
- Relationship["targetFallback"] = Record.Interface.Name;
- Relationship["kind"] = getRelationshipString(RelationshipKind::ExtensionTo);
- Relationships.emplace_back(std::move(Relationship));
+ if (!walkUpFromObjCCategoryRecord(Record))
+ return false;
- auto ObjCCategory = serializeAPIRecord(Record);
+ bool RetVal = traverseRecordContext(Record);
+ ModuleForCurrentSymbol = CurrentModule;
+ return RetVal;
+}
- if (!ObjCCategory)
- return;
+bool SymbolGraphSerializer::walkUpFromObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ return visitObjCCategoryRecord(Record);
+}
- Symbols.emplace_back(std::move(*ObjCCategory));
- serializeMembers(Record, Record.Methods);
- serializeMembers(Record, Record.Properties);
+bool SymbolGraphSerializer::visitObjCCategoryRecord(
+ const ObjCCategoryRecord *Record) {
+ // If we need to create a record for the category in the future do so here,
+ // otherwise everything is set up to pretend that the category is in fact the
+ // interface it extends.
+ for (const auto &Protocol : Record->Protocols)
+ serializeRelationship(ConformsTo, Record->Interface, Protocol,
+ getModuleForCurrentSymbol());
- // Surface the protocols of the category to the interface.
- for (const auto &Protocol : Record.Protocols)
- serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
+ return true;
}
-void SymbolGraphSerializer::visitMacroDefinitionRecord(
- const MacroDefinitionRecord &Record) {
- auto Macro = serializeAPIRecord(Record);
+bool SymbolGraphSerializer::visitObjCMethodRecord(
+ const ObjCMethodRecord *Record) {
+ if (!CurrentSymbol)
+ return true;
- if (!Macro)
- return;
+ serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
+ return true;
+}
- Symbols.emplace_back(std::move(*Macro));
+bool SymbolGraphSerializer::visitObjCInstanceVariableRecord(
+ const ObjCInstanceVariableRecord *Record) {
+ // FIXME: serialize ivar access control here.
+ return true;
}
-void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
- switch (Record->getKind()) {
- case APIRecord::RK_Unknown:
- llvm_unreachable("Records should have a known kind!");
- case APIRecord::RK_GlobalFunction:
- visitGlobalFunctionRecord(*cast<GlobalFunctionRecord>(Record));
- break;
- case APIRecord::RK_GlobalVariable:
- visitGlobalVariableRecord(*cast<GlobalVariableRecord>(Record));
- break;
- case APIRecord::RK_Enum:
- visitEnumRecord(*cast<EnumRecord>(Record));
- break;
- case APIRecord::RK_Struct:
- LLVM_FALLTHROUGH;
- case APIRecord::RK_Union:
- visitRecordRecord(*cast<RecordRecord>(Record));
- break;
- case APIRecord::RK_StaticField:
- visitStaticFieldRecord(*cast<StaticFieldRecord>(Record));
- break;
- case APIRecord::RK_CXXClass:
- visitCXXClassRecord(*cast<CXXClassRecord>(Record));
- break;
- case APIRecord::RK_ObjCInterface:
- visitObjCContainerRecord(*cast<ObjCInterfaceRecord>(Record));
- break;
- case APIRecord::RK_ObjCProtocol:
- visitObjCContainerRecord(*cast<ObjCProtocolRecord>(Record));
- break;
- case APIRecord::RK_ObjCCategory:
- visitObjCCategoryRecord(*cast<ObjCCategoryRecord>(Record));
- break;
- case APIRecord::RK_MacroDefinition:
- visitMacroDefinitionRecord(*cast<MacroDefinitionRecord>(Record));
- break;
- case APIRecord::RK_Typedef:
- visitTypedefRecord(*cast<TypedefRecord>(Record));
- break;
- default:
- if (auto Obj = serializeAPIRecord(*Record)) {
- Symbols.emplace_back(std::move(*Obj));
- auto &ParentInformation = Record->ParentInformation;
- if (!ParentInformation.empty())
- serializeRelationship(RelationshipKind::MemberOf, *Record,
- *ParentInformation.ParentRecord);
- }
- break;
- }
+bool SymbolGraphSerializer::walkUpFromTypedefRecord(
+ const TypedefRecord *Record) {
+ // Short-circuit walking up the class hierarchy and handle creating typedef
+ // symbol objects manually as there are additional symbol dropping rules to
+ // respect.
+ return visitTypedefRecord(Record);
}
-void SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord &Record) {
+bool SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord *Record) {
// Typedefs of anonymous types have their entries unified with the underlying
// type.
- bool ShouldDrop = Record.UnderlyingType.Name.empty();
+ bool ShouldDrop = Record->UnderlyingType.Name.empty();
// enums declared with `NS_OPTION` have a named enum and a named typedef, with
// the same name
- ShouldDrop |= (Record.UnderlyingType.Name == Record.Name);
+ ShouldDrop |= (Record->UnderlyingType.Name == Record->Name);
if (ShouldDrop)
- return;
+ return true;
- auto Typedef = serializeAPIRecord(Record);
- if (!Typedef)
- return;
+ // Create the symbol record if the other symbol droppping rules permit it.
+ serializeAPIRecord(Record);
+ if (!CurrentSymbol)
+ return true;
- (*Typedef)["type"] = Record.UnderlyingType.USR;
+ (*CurrentSymbol)["type"] = Record->UnderlyingType.USR;
- Symbols.emplace_back(std::move(*Typedef));
+ return true;
}
-Object SymbolGraphSerializer::serialize() {
- traverseAPISet();
- return serializeCurrentGraph();
+void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
+ switch (Record->getKind()) {
+ // dispatch to the relevant walkUpFromMethod
+#define CONCRETE_RECORD(CLASS, BASE, KIND) \
+ case APIRecord::KIND: { \
+ walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
+ break; \
+ }
+#include "clang/ExtractAPI/APIRecords.inc"
+ // otherwise fallback on the only behavior we can implement safely.
+ case APIRecord::RK_Unknown:
+ visitAPIRecord(Record);
+ break;
+ default:
+ llvm_unreachable("API Record with uninstantiable kind");
+ }
}
-Object SymbolGraphSerializer::serializeCurrentGraph() {
+Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
+ ExtendedModule &&EM) {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
- serializeObject(Root, "module", serializeModule());
+ serializeObject(Root, "module", serializeModuleObject(ModuleName));
- Root["symbols"] = std::move(Symbols);
- Root["relationships"] = std::move(Relationships);
+ Root["symbols"] = std::move(EM.Symbols);
+ Root["relationships"] = std::move(EM.Relationships);
return Root;
}
-void SymbolGraphSerializer::serialize(raw_ostream &os) {
- Object root = serialize();
+void SymbolGraphSerializer::serializeGraphToStream(
+ raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName,
+ ExtendedModule &&EM) {
+ Object Root = serializeGraph(ModuleName, std::move(EM));
if (Options.Compact)
- os << formatv("{0}", Value(std::move(root))) << "\n";
+ OS << formatv("{0}", Value(std::move(Root))) << "\n";
else
- os << formatv("{0:2}", Value(std::move(root))) << "\n";
+ OS << formatv("{0:2}", Value(std::move(Root))) << "\n";
+}
+
+void SymbolGraphSerializer::serializeMainSymbolGraph(
+ raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList,
+ SymbolGraphSerializerOption Options) {
+ SymbolGraphSerializer Serializer(API, IgnoresList,
+ Options.EmitSymbolLabelsForTesting);
+ Serializer.traverseAPISet();
+ Serializer.serializeGraphToStream(OS, Options, API.ProductName,
+ std::move(Serializer.MainModule));
+ // FIXME: TODO handle extended modules here
+}
+
+void SymbolGraphSerializer::serializeWithExtensionGraphs(
+ raw_ostream &MainOutput, const APISet &API,
+ const APIIgnoresList &IgnoresList,
+ llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
+ CreateOutputStream,
+ SymbolGraphSerializerOption Options) {
+ SymbolGraphSerializer Serializer(API, IgnoresList,
+ Options.EmitSymbolLabelsForTesting);
+ Serializer.traverseAPISet();
+
+ Serializer.serializeGraphToStream(MainOutput, Options, API.ProductName,
+ std::move(Serializer.MainModule));
+
+ for (auto &ExtensionSGF : Serializer.ExtendedModules) {
+ if (auto ExtensionOS =
+ CreateOutputStream(ExtensionSGF.getKey() + "@" + API.ProductName))
+ Serializer.serializeGraphToStream(*ExtensionOS, Options,
+ ExtensionSGF.getKey(),
+ std::move(ExtensionSGF.getValue()));
+ }
}
std::optional<Object>
@@ -1262,14 +1070,20 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object Root;
APIIgnoresList EmptyIgnores;
SymbolGraphSerializer Serializer(API, EmptyIgnores,
- /*Options.Compact*/ {true},
- /*ShouldRecurse*/ false);
+ /*EmitSymbolLabelsForTesting*/ false,
+ /*ForceEmitToMainModule*/ true);
+
+ // Set up serializer parent chain
+ Serializer.Hierarchy = generateHierarchyFromRecord(Record);
+
Serializer.serializeSingleRecord(Record);
- serializeObject(Root, "symbolGraph", Serializer.serializeCurrentGraph());
+ serializeObject(Root, "symbolGraph",
+ Serializer.serializeGraph(API.ProductName,
+ std::move(Serializer.MainModule)));
Language Lang = API.getLanguage();
serializeArray(Root, "parentContexts",
- generateParentContexts(*Record, API, Lang));
+ generateParentContexts(Serializer.Hierarchy, Lang));
Array RelatedSymbols;
@@ -1287,14 +1101,15 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object RelatedSymbol;
RelatedSymbol["usr"] = RelatedRecord->USR;
RelatedSymbol["declarationLanguage"] = getLanguageName(Lang);
- // TODO: once we record this properly let's serialize it right.
- RelatedSymbol["accessLevel"] = "public";
+ RelatedSymbol["accessLevel"] = RelatedRecord->Access.getAccess();
RelatedSymbol["filePath"] = RelatedRecord->Location.getFilename();
RelatedSymbol["moduleName"] = API.ProductName;
RelatedSymbol["isSystem"] = RelatedRecord->IsFromSystemHeader;
serializeArray(RelatedSymbol, "parentContexts",
- generateParentContexts(*RelatedRecord, API, Lang));
+ generateParentContexts(
+ generateHierarchyFromRecord(RelatedRecord), Lang));
+
RelatedSymbols.push_back(std::move(RelatedSymbol));
}
diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
index 3a5f62c9b2e6cc..41e4e0cf1795f9 100644
--- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
+++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
+#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
using namespace clang;
@@ -50,17 +51,20 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
SmallString<128> TypeUSR;
const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
const TypedefType *TypedefTy = Type->getAs<TypedefType>();
+ StringRef OwningModuleName;
if (TypeDecl) {
if (!TypedefTy)
TypeName = TypeDecl->getName().str();
clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
+ if (auto *OwningModule = TypeDecl->getImportedOwningModule())
+ OwningModuleName = OwningModule->Name;
} else {
clang::index::generateUSRForType(Type, Context, TypeUSR);
}
- return {API.copyString(TypeName), API.copyString(TypeUSR)};
+ return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
}
std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 2446aee571f440..f85f0365616f9a 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -181,9 +181,13 @@ CreateFrontendAction(CompilerInstance &CI) {
#endif
// Wrap the base FE action in an extract api action to generate
- // symbol graph as a biproduct of compilation ( enabled with
- // --emit-symbol-graph option )
- if (!FEOpts.SymbolGraphOutputDir.empty()) {
+ // symbol graph as a biproduct of compilation (enabled with
+ // --emit-symbol-graph option)
+ if (FEOpts.EmitSymbolGraph) {
+ if (FEOpts.SymbolGraphOutputDir.empty()) {
+ CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
+ CI.getFrontendOpts().SymbolGraphOutputDir = ".";
+ }
CI.getCodeGenOpts().ClearASTBeforeBackend = false;
Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));
}
diff --git a/clang/test/ExtractAPI/anonymous_record_no_typedef.c b/clang/test/ExtractAPI/anonymous_record_no_typedef.c
index 0e50f4a0948c94..049e8b1f85bb96 100644
--- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c
+++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c
@@ -1,8 +1,9 @@
+// XFAIL: *
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c
index 3c1ef5c45b634d..12ac73f0d4295a 100644
--- a/clang/test/ExtractAPI/availability.c
+++ b/clang/test/ExtractAPI/availability.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=Availability -triple arm64-apple-macosx -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
diff --git a/clang/test/ExtractAPI/bool.c b/clang/test/ExtractAPI/bool.c
index f4082edeb02ede..efab6dfeef03b2 100644
--- a/clang/test/ExtractAPI/bool.c
+++ b/clang/test/ExtractAPI/bool.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/bool.cpp b/clang/test/ExtractAPI/bool.cpp
index 1b445e220a4a0e..f7d10c61dba4b7 100644
--- a/clang/test/ExtractAPI/bool.cpp
+++ b/clang/test/ExtractAPI/bool.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class.cpp b/clang/test/ExtractAPI/class.cpp
index 21cac43057524a..0c5db8e9c9d215 100644
--- a/clang/test/ExtractAPI/class.cpp
+++ b/clang/test/ExtractAPI/class.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp
index b04dca6bffda16..4f2670d7b69977 100644
--- a/clang/test/ExtractAPI/class_template.cpp
+++ b/clang/test/ExtractAPI/class_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
index 0d38fd1b7f5306..3d7b09f93ed6de 100644
--- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp
+++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp
index eba069319ce450..c8d9cc78d41c5c 100644
--- a/clang/test/ExtractAPI/class_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_partial_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -15,7 +15,7 @@ template<typename X, typename Y> class Foo {};
template<typename Z> class Foo<Z, int> {};
-/// expected-no-diagnostics
+// expected-no-diagnostics
//--- reference.output.json.in
{
diff --git a/clang/test/ExtractAPI/class_template_spec.cpp b/clang/test/ExtractAPI/class_template_spec.cpp
index 4b183cbb844580..06a95314dc4aa0 100644
--- a/clang/test/ExtractAPI/class_template_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp
index ff4e71026e7283..443eac2971f0e5 100644
--- a/clang/test/ExtractAPI/concept.cpp
+++ b/clang/test/ExtractAPI/concept.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -std=c++20 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/constructor_destructor.cpp b/clang/test/ExtractAPI/constructor_destructor.cpp
index 9742d4bae26133..27112c95ac45c2 100644
--- a/clang/test/ExtractAPI/constructor_destructor.cpp
+++ b/clang/test/ExtractAPI/constructor_destructor.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -137,7 +137,7 @@ class Foo {
"precise": "c:@S at Foo@F at Foo#"
},
"kind": {
- "displayName": "Instance Method",
+ "displayName": "Constructor",
"identifier": "c++.method"
},
"location": {
@@ -193,7 +193,7 @@ class Foo {
"precise": "c:@S at Foo@F@~Foo#"
},
"kind": {
- "displayName": "Instance Method",
+ "displayName": "Destructor",
"identifier": "c++.method"
},
"location": {
diff --git a/clang/test/ExtractAPI/conversions.cpp b/clang/test/ExtractAPI/conversions.cpp
index fc8d0675443730..07688ff770979e 100644
--- a/clang/test/ExtractAPI/conversions.cpp
+++ b/clang/test/ExtractAPI/conversions.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
index e6b72d5881e7d1..e668f69bc7e05f 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
@@ -5,18 +5,19 @@
// RUN: %t/reference.main.json.in >> %t/reference.main.json
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.test.json.in >> %t/reference.test.json
-// RUN: %clang_cc1 %t/test.c %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
+// RUN: %clang_cc1 %t/test.c %t/main.c -emit-symbol-graph --pretty-sgf \
+// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=multifile_test -triple=x86_64-apple-macosx12.0.0
// Test main.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/main.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.c.symbols.json > %t/output-normalized.json
// RUN: diff %t/reference.main.json %t/output-normalized.json
// Test test.json
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/test.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/test.c.symbols.json > %t/output-normalized.json
// RUN: diff %t/reference.test.json %t/output-normalized.json
// CHECK-NOT: error:
diff --git a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
index 8599e82e10783a..b00b5f5237c9a3 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
@@ -3,11 +3,12 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 %t/main.c --emit-symbol-graph=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
+// RUN: %clang_cc1 %t/main.c -emit-symbol-graph --pretty-sgf \
+// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/SymbolGraphs/main.json >> %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.c.symbols.json >> %t/output-normalized.json
// RUN: diff %t/reference.output.json %t/output-normalized.json
// CHECK-NOT: error:
diff --git a/clang/test/ExtractAPI/enum.c b/clang/test/ExtractAPI/enum.c
index 94499d9fc3a639..1cdf45ca3cdf4b 100644
--- a/clang/test/ExtractAPI/enum.c
+++ b/clang/test/ExtractAPI/enum.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp
index f05e826a8eb491..2058ed008cfe40 100644
--- a/clang/test/ExtractAPI/field_template.cpp
+++ b/clang/test/ExtractAPI/field_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/function_noexcepts.cpp b/clang/test/ExtractAPI/function_noexcepts.cpp
index 3fc7263cd6a186..d95eaaa7e769a5 100644
--- a/clang/test/ExtractAPI/function_noexcepts.cpp
+++ b/clang/test/ExtractAPI/function_noexcepts.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp
index 8def9745bcce8e..f43a618ec0c366 100644
--- a/clang/test/ExtractAPI/global_func_template.cpp
+++ b/clang/test/ExtractAPI/global_func_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp
index a24263dc14584f..fe046e9c3b9dac 100644
--- a/clang/test/ExtractAPI/global_func_template_spec.cpp
+++ b/clang/test/ExtractAPI/global_func_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_record.c b/clang/test/ExtractAPI/global_record.c
index 623032b45bfd2c..a08d51d21f9556 100644
--- a/clang/test/ExtractAPI/global_record.c
+++ b/clang/test/ExtractAPI/global_record.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_record_multifile.c b/clang/test/ExtractAPI/global_record_multifile.c
index f9d3889b5d9de3..ffdfbcb7eb8087 100644
--- a/clang/test/ExtractAPI/global_record_multifile.c
+++ b/clang/test/ExtractAPI/global_record_multifile.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
// RUN: %t/input1.h %t/input2.h %t/input3.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template.cpp b/clang/test/ExtractAPI/global_var_template.cpp
index bee2ea601bd72b..94f3713cd3d31b 100644
--- a/clang/test/ExtractAPI/global_var_template.cpp
+++ b/clang/test/ExtractAPI/global_var_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
index e98076cdb1d016..91084f258878ee 100644
--- a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp
index cca2ab3db7b8bd..ff4d8d17aecbe9 100644
--- a/clang/test/ExtractAPI/global_var_template_spec.cpp
+++ b/clang/test/ExtractAPI/global_var_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/known_files_only.c b/clang/test/ExtractAPI/known_files_only.c
index 68881aa9e3aadb..de1e786c1969dd 100644
--- a/clang/test/ExtractAPI/known_files_only.c
+++ b/clang/test/ExtractAPI/known_files_only.c
@@ -1,17 +1,7 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=GlobalRecord -target arm64-apple-macosx \
-// RUN: %t/input1.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=GlobalRecord -triple arm64-apple-macosx \
+// RUN: %t/input1.h -verify -o - | FileCheck %s
//--- input1.h
int num;
@@ -24,87 +14,6 @@ char not_emitted;
void foo(int);
struct Foo { int a; };
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "GlobalRecord",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "num"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@num"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "c.var"
- },
- "location": {
- "position": {
- "character": 4,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input1.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "num"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "num"
- }
- ],
- "title": "num"
- },
- "pathComponents": [
- "num"
- ]
- }
- ]
-}
+// CHECK-NOT: input2.h
+
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c
index fe98626c84613e..90832fd8a2aff9 100644
--- a/clang/test/ExtractAPI/language.c
+++ b/clang/test/ExtractAPI/language.c
@@ -7,11 +7,11 @@
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json
-// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x c-header -triple arm64-apple-macosx \
// RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s
-// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c-header -triple arm64-apple-macosx \
// RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s
-// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -x objective-c++-header -triple arm64-apple-macosx \
// RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/macro_undefined.c b/clang/test/ExtractAPI/macro_undefined.c
index 1a4ed20545e0d6..ec60f95d3d6c4f 100644
--- a/clang/test/ExtractAPI/macro_undefined.c
+++ b/clang/test/ExtractAPI/macro_undefined.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/macros.c b/clang/test/ExtractAPI/macros.c
index d5807f6377ff63..10003fe6f6e40f 100644
--- a/clang/test/ExtractAPI/macros.c
+++ b/clang/test/ExtractAPI/macros.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/metadata_and_module.c b/clang/test/ExtractAPI/metadata_and_module.c
new file mode 100644
index 00000000000000..79574a20ed95a9
--- /dev/null
+++ b/clang/test/ExtractAPI/metadata_and_module.c
@@ -0,0 +1,32 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=module -triple arm64-apple-macosx -x c-header %s -o %t/module.symbols.json -verify
+
+// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix METADATA
+// RUN: FileCheck %s --input-file %t/module.symbols.json --check-prefix MOD
+
+// expected-no-diagnostics
+
+// METADATA: "metadata": {
+// METADATA-NEXT: "formatVersion": {
+// METADATA-NEXT: "major":
+// METADATA-NEXT: "minor":
+// METADATA-NEXT: "patch":
+// METADATA-NEXT: },
+// METADATA-NEXT: "generator":
+// METADATA-NEXT: }
+
+// MOD: "module": {
+// MOD-NEXT: "name": "module",
+// MOD-NEXT: "platform": {
+// MOD-NEXT: "architecture": "arm64",
+// MOD-NEXT: "operatingSystem": {
+// MOD-NEXT: "minimumVersion": {
+// MOD-NEXT: "major":
+// MOD-NEXT: "minor":
+// MOD-NEXT: "patch":
+// MOD-NEXT: },
+// MOD-NEXT: "name": "macosx"
+// MOD-NEXT: },
+// MOD-NEXT: "vendor": "apple"
+// MOD-NEXT: }
+// MOD-NEXT: }
diff --git a/clang/test/ExtractAPI/method_template.cpp b/clang/test/ExtractAPI/method_template.cpp
index 8d832337216a28..714f9cac26c208 100644
--- a/clang/test/ExtractAPI/method_template.cpp
+++ b/clang/test/ExtractAPI/method_template.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp
index 706d99da558fe2..8eaffdefd827a9 100644
--- a/clang/test/ExtractAPI/method_template_spec.cpp
+++ b/clang/test/ExtractAPI/method_template_spec.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/methods.cpp b/clang/test/ExtractAPI/methods.cpp
index 8b024a8c3036f1..412c0bb3f903c3 100644
--- a/clang/test/ExtractAPI/methods.cpp
+++ b/clang/test/ExtractAPI/methods.cpp
@@ -1,467 +1,221 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
-// RUN: -x c++-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x c++-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
class Foo {
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETCOUNT
int getCount();
+ // GETCOUNT: "!testRelLabel": "memberOf $ c:@S at Foo@F at getCount# $ c:@S at Foo"
+ // GETCOUNT-LABEL: "!testLabel": "c:@S at Foo@F at getCount#"
+ // GETCOUNT: "accessLevel": "private",
+ // GETCOUNT: "declarationFragments": [
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "typeIdentifier",
+ // GETCOUNT-NEXT: "preciseIdentifier": "c:I",
+ // GETCOUNT-NEXT: "spelling": "int"
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "text",
+ // GETCOUNT-NEXT: "spelling": " "
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "identifier",
+ // GETCOUNT-NEXT: "spelling": "getCount"
+ // GETCOUNT-NEXT: },
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "text",
+ // GETCOUNT-NEXT: "spelling": "();"
+ // GETCOUNT-NEXT: }
+ // GETCOUNT-NEXT: ],
+ // GETCOUNT: "functionSignature": {
+ // GETCOUNT-NEXT: "returns": [
+ // GETCOUNT-NEXT: {
+ // GETCOUNT-NEXT: "kind": "typeIdentifier",
+ // GETCOUNT-NEXT: "preciseIdentifier": "c:I",
+ // GETCOUNT-NEXT: "spelling": "int"
+ // GETCOUNT-NEXT: }
+ // GETCOUNT-NEXT: ]
+ // GETCOUNT-NEXT: },
+ // GETCOUNT: "displayName": "Instance Method",
+ // GETCOUNT-NEXT: "identifier": "c++.method"
+ // GETCOUNT: "title": "getCount"
+ // GETCOUNT: "pathComponents": [
+ // GETCOUNT-NEXT: "Foo",
+ // GETCOUNT-NEXT: "getCount"
+ // GETCOUNT-NEXT: ]
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SETL
void setLength(int length) noexcept;
+ // SETL: "!testRelLabel": "memberOf $ c:@S at Foo@F at setLength#I# $ c:@S at Foo"
+ // SETL-LABEL: "!testLabel": "c:@S at Foo@F at setLength#I#"
+ // SETL: "declarationFragments": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:v",
+ // SETL-NEXT: "spelling": "void"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "identifier",
+ // SETL-NEXT: "spelling": "setLength"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": "("
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:I",
+ // SETL-NEXT: "spelling": "int"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "internalParam",
+ // SETL-NEXT: "spelling": "length"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": ")"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "keyword",
+ // SETL-NEXT: "spelling": "noexcept"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": ";"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL: "functionSignature": {
+ // SETL-NEXT: "parameters": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "declarationFragments": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:I",
+ // SETL-NEXT: "spelling": "int"
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "text",
+ // SETL-NEXT: "spelling": " "
+ // SETL-NEXT: },
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "internalParam",
+ // SETL-NEXT: "spelling": "length"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL-NEXT: "name": "length"
+ // SETL-NEXT: }
+ // SETL-NEXT: ],
+ // SETL-NEXT: "returns": [
+ // SETL-NEXT: {
+ // SETL-NEXT: "kind": "typeIdentifier",
+ // SETL-NEXT: "preciseIdentifier": "c:v",
+ // SETL-NEXT: "spelling": "void"
+ // SETL-NEXT: }
+ // SETL-NEXT: ]
+ // SETL-NEXT: },
public:
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETFOO
static double getFoo();
+ // GETFOO: "!testRelLabel": "memberOf $ c:@S at Foo@F at getFoo#S $ c:@S at Foo"
+
+ // GETFOO-LABEL: "!testLabel": "c:@S at Foo@F at getFoo#S"
+ // GETFOO: "accessLevel": "public",
+ // GETFOO: "declarationFragments": [
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "keyword",
+ // GETFOO-NEXT: "spelling": "static"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": " "
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "typeIdentifier",
+ // GETFOO-NEXT: "preciseIdentifier": "c:d",
+ // GETFOO-NEXT: "spelling": "double"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": " "
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "identifier",
+ // GETFOO-NEXT: "spelling": "getFoo"
+ // GETFOO-NEXT: },
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "text",
+ // GETFOO-NEXT: "spelling": "();"
+ // GETFOO-NEXT: }
+ // GETFOO-NEXT: ],
+ // GETFOO: "functionSignature": {
+ // GETFOO-NEXT: "returns": [
+ // GETFOO-NEXT: {
+ // GETFOO-NEXT: "kind": "typeIdentifier",
+ // GETFOO-NEXT: "preciseIdentifier": "c:d",
+ // GETFOO-NEXT: "spelling": "double"
+ // GETFOO-NEXT: }
+ // GETFOO-NEXT: ]
+ // GETFOO-NEXT: },
+ // GETFOO: "kind": {
+ // GETFOO-NEXT: "displayName": "Static Method",
+ // GETFOO-NEXT: "identifier": "c++.type.method"
+ // GETFOO-NEXT: },
protected:
+ // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETBAR
constexpr int getBar() const;
+ // GETBAR: "!testRelLabel": "memberOf $ c:@S at Foo@F at getBar#1 $ c:@S at Foo"
+
+ // GETBAR-LABEL: "!testLabel": "c:@S at Foo@F at getBar#1"
+ // GETBAR: "accessLevel": "protected"
+ // GETBAR: "declarationFragments": [
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "keyword",
+ // GETBAR-NEXT: "spelling": "constexpr"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": " "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "typeIdentifier",
+ // GETBAR-NEXT: "preciseIdentifier": "c:I",
+ // GETBAR-NEXT: "spelling": "int"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": " "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "identifier",
+ // GETBAR-NEXT: "spelling": "getBar"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": "() "
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "keyword",
+ // GETBAR-NEXT: "spelling": "const"
+ // GETBAR-NEXT: },
+ // GETBAR-NEXT: {
+ // GETBAR-NEXT: "kind": "text",
+ // GETBAR-NEXT: "spelling": ";"
+ // GETBAR-NEXT: }
+ // GETBAR-NEXT: ],
};
-/// expected-no-diagnostics
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@S at Foo@F at getCount#",
- "target": "c:@S at Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S at Foo@F at setLength#I#",
- "target": "c:@S at Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S at Foo@F at getBar#1",
- "target": "c:@S at Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:@S at Foo@F at getFoo#S",
- "target": "c:@S at Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S at Foo"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "c++.class"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "private",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getCount"
- },
- {
- "kind": "text",
- "spelling": "();"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at getCount#"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getCount"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getCount"
- }
- ],
- "title": "getCount"
- },
- "pathComponents": [
- "Foo",
- "getCount"
- ]
- },
- {
- "accessLevel": "private",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "setLength"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "length"
- },
- {
- "kind": "text",
- "spelling": ")"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "noexcept"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "length"
- }
- ],
- "name": "length"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at setLength#I#"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "setLength"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "setLength"
- }
- ],
- "title": "setLength"
- },
- "pathComponents": [
- "Foo",
- "setLength"
- ]
- },
- {
- "accessLevel": "protected",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "constexpr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getBar"
- },
- {
- "kind": "text",
- "spelling": "() "
- },
- {
- "kind": "keyword",
- "spelling": "const"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at getBar#1"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
- },
- "location": {
- "position": {
- "character": 16,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getBar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getBar"
- }
- ],
- "title": "getBar"
- },
- "pathComponents": [
- "Foo",
- "getBar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "static"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "getFoo"
- },
- {
- "kind": "text",
- "spelling": "();"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at getFoo#S"
- },
- "kind": {
- "displayName": "Static Method",
- "identifier": "c++.type.method"
- },
- "location": {
- "position": {
- "character": 16,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getFoo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "getFoo"
- }
- ],
- "title": "getFoo"
- },
- "pathComponents": [
- "Foo",
- "getFoo"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/multiple_inheritance.cpp b/clang/test/ExtractAPI/multiple_inheritance.cpp
index a1f069be0de617..7d49cf4326465e 100644
--- a/clang/test/ExtractAPI/multiple_inheritance.cpp
+++ b/clang/test/ExtractAPI/multiple_inheritance.cpp
@@ -3,7 +3,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/namespace.cpp b/clang/test/ExtractAPI/namespace.cpp
index e0c36dd3d60fed..73e0728b9a4416 100644
--- a/clang/test/ExtractAPI/namespace.cpp
+++ b/clang/test/ExtractAPI/namespace.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/nested_namespaces.cpp b/clang/test/ExtractAPI/nested_namespaces.cpp
index bd13ef93807c01..c6912cfb46312f 100644
--- a/clang/test/ExtractAPI/nested_namespaces.cpp
+++ b/clang/test/ExtractAPI/nested_namespaces.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/objc_block.m b/clang/test/ExtractAPI/objc_block.m
index a7a4f5696333c1..4a4335ec09832d 100644
--- a/clang/test/ExtractAPI/objc_block.m
+++ b/clang/test/ExtractAPI/objc_block.m
@@ -1,965 +1,630 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -fblocks -triple arm64-apple-macosx \
-// RUN: -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -fblocks -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
@interface Foo
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NOPARAM
-(void)methodBlockNoParam:(void (^)())block;
+// NOPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockNoParam:"
+// NOPARAM: "declarationFragments": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "- ("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ") "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "identifier",
+// NOPARAM-NEXT: "spelling": "methodBlockNoParam:"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": " (^"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ")()) "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "internalParam",
+// NOPARAM-NEXT: "spelling": "block"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ";"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM: "functionSignature": {
+// NOPARAM-NEXT: "parameters": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "declarationFragments": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": "("
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": " (^"
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "text",
+// NOPARAM-NEXT: "spelling": ")()) "
+// NOPARAM-NEXT: },
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "internalParam",
+// NOPARAM-NEXT: "spelling": "block"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM-NEXT: "name": "block"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ],
+// NOPARAM-NEXT: "returns": [
+// NOPARAM-NEXT: {
+// NOPARAM-NEXT: "kind": "typeIdentifier",
+// NOPARAM-NEXT: "preciseIdentifier": "c:v",
+// NOPARAM-NEXT: "spelling": "void"
+// NOPARAM-NEXT: }
+// NOPARAM-NEXT: ]
+// NOPARAM-NEXT: }
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PARAM
-(void)methodBlockWithParam:(int (^)(int foo))block;
+// PARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithParam:"
+// PARAM: "declarationFragments": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "- ("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:v",
+// PARAM-NEXT: "spelling": "void"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ") "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "identifier",
+// PARAM-NEXT: "spelling": "methodBlockWithParam:"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " (^"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "foo"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")) "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "block"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ";"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM: "functionSignature": {
+// PARAM-NEXT: "parameters": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "declarationFragments": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": "("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " (^"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")("
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:I",
+// PARAM-NEXT: "spelling": "int"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": " "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "foo"
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "text",
+// PARAM-NEXT: "spelling": ")) "
+// PARAM-NEXT: },
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "internalParam",
+// PARAM-NEXT: "spelling": "block"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM-NEXT: "name": "block"
+// PARAM-NEXT: }
+// PARAM-NEXT: ],
+// PARAM-NEXT: "returns": [
+// PARAM-NEXT: {
+// PARAM-NEXT: "kind": "typeIdentifier",
+// PARAM-NEXT: "preciseIdentifier": "c:v",
+// PARAM-NEXT: "spelling": "void"
+// PARAM-NEXT: }
+// PARAM-NEXT: ]
+// PARAM-NEXT: }
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MULTIPARAM
-(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block;
+// MULTIPARAM-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:"
+// MULTIPARAM: "declarationFragments": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "- ("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:v",
+// MULTIPARAM-NEXT: "spelling": "void"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ") "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "identifier",
+// MULTIPARAM-NEXT: "spelling": "methodBlockWithMultipleParam:"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " (^"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "foo"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ", "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:i",
+// MULTIPARAM-NEXT: "spelling": "unsigned int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "baz"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")) "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "block"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ";"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM: "functionSignature": {
+// MULTIPARAM-NEXT: "parameters": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "declarationFragments": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": "("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " (^"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")("
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:I",
+// MULTIPARAM-NEXT: "spelling": "int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "foo"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ", "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:i",
+// MULTIPARAM-NEXT: "spelling": "unsigned int"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": " "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "baz"
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "text",
+// MULTIPARAM-NEXT: "spelling": ")) "
+// MULTIPARAM-NEXT: },
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "internalParam",
+// MULTIPARAM-NEXT: "spelling": "block"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM-NEXT: "name": "block"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ],
+// MULTIPARAM-NEXT: "returns": [
+// MULTIPARAM-NEXT: {
+// MULTIPARAM-NEXT: "kind": "typeIdentifier",
+// MULTIPARAM-NEXT: "preciseIdentifier": "c:v",
+// MULTIPARAM-NEXT: "spelling": "void"
+// MULTIPARAM-NEXT: }
+// MULTIPARAM-NEXT: ]
+// MULTIPARAM-NEXT: },
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VARIADIC
-(void)methodBlockVariadic:(int (^)(int foo, ...))block;
+// VARIADIC-LABEL: "!testLabel": "c:objc(cs)Foo(im)methodBlockVariadic:"
+// VARIADIC: "declarationFragments": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "- ("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:v",
+// VARIADIC-NEXT: "spelling": "void"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ") "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "identifier",
+// VARIADIC-NEXT: "spelling": "methodBlockVariadic:"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " (^"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ")("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "foo"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ", ...)) "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "block"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ";"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC: "functionSignature": {
+// VARIADIC-NEXT: "parameters": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "declarationFragments": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": "("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " (^"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ")("
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:I",
+// VARIADIC-NEXT: "spelling": "int"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": " "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "foo"
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "text",
+// VARIADIC-NEXT: "spelling": ", ...)) "
+// VARIADIC-NEXT: },
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "internalParam",
+// VARIADIC-NEXT: "spelling": "block"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC-NEXT: "name": "block"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ],
+// VARIADIC-NEXT: "returns": [
+// VARIADIC-NEXT: {
+// VARIADIC-NEXT: "kind": "typeIdentifier",
+// VARIADIC-NEXT: "preciseIdentifier": "c:v",
+// VARIADIC-NEXT: "spelling": "void"
+// VARIADIC-NEXT: }
+// VARIADIC-NEXT: ]
+// VARIADIC-NEXT: },
@end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FUNC
void func(int (^arg)(int foo));
+// FUNC-LABEL: "!testLabel": "c:@F at func"
+// FUNC: "declarationFragments": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:v",
+// FUNC-NEXT: "spelling": "void"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "identifier",
+// FUNC-NEXT: "spelling": "func"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": "("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " (^"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "arg"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "foo"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": "));"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC: "functionSignature": {
+// FUNC-NEXT: "parameters": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "declarationFragments": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " (^"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "arg"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")("
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:I",
+// FUNC-NEXT: "spelling": "int"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": " "
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "internalParam",
+// FUNC-NEXT: "spelling": "foo"
+// FUNC-NEXT: },
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "text",
+// FUNC-NEXT: "spelling": ")"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC-NEXT: "name": "arg"
+// FUNC-NEXT: }
+// FUNC-NEXT: ],
+// FUNC-NEXT: "returns": [
+// FUNC-NEXT: {
+// FUNC-NEXT: "kind": "typeIdentifier",
+// FUNC-NEXT: "preciseIdentifier": "c:v",
+// FUNC-NEXT: "spelling": "void"
+// FUNC-NEXT: }
+// FUNC-NEXT: ]
+// FUNC-NEXT: },
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBAL
int (^global)(int foo);
+// GLOBAL-LABEL: "!testLabel": "c:@global"
+// GLOBAL: "declarationFragments": [
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "typeIdentifier",
+// GLOBAL-NEXT: "preciseIdentifier": "c:I",
+// GLOBAL-NEXT: "spelling": "int"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": " (^"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "identifier",
+// GLOBAL-NEXT: "spelling": "global"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": ")("
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "typeIdentifier",
+// GLOBAL-NEXT: "preciseIdentifier": "c:I",
+// GLOBAL-NEXT: "spelling": "int"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": " "
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "internalParam",
+// GLOBAL-NEXT: "spelling": "foo"
+// GLOBAL-NEXT: },
+// GLOBAL-NEXT: {
+// GLOBAL-NEXT: "kind": "text",
+// GLOBAL-NEXT: "spelling": ");"
+// GLOBAL-NEXT: }
+// GLOBAL-NEXT: ],
///expected-no-diagnostics
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockNoParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockWithParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Foo(im)methodBlockVariadic:",
- "target": "c:objc(cs)Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "identifier",
- "spelling": "global"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@global"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "objective-c.var"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "global"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "global"
- }
- ],
- "title": "global"
- },
- "pathComponents": [
- "global"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "func"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "internalParam",
- "spelling": "arg"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": "));"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "internalParam",
- "spelling": "arg"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "name": "arg"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F at func"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "func"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "func"
- }
- ],
- "title": "func"
- },
- "pathComponents": [
- "func"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")()) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")()) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockNoParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockNoParam:"
- }
- ],
- "title": "methodBlockNoParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockNoParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockWithParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithParam:"
- }
- ],
- "title": "methodBlockWithParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockWithParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": ")) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockWithMultipleParam:"
- }
- ],
- "title": "methodBlockWithMultipleParam:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockWithMultipleParam:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", ...)) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " (^"
- },
- {
- "kind": "text",
- "spelling": ")("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": ", ...)) "
- },
- {
- "kind": "internalParam",
- "spelling": "block"
- }
- ],
- "name": "block"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Foo(im)methodBlockVariadic:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "methodBlockVariadic:"
- }
- ],
- "title": "methodBlockVariadic:"
- },
- "pathComponents": [
- "Foo",
- "methodBlockVariadic:"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_category.m
index 34b0a9e31f553c..9177d40b82644a 100644
--- a/clang/test/ExtractAPI/objc_category.m
+++ b/clang/test/ExtractAPI/objc_category.m
@@ -1,341 +1,21 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
- at protocol Protocol;
+ at protocol Protocol
+ at end
@interface Interface
@end
@interface Interface (Category) <Protocol>
+// CHECK-DAG: "!testRelLabel": "conformsTo $ c:objc(cs)Interface $ c:objc(pl)Protocol"
@property int Property;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)Property $ c:objc(cs)Interface"
- (void)InstanceMethod;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(im)InstanceMethod $ c:objc(cs)Interface"
+ (void)ClassMethod;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cm)ClassMethod $ c:objc(cs)Interface"
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(im)InstanceMethod",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cm)ClassMethod",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)Property",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Interface",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "title": "Interface"
- },
- "pathComponents": [
- "Interface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(im)InstanceMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "InstanceMethod"
- }
- ],
- "title": "InstanceMethod"
- },
- "pathComponents": [
- "Interface",
- "InstanceMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "+ ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cm)ClassMethod"
- },
- "kind": {
- "displayName": "Type Method",
- "identifier": "objective-c.type.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "+ "
- },
- {
- "kind": "identifier",
- "spelling": "ClassMethod"
- }
- ],
- "title": "ClassMethod"
- },
- "pathComponents": [
- "Interface",
- "ClassMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)Property"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "title": "Property"
- },
- "pathComponents": [
- "Interface",
- "Property"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m
new file mode 100644
index 00000000000000..47e699cb91c0e4
--- /dev/null
+++ b/clang/test/ExtractAPI/objc_external_category.m
@@ -0,0 +1,49 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \
+// RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify
+
+//--- input.h
+#include "ExternalModule.h"
+
+ at interface ExtInterface (Category)
+ at property int Property;
+- (void)InstanceMethod;
++ (void)ClassMethod;
+ at end
+
+ at interface ModInterface
+ at end
+
+// expected-no-diagnostics
+
+//--- ExternalModule.h
+ at interface ExtInterface
+ at end
+
+//--- module.modulemap
+module ExternalModule {
+ header "ExternalModule.h"
+}
+
+// RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
+// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface"
+// MOD-DAG: "!testLabel": "c:objc(cs)ModInterface"
+
+// RUN: FileCheck %s --input-file %t/symbols/ExternalModule at Module.symbols.json --check-prefix EXT
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(py)Property"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(im)InstanceMethod"
+// EXT-DAG: "!testLabel": "c:objc(cs)ExtInterface(cm)ClassMethod"
+// EXT-NOT: "!testLabel": "c:objc(cs)ExtInterface"
+// EXT-NOT: "!testLabel": "c:objc(cs)ModInterface"
diff --git a/clang/test/ExtractAPI/objc_id_protocol.m b/clang/test/ExtractAPI/objc_id_protocol.m
index 0b0f1b39d2bd61..f2a03a9c575857 100644
--- a/clang/test/ExtractAPI/objc_id_protocol.m
+++ b/clang/test/ExtractAPI/objc_id_protocol.m
@@ -1,317 +1,56 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
@protocol MyProtocol
@end
@interface MyInterface
@property(copy, readwrite) id<MyProtocol> obj1;
- at property(readwrite) id<MyProtocol> *obj2;
+// CHECK-LABEL: "!testLabel": "c:objc(cs)MyInterface(py)obj1"
+// CHECK: "declarationFragments": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "@property"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": " ("
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "copy"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ", "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "keyword",
+// CHECK-NEXT: "spelling": "readwrite"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ") "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "typeIdentifier",
+// CHECK-NEXT: "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
+// CHECK-NEXT: "spelling": "id<MyProtocol>"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": " "
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "identifier",
+// CHECK-NEXT: "spelling": "obj1"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "text",
+// CHECK-NEXT: "spelling": ";"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyInterface(py)obj1",
- "target": "c:objc(cs)MyInterface",
- "targetFallback": "MyInterface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyInterface(py)obj2",
- "target": "c:objc(cs)MyInterface",
- "targetFallback": "MyInterface"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyInterface"
- }
- ],
- "title": "MyInterface"
- },
- "pathComponents": [
- "MyInterface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "copy"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "keyword",
- "spelling": "readwrite"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
- "spelling": "id<MyProtocol>"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "obj1"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface(py)obj1"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 42,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "obj1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "obj1"
- }
- ],
- "title": "obj1"
- },
- "pathComponents": [
- "MyInterface",
- "obj1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "readwrite"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:Qoobjc(pl)MyProtocol",
- "spelling": "id<MyProtocol>"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "identifier",
- "spelling": "obj2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyInterface(py)obj2"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 37,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "obj2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "obj2"
- }
- ],
- "title": "obj2"
- },
- "pathComponents": [
- "MyInterface",
- "obj2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@protocol"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)MyProtocol"
- },
- "kind": {
- "displayName": "Protocol",
- "identifier": "objective-c.protocol"
- },
- "location": {
- "position": {
- "character": 10,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyProtocol"
- }
- ],
- "title": "MyProtocol"
- },
- "pathComponents": [
- "MyProtocol"
- ]
- }
- ]
-}
+
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m
index d9d259f2d56028..071ebe440918aa 100644
--- a/clang/test/ExtractAPI/objc_instancetype.m
+++ b/clang/test/ExtractAPI/objc_instancetype.m
@@ -1,8 +1,8 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
- // RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %t/reference.output.json.in >> %t/reference.output.json
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
diff --git a/clang/test/ExtractAPI/objc_interface.m b/clang/test/ExtractAPI/objc_interface.m
index ab1772a0c529bb..4abccddc3b5c8e 100644
--- a/clang/test/ExtractAPI/objc_interface.m
+++ b/clang/test/ExtractAPI/objc_interface.m
@@ -1,701 +1,360 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x objective-c-header -triple arm64-apple-macosx %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
- at protocol Protocol;
+ at protocol Protocol
+ at end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SUPER
@interface Super <Protocol>
+// SUPER: "!testRelLabel": "conformsTo $ c:objc(cs)Super $ c:objc(pl)Protocol"
+// SUPER-LABEL: "!testLabel": "c:objc(cs)Super"
+// SUPER: "accessLevel": "public",
+// SUPER: "declarationFragments": [
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "keyword",
+// SUPER-NEXT: "spelling": "@interface"
+// SUPER-NEXT: },
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "text",
+// SUPER-NEXT: "spelling": " "
+// SUPER-NEXT: },
+// SUPER-NEXT: {
+// SUPER-NEXT: "kind": "identifier",
+// SUPER-NEXT: "spelling": "Super"
+// SUPER-NEXT: }
+// SUPER-NEXT: ],
+// SUPER: "kind": {
+// SUPER-NEXT: "displayName": "Class",
+// SUPER-NEXT: "identifier": "objective-c.class"
+// SUPER-NEXT: },
+// SUPER: "title": "Super"
+// SUPER: "pathComponents": [
+// SUPER-NEXT: "Super"
+// SUPER-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PROP
@property(readonly, getter=getProperty) unsigned Property;
+// PROP: "!testRelLabel": "memberOf $ c:objc(cs)Super(py)Property $ c:objc(cs)Super"
+// PROP: "!testLabel": "c:objc(cs)Super(py)Property"
+// PROP: "accessLevel": "public",
+// PROP: "declarationFragments": [
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "@property"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": " ("
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "readonly"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ", "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "keyword",
+// PROP-NEXT: "spelling": "getter"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": "="
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "identifier",
+// PROP-NEXT: "spelling": "getProperty"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ") "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "typeIdentifier",
+// PROP-NEXT: "preciseIdentifier": "c:i",
+// PROP-NEXT: "spelling": "unsigned int"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": " "
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "identifier",
+// PROP-NEXT: "spelling": "Property"
+// PROP-NEXT: },
+// PROP-NEXT: {
+// PROP-NEXT: "kind": "text",
+// PROP-NEXT: "spelling": ";"
+// PROP-NEXT: }
+// PROP-NEXT: ],
+// PROP: "kind": {
+// PROP-NEXT: "displayName": "Instance Property",
+// PROP-NEXT: "identifier": "objective-c.property"
+// PROP-NEXT: },
+// PROP: "title": "Property"
+// PROP: "pathComponents": [
+// PROP-NEXT: "Super",
+// PROP-NEXT: "Property"
+// PROP-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GET
+ (id)getWithProperty:(unsigned) Property;
+// GET: "!testRelLabel": "memberOf $ c:objc(cs)Super(cm)getWithProperty: $ c:objc(cs)Super"
+// GET-LABEL: "!testLabel": "c:objc(cs)Super(cm)getWithProperty:"
+// GET: "accessLevel": "public",
+// GET: "declarationFragments": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "+ ("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "keyword",
+// GET-NEXT: "spelling": "id"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "identifier",
+// GET-NEXT: "spelling": "getWithProperty:"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "typeIdentifier",
+// GET-NEXT: "preciseIdentifier": "c:i",
+// GET-NEXT: "spelling": "unsigned int"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "internalParam",
+// GET-NEXT: "spelling": "Property"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ";"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET: "functionSignature": {
+// GET-NEXT: "parameters": [
+// GET-NEXT: {
+// GET-NEXT: "declarationFragments": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": "("
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "typeIdentifier",
+// GET-NEXT: "preciseIdentifier": "c:i",
+// GET-NEXT: "spelling": "unsigned int"
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "text",
+// GET-NEXT: "spelling": ") "
+// GET-NEXT: },
+// GET-NEXT: {
+// GET-NEXT: "kind": "internalParam",
+// GET-NEXT: "spelling": "Property"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET-NEXT: "name": "Property"
+// GET-NEXT: }
+// GET-NEXT: ],
+// GET-NEXT: "returns": [
+// GET-NEXT: {
+// GET-NEXT: "kind": "keyword",
+// GET-NEXT: "spelling": "id"
+// GET-NEXT: }
+// GET-NEXT: ]
+// GET-NEXT: },
+// GET: "kind": {
+// GET-NEXT: "displayName": "Type Method",
+// GET-NEXT: "identifier": "objective-c.type.method"
+// GET-NEXT: },
+// GET: "title": "getWithProperty:"
+// GET: "pathComponents": [
+// GET-NEXT: "Super",
+// GET-NEXT: "getWithProperty:"
+// GET-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix SET
- (void)setProperty:(unsigned) Property andOtherThing: (unsigned) Thing;
+// SET: "!testRelLabel": "memberOf $ c:objc(cs)Super(im)setProperty:andOtherThing: $ c:objc(cs)Super"
+// SET-LABEL: "!testLabel": "c:objc(cs)Super(im)setProperty:andOtherThing:"
+// SET: "accessLevel": "public",
+// SET: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "- ("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:v",
+// SET-NEXT: "spelling": "void"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "identifier",
+// SET-NEXT: "spelling": "setProperty:"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Property"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": " "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "identifier",
+// SET-NEXT: "spelling": "andOtherThing:"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Thing"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ";"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET: "functionSignature": {
+// SET-NEXT: "parameters": [
+// SET-NEXT: {
+// SET-NEXT: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Property"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "name": "Property"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "declarationFragments": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": "("
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:i",
+// SET-NEXT: "spelling": "unsigned int"
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "text",
+// SET-NEXT: "spelling": ") "
+// SET-NEXT: },
+// SET-NEXT: {
+// SET-NEXT: "kind": "internalParam",
+// SET-NEXT: "spelling": "Thing"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "name": "Thing"
+// SET-NEXT: }
+// SET-NEXT: ],
+// SET-NEXT: "returns": [
+// SET-NEXT: {
+// SET-NEXT: "kind": "typeIdentifier",
+// SET-NEXT: "preciseIdentifier": "c:v",
+// SET-NEXT: "spelling": "void"
+// SET-NEXT: }
+// SET-NEXT: ]
+// SET-NEXT: },
+// SET: "kind": {
+// SET-NEXT: "displayName": "Instance Method",
+// SET-NEXT: "identifier": "objective-c.method"
+// SET-NEXT: },
+// SET: "title": "setProperty:andOtherThing:"
@end
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix DERIVED
@interface Derived : Super {
+// DERIVED: "!testRelLabel": "inheritsFrom $ c:objc(cs)Derived $ c:objc(cs)Super"
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix IVAR
char Ivar;
+// IVAR: "!testRelLabel": "memberOf $ c:objc(cs)Derived at Ivar $ c:objc(cs)Derived"
+// IVAR-LABEL: "!testLabel": "c:objc(cs)Derived at Ivar"
+// IVAR: "accessLevel": "public",
+// IVAR: "declarationFragments": [
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "typeIdentifier",
+// IVAR-NEXT: "preciseIdentifier": "c:C",
+// IVAR-NEXT: "spelling": "char"
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "text",
+// IVAR-NEXT: "spelling": " "
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "identifier",
+// IVAR-NEXT: "spelling": "Ivar"
+// IVAR-NEXT: },
+// IVAR-NEXT: {
+// IVAR-NEXT: "kind": "text",
+// IVAR-NEXT: "spelling": ";"
+// IVAR-NEXT: }
+// IVAR-NEXT: ],
+// IVAR: "kind": {
+// IVAR-NEXT: "displayName": "Instance Variable",
+// IVAR-NEXT: "identifier": "objective-c.ivar"
+// IVAR-NEXT: },
+// IVAR: "title": "Ivar"
+// IVAR: "pathComponents": [
+// IVAR-NEXT: "Derived",
+// IVAR-NEXT: "Ivar"
+// IVAR-NEXT: ]
}
-- (char)getIvar;
@end
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(cm)getWithProperty:",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(im)setProperty:andOtherThing:",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Super(py)Property",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Super",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Derived at Ivar",
- "target": "c:objc(cs)Derived",
- "targetFallback": "Derived"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Derived(im)getIvar",
- "target": "c:objc(cs)Derived",
- "targetFallback": "Derived"
- },
- {
- "kind": "inheritsFrom",
- "source": "c:objc(cs)Derived",
- "target": "c:objc(cs)Super",
- "targetFallback": "Super"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Super"
- }
- ],
- "title": "Super"
- },
- "pathComponents": [
- "Super"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "+ ("
- },
- {
- "kind": "keyword",
- "spelling": "id"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- }
- ],
- "name": "Property"
- }
- ],
- "returns": [
- {
- "kind": "keyword",
- "spelling": "id"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(cm)getWithProperty:"
- },
- "kind": {
- "displayName": "Type Method",
- "identifier": "objective-c.type.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "+ "
- },
- {
- "kind": "identifier",
- "spelling": "getWithProperty:"
- }
- ],
- "title": "getWithProperty:"
- },
- "pathComponents": [
- "Super",
- "getWithProperty:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "setProperty:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "andOtherThing:"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Thing"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Property"
- }
- ],
- "name": "Property"
- },
- {
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "internalParam",
- "spelling": "Thing"
- }
- ],
- "name": "Thing"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(im)setProperty:andOtherThing:"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "setProperty:andOtherThing:"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "setProperty:andOtherThing:"
- }
- ],
- "title": "setProperty:andOtherThing:"
- },
- "pathComponents": [
- "Super",
- "setProperty:andOtherThing:"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "readonly"
- },
- {
- "kind": "text",
- "spelling": ", "
- },
- {
- "kind": "keyword",
- "spelling": "getter"
- },
- {
- "kind": "text",
- "spelling": "="
- },
- {
- "kind": "identifier",
- "spelling": "getProperty"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Property"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Super(py)Property"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 49,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Property"
- }
- ],
- "title": "Property"
- },
- "pathComponents": [
- "Super",
- "Property"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Derived"
- },
- {
- "kind": "text",
- "spelling": " : "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)Super",
- "spelling": "Super"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Derived"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Derived"
- }
- ],
- "title": "Derived"
- },
- "pathComponents": [
- "Derived"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Ivar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived at Ivar"
- },
- "kind": {
- "displayName": "Instance Variable",
- "identifier": "objective-c.ivar"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Ivar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Ivar"
- }
- ],
- "title": "Ivar"
- },
- "pathComponents": [
- "Derived",
- "Ivar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "getIvar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:C",
- "spelling": "char"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Derived(im)getIvar"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "getIvar"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "getIvar"
- }
- ],
- "title": "getIvar"
- },
- "pathComponents": [
- "Derived",
- "getIvar"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_module_category.m b/clang/test/ExtractAPI/objc_module_category.m
deleted file mode 100644
index 708ed10be821d7..00000000000000
--- a/clang/test/ExtractAPI/objc_module_category.m
+++ /dev/null
@@ -1,404 +0,0 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header \
-// RUN: -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-#import "Foundation.h"
-
-/// Doc comment 1
- at interface NSString (Category1)
--(void)method1;
- at end
-
-/// Doc comment 2
- at interface NSString (Category2)
--(void)method2;
- at end
-
-//--- Foundation.h
- at interface NSString
- at end
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString at Category1",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)method1",
- "target": "c:objc(cy)NSString at Category1",
- "targetFallback": "Category1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString at Category2",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)method2",
- "target": "c:objc(cy)NSString at Category2",
- "targetFallback": "Category2"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category1"
- },
- "kind": {
- "displayName": "Module Extension",
- "identifier": "objective-c.module.extension"
- }
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category1"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "docComment": {
- "lines": [
- {
- "range": {
- "end": {
- "character": 17,
- "line": 2
- },
- "start": {
- "character": 4,
- "line": 2
- }
- },
- "text": "Doc comment 1"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category1"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "title": "NSString (Category1)"
- },
- "pathComponents": [
- "Category1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "method1"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)method1"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "method1"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "method1"
- }
- ],
- "title": "method1"
- },
- "pathComponents": [
- "Category1",
- "method1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category2"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "docComment": {
- "lines": [
- {
- "range": {
- "end": {
- "character": 17,
- "line": 7
- },
- "start": {
- "character": 4,
- "line": 7
- }
- },
- "text": "Doc comment 2"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category2"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "title": "NSString (Category2)"
- },
- "pathComponents": [
- "Category2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "method2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)method2"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "method2"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "method2"
- }
- ],
- "title": "method2"
- },
- "pathComponents": [
- "Category2",
- "method2"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/objc_property.m b/clang/test/ExtractAPI/objc_property.m
index 5712abc15393b6..f05584c885d91f 100644
--- a/clang/test/ExtractAPI/objc_property.m
+++ b/clang/test/ExtractAPI/objc_property.m
@@ -1,608 +1,26 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x objective-c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o - -verify | FileCheck %s
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
@protocol Protocol
@property(class) int myProtocolTypeProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(cpy)myProtocolTypeProp $ c:objc(pl)Protocol"
@property int myProtocolInstanceProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(pl)Protocol(py)myProtocolInstanceProp $ c:objc(pl)Protocol"
@end
@interface Interface
@property(class) int myInterfaceTypeProp;
+// CHECk-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myInterfaceTypeProp $ c:objc(cs)Interface"
@property int myInterfaceInstanceProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myInterfaceInstanceProp $ c:objc(cs)Interface"
@end
@interface Interface (Category) <Protocol>
@property(class) int myCategoryTypeProp;
+// CHECK-DAG: "!testRelLabel": "memberOf $ c:objc(cs)Interface(cpy)myCategoryTypeProp $ c:objc(cs)Interface"
@property int myCategoryInstanceProp;
+// CHECK-DAG "!testRelLabel": "memberOf $ c:objc(cs)Interface(py)myCategoryInstanceProp $ c:objc(cs)Interface"
@end
-// expected-no-diagnostics
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cpy)myInterfaceTypeProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)myInterfaceInstanceProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(cpy)myCategoryTypeProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)Interface(py)myCategoryInstanceProp",
- "target": "c:objc(cs)Interface",
- "targetFallback": "Interface"
- },
- {
- "kind": "conformsTo",
- "source": "c:objc(cs)Interface",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(pl)Protocol(cpy)myProtocolTypeProp",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(pl)Protocol(py)myProtocolInstanceProp",
- "target": "c:objc(pl)Protocol",
- "targetFallback": "Protocol"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Interface"
- }
- ],
- "title": "Interface"
- },
- "pathComponents": [
- "Interface"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cpy)myInterfaceTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceTypeProp"
- }
- ],
- "title": "myInterfaceTypeProp"
- },
- "pathComponents": [
- "Interface",
- "myInterfaceTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)myInterfaceInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myInterfaceInstanceProp"
- }
- ],
- "title": "myInterfaceInstanceProp"
- },
- "pathComponents": [
- "Interface",
- "myInterfaceInstanceProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(cpy)myCategoryTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myCategoryTypeProp"
- }
- ],
- "title": "myCategoryTypeProp"
- },
- "pathComponents": [
- "Interface",
- "myCategoryTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)Interface(py)myCategoryInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myCategoryInstanceProp"
- }
- ],
- "title": "myCategoryInstanceProp"
- },
- "pathComponents": [
- "Interface",
- "myCategoryInstanceProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@protocol"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol"
- },
- "kind": {
- "displayName": "Protocol",
- "identifier": "objective-c.protocol"
- },
- "location": {
- "position": {
- "character": 10,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Protocol"
- }
- ],
- "title": "Protocol"
- },
- "pathComponents": [
- "Protocol"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "keyword",
- "spelling": "class"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol(cpy)myProtocolTypeProp"
- },
- "kind": {
- "displayName": "Type Property",
- "identifier": "objective-c.type.property"
- },
- "location": {
- "position": {
- "character": 21,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myProtocolTypeProp"
- }
- ],
- "title": "myProtocolTypeProp"
- },
- "pathComponents": [
- "Protocol",
- "myProtocolTypeProp"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@property"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(pl)Protocol(py)myProtocolInstanceProp"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "objective-c.property"
- },
- "location": {
- "position": {
- "character": 14,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "myProtocolInstanceProp"
- }
- ],
- "title": "myProtocolInstanceProp"
- },
- "pathComponents": [
- "Protocol",
- "myProtocolInstanceProp"
- ]
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/objc_protocol.m b/clang/test/ExtractAPI/objc_protocol.m
index a04936fe041234..06f7ee3d20363e 100644
--- a/clang/test/ExtractAPI/objc_protocol.m
+++ b/clang/test/ExtractAPI/objc_protocol.m
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -x objective-c-header -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/objc_various_categories.m b/clang/test/ExtractAPI/objc_various_categories.m
deleted file mode 100644
index adaef5a7b31a99..00000000000000
--- a/clang/test/ExtractAPI/objc_various_categories.m
+++ /dev/null
@@ -1,507 +0,0 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -x objective-c-header \
-// RUN: -target arm64-apple-macosx \
-// RUN: %t/myclass_1.h \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
-#import "myclass_1.h"
-#import "Foundation.h"
-
- at interface MyClass1 (MyCategory1)
-- (int) SomeMethod;
- at end
-
- at interface NSString (Category1)
--(void) StringMethod;
- at end
-
- at interface NSString (Category2)
--(void) StringMethod2;
- at end
-
-//--- myclass_1.h
- at interface MyClass1
- at end
-
-//--- Foundation.h
- at interface NSString
- at end
-
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:objc(cs)MyClass1(im)SomeMethod",
- "target": "c:objc(cs)MyClass1",
- "targetFallback": "MyClass1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString at Category1",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)StringMethod",
- "target": "c:objc(cy)NSString at Category1",
- "targetFallback": "Category1"
- },
- {
- "kind": "extensionTo",
- "source": "c:objc(cy)NSString at Category2",
- "target": "c:objc(cs)NSString",
- "targetFallback": "NSString"
- },
- {
- "kind": "memberOf",
- "source": "c:objc(cs)NSString(im)StringMethod2",
- "target": "c:objc(cy)NSString at Category2",
- "targetFallback": "Category2"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyClass1"
- },
- "kind": {
- "displayName": "Class",
- "identifier": "objective-c.class"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 0
- },
- "uri": "file://INPUT_DIR/myclass_1.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyClass1"
- }
- ],
- "title": "MyClass1"
- },
- "pathComponents": [
- "MyClass1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)MyClass1(im)SomeMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "SomeMethod"
- }
- ],
- "title": "SomeMethod"
- },
- "pathComponents": [
- "MyClass1",
- "SomeMethod"
- ]
- },
- {
- "accessLevel": "public",
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category1"
- },
- "kind": {
- "displayName": "Module Extension",
- "identifier": "objective-c.module.extension"
- }
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category1"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category1"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 7
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category1"
- }
- ],
- "title": "NSString (Category1)"
- },
- "pathComponents": [
- "Category1"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)StringMethod"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod"
- }
- ],
- "title": "StringMethod"
- },
- "pathComponents": [
- "Category1",
- "StringMethod"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "@interface"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:objc(cs)NSString",
- "spelling": "NSString"
- },
- {
- "kind": "text",
- "spelling": " ("
- },
- {
- "kind": "identifier",
- "spelling": "Category2"
- },
- {
- "kind": "text",
- "spelling": ")"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cy)NSString at Category2"
- },
- "kind": {
- "displayName": "Class Extension",
- "identifier": "objective-c.class.extension"
- },
- "location": {
- "position": {
- "character": 11,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Category2"
- }
- ],
- "title": "NSString (Category2)"
- },
- "pathComponents": [
- "Category2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "text",
- "spelling": "- ("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": ") "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "functionSignature": {
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:objc(cs)NSString(im)StringMethod2"
- },
- "kind": {
- "displayName": "Instance Method",
- "identifier": "objective-c.method"
- },
- "location": {
- "position": {
- "character": 0,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- }
- ],
- "subHeading": [
- {
- "kind": "text",
- "spelling": "- "
- },
- {
- "kind": "identifier",
- "spelling": "StringMethod2"
- }
- ],
- "title": "StringMethod2"
- },
- "pathComponents": [
- "Category2",
- "StringMethod2"
- ]
- }
- ]
-}
diff --git a/clang/test/ExtractAPI/operator_overload.cpp b/clang/test/ExtractAPI/operator_overload.cpp
index 511a5a7ae8fdf0..9430c58a991e17 100644
--- a/clang/test/ExtractAPI/operator_overload.cpp
+++ b/clang/test/ExtractAPI/operator_overload.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/relative_include.m b/clang/test/ExtractAPI/relative_include.m
index 46cbdaeeb280c1..e5a02683cbd816 100644
--- a/clang/test/ExtractAPI/relative_include.m
+++ b/clang/test/ExtractAPI/relative_include.m
@@ -15,7 +15,7 @@
// RUN: %hmaptool write %t/headermap.hmap.json %t/headermap.hmap
// Input headers use paths to the framework root/DSTROOT
-// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -I%t/headermap.hmap -F%t/Frameworks \
// RUN: -x objective-c-header \
diff --git a/clang/test/ExtractAPI/simple_inheritance.cpp b/clang/test/ExtractAPI/simple_inheritance.cpp
index 5fe99afe087633..58c3c4e1e5cb8a 100644
--- a/clang/test/ExtractAPI/simple_inheritance.cpp
+++ b/clang/test/ExtractAPI/simple_inheritance.cpp
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/struct.c b/clang/test/ExtractAPI/struct.c
index 4284b734cd0595..1995a6aedbfd35 100644
--- a/clang/test/ExtractAPI/struct.c
+++ b/clang/test/ExtractAPI/struct.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/typedef.c b/clang/test/ExtractAPI/typedef.c
index c30e65549f2b74..a4c3619bfd210a 100644
--- a/clang/test/ExtractAPI/typedef.c
+++ b/clang/test/ExtractAPI/typedef.c
@@ -1,391 +1,93 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=Typedef -target arm64-apple-macosx \
-// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT
typedef int MyInt;
+// MYINT-LABEL: "!testLabel": "c:typedef.c at T@MyInt"
+// MYINT: "accessLevel": "public",
+// MYINT: "declarationFragments": [
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "keyword",
+// MYINT-NEXT: "spelling": "typedef"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": " "
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "typeIdentifier",
+// MYINT-NEXT: "preciseIdentifier": "c:I",
+// MYINT-NEXT: "spelling": "int"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": " "
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "identifier",
+// MYINT-NEXT: "spelling": "MyInt"
+// MYINT-NEXT: },
+// MYINT-NEXT: {
+// MYINT-NEXT: "kind": "text",
+// MYINT-NEXT: "spelling": ";"
+// MYINT-NEXT: }
+// MYINT-NEXT: ],
+// MYINT: "kind": {
+// MYINT-NEXT: "displayName": "Type Alias",
+// MYINT-NEXT: "identifier": "objective-c.typealias"
+// MYINT-NEXT: },
+// MYINT: "title": "MyInt"
+// MYINT: "pathComponents": [
+// MYINT-NEXT: "MyInt"
+// MYINT-NEXT: ],
+// MYINT: "type": "c:I"
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BARPTR
typedef struct Bar *BarPtr;
+// BARPTR-LABEL: "!testLabel": "c:typedef.c at T@BarPtr"
+// BARPTR: "accessLevel": "public",
+// BARPTR: "declarationFragments": [
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "keyword",
+// BARPTR-NEXT: "spelling": "typedef"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "keyword",
+// BARPTR-NEXT: "spelling": "struct"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "typeIdentifier",
+// BARPTR-NEXT: "preciseIdentifier": "c:@S at Bar",
+// BARPTR-NEXT: "spelling": "Bar"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": " * "
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "identifier",
+// BARPTR-NEXT: "spelling": "BarPtr"
+// BARPTR-NEXT: },
+// BARPTR-NEXT: {
+// BARPTR-NEXT: "kind": "text",
+// BARPTR-NEXT: "spelling": ";"
+// BARPTR-NEXT: }
+// BARPTR-NEXT: ],
+// BARPTR: "type": "c:*$@S at Bar"
+// RUN: FileCheck %s --input-file %t/output.symbols.json
void foo(BarPtr value);
void baz(BarPtr *value);
+// CHECK-NOT: struct Bar *
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "Typedef",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "foo"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- }
- ],
- "name": "value"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F at foo"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "foo"
- }
- ],
- "title": "foo"
- },
- "pathComponents": [
- "foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "baz"
- },
- {
- "kind": "text",
- "spelling": "("
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- },
- {
- "kind": "text",
- "spelling": ");"
- }
- ],
- "functionSignature": {
- "parameters": [
- {
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@BarPtr",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "internalParam",
- "spelling": "value"
- }
- ],
- "name": "value"
- }
- ],
- "returns": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:v",
- "spelling": "void"
- }
- ]
- },
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:@F at baz"
- },
- "kind": {
- "displayName": "Function",
- "identifier": "objective-c.func"
- },
- "location": {
- "position": {
- "character": 5,
- "line": 6
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "baz"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "baz"
- }
- ],
- "title": "baz"
- },
- "pathComponents": [
- "baz"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyInt"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:input.h at T@MyInt"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "objective-c.typealias"
- },
- "location": {
- "position": {
- "character": 12,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyInt"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyInt"
- }
- ],
- "title": "MyInt"
- },
- "pathComponents": [
- "MyInt"
- ],
- "type": "c:I"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@S at Bar",
- "spelling": "Bar"
- },
- {
- "kind": "text",
- "spelling": " * "
- },
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "objective-c",
- "precise": "c:input.h at T@BarPtr"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "objective-c.typealias"
- },
- "location": {
- "position": {
- "character": 20,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "BarPtr"
- }
- ],
- "title": "BarPtr"
- },
- "pathComponents": [
- "BarPtr"
- ],
- "type": "c:*$@S at Bar"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c
index 3e4c3e1dd60c4f..9e00ff75254654 100644
--- a/clang/test/ExtractAPI/typedef_anonymous_record.c
+++ b/clang/test/ExtractAPI/typedef_anonymous_record.c
@@ -1,468 +1,158 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --product-name=TypedefChain -triple arm64-apple-macosx \
-// RUN: -x c-header %t/input.h -o %t/output.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: --product-name=TypedefChain -triple arm64-apple-macosx -x c-header %s -o %t/typedefchain.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT
typedef struct { } MyStruct;
+// MYSTRUCT-LABEL: "!testLabel": "c:@SA at MyStruct"
+// MYSTRUCT: "accessLevel": "public",
+// MYSTRUCT: "declarationFragments": [
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCT-NEXT: "spelling": "typedef"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": " "
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCT-NEXT: "spelling": "struct"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": " "
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "identifier",
+// MYSTRUCT-NEXT: "spelling": "MyStruct"
+// MYSTRUCT-NEXT: },
+// MYSTRUCT-NEXT: {
+// MYSTRUCT-NEXT: "kind": "text",
+// MYSTRUCT-NEXT: "spelling": ";"
+// MYSTRUCT-NEXT: }
+// MYSTRUCT-NEXT: ]
+// MYSTRUCT: "kind": {
+// MYSTRUCT-NEXT: "displayName": "Structure",
+// MYSTRUCT-NEXT: "identifier": "c.struct"
+// MYSTRUCT: "title": "MyStruct"
+// MYSTRUCT: "pathComponents": [
+// MYSTRUCT-NEXT: "MyStruct"
+// MYSTRUCT-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT
typedef MyStruct MyStructStruct;
-typedef MyStructStruct MyStructStructStruct;
+// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c at T@MyStructStruct"
+// MYSTRUCTSTRUCT: "accessLevel": "public",
+// MYSTRUCTSTRUCT: "declarationFragments": [
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "keyword",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "typedef"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": " "
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "typeIdentifier",
+// MYSTRUCTSTRUCT-NEXT: "preciseIdentifier": "c:@SA at MyStruct",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStruct"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": " "
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "identifier",
+// MYSTRUCTSTRUCT-NEXT: "spelling": "MyStructStruct"
+// MYSTRUCTSTRUCT-NEXT: },
+// MYSTRUCTSTRUCT-NEXT: {
+// MYSTRUCTSTRUCT-NEXT: "kind": "text",
+// MYSTRUCTSTRUCT-NEXT: "spelling": ";"
+// MYSTRUCTSTRUCT-NEXT: }
+// MYSTRUCTSTRUCT-NEXT:],
+// MYSTRUCTSTRUCT: "kind": {
+// MYSTRUCTSTRUCT-NEXT: "displayName": "Type Alias",
+// MYSTRUCTSTRUCT-NEXT: "identifier": "c.typealias"
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUM
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix CASE
typedef enum { Case } MyEnum;
+// MYENUM: "source": "c:@EA at MyEnum@Case",
+// MYENUM-NEXT: "target": "c:@EA at MyEnum",
+// MYENUM-NEXT: "targetFallback": "MyEnum"
+// MYENUM-LABEL: "!testLabel": "c:@EA at MyEnum"
+// MYENUM: "declarationFragments": [
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "keyword",
+// MYENUM-NEXT: "spelling": "typedef"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": " "
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "keyword",
+// MYENUM-NEXT: "spelling": "enum"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": " "
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "identifier",
+// MYENUM-NEXT: "spelling": "MyEnum"
+// MYENUM-NEXT: },
+// MYENUM-NEXT: {
+// MYENUM-NEXT: "kind": "text",
+// MYENUM-NEXT: "spelling": ";"
+// MYENUM-NEXT: }
+// MYENUM-NEXT:],
+// MYENUM: "kind": {
+// MYENUM-NEXT: "displayName": "Enumeration",
+// MYENUM-NEXT: "identifier": "c.enum"
+// MYENUM: "title": "MyEnum"
+
+// CASE-LABEL: "!testLabel": "c:@EA at MyEnum@Case"
+// CASE: "pathComponents": [
+// CASE-NEXT: "MyEnum",
+// CASE-NEXT: "Case"
+// CASE-NEXT: ]
+
+// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYENUMENUM
typedef MyEnum MyEnumEnum;
-typedef MyEnumEnum MyEnumEnumEnum;
-// expected-no-diagnostics
+// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c at T@MyEnumEnum"
+// MYENUMENUM: "declarationFragments": [
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "keyword",
+// MYENUMENUM-NEXT: "spelling": "typedef"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": " "
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "typeIdentifier",
+// MYENUMENUM-NEXT: "preciseIdentifier": "c:@EA at MyEnum",
+// MYENUMENUM-NEXT: "spelling": "MyEnum"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": " "
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "identifier",
+// MYENUMENUM-NEXT: "spelling": "MyEnumEnum"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM-NEXT: {
+// MYENUMENUM-NEXT: "kind": "text",
+// MYENUMENUM-NEXT: "spelling": ";"
+// MYENUMENUM-NEXT: }
+// MYENUMENUM-NEXT: ],
+// MYENUMENUM: "kind": {
+// MYENUMENUM-NEXT: "displayName": "Type Alias",
+// MYENUMENUM-NEXT: "identifier": "c.typealias"
+// MYENUMENUM-NEXT: },
+// MYENUMENUM: "title": "MyEnumEnum"
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "TypedefChain",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@EA at MyEnum@Case",
- "target": "c:@EA at MyEnum",
- "targetFallback": "MyEnum"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "enum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@EA at MyEnum"
- },
- "kind": {
- "displayName": "Enumeration",
- "identifier": "c.enum"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnum"
- }
- ],
- "title": "MyEnum"
- },
- "pathComponents": [
- "MyEnum"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@EA at MyEnum@Case"
- },
- "kind": {
- "displayName": "Enumeration Case",
- "identifier": "c.enum.case"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Case"
- }
- ],
- "title": "Case"
- },
- "pathComponents": [
- "MyEnum",
- "Case"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@SA at MyStruct"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStruct"
- }
- ],
- "title": "MyStruct"
- },
- "pathComponents": [
- "MyStruct"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@SA at MyStruct",
- "spelling": "MyStruct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@MyStructStruct"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 17,
- "line": 1
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyStructStruct"
- }
- ],
- "title": "MyStructStruct"
- },
- "pathComponents": [
- "MyStructStruct"
- ],
- "type": "c:@SA at MyStruct"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@MyStructStruct",
- "spelling": "MyStructStruct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@MyStructStructStruct"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 23,
- "line": 2
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyStructStructStruct"
- }
- ],
- "title": "MyStructStructStruct"
- },
- "pathComponents": [
- "MyStructStructStruct"
- ],
- "type": "c:input.h at T@MyStructStruct"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@EA at MyEnum",
- "spelling": "MyEnum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@MyEnumEnum"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnum"
- }
- ],
- "title": "MyEnumEnum"
- },
- "pathComponents": [
- "MyEnumEnum"
- ],
- "type": "c:@EA at MyEnum"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:input.h at T@MyEnumEnum",
- "spelling": "MyEnumEnum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@MyEnumEnumEnum"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 19,
- "line": 5
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "MyEnumEnumEnum"
- }
- ],
- "title": "MyEnumEnumEnum"
- },
- "pathComponents": [
- "MyEnumEnumEnum"
- ],
- "type": "c:input.h at T@MyEnumEnum"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/typedef_chain.c b/clang/test/ExtractAPI/typedef_chain.c
index 9e6151c8ebd905..05d4eb52cef36b 100644
--- a/clang/test/ExtractAPI/typedef_chain.c
+++ b/clang/test/ExtractAPI/typedef_chain.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --product-name=TypedefChain -target arm64-apple-macosx \
+// RUN: %clang -extract-api --pretty-sgf --product-name=TypedefChain -target arm64-apple-macosx \
// RUN: -x objective-c-header %t/input.h -o %t/output.json | FileCheck -allow-empty %s
// Generator version is not consistent across test runs, normalize it.
diff --git a/clang/test/ExtractAPI/typedef_struct_enum.c b/clang/test/ExtractAPI/typedef_struct_enum.c
index 15357d5b055fb2..fb6fbe987624f8 100644
--- a/clang/test/ExtractAPI/typedef_struct_enum.c
+++ b/clang/test/ExtractAPI/typedef_struct_enum.c
@@ -1,445 +1,146 @@
// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api -target arm64-apple-macosx \
-// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s
+// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \
+// RUN: -x c-header %s -triple arm64-apple-macos -o %t/output.symbols.json -verify
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-// CHECK-NOT: error:
-// CHECK-NOT: warning:
-
-//--- input.h
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST
typedef struct Test {
} Test;
+// TEST-LABEL: "!testLabel": "c:@S at Test"
+// TEST: "declarationFragments": [
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "keyword",
+// TEST-NEXT: "spelling": "typedef"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "keyword",
+// TEST-NEXT: "spelling": "struct"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "identifier",
+// TEST-NEXT: "spelling": "Test"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": " { ... } "
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "identifier",
+// TEST-NEXT: "spelling": "Test"
+// TEST-NEXT: },
+// TEST-NEXT: {
+// TEST-NEXT: "kind": "text",
+// TEST-NEXT: "spelling": ";"
+// TEST-NEXT: }
+// TEST-NEXT: ],
+// TEST: "displayName": "Structure",
+// TEST: "title": "Test"
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST2
typedef enum Test2 {
simple
} Test2;
+// TEST2-LABEL: "!testLabel": "c:@E at Test2"
+// TEST2: "declarationFragments": [
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "keyword",
+// TEST2-NEXT: "spelling": "typedef"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "keyword",
+// TEST2-NEXT: "spelling": "enum"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "identifier",
+// TEST2-NEXT: "spelling": "Test2"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": ": "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "typeIdentifier",
+// TEST2-NEXT: "preciseIdentifier": "c:i",
+// TEST2-NEXT: "spelling": "unsigned int"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": " { ... } "
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "identifier",
+// TEST2-NEXT: "spelling": "Test2"
+// TEST2-NEXT: },
+// TEST2-NEXT: {
+// TEST2-NEXT: "kind": "text",
+// TEST2-NEXT: "spelling": ";"
+// TEST2-NEXT: }
+// TEST2-NEXT: ],
+// TEST2: "displayName": "Enumeration",
+// TEST2: "title": "Test2"
+
struct Foo;
+
+// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPEDEF
typedef struct Foo TypedefedFoo;
+// TYPEDEF-LABEL: "!testLabel": "c:typedef_struct_enum.c at T@TypedefedFoo"
+// TYPEDEF: "declarationFragments": [
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "keyword",
+// TYPEDEF-NEXT: "spelling": "typedef"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "keyword",
+// TYPEDEF-NEXT: "spelling": "struct"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "typeIdentifier",
+// TYPEDEF-NEXT: "preciseIdentifier": "c:@S at Foo",
+// TYPEDEF-NEXT: "spelling": "Foo"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": " "
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "identifier",
+// TYPEDEF-NEXT: "spelling": "TypedefedFoo"
+// TYPEDEF-NEXT: },
+// TYPEDEF-NEXT: {
+// TYPEDEF-NEXT: "kind": "text",
+// TYPEDEF-NEXT: "spelling": ";"
+// TYPEDEF-NEXT: }
+// TYPEDEF-NEXT: ],
+// TYPEDEF: "displayName": "Type Alias",
+// TYPEDEF: "title": "TypedefedFoo"
+// TYPEDEF: "type": "c:@S at Foo"
+
struct Foo {
int bar;
};
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@E at Test2@simple",
- "target": "c:@E at Test2",
- "targetFallback": "Test2"
- },
- {
- "kind": "memberOf",
- "source": "c:@S at Foo@FI at bar",
- "target": "c:@S at Foo",
- "targetFallback": "Foo"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "enum"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Test2"
- },
- {
- "kind": "text",
- "spelling": ": "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:i",
- "spelling": "unsigned int"
- },
- {
- "kind": "text",
- "spelling": " { ... } "
- },
- {
- "kind": "identifier",
- "spelling": "Test2"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@E at Test2"
- },
- "kind": {
- "displayName": "Enumeration",
- "identifier": "c.enum"
- },
- "location": {
- "position": {
- "character": 13,
- "line": 3
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Test2"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Test2"
- }
- ],
- "title": "Test2"
- },
- "pathComponents": [
- "Test2"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@E at Test2@simple"
- },
- "kind": {
- "displayName": "Enumeration Case",
- "identifier": "c.enum.case"
- },
- "location": {
- "position": {
- "character": 2,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "simple"
- }
- ],
- "title": "simple"
- },
- "pathComponents": [
- "Test2",
- "simple"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Test"
- },
- {
- "kind": "text",
- "spelling": " { ... } "
- },
- {
- "kind": "identifier",
- "spelling": "Test"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S at Test"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 15,
- "line": 0
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Test"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Test"
- }
- ],
- "title": "Test"
- },
- "pathComponents": [
- "Test"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S at Foo"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 9
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "Foo"
- }
- ],
- "title": "Foo"
- },
- "pathComponents": [
- "Foo"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "bar"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S at Foo@FI at bar"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "c.property"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 10
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "bar"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "bar"
- }
- ],
- "title": "bar"
- },
- "pathComponents": [
- "Foo",
- "bar"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@S at Foo",
- "spelling": "Foo"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@TypedefedFoo"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 19,
- "line": 8
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "TypedefedFoo"
- }
- ],
- "title": "TypedefedFoo"
- },
- "pathComponents": [
- "TypedefedFoo"
- ],
- "type": "c:@S at Foo"
- }
- ]
-}
+// expected-no-diagnostics
diff --git a/clang/test/ExtractAPI/underscored.c b/clang/test/ExtractAPI/underscored.c
index 30d2b63f763eff..204ec36f1fab1f 100644
--- a/clang/test/ExtractAPI/underscored.c
+++ b/clang/test/ExtractAPI/underscored.c
@@ -1,17 +1,5 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
-// RUN: %t/reference.output.json.in >> %t/reference.output.json
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
-// RUN: -x c-header %t/input.h -o %t/output.json -verify
-
-// Generator version is not consistent across test runs, normalize it.
-// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
-// RUN: %t/output.json >> %t/output-normalized.json
-// RUN: diff %t/reference.output.json %t/output-normalized.json
-
-//--- input.h
-// expected-no-diagnostics
+// RUN: -x c-header %s -o - -verify | FileCheck %s
// Global record
int _HiddenGlobal;
@@ -19,399 +7,22 @@ int exposed_global;
// Record type
struct _HiddenRecord {
- int a;
+ int HiddenRecordMember;
};
struct ExposedRecord {
- int a;
+ int ExposedRecordMember;
};
-// Typedef
-typedef struct {} _HiddenTypedef;
-typedef int ExposedTypedef;
-typedef _HiddenTypedef ExposedTypedefToHidden;
-
// Macros
#define _HIDDEN_MACRO 5
#define EXPOSED_MACRO 5
-// Symbols that start with '_' should not appear in the reference output
-//--- reference.output.json.in
-{
- "metadata": {
- "formatVersion": {
- "major": 0,
- "minor": 5,
- "patch": 3
- },
- "generator": "?"
- },
- "module": {
- "name": "",
- "platform": {
- "architecture": "arm64",
- "operatingSystem": {
- "minimumVersion": {
- "major": 11,
- "minor": 0,
- "patch": 0
- },
- "name": "macosx"
- },
- "vendor": "apple"
- }
- },
- "relationships": [
- {
- "kind": "memberOf",
- "source": "c:@S at ExposedRecord@FI at a",
- "target": "c:@S at ExposedRecord",
- "targetFallback": "ExposedRecord"
- }
- ],
- "symbols": [
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@exposed_global"
- },
- "kind": {
- "displayName": "Global Variable",
- "identifier": "c.var"
- },
- "location": {
- "position": {
- "character": 4,
- "line": 4
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "exposed_global"
- }
- ],
- "title": "exposed_global"
- },
- "pathComponents": [
- "exposed_global"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "struct"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S at ExposedRecord"
- },
- "kind": {
- "displayName": "Structure",
- "identifier": "c.struct"
- },
- "location": {
- "position": {
- "character": 7,
- "line": 11
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedRecord"
- }
- ],
- "title": "ExposedRecord"
- },
- "pathComponents": [
- "ExposedRecord"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "a"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:@S at ExposedRecord@FI at a"
- },
- "kind": {
- "displayName": "Instance Property",
- "identifier": "c.property"
- },
- "location": {
- "position": {
- "character": 6,
- "line": 12
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "a"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "a"
- }
- ],
- "title": "a"
- },
- "pathComponents": [
- "ExposedRecord",
- "a"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "#define"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at 335@macro at EXPOSED_MACRO"
- },
- "kind": {
- "displayName": "Macro",
- "identifier": "c.macro"
- },
- "location": {
- "position": {
- "character": 8,
- "line": 22
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "EXPOSED_MACRO"
- }
- ],
- "title": "EXPOSED_MACRO"
- },
- "pathComponents": [
- "EXPOSED_MACRO"
- ]
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@ExposedTypedef"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 12,
- "line": 17
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedef"
- }
- ],
- "title": "ExposedTypedef"
- },
- "pathComponents": [
- "ExposedTypedef"
- ],
- "type": "c:I"
- },
- {
- "accessLevel": "public",
- "declarationFragments": [
- {
- "kind": "keyword",
- "spelling": "typedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "typeIdentifier",
- "preciseIdentifier": "c:@SA at _HiddenTypedef",
- "spelling": "_HiddenTypedef"
- },
- {
- "kind": "text",
- "spelling": " "
- },
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- },
- {
- "kind": "text",
- "spelling": ";"
- }
- ],
- "identifier": {
- "interfaceLanguage": "c",
- "precise": "c:input.h at T@ExposedTypedefToHidden"
- },
- "kind": {
- "displayName": "Type Alias",
- "identifier": "c.typealias"
- },
- "location": {
- "position": {
- "character": 23,
- "line": 18
- },
- "uri": "file://INPUT_DIR/input.h"
- },
- "names": {
- "navigator": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- }
- ],
- "subHeading": [
- {
- "kind": "identifier",
- "spelling": "ExposedTypedefToHidden"
- }
- ],
- "title": "ExposedTypedefToHidden"
- },
- "pathComponents": [
- "ExposedTypedefToHidden"
- ],
- "type": "c:@SA at _HiddenTypedef"
- }
- ]
-}
+// expected-no-diagnostics
+
+// CHECK-NOT: _HiddenRecord
+// CHECK-NOT: HiddenRecordMember
+// CHECK: ExposedRecord
+// CHECK: ExposedRecordMember
+// CHECK-NOT: _HIDDEN_MACRO
+// CHECK: EXPOSED_MACRO
diff --git a/clang/test/ExtractAPI/union.c b/clang/test/ExtractAPI/union.c
index 6ec9fd3ddf6e99..8f8300b2c9a52d 100644
--- a/clang/test/ExtractAPI/union.c
+++ b/clang/test/ExtractAPI/union.c
@@ -2,7 +2,7 @@
// RUN: split-file %s %t
// RUN: sed -e "s at INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx -x c-header\
+// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x c-header\
// RUN: %t/input.h -o %t/output.json -verify
// Generator version is not consistent across test runs, normalize it.
@@ -12,7 +12,7 @@
//--- input.h
/// My Union
-union Union{
+union Union {
/// the a option
int a;
/// the b option
diff --git a/clang/test/ExtractAPI/vfs_redirected_include.m b/clang/test/ExtractAPI/vfs_redirected_include.m
index 9ba7e1dedb601e..db0382052ba3ef 100644
--- a/clang/test/ExtractAPI/vfs_redirected_include.m
+++ b/clang/test/ExtractAPI/vfs_redirected_include.m
@@ -14,7 +14,7 @@
// RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml
// Input headers use paths to the framework root/DSTROOT
-// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api --pretty-sgf -v --product-name=MyFramework \
// RUN: -triple arm64-apple-macosx \
// RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \
// RUN: -x objective-c-header \
diff --git a/clang/test/Index/extract-api-cursor.m b/clang/test/Index/extract-api-cursor.m
index 1b27b6f61437be..9d9d3a1e40f145 100644
--- a/clang/test/Index/extract-api-cursor.m
+++ b/clang/test/Index/extract-api-cursor.m
@@ -31,6 +31,8 @@ @implementation Derived
- (void)derivedMethodWithValue:(id<Protocol>)value {
int a = 5;
}
+/// Impl only docs
+- (void)implOnlyMethod { }
@end
// RUN: c-index-test -single-symbol-sgf-at=%s:4:9 local %s | FileCheck -check-prefix=CHECK-FOO %s
@@ -118,3 +120,10 @@ - (void)derivedMethodWithValue:(id<Protocol>)value {
// CHECK-DERIVED-METHOD-IMPL: "text":"Derived method docs"
// CHECK-DERIVED-METHOD-IMPL: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
// CHECK-DERIVED-METHOD-IMPL: "title":"derivedMethodWithValue:"
+
+// RUN: c-index-test -single-symbol-sgf-at=%s:35:11 local %s | FileCheck -check-prefix=CHECK-IMPL-ONLY %s
+// CHECK-IMPL-ONLY: "relatedSymbols":[]
+// CHECK-IMPL-ONLY: "relationships":[{"kind":"memberOf","source":"c:objc(cs)Derived(im)implOnlyMethod","target":"c:objc(cs)Derived"
+// CHECK-IMPL-ONLY: "text":"Impl only docs"
+// CHECK-IMPL-ONLY: "kind":{"displayName":"Instance Method","identifier":"objective-c.method"}
+// CHECK-IMPL-ONLY: "title":"implOnlyMethod"
diff --git a/clang/tools/libclang/CXExtractAPI.cpp b/clang/tools/libclang/CXExtractAPI.cpp
index 05098c96829fcd..d74f3740406c5c 100644
--- a/clang/tools/libclang/CXExtractAPI.cpp
+++ b/clang/tools/libclang/CXExtractAPI.cpp
@@ -18,6 +18,7 @@
#include "clang-c/Index.h"
#include "clang-c/Platform.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/ExtractAPI/API.h"
@@ -54,41 +55,20 @@ struct LibClangExtractAPIVisitor
if (!shouldDeclBeIncluded(Decl))
return true;
- const ObjCInterfaceDecl *Interface = Decl->getClassInterface();
- StringRef Name = Interface->getName();
- StringRef USR = API.recordUSR(Decl);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Decl->getLocation());
- LinkageInfo Linkage = Decl->getLinkageAndVisibility();
- DocComment Comment;
- if (auto *RawComment = fetchRawCommentForDecl(Interface))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments and sub-heading by generating them for the
- // interface.
- DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface);
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Decl);
-
- // Collect super class information.
- SymbolReference SuperClass;
- if (const auto *SuperClassDecl = Decl->getSuperClass()) {
- SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
- SuperClass.USR = API.recordUSR(SuperClassDecl);
- }
+ auto *Interface = Decl->getClassInterface();
- ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
- Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
- Comment, Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
+ if (!VisitObjCInterfaceDecl(Interface))
+ return false;
- // Record all methods (selectors). This doesn't include automatically
- // synthesized property methods.
- recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
- recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
- recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
+ SmallString<128> USR;
+ index::generateUSRForDecl(Interface, USR);
+ if (auto *InterfaceRecord = dyn_cast_if_present<ObjCInterfaceRecord>(
+ API.findRecordForUSR(USR))) {
+ recordObjCMethods(InterfaceRecord, Decl->methods());
+ recordObjCProperties(InterfaceRecord, Decl->properties());
+ recordObjCInstanceVariables(InterfaceRecord, Decl->ivars());
+ }
return true;
}
};
@@ -96,21 +76,14 @@ struct LibClangExtractAPIVisitor
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
-static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
- Decl *D);
-
-template <typename DeclTy>
-static bool WalkupParentContext(DeclContext *Parent,
- LibClangExtractAPIVisitor &Visitor) {
- if (auto *D = dyn_cast<DeclTy>(Parent)) {
- WalkupFromMostDerivedType(Visitor, D);
- return true;
- }
- return false;
-}
-
+// Visits the Decl D and it's transitive DeclContexts recursively, starting from
+// the outer-most context. This is guaranteed to visit every Decl we need in the
+// right order to generate symbol graph information for D.
static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
Decl *D) {
+ if (auto *Parent = D->getDeclContext())
+ WalkupFromMostDerivedType(Visitor, cast<Decl>(Parent));
+
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
#define DECL(CLASS, BASE) \
@@ -119,20 +92,12 @@ static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
break;
#include "clang/AST/DeclNodes.inc"
}
-
- for (auto *Parent = D->getDeclContext(); Parent != nullptr;
- Parent = Parent->getParent()) {
- if (WalkupParentContext<ObjCContainerDecl>(Parent, Visitor))
- return;
- if (WalkupParentContext<TagDecl>(Parent, Visitor))
- return;
- }
}
static CXString GenerateCXStringFromSymbolGraphData(llvm::json::Object Obj) {
llvm::SmallString<0> BackingString;
llvm::raw_svector_ostream OS(BackingString);
- OS << Value(std::move(Obj));
+ OS << llvm::formatv("{0}", Value(std::move(Obj)));
return cxstring::createDup(BackingString.str());
}
>From 51b6e276694d91ef3021c4a0f27f151bee7baadb Mon Sep 17 00:00:00 2001
From: Daniel Grumberg <dgrumberg at apple.com>
Date: Tue, 2 Apr 2024 15:37:53 +0100
Subject: [PATCH 2/2] Add diagnostic group for missing symbol-graph-dir warning
---
clang/include/clang/Basic/DiagnosticFrontendKinds.td | 4 +++-
clang/include/clang/Basic/DiagnosticGroups.td | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 241544b2b8c6fa..14b08d4927ec5e 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -366,6 +366,8 @@ def warn_profile_data_misexpect : Warning<
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
-def warn_missing_symbol_graph_dir : Warning<"Missing symbol graph output directory, defaulting to working directory">;
+def warn_missing_symbol_graph_dir : Warning<
+ "Missing symbol graph output directory, defaulting to working directory">,
+ InGroup<ExtractAPIMisuse>;
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 520168f01fd846..5251774ff4efd6 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1517,3 +1517,5 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon
// Warnings and notes InstallAPI verification.
def InstallAPIViolation : DiagGroup<"installapi-violation">;
+// Warnings about misuse of ExtractAPI options.
+def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
More information about the cfe-commits
mailing list