summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@gmail.com>2024-04-03 17:22:45 -0700
committerGitHub <noreply@github.com>2024-04-03 17:22:45 -0700
commit28fa873d3642324ba64f1624a8ae0cc34c582489 (patch)
tree3c2c6c57cc31ac50e3cf89f706ddb3d0956b63f4
parent7e2a1d6f23cb604203324b47237f8e463704a497 (diff)
Revert "Reenable external categories (#87357)"upstream/revert-87357-reenable-external-categories
This reverts commit e05c1b46d0d3739cc48ad912dbe6e9affce05927.
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td6
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td4
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--clang/include/clang/Driver/Options.td21
-rw-r--r--clang/include/clang/ExtractAPI/API.h1547
-rw-r--r--clang/include/clang/ExtractAPI/APIRecords.inc103
-rw-r--r--clang/include/clang/ExtractAPI/DeclarationFragments.h14
-rw-r--r--clang/include/clang/ExtractAPI/ExtractAPIActionBase.h8
-rw-r--r--clang/include/clang/ExtractAPI/ExtractAPIVisitor.h674
-rw-r--r--clang/include/clang/ExtractAPI/FrontendActions.h6
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h172
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/SerializerBase.h314
-rw-r--r--clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h254
-rw-r--r--clang/include/clang/Frontend/FrontendOptions.h21
-rw-r--r--clang/lib/Driver/Driver.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp15
-rw-r--r--clang/lib/ExtractAPI/API.cpp544
-rw-r--r--clang/lib/ExtractAPI/DeclarationFragments.cpp71
-rw-r--r--clang/lib/ExtractAPI/ExtractAPIConsumer.cpp112
-rw-r--r--clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp943
-rw-r--r--clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp6
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp10
-rw-r--r--clang/test/ExtractAPI/anonymous_record_no_typedef.c3
-rw-r--r--clang/test/ExtractAPI/availability.c2
-rw-r--r--clang/test/ExtractAPI/bool.c2
-rw-r--r--clang/test/ExtractAPI/bool.cpp2
-rw-r--r--clang/test/ExtractAPI/class.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template_param_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/class_template_partial_spec.cpp4
-rw-r--r--clang/test/ExtractAPI/class_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/concept.cpp2
-rw-r--r--clang/test/ExtractAPI/constructor_destructor.cpp6
-rw-r--r--clang/test/ExtractAPI/conversions.cpp2
-rw-r--r--clang/test/ExtractAPI/emit-symbol-graph/multi_file.c7
-rw-r--r--clang/test/ExtractAPI/emit-symbol-graph/single_file.c5
-rw-r--r--clang/test/ExtractAPI/enum.c2
-rw-r--r--clang/test/ExtractAPI/field_template.cpp2
-rw-r--r--clang/test/ExtractAPI/function_noexcepts.cpp2
-rw-r--r--clang/test/ExtractAPI/global_func_template.cpp2
-rw-r--r--clang/test/ExtractAPI/global_func_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/global_record.c2
-rw-r--r--clang/test/ExtractAPI/global_record_multifile.c2
-rw-r--r--clang/test/ExtractAPI/global_var_template.cpp2
-rw-r--r--clang/test/ExtractAPI/global_var_template_partial_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/global_var_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/known_files_only.c101
-rw-r--r--clang/test/ExtractAPI/language.c6
-rw-r--r--clang/test/ExtractAPI/macro_undefined.c2
-rw-r--r--clang/test/ExtractAPI/macros.c2
-rw-r--r--clang/test/ExtractAPI/metadata_and_module.c32
-rw-r--r--clang/test/ExtractAPI/method_template.cpp2
-rw-r--r--clang/test/ExtractAPI/method_template_spec.cpp2
-rw-r--r--clang/test/ExtractAPI/methods.cpp660
-rw-r--r--clang/test/ExtractAPI/multiple_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/namespace.cpp2
-rw-r--r--clang/test/ExtractAPI/nested_namespaces.cpp2
-rw-r--r--clang/test/ExtractAPI/objc_block.m1567
-rw-r--r--clang/test/ExtractAPI/objc_category.m338
-rw-r--r--clang/test/ExtractAPI/objc_external_category.m49
-rw-r--r--clang/test/ExtractAPI/objc_id_protocol.m357
-rw-r--r--clang/test/ExtractAPI/objc_instancetype.m4
-rw-r--r--clang/test/ExtractAPI/objc_interface.m1033
-rw-r--r--clang/test/ExtractAPI/objc_module_category.m404
-rw-r--r--clang/test/ExtractAPI/objc_property.m600
-rw-r--r--clang/test/ExtractAPI/objc_protocol.m2
-rw-r--r--clang/test/ExtractAPI/objc_various_categories.m507
-rw-r--r--clang/test/ExtractAPI/operator_overload.cpp2
-rw-r--r--clang/test/ExtractAPI/relative_include.m2
-rw-r--r--clang/test/ExtractAPI/simple_inheritance.cpp2
-rw-r--r--clang/test/ExtractAPI/struct.c2
-rw-r--r--clang/test/ExtractAPI/typedef.c464
-rw-r--r--clang/test/ExtractAPI/typedef_anonymous_record.c612
-rw-r--r--clang/test/ExtractAPI/typedef_chain.c2
-rw-r--r--clang/test/ExtractAPI/typedef_struct_enum.c561
-rw-r--r--clang/test/ExtractAPI/underscored.c411
-rw-r--r--clang/test/ExtractAPI/union.c4
-rw-r--r--clang/test/ExtractAPI/vfs_redirected_include.m2
-rw-r--r--clang/test/Index/extract-api-cursor.m9
-rw-r--r--clang/tools/libclang/CXExtractAPI.cpp73
80 files changed, 8845 insertions, 3892 deletions
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 3d86f7510bde..592ed3bda515 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -548,12 +548,6 @@ 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 14b08d4927ec..ba23cf84c5e3 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -366,8 +366,4 @@ 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">,
- InGroup<ExtractAPIMisuse>;
-
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 5251774ff4ef..520168f01fd8 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1517,5 +1517,3 @@ 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">;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index c3e90a70925b..f5289fb00c89 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1507,29 +1507,14 @@ def extract_api : Flag<["-"], "extract-api">,
def product_name_EQ: Joined<["--"], "product-name=">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<FrontendOpts<"ProductName">>;
-def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">,
+def emit_symbol_graph_EQ: JoinedOrSeparate<["--"], "emit-symbol-graph=">,
Visibility<[ClangOption, CC1Option]>,
- 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">>;
+ HelpText<"Generate Extract API information as a side effect of compilation.">,
+ MarshallingInfoString<FrontendOpts<"SymbolGraphOutputDir">>;
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 92cacf65c7d6..b220db294101 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -20,25 +20,17 @@
#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 {
@@ -157,58 +149,15 @@ public:
/// \endcode
using DocComment = std::vector<RawComment::CommentLine>;
-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!
+// 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
/// 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,
@@ -217,11 +166,18 @@ 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,
@@ -234,15 +190,40 @@ 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;
@@ -261,169 +242,79 @@ 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,
- 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),
+ PresumedLoc Location, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ bool IsFromSystemHeader)
+ : USR(USR), Name(Name), Location(Location),
Availability(std::move(Availability)), Linkage(Linkage),
Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
- IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
- Kind(Kind) {}
+ IsFromSystemHeader(IsFromSystemHeader), 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, RecordContext {
- NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
- DeclarationFragments Declaration,
+struct NamespaceRecord : APIRecord {
+ NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- RecordContext(RK_Namespace) {}
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_Namespace;
}
- 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, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
- std::move(Availability), Linkage, Comment, Declaration,
- SubHeading, IsFromSystemHeader),
+ : APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading,
+ IsFromSystemHeader),
Signature(Signature) {}
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading, IsFromSystemHeader),
Signature(Signature) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_GlobalFunction;
}
- static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
private:
virtual void anchor();
@@ -432,74 +323,63 @@ private:
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
Template Templ;
- GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
+ GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, Template Template,
bool IsFromSystemHeader)
- : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
+ : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_GlobalFunctionTemplate;
+ return Record->getKind() == RK_GlobalFunctionTemplate;
}
};
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
- Parent, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading, Signature,
+ Loc, std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, Signature,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_GlobalFunctionTemplateSpecialization;
+ return Record->getKind() == RK_GlobalFunctionTemplateSpecialization;
}
};
/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
- GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
- std::move(Availability), Linkage, Comment, Declaration,
- SubHeading, IsFromSystemHeader) {}
+ : APIRecord(RK_GlobalVariable, USR, Name, 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, Parent, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_GlobalVariable;
}
- static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
private:
virtual void anchor();
@@ -508,42 +388,34 @@ private:
struct GlobalVariableTemplateRecord : GlobalVariableRecord {
Template Templ;
- GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
+ GlobalVariableTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
class Template Template, bool IsFromSystemHeader)
- : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
+ : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_GlobalVariableTemplate;
+ return Record->getKind() == RK_GlobalVariableTemplate;
}
};
struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
- Parent, Loc, std::move(Availability), Linkage,
- Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ Loc, std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_GlobalVariableTemplateSpecialization;
+ return Record->getKind() == RK_GlobalVariableTemplateSpecialization;
}
};
@@ -552,203 +424,126 @@ struct GlobalVariableTemplatePartialSpecializationRecord
Template Templ;
GlobalVariableTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, class Template Template,
bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
- USR, Name, Parent, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
+ USR, Name, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_GlobalVariableTemplatePartialSpecialization;
+ return Record->getKind() == RK_GlobalVariableTemplatePartialSpecialization;
}
};
/// This holds information associated with enum constants.
struct EnumConstantRecord : APIRecord {
- EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
- std::move(Availability), LinkageInfo::none(), Comment,
- Declaration, SubHeading, IsFromSystemHeader) {}
+ : APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availability),
+ LinkageInfo::none(), Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_EnumConstant;
}
- static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
private:
virtual void anchor();
};
/// This holds information associated with enums.
-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),
+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),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- RecordContext(RK_Enum) {}
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_Enum;
}
- static bool classofKind(RecordKind K) { return K == RK_Enum; }
private:
virtual void anchor();
};
-/// This holds information associated with struct or union fields fields.
+/// This holds information associated with struct fields.
struct RecordFieldRecord : APIRecord {
- RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
+ RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
- DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ DeclarationFragments SubHeading, RecordKind Kind,
+ bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_StructField || K == RK_UnionField;
+ return Record->getKind() == RK_StructField ||
+ Record->getKind() == RK_UnionField;
}
- virtual ~RecordFieldRecord() = 0;
-};
-
-/// 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, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
- LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- RecordContext(Kind) {}
-
- static bool classof(const APIRecord *Record) {
- 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 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) {}
-
- 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; }
+/// This holds information associated with structs.
+struct RecordRecord : APIRecord {
+ SmallVector<std::unique_ptr<RecordFieldRecord>> Fields;
-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) {}
+ RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, RecordKind Kind,
+ bool IsFromSystemHeader)
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
+ LinkageInfo::none(), Comment, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_Struct || Record->getKind() == RK_Union;
}
- 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,
+ AccessControl Access;
+
+ CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader, std::move(Access)) {}
+ IsFromSystemHeader),
+ Access(Access) {}
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader, std::move(Access)) {}
+ IsFromSystemHeader),
+ Access(Access) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
+ return Record->getKind() == RK_CXXField;
}
private:
@@ -758,122 +553,111 @@ private:
struct CXXFieldTemplateRecord : CXXFieldRecord {
Template Templ;
- CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
+ : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, std::move(Access), IsFromSystemHeader),
+ SubHeading, Access, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXFieldTemplate;
}
- 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,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader, std::move(Access)),
- Signature(Signature) {}
+ IsFromSystemHeader),
+ Signature(Signature), Access(Access) {}
virtual ~CXXMethodRecord() = 0;
};
struct CXXConstructorRecord : CXXMethodRecord {
- CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
+ : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader) {}
+ SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXConstructorMethod;
}
- static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
private:
virtual void anchor();
};
struct CXXDestructorRecord : CXXMethodRecord {
- CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
+ : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader) {}
+ SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXDestructorMethod;
}
- static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
private:
virtual void anchor();
};
struct CXXStaticMethodRecord : CXXMethodRecord {
- CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
+ : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader) {}
+ SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXStaticMethod;
}
- static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
private:
virtual void anchor();
};
struct CXXInstanceMethodRecord : CXXMethodRecord {
- CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
+ : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader) {}
+ SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXInstanceMethod;
}
- static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
private:
virtual void anchor();
@@ -882,42 +666,36 @@ private:
struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;
- CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
+ : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader),
+ SubHeading, Signature, Access, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_CXXMethodTemplate;
}
- static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
};
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
- : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
- Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, std::move(Access),
- IsFromSystemHeader) {}
+ : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_CXXMethodTemplateSpecialization;
+ return Record->getKind() == RK_CXXMethodTemplateSpecialization;
}
};
@@ -936,13 +714,13 @@ struct ObjCPropertyRecord : APIRecord {
bool IsOptional;
ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
+ 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, Parent, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
@@ -955,44 +733,44 @@ struct ObjCPropertyRecord : APIRecord {
};
struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
- 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,
+ 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,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCInstanceProperty;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
private:
virtual void anchor();
};
struct ObjCClassPropertyRecord : ObjCPropertyRecord {
- ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ ObjCClassPropertyRecord(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_ObjCClassProperty, USR, Name, Parent, Loc,
+ : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCClassProperty;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
private:
virtual void anchor();
@@ -1000,21 +778,23 @@ private:
/// This holds information associated with Objective-C instance variables.
struct ObjCInstanceVariableRecord : APIRecord {
- ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
+ using AccessControl = ObjCIvarDecl::AccessControl;
+ AccessControl Access;
+
+ ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
- bool IsFromSystemHeader)
- : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
+ AccessControl Access, bool IsFromSystemHeader)
+ : APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader) {}
+ IsFromSystemHeader),
+ Access(Access) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCIvar;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
private:
virtual void anchor();
@@ -1027,12 +807,11 @@ struct ObjCMethodRecord : APIRecord {
ObjCMethodRecord() = delete;
ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, const DocComment &Comment,
- DeclarationFragments Declaration,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
@@ -1041,103 +820,122 @@ struct ObjCMethodRecord : APIRecord {
};
struct ObjCInstanceMethodRecord : ObjCMethodRecord {
- ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
+ ObjCInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
+ : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCInstanceMethod;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
private:
virtual void anchor();
};
struct ObjCClassMethodRecord : ObjCMethodRecord {
- ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
+ ObjCClassMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
- : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
+ : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCClassMethod;
}
- 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 {
- 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) {}
+ 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) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_StaticField;
}
- 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, RecordContext {
+struct ObjCContainerRecord : APIRecord {
+ SmallVector<std::unique_ptr<ObjCMethodRecord>> Methods;
+ SmallVector<std::unique_ptr<ObjCPropertyRecord>> Properties;
+ SmallVector<std::unique_ptr<ObjCInstanceVariableRecord>> Ivars;
SmallVector<SymbolReference> Protocols;
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
- SymbolReference Parent, PresumedLoc Loc,
- AvailabilityInfo Availability, LinkageInfo Linkage,
- const DocComment &Comment,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
- Linkage, Comment, Declaration, SubHeading,
- IsFromSystemHeader),
- RecordContext(Kind) {}
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
+ Comment, Declaration, SubHeading, IsFromSystemHeader) {}
virtual ~ObjCContainerRecord() = 0;
};
-struct CXXClassRecord : APIRecord, RecordContext {
+struct CXXClassRecord : APIRecord {
+ SmallVector<std::unique_ptr<CXXFieldRecord>> Fields;
+ SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
SmallVector<SymbolReference> Bases;
+ AccessControl Access;
- CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
- : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
- IsFromSystemHeader, std::move(Access)),
- RecordContext(Kind) {}
+ IsFromSystemHeader),
+ Access(Access) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_CXXClass || K == RK_ClassTemplate ||
- K == RK_ClassTemplateSpecialization ||
- K == RK_ClassTemplatePartialSpecialization;
+ return (Record->getKind() == RK_CXXClass);
}
private:
@@ -1147,108 +945,86 @@ private:
struct ClassTemplateRecord : CXXClassRecord {
Template Templ;
- ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
- Declaration, SubHeading, RK_ClassTemplate,
- std::move(Access), IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, RK_ClassTemplate, Access,
+ IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ClassTemplate;
}
- static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
};
struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
+ : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_ClassTemplateSpecialization;
+ return Record->getKind() == RK_ClassTemplateSpecialization;
}
};
struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
Template Templ;
ClassTemplatePartialSpecializationRecord(
- StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
+ StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader)
- : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
- Declaration, SubHeading,
- RK_ClassTemplatePartialSpecialization, Access,
- IsFromSystemHeader),
+ : CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, RK_ClassTemplateSpecialization,
+ Access, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
- }
- static bool classofKind(RecordKind K) {
- return K == RK_ClassTemplatePartialSpecialization;
+ return Record->getKind() == RK_ClassTemplatePartialSpecialization;
}
};
struct ConceptRecord : APIRecord {
Template Templ;
- ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader)
- : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(RK_Concept, USR, Name, 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, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
+ : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Interface(Interface) {}
static bool classof(const APIRecord *Record) {
- 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;
+ return Record->getKind() == RK_ObjCCategory;
}
private:
@@ -1258,22 +1034,23 @@ private:
/// 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, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- LinkageInfo Linkage, const DocComment &Comment,
+ ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
+ : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
SuperClass(SuperClass) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCInterface;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
private:
virtual void anchor();
@@ -1281,20 +1058,18 @@ private:
/// This holds information associated with Objective-C protocols.
struct ObjCProtocolRecord : ObjCContainerRecord {
- ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment,
+ ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
- : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
+ : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_ObjCProtocol;
}
- static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
private:
virtual void anchor();
@@ -1302,18 +1077,17 @@ private:
/// This holds information associated with macro definitions.
struct MacroDefinitionRecord : APIRecord {
- MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, DeclarationFragments Declaration,
+ MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
- : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
- AvailabilityInfo(), LinkageInfo(), {}, Declaration,
- SubHeading, IsFromSystemHeader) {}
+ : APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(),
+ LinkageInfo(), {}, Declaration, SubHeading,
+ IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_MacroDefinition;
}
- static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
private:
virtual void anchor();
@@ -1327,228 +1101,575 @@ private:
struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
- TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
- PresumedLoc Loc, AvailabilityInfo Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
+ TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType,
bool IsFromSystemHeader)
- : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
+ : APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availability),
LinkageInfo(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
UnderlyingType(UnderlyingType) {}
static bool classof(const APIRecord *Record) {
- return classofKind(Record->getKind());
+ return Record->getKind() == RK_Typedef;
}
- 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:
- /// Get the target triple for the ExtractAPI invocation.
- const llvm::Triple &getTarget() const { return Target; }
+ 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 language used by the APIs.
- Language getLanguage() const { return Lang; }
+ GlobalVariableTemplateRecord *
+ addGlobalVariableTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, Template Template,
+ bool IsFromSystemHeader);
- /// Finds the APIRecord for a given USR.
+ /// Create and add a function record into the API set.
///
- /// \returns a pointer to the APIRecord associated with that USR or nullptr.
- APIRecord *findRecordForUSR(StringRef USR) const;
+ /// 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);
- /// Copy \p String into the Allocator in this APISet.
+ 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);
+
+ /// Create and add an enum constant record into the API set.
///
- /// \returns a StringRef of the copied string in APISet::Allocator.
- StringRef copyString(StringRef String);
+ /// 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);
- SymbolReference createSymbolReference(StringRef Name, StringRef USR,
- StringRef Source = "");
+ /// 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);
- /// Create a subclass of \p APIRecord and store it in the APISet.
+ /// Create and add a record field record into the API set.
///
- /// \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;
- }
+ /// 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);
- APISet(const llvm::Triple &Target, Language Lang,
- const std::string &ProductName)
- : Target(Target), Lang(Lang), ProductName(ProductName) {}
+ /// 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);
- // Prevent moves and copies
- APISet(const APISet &Other) = delete;
- APISet &operator=(const APISet &Other) = delete;
- APISet(APISet &&Other) = delete;
- APISet &operator=(APISet &&Other) = delete;
+ 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);
-private:
- /// BumpPtrAllocator that serves as the memory arena for the allocated objects
- llvm::BumpPtrAllocator Allocator;
+ ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ AccessControl Access, bool IsFromSystemHeader);
- const llvm::Triple Target;
- const Language Lang;
+ 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);
- struct APIRecordDeleter {
- void operator()(APIRecord *Record) { Record->~APIRecord(); }
- };
+ GlobalVariableTemplateSpecializationRecord *
+ addGlobalVariableTemplateSpecialization(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, 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;
+ GlobalVariableTemplatePartialSpecializationRecord *
+ addGlobalVariableTemplatePartialSpecialization(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, Template Template,
+ bool IsFromSystemHeader);
-public:
- const std::string ProductName;
-};
+ 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);
-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());
- }
+ 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);
- return Record;
-}
+ 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);
-// 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");
+ 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);
- static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
+ 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);
- static RecordContext *doCast(FromTy *From) {
- return APIRecord::castToRecordContext(From);
- }
-};
+ ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, Template Template,
+ bool IsFromSystemHeader);
-// 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);
- }
-};
+ /// 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);
-// 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());
- }
+ /// 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);
- static ToTy *doCast(RecordContext *Ctx) {
- return APIRecord::castFromRecordContext(Ctx);
- }
-};
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
-// 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());
+ /// 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>>;
+
+ /// Get the target triple for the ExtractAPI invocation.
+ const llvm::Triple &getTarget() const { return Target; }
+
+ /// Get the language used by the APIs.
+ Language getLanguage() const { return Lang; }
+
+ const RecordMap<NamespaceRecord> &getNamespaces() const { return Namespaces; }
+ const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
+ return GlobalFunctions;
}
- static RecordContext *doCast(RecordContext *Ctx) {
- return static_cast<ToTy *>(Ctx);
+ 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;
+ }
+ 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;
+ }
+ const RecordMap<ClassTemplatePartialSpecializationRecord> &
+ getClassTemplatePartialSpecializations() const {
+ return ClassTemplatePartialSpecializations;
+ }
+ const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
+ const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
+ return ObjCCategories;
+ }
+ const RecordMap<ObjCInterfaceRecord> &getObjCInterfaces() const {
+ return ObjCInterfaces;
+ }
+ const RecordMap<ObjCProtocolRecord> &getObjCProtocols() const {
+ return ObjCProtocols;
+ }
+ const RecordMap<MacroDefinitionRecord> &getMacros() const { return Macros; }
+ const RecordMap<TypedefRecord> &getTypedefs() const { return Typedefs; }
-} // namespace extractapi
-} // namespace clang
+ /// Finds the APIRecord for a given USR.
+ ///
+ /// \returns a pointer to the APIRecord associated with that USR or nullptr.
+ APIRecord *findRecordForUSR(StringRef USR) const;
-// 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);
- }
+ /// 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);
- static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
- return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast(
- From);
- }
-};
+ /// 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);
-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);
- }
+ /// Copy \p String into the Allocator in this APISet.
+ ///
+ /// \returns a StringRef of the copied string in APISet::Allocator.
+ StringRef copyString(StringRef String);
- static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
- return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast(
- Ctx);
- }
-};
+ APISet(const llvm::Triple &Target, Language Lang,
+ const std::string &ProductName)
+ : Target(Target), Lang(Lang), ProductName(ProductName) {}
+
+private:
+ /// BumpPtrAllocator to store generated/copied strings.
+ ///
+ /// Note: The main use for this is being able to deduplicate strings.
+ llvm::BumpPtrAllocator StringAllocator;
+
+ const llvm::Triple Target;
+ const Language Lang;
-template <typename ToTy>
-struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
- : public ConstStrippingForwardingCast<
- ToTy, const ::clang::extractapi::RecordContext *,
- CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
+ 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;
-} // namespace llvm
+public:
+ const std::string ProductName;
+};
+
+} // namespace extractapi
+} // namespace clang
#endif // LLVM_CLANG_EXTRACTAPI_API_H
diff --git a/clang/include/clang/ExtractAPI/APIRecords.inc b/clang/include/clang/ExtractAPI/APIRecords.inc
deleted file mode 100644
index 15fee809656d..000000000000
--- a/clang/include/clang/ExtractAPI/APIRecords.inc
+++ /dev/null
@@ -1,103 +0,0 @@
-//===- 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 94392c185165..8a3a22d9a594 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -180,18 +180,6 @@ public:
/// 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);
@@ -204,14 +192,12 @@ public:
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 08210a7ee059..ac4f391db5f1 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIActionBase.h
@@ -17,8 +17,6 @@
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/APIIgnoresList.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -31,8 +29,8 @@ protected:
/// A representation of the APIs this action extracts.
std::unique_ptr<extractapi::APISet> API;
- /// A stream to the main output file of this action.
- std::unique_ptr<llvm::raw_pwrite_stream> OS;
+ /// A stream to the output file of this action.
+ std::unique_ptr<raw_pwrite_stream> OS;
/// The product this action is extracting API information for.
std::string ProductName;
@@ -48,7 +46,7 @@ protected:
///
/// Use the serializer to generate output symbol graph files from
/// the information gathered during the execution of Action.
- void ImplEndSourceFileAction(CompilerInstance &CI);
+ void ImplEndSourceFileAction();
};
} // namespace clang
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
index 4cb866892b5d..e1c3e41c750d 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/ASTContext.h"
+#include "clang/AST/Availability.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,6 +130,12 @@ protected:
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,
@@ -166,7 +172,6 @@ private:
return *static_cast<Derived *>(this);
}
-protected:
SmallVector<SymbolReference> getBases(const CXXRecordDecl *Decl) {
// FIXME: store AccessSpecifier given by inheritance
SmallVector<SymbolReference> Bases;
@@ -177,54 +182,49 @@ protected:
SymbolReference BaseClass;
if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) {
BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString());
- 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));
- }
+ BaseClass.USR = API.recordUSR(
+ BaseSpecifier.getType()->getAs<TemplateTypeParmType>()->getDecl());
} else {
- BaseClass = createSymbolReferenceForDecl(
- *BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl());
+ CXXRecordDecl *BaseClassDecl =
+ BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl();
+ BaseClass.Name = BaseClassDecl->getName();
+ BaseClass.USR = API.recordUSR(BaseClassDecl);
}
Bases.emplace_back(BaseClass);
}
return Bases;
}
- StringRef getOwningModuleName(const Decl &D) {
- if (auto *OwningModule = D.getImportedOwningModule())
- return OwningModule->Name;
+ APIRecord *determineParentRecord(const DeclContext *Context) {
+ SmallString<128> ParentUSR;
+ if (Context->getDeclKind() == Decl::TranslationUnit)
+ return nullptr;
- return {};
- }
+ index::generateUSRForDecl(dyn_cast<Decl>(Context), ParentUSR);
- SymbolReference createHierarchyInformationForDecl(const Decl &D) {
- const auto *Context = cast_if_present<Decl>(D.getDeclContext());
-
- if (!Context || isa<TranslationUnitDecl>(Context))
- return {};
-
- return createSymbolReferenceForDecl(*Context);
+ APIRecord *Parent = API.findRecordForUSR(ParentUSR);
+ return Parent;
}
+};
- 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 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;
+ }
}
-};
+}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
@@ -251,8 +251,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -268,17 +267,21 @@ 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.createRecord<StaticFieldRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, Access, isInSystemHeader(Decl));
+ API.addStaticField(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
+ Linkage, Comment, Declaration, SubHeading, Context,
+ Access, isInSystemHeader(Decl));
} else
// Add the global variable record to the API set.
- API.createRecord<GlobalVariableRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, isInSystemHeader(Decl));
+ API.addGlobalVar(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
+ Linkage, Comment, Declaration, SubHeading,
+ isInSystemHeader(Decl));
return true;
}
@@ -301,7 +304,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
return true;
}
- // Skip templated functions that aren't processed here.
+ // Skip templated functions.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
@@ -318,8 +321,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -335,19 +337,18 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
if (Decl->getTemplateSpecializationInfo())
- API.createRecord<GlobalFunctionTemplateSpecializationRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ API.addGlobalFunctionTemplateSpecialization(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
+ Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, isInSystemHeader(Decl));
else
// Add the function record to the API set.
- API.createRecord<GlobalFunctionRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
- DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
- Signature, isInSystemHeader(Decl));
+ API.addGlobalFunction(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
+ Comment, DeclarationFragmentsBuilder::getFragmentsForFunction(Decl),
+ SubHeading, Signature, isInSystemHeader(Decl));
return true;
}
@@ -367,8 +368,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
Name = QualifiedNameBuffer.str();
}
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
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);
- auto *ER = API.createRecord<EnumRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- isInSystemHeader(Decl));
+ EnumRecord *EnumRecord = API.addEnum(
+ API.copyString(Name), USR, Loc, AvailabilityInfo::createFromDecl(Decl),
+ Comment, Declaration, SubHeading, isInSystemHeader(Decl));
// Now collect information about the enumerators in this enum.
- getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
+ getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord,
+ 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();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
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);
- API.createRecord<NamespaceRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, isInSystemHeader(Decl));
+ APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
+ API.addNamespace(Parent, Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ Declaration, SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -509,20 +509,14 @@ 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()) {
- llvm::raw_svector_ostream OS(QualifiedNameBuffer);
- Decl->printQualifiedName(OS);
- Name = QualifiedNameBuffer.str();
- }
+ if (Name.empty())
+ return true;
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -537,16 +531,21 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- 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));
+ 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());
return true;
}
@@ -559,8 +558,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -582,25 +580,24 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
Kind = APIRecord::RecordKind::RK_CXXClass;
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- CXXClassRecord *Record;
+ APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
+ CXXClassRecord *CXXClassRecord;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
- Record = API.createRecord<ClassTemplateRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
- isInSystemHeader(Decl));
+ CXXClassRecord = API.addClassTemplate(
+ Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()),
+ Access, isInSystemHeader(Decl));
} else
- Record = API.createRecord<CXXClassRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Kind, Access, isInSystemHeader(Decl));
+ CXXClassRecord = API.addCXXClass(
+ Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, Kind, Access, isInSystemHeader(Decl));
- Record->Bases = getBases(Decl);
+ CXXClassRecord->Bases = getBases(Decl);
return true;
}
@@ -617,8 +614,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
return true;
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -631,10 +627,14 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
- if (FunctionTemplateDecl *TemplateDecl =
- Decl->getDescribedFunctionTemplate()) {
- API.createRecord<CXXMethodTemplateRecord>(
- USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
+ 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,
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.createRecord<CXXMethodTemplateSpecializationRecord>(
- USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
+ API.addCXXMethodTemplateSpec(
+ Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isOverloadedOperator())
- API.createRecord<CXXInstanceMethodRecord>(
- USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
- Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ API.addCXXInstanceMethod(
+ Parent, API.copyString(Decl->getNameAsString()), USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isStatic())
- API.createRecord<CXXStaticMethodRecord>(
- USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
+ API.addCXXStaticMethod(
+ Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
else
- API.createRecord<CXXInstanceMethodRecord>(
- USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc,
+ API.addCXXInstanceMethod(
+ Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
@@ -673,13 +673,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
const CXXConstructorDecl *Decl) {
- if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
- Decl->isImplicit())
- return true;
- auto Name = Decl->getNameAsString();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -696,24 +692,22 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
-
- API.createRecord<CXXConstructorRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- Signature, Access, isInSystemHeader(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));
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
const CXXDestructorDecl *Decl) {
- if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
- Decl->isImplicit())
- return true;
- auto Name = Decl->getNameAsString();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -730,10 +724,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- API.createRecord<CXXDestructorRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- Signature, Access, isInSystemHeader(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));
return true;
}
@@ -743,8 +740,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
return true;
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -756,10 +752,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForConcept(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.createRecord<ConceptRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- Template(Decl), isInSystemHeader(Decl));
+ API.addConcept(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
+ Comment, Declaration, SubHeading, Template(Decl),
+ isInSystemHeader(Decl));
return true;
}
@@ -770,8 +765,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
return true;
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -785,13 +779,14 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- auto *CTSR = API.createRecord<ClassTemplateSpecializationRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
+ APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
+ auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization(
+ Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading,
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
- CTSR->Bases = getBases(Decl);
+ ClassTemplateSpecializationRecord->Bases = getBases(Decl);
return true;
}
@@ -804,8 +799,7 @@ bool ExtractAPIVisitorBase<Derived>::
return true;
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -817,13 +811,15 @@ bool ExtractAPIVisitorBase<Derived>::
getFragmentsForClassTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- auto *CTPSR = API.createRecord<ClassTemplatePartialSpecializationRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl),
- isInSystemHeader(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));
- CTPSR->Bases = getBases(Decl);
+ ClassTemplatePartialSpecRecord->Bases = getBases(Decl);
return true;
}
@@ -836,8 +832,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -858,17 +853,20 @@ 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.createRecord<CXXFieldTemplateRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
- Template(Decl), isInSystemHeader(Decl));
+ API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading,
+ DeclarationFragmentsBuilder::getAccessControl(Decl),
+ Template(Decl), isInSystemHeader(Decl));
else
- API.createRecord<GlobalVariableTemplateRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, Template(Decl), isInSystemHeader(Decl));
+ API.addGlobalVariableTemplate(Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl),
+ Linkage, Comment, Declaration, SubHeading,
+ Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -880,8 +878,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -897,10 +894,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.createRecord<GlobalVariableTemplateSpecializationRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, isInSystemHeader(Decl));
+ API.addGlobalVariableTemplateSpecialization(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ Declaration, SubHeading, isInSystemHeader(Decl));
return true;
}
@@ -912,8 +908,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -928,10 +923,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
getFragmentsForVarTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- API.createRecord<GlobalVariableTemplatePartialSpecializationRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, Template(Decl), isInSystemHeader(Decl));
+ API.addGlobalVariableTemplatePartialSpecialization(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ Declaration, SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@@ -945,8 +939,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -961,9 +954,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(
Decl->getTemplatedDecl());
- API.createRecord<GlobalFunctionTemplateRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
+ API.addGlobalFunctionTemplate(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
@@ -978,8 +970,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
@@ -997,23 +988,24 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
// Collect super class information.
SymbolReference SuperClass;
- if (const auto *SuperClassDecl = Decl->getSuperClass())
- SuperClass = createSymbolReferenceForDecl(*SuperClassDecl);
+ if (const auto *SuperClassDecl = Decl->getSuperClass()) {
+ SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
+ SuperClass.USR = API.recordUSR(SuperClassDecl);
+ }
- auto *InterfaceRecord = API.createRecord<ObjCInterfaceRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
- SubHeading, SuperClass, isInSystemHeader(Decl));
+ ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
+ Name, USR, 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(InterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(ObjCInterfaceRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(ObjCInterfaceRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCInterfaceRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCInterfaceRecord,
Decl->protocols());
return true;
@@ -1027,8 +1019,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1043,15 +1034,15 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
- auto *ProtoRecord = API.createRecord<ObjCProtocolRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- isInSystemHeader(Decl));
+ ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, isInSystemHeader(Decl));
- getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord,
+ Decl->methods());
+ getDerivedExtractAPIVisitor().recordObjCProperties(ObjCProtocolRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCProtocolRecord,
Decl->protocols());
return true;
@@ -1070,36 +1061,25 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;
- 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;
+ // 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());
+ }
}
}
}
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef Name = Decl->getName();
+ StringRef USR = API.recordUSR(Decl);
DocComment Comment;
if (auto *RawComment =
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
@@ -1111,12 +1091,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
API);
- API.createRecord<TypedefRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment,
- DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
- DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
- isInSystemHeader(Decl));
+ API.addTypedef(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
+ Comment,
+ DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
+ DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
+ isInSystemHeader(Decl));
return true;
}
@@ -1128,8 +1107,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
return true;
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1144,20 +1122,29 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
DeclarationFragmentsBuilder::getSubHeading(Decl);
const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
- SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl);
+ 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;
+ }
+ }
- auto *CategoryRecord = API.createRecord<ObjCCategoryRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
- Interface, isInSystemHeader(Decl));
+ ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, Interface, isInSystemHeader(Decl),
+ IsFromExternalModule);
- getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord,
Decl->methods());
- getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProperties(ObjCCategoryRecord,
Decl->properties());
- getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCInstanceVariables(ObjCCategoryRecord,
Decl->ivars());
- getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord,
+ getDerivedExtractAPIVisitor().recordObjCProtocols(ObjCCategoryRecord,
Decl->protocols());
return true;
@@ -1171,8 +1158,7 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
for (const auto *Constant : Constants) {
// Collect symbol information.
StringRef Name = Constant->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Constant, USR);
+ StringRef USR = API.recordUSR(Constant);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Constant->getLocation());
DocComment Comment;
@@ -1187,26 +1173,51 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Constant);
- API.createRecord<EnumConstantRecord>(
- USR, Name, createHierarchyInformationForDecl(*Constant), Loc,
- AvailabilityInfo::createFromDecl(Constant), Comment, Declaration,
- SubHeading, isInSystemHeader(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));
}
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
- // ObjCIvars are handled separately
- if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl))
+ if (Decl->getDeclContext()->getDeclKind() == Decl::Record)
return true;
-
- if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
+ if (isa<ObjCIvarDecl>(Decl))
return true;
-
// Collect symbol information.
StringRef Name = Decl->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1220,40 +1231,22 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForField(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(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));
- }
-
+ 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));
return true;
}
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
const CXXConversionDecl *Decl) {
- if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
- Decl->isImplicit())
- return true;
-
- auto Name = Decl->getNameAsString();
- SmallString<128> USR;
- index::generateUSRForDecl(Decl, USR);
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
@@ -1271,17 +1264,19 @@ 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.createRecord<CXXStaticMethodRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Signature, Access, isInSystemHeader(Decl));
+ API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
else
- API.createRecord<CXXInstanceMethodRecord>(
- USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
- AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
- SubHeading, Signature, Access, isInSystemHeader(Decl));
-
+ API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Decl), Comment,
+ Declaration, SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
return true;
}
@@ -1296,9 +1291,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
if (Method->isPropertyAccessor())
continue;
- auto Name = Method->getSelector().getAsString();
- SmallString<128> USR;
- index::generateUSRForDecl(Method, USR);
+ StringRef Name = API.copyString(Method->getSelector().getAsString());
+ StringRef USR = API.recordUSR(Method);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Method->getLocation());
DocComment Comment;
@@ -1315,16 +1309,10 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(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));
+ API.addObjCMethod(Container, Name, USR, Loc,
+ AvailabilityInfo::createFromDecl(Method), Comment,
+ Declaration, SubHeading, Signature,
+ Method->isInstanceMethod(), isInSystemHeader(Method));
}
}
@@ -1334,8 +1322,7 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
const ObjCContainerDecl::prop_range Properties) {
for (const auto *Property : Properties) {
StringRef Name = Property->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Property, USR);
+ StringRef USR = API.recordUSR(Property);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Property->getLocation());
DocComment Comment;
@@ -1350,8 +1337,10 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Property);
- auto GetterName = Property->getGetterName().getAsString();
- auto SetterName = Property->getSetterName().getAsString();
+ StringRef GetterName =
+ API.copyString(Property->getGetterName().getAsString());
+ StringRef SetterName =
+ API.copyString(Property->getSetterName().getAsString());
// Get the attributes for property.
unsigned Attributes = ObjCPropertyRecord::NoAttr;
@@ -1359,22 +1348,14 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
ObjCPropertyAttribute::kind_readonly)
Attributes |= ObjCPropertyRecord::ReadOnly;
- 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));
+ 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));
}
}
@@ -1386,9 +1367,7 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
Ivars) {
for (const auto *Ivar : Ivars) {
StringRef Name = Ivar->getName();
- SmallString<128> USR;
- index::generateUSRForDecl(Ivar, USR);
-
+ StringRef USR = API.recordUSR(Ivar);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
DocComment Comment;
@@ -1403,10 +1382,12 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Ivar);
- API.createRecord<ObjCInstanceVariableRecord>(
- USR, Name, createHierarchyInformationForDecl(*Ivar), Loc,
- AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration,
- SubHeading, isInSystemHeader(Ivar));
+ ObjCInstanceVariableRecord::AccessControl Access =
+ Ivar->getCanonicalAccessControl();
+
+ API.addObjCInstanceVariable(
+ Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Ivar),
+ Comment, Declaration, SubHeading, Access, isInSystemHeader(Ivar));
}
}
@@ -1415,7 +1396,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProtocols(
ObjCContainerRecord *Container,
ObjCInterfaceDecl::protocol_range Protocols) {
for (const auto *Protocol : Protocols)
- Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol));
+ Container->Protocols.emplace_back(Protocol->getName(),
+ API.recordUSR(Protocol));
}
} // namespace impl
diff --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h
index 08045a30823d..c67864aac9af 100644
--- a/clang/include/clang/ExtractAPI/FrontendActions.h
+++ b/clang/include/clang/ExtractAPI/FrontendActions.h
@@ -49,6 +49,9 @@ private:
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
@@ -82,6 +85,9 @@ private:
/// 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
deleted file mode 100644
index 07f14f349f3d..000000000000
--- a/clang/include/clang/ExtractAPI/Serialization/APISetVisitor.h
+++ /dev/null
@@ -1,172 +0,0 @@
-//===- 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
new file mode 100644
index 000000000000..f0629a9ad56b
--- /dev/null
+++ b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
@@ -0,0 +1,314 @@
+//===- 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 724b087f7aea..4249ac405fd2 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -17,17 +17,11 @@
#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/APISetVisitor.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallString.h"
+#include "clang/ExtractAPI/Serialization/SerializerBase.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"
@@ -41,30 +35,7 @@ using namespace llvm::json;
/// Common options to customize the visitor output.
struct SymbolGraphSerializerOption {
/// Do not include unnecessary whitespaces to save space.
- bool Compact = true;
- bool EmitSymbolLabelsForTesting = false;
-};
-
-/// A representation of the contents of a given module symbol graph
-struct ExtendedModule {
- ExtendedModule() = default;
- ExtendedModule(ExtendedModule &&EM) = default;
- ExtendedModule &operator=(ExtendedModule &&EM) = default;
- // Copies are expensive so disable them.
- ExtendedModule(const ExtendedModule &EM) = delete;
- ExtendedModule &operator=(const ExtendedModule &EM) = delete;
-
- /// Add a symbol to the module, do not store the resulting pointer or use it
- /// across insertions.
- Object *addSymbol(Object &&Symbol);
-
- void addRelationship(Object &&Relationship);
-
- /// A JSON array of formatted symbols from an \c APISet.
- Array Symbols;
-
- /// A JSON array of formatted symbol relationships from an \c APISet.
- Array Relationships;
+ bool Compact;
};
/// The visitor that organizes API information in the Symbol Graph format.
@@ -73,54 +44,28 @@ struct ExtendedModule {
/// models an API set as a directed graph, where nodes are symbol declarations,
/// and edges are relationships between the connected symbols.
class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
-private:
- using Base = APISetVisitor<SymbolGraphSerializer>;
- /// The main symbol graph that contains symbols that are either top-level or a
- /// are related to symbols defined in this product/module.
- ExtendedModule MainModule;
+ /// A JSON array of formatted symbols in \c APISet.
+ Array Symbols;
- /// 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;
+ /// A JSON array of formatted symbol relationships in \c APISet.
+ Array Relationships;
/// The Symbol Graph format version used by this serializer.
static const VersionTuple FormatVersion;
- /// Indicates whether to take into account the extended module. This is only
+ /// Indicates whether child symbols should be visited. This is mainly
/// useful for \c serializeSingleSymbolSGF.
- bool ForceEmitToMainModule;
+ bool ShouldRecurse;
- // Stores the references required to construct path components for the
- // currently visited APIRecord.
- llvm::SmallVector<SymbolReference, 8> Hierarchy;
-
- /// The list of symbols to ignore.
+public:
+ /// Serialize the APIs in \c APISet in the Symbol Graph format.
///
- /// Note: This should be consulted before emitting a symbol.
- const APIIgnoresList &IgnoresList;
-
- const bool EmitSymbolLabelsForTesting = false;
-
- /// The object instantiated by the last call to serializeAPIRecord.
- Object *CurrentSymbol = nullptr;
+ /// \returns a JSON object that contains the root of the formatted
+ /// Symbol Graph.
+ Object serialize();
- /// 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 = {});
+ /// Wrap serialize(void) and write out the serialized JSON object to \p os.
+ void serialize(raw_ostream &os);
/// Serialize a single symbol SGF. This is primarily used for libclang.
///
@@ -130,7 +75,6 @@ public:
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.
@@ -150,32 +94,16 @@ private:
ExtensionTo,
};
- /// Serialize a single record.
- void serializeSingleRecord(const APIRecord *Record);
-
/// Get the string representation of the relationship kind.
static StringRef getRelationshipString(RelationshipKind Kind);
- void serializeRelationship(RelationshipKind Kind,
- const SymbolReference &Source,
- const SymbolReference &Target,
- ExtendedModule &Into);
-
enum ConstraintKind { Conformance, ConditionalConformance };
static StringRef getConstraintString(ConstraintKind Kind);
- /// Serialize the APIs in \c ExtendedModule.
- ///
- /// \returns a JSON object that contains the root of the formatted
- /// Symbol Graph.
- Object serializeGraph(StringRef ModuleName, ExtendedModule &&EM);
-
- /// Serialize the APIs in \c ExtendedModule in the Symbol Graph format and
- /// write them to the provide stream.
- void serializeGraphToStream(raw_ostream &OS,
- SymbolGraphSerializerOption Options,
- StringRef ModuleName, ExtendedModule &&EM);
+private:
+ /// Just serialize the currently recorded objects in Symbol Graph format.
+ Object serializeCurrentGraph();
/// Synthesize the metadata section of the Symbol Graph format.
///
@@ -189,92 +117,124 @@ private:
/// by the given API set.
/// Note that "module" here is not to be confused with the Clang/C++ module
/// concept.
- Object serializeModuleObject(StringRef ModuleName) const;
-
- Array serializePathComponents(const APIRecord *Record) const;
+ Object serializeModule() const;
/// Determine if the given \p Record should be skipped during serialization.
- bool shouldSkip(const APIRecord *Record) const;
-
- ExtendedModule &getModuleForCurrentSymbol();
+ bool shouldSkip(const APIRecord &Record) const;
/// Format the common API information for \p Record.
///
/// This handles the shared information of all kinds of API records,
- /// for example identifier, 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.
+ /// for example identifier and source location. The resulting object is then
+ /// augmented with kind-specific symbol information by the caller.
+ /// This method also checks if the given \p Record should be skipped during
+ /// serialization.
///
- /// \returns \c 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);
+ /// \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);
-public:
- // Handle if records should be skipped at this level of the traversal to
- // ensure that children of skipped records aren't serialized.
- bool traverseAPIRecord(const APIRecord *Record);
+protected:
+ /// The list of symbols to ignore.
+ ///
+ /// Note: This should be consulted before emitting a symbol.
+ const APIIgnoresList &IgnoresList;
+
+ SymbolGraphSerializerOption Options;
- bool visitAPIRecord(const APIRecord *Record);
+ llvm::StringSet<> visitedCategories;
+
+public:
+ void visitNamespaceRecord(const NamespaceRecord &Record);
/// Visit a global function record.
- bool visitGlobalFunctionRecord(const GlobalFunctionRecord *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);
- bool visitCXXClassRecord(const CXXClassRecord *Record);
+ void visitClassTemplateRecord(const ClassTemplateRecord &Record);
- bool visitClassTemplateRecord(const ClassTemplateRecord *Record);
+ void visitClassTemplateSpecializationRecord(
+ const ClassTemplateSpecializationRecord &Record);
- bool visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord *Record);
+ void visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord &Record);
- bool visitCXXMethodRecord(const CXXMethodRecord *Record);
+ void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
- bool visitCXXMethodTemplateRecord(const CXXMethodTemplateRecord *Record);
+ void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
- bool visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord *Record);
+ void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
- bool visitConceptRecord(const ConceptRecord *Record);
+ void visitMethodTemplateSpecializationRecord(
+ const CXXMethodTemplateSpecializationRecord &Record);
- bool
- visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord *Record);
+ void visitCXXFieldRecord(const CXXFieldRecord &Record);
- bool visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord *Record);
+ void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
- bool
- visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord *Record);
+ void visitConceptRecord(const ConceptRecord &Record);
- bool visitObjCContainerRecord(const ObjCContainerRecord *Record);
+ void
+ visitGlobalVariableTemplateRecord(const GlobalVariableTemplateRecord &Record);
- bool visitObjCInterfaceRecord(const ObjCInterfaceRecord *Record);
+ void visitGlobalVariableTemplateSpecializationRecord(
+ const GlobalVariableTemplateSpecializationRecord &Record);
- bool traverseObjCCategoryRecord(const ObjCCategoryRecord *Record);
- bool walkUpFromObjCCategoryRecord(const ObjCCategoryRecord *Record);
- bool visitObjCCategoryRecord(const ObjCCategoryRecord *Record);
+ void visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord &Record);
- bool visitObjCMethodRecord(const ObjCMethodRecord *Record);
+ void
+ visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
- bool
- visitObjCInstanceVariableRecord(const ObjCInstanceVariableRecord *Record);
+ void visitGlobalFunctionTemplateSpecializationRecord(
+ const GlobalFunctionTemplateSpecializationRecord &Record);
- bool walkUpFromTypedefRecord(const TypedefRecord *Record);
- bool visitTypedefRecord(const TypedefRecord *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);
+
+ /// Serialize a single record.
+ void serializeSingleRecord(const APIRecord *Record);
SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList,
- bool EmitSymbolLabelsForTesting = false,
- bool ForceEmitToMainModule = false)
- : Base(API), ForceEmitToMainModule(ForceEmitToMainModule),
- IgnoresList(IgnoresList),
- EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {}
+ SymbolGraphSerializerOption Options = {},
+ bool ShouldRecurse = true)
+ : APISetVisitor(API), ShouldRecurse(ShouldRecurse),
+ IgnoresList(IgnoresList), Options(Options) {}
};
} // namespace extractapi
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 864af66b3370..8085dbcbf671 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -15,7 +15,6 @@
#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>
@@ -388,22 +387,6 @@ public:
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.
@@ -513,8 +496,10 @@ public:
// 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. This overrides regular -o output file specification
+ // be dumped
std::string SymbolGraphOutputDir;
/// Args to pass to the plugins
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e6c1767a0082..1a0f5f27eda2 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -49,7 +49,6 @@
#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"
@@ -5890,12 +5889,6 @@ 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 b7ec7e0a6097..7fd6ad6a47d4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5046,26 +5046,11 @@ 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 5a62c5deb240..aa7a1e9360f4 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -13,67 +13,514 @@
//===----------------------------------------------------------------------===//
#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;
-SymbolReference::SymbolReference(const APIRecord *R)
- : Name(R->Name), USR(R->USR), Record(R) {}
+namespace {
-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");
- }
+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;
}
-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");
- }
+} // 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);
}
-void RecordContext::addToRecordChain(APIRecord *Record) const {
- if (!First) {
- First = Record;
- Last = Record;
- return;
- }
+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);
+}
- Last->NextInContext = Record;
- Last = Record;
+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();
+}
+
+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);
+}
+
+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);
+}
+
+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);
}
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
if (USR.empty())
return nullptr;
- auto FindIt = USRBasedLookupTable.find(USR);
- if (FindIt != USRBasedLookupTable.end())
- return FindIt->getSecond().get();
+ return USRBasedLookupTable.lookup(USR);
+}
+
+StringRef APISet::recordUSR(const Decl *D) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(D, USR);
+ return copyString(USR);
+}
- return nullptr;
+StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
+ const SourceManager &SM) {
+ SmallString<128> USR;
+ index::generateUSRForMacro(Name, SL, SM, USR);
+ return copyString(USR);
}
StringRef APISet::copyString(StringRef String) {
@@ -81,22 +528,15 @@ StringRef APISet::copyString(StringRef String) {
return {};
// No need to allocate memory and copy if the string has already been stored.
- if (Allocator.identifyObject(String.data()))
+ if (StringAllocator.identifyObject(String.data()))
return String;
- void *Ptr = Allocator.Allocate(String.size(), 1);
+ void *Ptr = StringAllocator.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() {}
@@ -106,10 +546,8 @@ void GlobalFunctionRecord::anchor() {}
void GlobalVariableRecord::anchor() {}
void EnumConstantRecord::anchor() {}
void EnumRecord::anchor() {}
-void StructFieldRecord::anchor() {}
-void StructRecord::anchor() {}
-void UnionFieldRecord::anchor() {}
-void UnionRecord::anchor() {}
+void RecordFieldRecord::anchor() {}
+void RecordRecord::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 0a243120b7c0..22b98e07c2c8 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -57,44 +57,23 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
} // namespace
-DeclarationFragments &
-DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
+DeclarationFragments &DeclarationFragments::appendSpace() {
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() != Character) { // avoid duplicates at end
- Last.Spelling.push_back(Character);
+ if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
+ Last.Spelling.push_back(' ');
}
} else {
- append("", FragmentKind::Text);
- Fragments.back().Spelling.push_back(Character);
+ append(" ", FragmentKind::Text);
}
}
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) {
@@ -487,7 +466,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -529,7 +508,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -559,7 +538,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
return Fragments;
}
@@ -719,7 +698,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
@@ -748,7 +727,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -764,7 +743,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
@@ -782,7 +761,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
@@ -797,7 +776,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -827,7 +806,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
@@ -867,7 +846,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -898,7 +877,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -930,7 +909,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
@@ -1018,7 +997,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1059,7 +1038,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1081,7 +1060,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1100,7 +1079,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1122,7 +1101,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1193,7 +1172,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
- .append(Interface->getName(),
+ .append(Category->getClassInterface()->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
@@ -1267,7 +1246,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
@@ -1368,7 +1347,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
@@ -1412,7 +1391,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Instantiate template for FunctionDecl.
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index d6335854cbf2..275f49be22e1 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -30,7 +30,6 @@
#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"
@@ -40,7 +39,6 @@
#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"
@@ -329,12 +327,11 @@ public:
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
- SmallString<128> USR;
- index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
- USR);
+ StringRef USR =
+ API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
- API.createRecord<extractapi::MacroDefinitionRecord>(
- USR, Name, SymbolReference(), Loc,
+ API.addMacroDefinition(
+ Name, USR, Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
@@ -375,57 +372,40 @@ private:
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(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);
- }
+void ExtractAPIActionBase::ImplEndSourceFileAction() {
+ if (!OS)
+ return;
- // Flush the stream and close the main output stream.
+ // 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);
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) {
- 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);
+ OS = CreateOutputFile(CI, InFile);
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>(
@@ -515,9 +495,7 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}
-void ExtractAPIAction::EndSourceFileAction() {
- ImplEndSourceFileAction(getCompilerInstance());
-}
+void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
@@ -528,9 +506,11 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
CreatedASTConsumer = true;
- ProductName = CI.getFrontendOpts().ProductName;
- auto InputFilename = llvm::sys::path::filename(InFile);
- OS = createAdditionalSymbolGraphFile(CI, InputFilename);
+ OS = CreateOutputFile(CI, InFile);
+ 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.
@@ -572,6 +552,32 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();
if (CreatedASTConsumer) {
- ImplEndSourceFileAction(getCompilerInstance());
+ ImplEndSourceFileAction();
}
}
+
+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 57f966c8b2be..545860acb7db 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -14,17 +14,13 @@
#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>
@@ -37,27 +33,26 @@ 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.
///
@@ -253,7 +248,6 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
return std::nullopt;
Object DocComment;
-
Array LinesArray;
for (const auto &CommentLine : Comment) {
Object Line;
@@ -262,8 +256,7 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
serializeSourceRange(CommentLine.Begin, CommentLine.End));
LinesArray.emplace_back(std::move(Line));
}
-
- serializeArray(DocComment, "lines", std::move(LinesArray));
+ serializeArray(DocComment, "lines", LinesArray);
return DocComment;
}
@@ -329,14 +322,19 @@ 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;
- Names["title"] = Record->Name;
+ if (auto *CategoryRecord =
+ dyn_cast_or_null<const ObjCCategoryRecord>(&Record))
+ Names["title"] =
+ (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str();
+ else
+ 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",
@@ -353,8 +351,7 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Object Kind;
switch (RK) {
case APIRecord::RK_Unknown:
- Kind["identifier"] = AddLangPrefix("unknown");
- Kind["displayName"] = "Unknown";
+ llvm_unreachable("Records should have an explicit kind");
break;
case APIRecord::RK_Namespace:
Kind["identifier"] = AddLangPrefix("namespace");
@@ -487,6 +484,10 @@ 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";
@@ -499,8 +500,6 @@ 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;
@@ -515,18 +514,12 @@ 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>
-void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
+std::optional<Object>
+serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
const auto &FS = Record.Signature;
if (FS.empty())
- return;
+ return std::nullopt;
Object Signature;
serializeArray(Signature, "returns",
@@ -544,14 +537,63 @@ void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
if (!Parameters.empty())
Signature["parameters"] = std::move(Parameters);
- serializeObject(Paren, "functionSignature", std::move(Signature));
+ return Signature;
}
template <typename RecordTy>
-void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
+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) {
const auto &Template = Record.Templ;
if (Template.empty())
- return;
+ return std::nullopt;
Object Generics;
Array GenericParameters;
@@ -577,66 +619,97 @@ void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
if (!GenericConstraints.empty())
Generics["constraints"] = std::move(GenericConstraints);
- serializeObject(Paren, "swiftGenerics", Generics);
+ return Generics;
}
-Array generateParentContexts(const SmallVectorImpl<SymbolReference> &Parents,
- Language Lang) {
- Array ParentContexts;
-
- 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));
- }
+template <typename RecordTy>
+std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
+ std::false_type) {
+ return std::nullopt;
+}
- return ParentContexts;
+template <typename RecordTy>
+void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
+ serializeObject(Paren, "swiftGenerics",
+ serializeTemplateMixinImpl(Record, has_template<RecordTy>()));
}
-/// 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.
+struct PathComponent {
+ StringRef USR;
+ StringRef Name;
+ APIRecord::RecordKind Kind;
+
+ PathComponent(StringRef USR, StringRef Name, APIRecord::RecordKind Kind)
+ : USR(USR), Name(Name), Kind(Kind) {}
+};
+
+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;
}
- return SymbolReference(Record);
-}
+ for (const auto &PC : reverse(ReverseComponenents))
+ ComponentTransformer(PC);
-} // namespace
+ return FailedToFindParent;
+}
-Object *ExtendedModule::addSymbol(Object &&Symbol) {
- Symbols.emplace_back(std::move(Symbol));
- return Symbols.back().getAsObject();
+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;
}
-void ExtendedModule::addRelationship(Object &&Relationship) {
- Relationships.emplace_back(std::move(Relationship));
+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));
+ });
+
+ return ParentContexts;
}
+} // namespace
/// Defines the format version emitted by SymbolGraphSerializer.
const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
@@ -649,44 +722,84 @@ Object SymbolGraphSerializer::serializeMetadata() const {
return Metadata;
}
-Object
-SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName) const {
+Object SymbolGraphSerializer::serializeModule() const {
Object Module;
- Module["name"] = ModuleName;
+ // The user is expected to always pass `--product-name=` on the command line
+ // to populate this field.
+ Module["name"] = API.ProductName;
serializeObject(Module, "platform", serializePlatform(API.getTarget()));
return Module;
}
-bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
- if (!Record)
+bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
+ // Skip explicitly ignored symbols.
+ if (IgnoresList.shouldIgnore(Record.Name))
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("_"))
- return true;
-
- // Skip explicitly ignored symbols.
- if (IgnoresList.shouldIgnore(Record->Name))
+ if (Record.Name.starts_with("_"))
return true;
return false;
}
-ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
- if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
- return *ModuleForCurrentSymbol;
+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));
- return MainModule;
+ serializeFunctionSignatureMixin(Obj, Record);
+ serializeAccessMixin(Obj, Record);
+ serializeTemplateMixin(Obj, Record);
+
+ return Obj;
}
-Array SymbolGraphSerializer::serializePathComponents(
- const APIRecord *Record) const {
- return Array(map_range(Hierarchy, [](auto Elt) { return Elt.Name; }));
+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);
+ }
}
StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
@@ -703,33 +816,6 @@ 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:
@@ -740,324 +826,430 @@ StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
llvm_unreachable("Unhandled constraint kind");
}
-void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) {
- Object Obj;
-
- // 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::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);
- 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));
+ Relationships.emplace_back(std::move(Relationship));
+}
- Obj["pathComponents"] = serializePathComponents(Record);
- Obj["accessLevel"] = Record->Access.getAccess();
+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);
+}
- 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);
+void SymbolGraphSerializer::visitGlobalFunctionRecord(
+ const GlobalFunctionRecord &Record) {
+ auto Obj = serializeAPIRecord(Record);
+ if (!Obj)
+ return;
- CurrentSymbol = Module.addSymbol(std::move(Obj));
+ Symbols.emplace_back(std::move(*Obj));
}
-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::visitGlobalVariableRecord(
+ const GlobalVariableRecord &Record) {
+ auto Obj = serializeAPIRecord(Record);
+ if (!Obj)
+ return;
+
+ Symbols.emplace_back(std::move(*Obj));
}
-bool SymbolGraphSerializer::visitAPIRecord(const APIRecord *Record) {
- serializeAPIRecord(Record);
- return true;
+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::visitGlobalFunctionRecord(
- const GlobalFunctionRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitRecordRecord(const RecordRecord &Record) {
+ auto SerializedRecord = serializeAPIRecord(Record);
+ if (!SerializedRecord)
+ return;
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*SerializedRecord));
+ serializeMembers(Record, Record.Fields);
}
-bool SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord *Record) {
- if (!CurrentSymbol)
- 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);
+}
- for (const auto &Base : Record->Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base,
- getModuleForCurrentSymbol());
- return true;
+void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
+
+ 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);
}
-bool SymbolGraphSerializer::visitClassTemplateRecord(
- const ClassTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplateRecord(
+ const ClassTemplateRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- 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);
}
-bool SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplateSpecializationRecord(
+ const ClassTemplateSpecializationRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- 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);
}
-bool SymbolGraphSerializer::visitCXXMethodRecord(
- const CXXMethodRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
+
+ Symbols.emplace_back(std::move(*Class));
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
+ for (const auto &Base : Record.Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitCXXMethodTemplateRecord(
- const CXXMethodTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitCXXInstanceMethodRecord(
+ const CXXInstanceMethodRecord &Record) {
+ auto InstanceMethod = serializeAPIRecord(Record);
+ if (!InstanceMethod)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*InstanceMethod));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitCXXFieldTemplateRecord(
- const CXXFieldTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitCXXStaticMethodRecord(
+ const CXXStaticMethodRecord &Record) {
+ auto StaticMethod = serializeAPIRecord(Record);
+ if (!StaticMethod)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*StaticMethod));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitConceptRecord(const ConceptRecord *Record) {
- if (!CurrentSymbol)
- 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);
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- 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);
}
-bool SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord *Record) {
- if (!CurrentSymbol)
- 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);
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- 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);
}
-bool SymbolGraphSerializer::
- visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
+ auto Concept = serializeAPIRecord(Record);
+ if (!Concept)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*Concept));
}
-bool SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
+ const GlobalVariableTemplateRecord &Record) {
+ auto GlobalVariableTemplate = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplate)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplate));
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord(
+ const GlobalVariableTemplateSpecializationRecord &Record) {
+ auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplateSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization));
}
-bool SymbolGraphSerializer::visitObjCContainerRecord(
- const ObjCContainerRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::
+ visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord &Record) {
+ auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplatePartialSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
+}
- for (const auto &Protocol : Record->Protocols)
- serializeRelationship(ConformsTo, Record, Protocol,
- getModuleForCurrentSymbol());
+void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord &Record) {
+ auto GlobalFunctionTemplate = serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplate)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
+}
- return true;
+void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord(
+ const GlobalFunctionTemplateSpecializationRecord &Record) {
+ auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplateSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
}
-bool SymbolGraphSerializer::visitObjCInterfaceRecord(
- const ObjCInterfaceRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitObjCContainerRecord(
+ const ObjCContainerRecord &Record) {
+ auto ObjCContainer = serializeAPIRecord(Record);
+ if (!ObjCContainer)
+ return;
- if (!Record->SuperClass.empty())
- serializeRelationship(InheritsFrom, Record, Record->SuperClass,
- getModuleForCurrentSymbol());
- 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);
+ }
+ }
}
-bool SymbolGraphSerializer::traverseObjCCategoryRecord(
- const ObjCCategoryRecord *Record) {
- auto *CurrentModule = ModuleForCurrentSymbol;
- if (Record->isExtendingExternalModule())
- ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source];
+void SymbolGraphSerializer::visitObjCCategoryRecord(
+ const ObjCCategoryRecord &Record) {
+ if (!Record.IsFromExternalModule)
+ return;
- if (!walkUpFromObjCCategoryRecord(Record))
- return false;
+ // 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 RetVal = traverseRecordContext(Record);
- ModuleForCurrentSymbol = CurrentModule;
- return RetVal;
-}
+ 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));
-bool SymbolGraphSerializer::walkUpFromObjCCategoryRecord(
- const ObjCCategoryRecord *Record) {
- return visitObjCCategoryRecord(Record);
-}
+ auto ObjCCategory = serializeAPIRecord(Record);
+
+ if (!ObjCCategory)
+ return;
-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());
+ Symbols.emplace_back(std::move(*ObjCCategory));
+ serializeMembers(Record, Record.Methods);
+ serializeMembers(Record, Record.Properties);
- return true;
+ // Surface the protocols of the category to the interface.
+ for (const auto &Protocol : Record.Protocols)
+ serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
}
-bool SymbolGraphSerializer::visitObjCMethodRecord(
- const ObjCMethodRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitMacroDefinitionRecord(
+ const MacroDefinitionRecord &Record) {
+ auto Macro = serializeAPIRecord(Record);
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
-}
+ if (!Macro)
+ return;
-bool SymbolGraphSerializer::visitObjCInstanceVariableRecord(
- const ObjCInstanceVariableRecord *Record) {
- // FIXME: serialize ivar access control here.
- return true;
+ Symbols.emplace_back(std::move(*Macro));
}
-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::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::visitTypedefRecord(const TypedefRecord *Record) {
+void 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 true;
+ return;
- // Create the symbol record if the other symbol droppping rules permit it.
- serializeAPIRecord(Record);
- if (!CurrentSymbol)
- return true;
+ auto Typedef = serializeAPIRecord(Record);
+ if (!Typedef)
+ return;
- (*CurrentSymbol)["type"] = Record->UnderlyingType.USR;
+ (*Typedef)["type"] = Record.UnderlyingType.USR;
- return true;
+ Symbols.emplace_back(std::move(*Typedef));
}
-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::serialize() {
+ traverseAPISet();
+ return serializeCurrentGraph();
}
-Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
- ExtendedModule &&EM) {
+Object SymbolGraphSerializer::serializeCurrentGraph() {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
- serializeObject(Root, "module", serializeModuleObject(ModuleName));
+ serializeObject(Root, "module", serializeModule());
- Root["symbols"] = std::move(EM.Symbols);
- Root["relationships"] = std::move(EM.Relationships);
+ Root["symbols"] = std::move(Symbols);
+ Root["relationships"] = std::move(Relationships);
return Root;
}
-void SymbolGraphSerializer::serializeGraphToStream(
- raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName,
- ExtendedModule &&EM) {
- Object Root = serializeGraph(ModuleName, std::move(EM));
+void SymbolGraphSerializer::serialize(raw_ostream &os) {
+ Object root = serialize();
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";
-}
-
-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()));
- }
+ os << formatv("{0:2}", Value(std::move(root))) << "\n";
}
std::optional<Object>
@@ -1070,20 +1262,14 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object Root;
APIIgnoresList EmptyIgnores;
SymbolGraphSerializer Serializer(API, EmptyIgnores,
- /*EmitSymbolLabelsForTesting*/ false,
- /*ForceEmitToMainModule*/ true);
-
- // Set up serializer parent chain
- Serializer.Hierarchy = generateHierarchyFromRecord(Record);
-
+ /*Options.Compact*/ {true},
+ /*ShouldRecurse*/ false);
Serializer.serializeSingleRecord(Record);
- serializeObject(Root, "symbolGraph",
- Serializer.serializeGraph(API.ProductName,
- std::move(Serializer.MainModule)));
+ serializeObject(Root, "symbolGraph", Serializer.serializeCurrentGraph());
Language Lang = API.getLanguage();
serializeArray(Root, "parentContexts",
- generateParentContexts(Serializer.Hierarchy, Lang));
+ generateParentContexts(*Record, API, Lang));
Array RelatedSymbols;
@@ -1101,15 +1287,14 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object RelatedSymbol;
RelatedSymbol["usr"] = RelatedRecord->USR;
RelatedSymbol["declarationLanguage"] = getLanguageName(Lang);
- RelatedSymbol["accessLevel"] = RelatedRecord->Access.getAccess();
+ // TODO: once we record this properly let's serialize it right.
+ RelatedSymbol["accessLevel"] = "public";
RelatedSymbol["filePath"] = RelatedRecord->Location.getFilename();
RelatedSymbol["moduleName"] = API.ProductName;
RelatedSymbol["isSystem"] = RelatedRecord->IsFromSystemHeader;
serializeArray(RelatedSymbol, "parentContexts",
- generateParentContexts(
- generateHierarchyFromRecord(RelatedRecord), Lang));
-
+ generateParentContexts(*RelatedRecord, API, Lang));
RelatedSymbols.push_back(std::move(RelatedSymbol));
}
diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
index 41e4e0cf1795..3a5f62c9b2e6 100644
--- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
+++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
-#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
using namespace clang;
@@ -51,20 +50,17 @@ 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.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
+ return {API.copyString(TypeName), API.copyString(TypeUSR)};
}
std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index f85f0365616f..2446aee571f4 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -181,13 +181,9 @@ 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.EmitSymbolGraph) {
- if (FEOpts.SymbolGraphOutputDir.empty()) {
- CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
- CI.getFrontendOpts().SymbolGraphOutputDir = ".";
- }
+ // symbol graph as a biproduct of compilation ( enabled with
+ // --emit-symbol-graph option )
+ if (!FEOpts.SymbolGraphOutputDir.empty()) {
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 049e8b1f85bb..0e50f4a0948c 100644
--- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c
+++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c
@@ -1,9 +1,8 @@
-// XFAIL: *
// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c
index 12ac73f0d429..3c1ef5c45b63 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// 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
+// RUN: %clang_cc1 -extract-api --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 efab6dfeef03..f4082edeb02e 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
+// RUN: %clang -extract-api -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 f7d10c61dba4..1b445e220a4a 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/class.cpp b/clang/test/ExtractAPI/class.cpp
index 0c5db8e9c9d2..21cac4305752 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp
index 4f2670d7b699..b04dca6bffda 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
index 3d7b09f93ed6..0d38fd1b7f53 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp
index c8d9cc78d41c..eba069319ce4 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
@@ -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 06a95314dc4a..4b183cbb8445 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp
index 443eac2971f0..ff4e71026e72 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -std=c++20 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -std=c++20 -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.
diff --git a/clang/test/ExtractAPI/constructor_destructor.cpp b/clang/test/ExtractAPI/constructor_destructor.cpp
index 27112c95ac45..9742d4bae261 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
@@ -137,7 +137,7 @@ class Foo {
"precise": "c:@S@Foo@F@Foo#"
},
"kind": {
- "displayName": "Constructor",
+ "displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
@@ -193,7 +193,7 @@ class Foo {
"precise": "c:@S@Foo@F@~Foo#"
},
"kind": {
- "displayName": "Destructor",
+ "displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
diff --git a/clang/test/ExtractAPI/conversions.cpp b/clang/test/ExtractAPI/conversions.cpp
index 07688ff77097..fc8d06754437 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
index e668f69bc7e0..e6b72d5881e7 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/multi_file.c
@@ -5,19 +5,18 @@
// RUN: %t/reference.main.json.in >> %t/reference.main.json
// RUN: sed -e "s@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 --pretty-sgf \
-// RUN: --symbol-graph-dir=%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=%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.c.symbols.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.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.c.symbols.json > %t/output-normalized.json
+// RUN: %t/SymbolGraphs/test.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 b00b5f5237c9..8599e82e1078 100644
--- a/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
+++ b/clang/test/ExtractAPI/emit-symbol-graph/single_file.c
@@ -3,12 +3,11 @@
// RUN: split-file %s %t
// RUN: sed -e "s@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 --pretty-sgf \
-// RUN: --symbol-graph-dir=%t/SymbolGraphs --product-name=basicfile -triple=x86_64-apple-macosx12.0.0
+// RUN: %clang_cc1 %t/main.c --emit-symbol-graph=%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.c.symbols.json >> %t/output-normalized.json
+// RUN: %t/SymbolGraphs/main.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 1cdf45ca3cdf..94499d9fc3a6 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp
index 2058ed008cfe..f05e826a8eb4 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/function_noexcepts.cpp b/clang/test/ExtractAPI/function_noexcepts.cpp
index d95eaaa7e769..3fc7263cd6a1 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp
index f43a618ec0c3..8def9745bcce 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp
index fe046e9c3b9d..a24263dc1458 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/global_record.c b/clang/test/ExtractAPI/global_record.c
index a08d51d21f95..623032b45bfd 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --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 ffdfbcb7eb80..f9d3889b5d9d 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf --product-name=GlobalRecord -target arm64-apple-macosx \
+// RUN: %clang -extract-api --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 94f3713cd3d3..bee2ea601bd7 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
index 91084f258878..e98076cdb1d0 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp
index ff4d8d17aecb..cca2ab3db7b8 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/known_files_only.c b/clang/test/ExtractAPI/known_files_only.c
index de1e786c1969..68881aa9e3aa 100644
--- a/clang/test/ExtractAPI/known_files_only.c
+++ b/clang/test/ExtractAPI/known_files_only.c
@@ -1,7 +1,17 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
-// RUN: %clang_cc1 -extract-api --pretty-sgf --product-name=GlobalRecord -triple arm64-apple-macosx \
-// RUN: %t/input1.h -verify -o - | FileCheck %s
+// RUN: sed -e "s@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:
//--- input1.h
int num;
@@ -14,6 +24,87 @@ char not_emitted;
void foo(int);
struct Foo { int a; };
-// CHECK-NOT: input2.h
-
-// expected-no-diagnostics
+//--- 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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c
index 90832fd8a2af..fe98626c8461 100644
--- a/clang/test/ExtractAPI/language.c
+++ b/clang/test/ExtractAPI/language.c
@@ -7,11 +7,11 @@
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -x c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api -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 --pretty-sgf -x objective-c-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api -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 --pretty-sgf -x objective-c++-header -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -extract-api -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 ec60f95d3d6c..1a4ed20545e0 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --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 10003fe6f6e4..d5807f6377ff 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf --product-name=Macros -target arm64-apple-macosx \
+// RUN: %clang -extract-api --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
deleted file mode 100644
index 79574a20ed95..000000000000
--- a/clang/test/ExtractAPI/metadata_and_module.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 714f9cac26c2..8d832337216a 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp
index 8eaffdefd827..706d99da558f 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/methods.cpp b/clang/test/ExtractAPI/methods.cpp
index 412c0bb3f903..8b024a8c3036 100644
--- a/clang/test/ExtractAPI/methods.cpp
+++ b/clang/test/ExtractAPI/methods.cpp
@@ -1,221 +1,467 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
class Foo {
- // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GETCOUNT
int getCount();
- // GETCOUNT: "!testRelLabel": "memberOf $ c:@S@Foo@F@getCount# $ c:@S@Foo"
- // GETCOUNT-LABEL: "!testLabel": "c:@S@Foo@F@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@Foo@F@setLength#I# $ c:@S@Foo"
- // SETL-LABEL: "!testLabel": "c:@S@Foo@F@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@Foo@F@getFoo#S $ c:@S@Foo"
-
- // GETFOO-LABEL: "!testLabel": "c:@S@Foo@F@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@Foo@F@getBar#1 $ c:@S@Foo"
-
- // GETBAR-LABEL: "!testLabel": "c:@S@Foo@F@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
-// 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@Foo@F@getCount#",
+ "target": "c:@S@Foo",
+ "targetFallback": "Foo"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@S@Foo@F@setLength#I#",
+ "target": "c:@S@Foo",
+ "targetFallback": "Foo"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@S@Foo@F@getBar#1",
+ "target": "c:@S@Foo",
+ "targetFallback": "Foo"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@S@Foo@F@getFoo#S",
+ "target": "c:@S@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@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@Foo@F@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@Foo@F@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@Foo@F@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@Foo@F@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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/multiple_inheritance.cpp b/clang/test/ExtractAPI/multiple_inheritance.cpp
index 7d49cf432646..a1f069be0de6 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/namespace.cpp b/clang/test/ExtractAPI/namespace.cpp
index 73e0728b9a44..e0c36dd3d60f 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -std=c++20 -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.
diff --git a/clang/test/ExtractAPI/nested_namespaces.cpp b/clang/test/ExtractAPI/nested_namespaces.cpp
index c6912cfb4631..bd13ef93807c 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// RUN: %clang_cc1 -std=c++20 -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.
diff --git a/clang/test/ExtractAPI/objc_block.m b/clang/test/ExtractAPI/objc_block.m
index 4a4335ec0983..a7a4f5696333 100644
--- a/clang/test/ExtractAPI/objc_block.m
+++ b/clang/test/ExtractAPI/objc_block.m
@@ -1,630 +1,965 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
+// 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@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@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 9177d40b8264..34b0a9e31f55 100644
--- a/clang/test/ExtractAPI/objc_category.m
+++ b/clang/test/ExtractAPI/objc_category.m
@@ -1,21 +1,341 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
-@protocol Protocol
-@end
+// 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 Protocol;
@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
-// 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(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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m
deleted file mode 100644
index 47e699cb91c0..000000000000
--- a/clang/test/ExtractAPI/objc_external_category.m
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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"
-
-@interface ExtInterface (Category)
-@property int Property;
-- (void)InstanceMethod;
-+ (void)ClassMethod;
-@end
-
-@interface ModInterface
-@end
-
-// expected-no-diagnostics
-
-//--- ExternalModule.h
-@interface ExtInterface
-@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@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 f2a03a9c5758..0b0f1b39d2bd 100644
--- a/clang/test/ExtractAPI/objc_id_protocol.m
+++ b/clang/test/ExtractAPI/objc_id_protocol.m
@@ -1,56 +1,317 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
+// 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;
-// 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: ],
+@property(readwrite) id<MyProtocol> *obj2;
@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)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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m
index 071ebe440918..d9d259f2d560 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@INPUT_DIR@%{/t:regex_replacement}@g" \
-// 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
+ // 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
// 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 4abccddc3b5c..ab1772a0c529 100644
--- a/clang/test/ExtractAPI/objc_interface.m
+++ b/clang/test/ExtractAPI/objc_interface.m
@@ -1,360 +1,701 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
-@protocol Protocol
-@end
+// 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
-// 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: ]
+// CHECK-NOT: error:
+// CHECK-NOT: warning:
-// 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: ]
+//--- input.h
+@protocol Protocol;
-// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GET
+@interface Super <Protocol>
+@property(readonly, getter=getProperty) unsigned Property;
+ (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@Ivar $ c:objc(cs)Derived"
-// IVAR-LABEL: "!testLabel": "c:objc(cs)Derived@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
-// 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)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@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@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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/objc_module_category.m b/clang/test/ExtractAPI/objc_module_category.m
new file mode 100644
index 000000000000..708ed10be821
--- /dev/null
+++ b/clang/test/ExtractAPI/objc_module_category.m
@@ -0,0 +1,404 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
+@interface NSString (Category1)
+-(void)method1;
+@end
+
+/// Doc comment 2
+@interface NSString (Category2)
+-(void)method2;
+@end
+
+//--- Foundation.h
+@interface NSString
+@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@Category1",
+ "target": "c:objc(cs)NSString",
+ "targetFallback": "NSString"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:objc(cs)NSString(im)method1",
+ "target": "c:objc(cy)NSString@Category1",
+ "targetFallback": "Category1"
+ },
+ {
+ "kind": "extensionTo",
+ "source": "c:objc(cy)NSString@Category2",
+ "target": "c:objc(cs)NSString",
+ "targetFallback": "NSString"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:objc(cs)NSString(im)method2",
+ "target": "c:objc(cy)NSString@Category2",
+ "targetFallback": "Category2"
+ }
+ ],
+ "symbols": [
+ {
+ "accessLevel": "public",
+ "identifier": {
+ "interfaceLanguage": "objective-c",
+ "precise": "c:objc(cy)NSString@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@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@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 f05584c885d9..5712abc15393 100644
--- a/clang/test/ExtractAPI/objc_property.m
+++ b/clang/test/ExtractAPI/objc_property.m
@@ -1,26 +1,608 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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
+// 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"
+ ]
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/objc_protocol.m b/clang/test/ExtractAPI/objc_protocol.m
index 06f7ee3d2036..a04936fe0412 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf -x objective-c-header -target arm64-apple-macosx \
+// RUN: %clang -extract-api -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
new file mode 100644
index 000000000000..adaef5a7b31a
--- /dev/null
+++ b/clang/test/ExtractAPI/objc_various_categories.m
@@ -0,0 +1,507 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@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"
+
+@interface MyClass1 (MyCategory1)
+- (int) SomeMethod;
+@end
+
+@interface NSString (Category1)
+-(void) StringMethod;
+@end
+
+@interface NSString (Category2)
+-(void) StringMethod2;
+@end
+
+//--- myclass_1.h
+@interface MyClass1
+@end
+
+//--- Foundation.h
+@interface NSString
+@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@Category1",
+ "target": "c:objc(cs)NSString",
+ "targetFallback": "NSString"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:objc(cs)NSString(im)StringMethod",
+ "target": "c:objc(cy)NSString@Category1",
+ "targetFallback": "Category1"
+ },
+ {
+ "kind": "extensionTo",
+ "source": "c:objc(cy)NSString@Category2",
+ "target": "c:objc(cs)NSString",
+ "targetFallback": "NSString"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:objc(cs)NSString(im)StringMethod2",
+ "target": "c:objc(cy)NSString@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@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@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@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 9430c58a991e..511a5a7ae8fd 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/relative_include.m b/clang/test/ExtractAPI/relative_include.m
index e5a02683cbd8..46cbdaeeb280 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 --pretty-sgf -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api -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 58c3c4e1e5cb..5fe99afe0876 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \
+// 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.
diff --git a/clang/test/ExtractAPI/struct.c b/clang/test/ExtractAPI/struct.c
index 1995a6aedbfd..4284b734cd05 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
+// RUN: %clang -extract-api -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 a4c3619bfd21..c30e65549f2b 100644
--- a/clang/test/ExtractAPI/typedef.c
+++ b/clang/test/ExtractAPI/typedef.c
@@ -1,93 +1,391 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT
+// 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
typedef int MyInt;
-// MYINT-LABEL: "!testLabel": "c:typedef.c@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@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@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@Bar"
-// RUN: FileCheck %s --input-file %t/output.symbols.json
void foo(BarPtr value);
void baz(BarPtr *value);
-// CHECK-NOT: struct Bar *
-// expected-no-diagnostics
+//--- 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@T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ },
+ {
+ "kind": "text",
+ "spelling": ");"
+ }
+ ],
+ "functionSignature": {
+ "parameters": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h@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@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@T@BarPtr",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": " * "
+ },
+ {
+ "kind": "internalParam",
+ "spelling": "value"
+ },
+ {
+ "kind": "text",
+ "spelling": ");"
+ }
+ ],
+ "functionSignature": {
+ "parameters": [
+ {
+ "declarationFragments": [
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h@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@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@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@Bar",
+ "spelling": "Bar"
+ },
+ {
+ "kind": "text",
+ "spelling": " * "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "BarPtr"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "objective-c",
+ "precise": "c:input.h@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@Bar"
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c
index 9e00ff752546..3e4c3e1dd60c 100644
--- a/clang/test/ExtractAPI/typedef_anonymous_record.c
+++ b/clang/test/ExtractAPI/typedef_anonymous_record.c
@@ -1,158 +1,468 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCT
-typedef struct { } MyStruct;
-// MYSTRUCT-LABEL: "!testLabel": "c:@SA@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: ]
+// 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
-// RUN: FileCheck %s --input-file %t/typedefchain.symbols.json --check-prefix MYSTRUCTSTRUCT
+//--- input.h
+typedef struct { } MyStruct;
typedef MyStruct MyStructStruct;
-// MYSTRUCTSTRUCT-LABEL: "!testLabel": "c:typedef_anonymous_record.c@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@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 MyStructStruct MyStructStructStruct;
typedef enum { Case } MyEnum;
-// MYENUM: "source": "c:@EA@MyEnum@Case",
-// MYENUM-NEXT: "target": "c:@EA@MyEnum",
-// MYENUM-NEXT: "targetFallback": "MyEnum"
-// MYENUM-LABEL: "!testLabel": "c:@EA@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@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;
-// MYENUMENUM-LABEL: "!testLabel": "c:typedef_anonymous_record.c@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@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"
-
+typedef MyEnumEnum MyEnumEnumEnum;
// expected-no-diagnostics
+
+//--- 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@MyEnum@Case",
+ "target": "c:@EA@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@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@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@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@MyStruct",
+ "spelling": "MyStruct"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "MyStructStruct"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@MyStruct"
+ },
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "typedef"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h@T@MyStructStruct",
+ "spelling": "MyStructStruct"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "MyStructStructStruct"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@T@MyStructStruct"
+ },
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "typedef"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:@EA@MyEnum",
+ "spelling": "MyEnum"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "MyEnumEnum"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@MyEnum"
+ },
+ {
+ "accessLevel": "public",
+ "declarationFragments": [
+ {
+ "kind": "keyword",
+ "spelling": "typedef"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "typeIdentifier",
+ "preciseIdentifier": "c:input.h@T@MyEnumEnum",
+ "spelling": "MyEnumEnum"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "MyEnumEnumEnum"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@T@MyEnumEnum"
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/typedef_chain.c b/clang/test/ExtractAPI/typedef_chain.c
index 05d4eb52cef3..9e6151c8ebd9 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang -extract-api --pretty-sgf --product-name=TypedefChain -target arm64-apple-macosx \
+// RUN: %clang -extract-api --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 fb6fbe987624..15357d5b055f 100644
--- a/clang/test/ExtractAPI/typedef_struct_enum.c
+++ b/clang/test/ExtractAPI/typedef_struct_enum.c
@@ -1,146 +1,445 @@
// RUN: rm -rf %t
-// 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
+// RUN: split-file %s %t
+// RUN: sed -e "s@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: FileCheck %s --input-file %t/output.symbols.json --check-prefix TEST
+// 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
typedef struct Test {
} Test;
-// TEST-LABEL: "!testLabel": "c:@S@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@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@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@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@Foo"
-
struct Foo {
int bar;
};
-// 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:@E@Test2@simple",
+ "target": "c:@E@Test2",
+ "targetFallback": "Test2"
+ },
+ {
+ "kind": "memberOf",
+ "source": "c:@S@Foo@FI@bar",
+ "target": "c:@S@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@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@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@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@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@Foo@FI@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@Foo",
+ "spelling": "Foo"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "TypedefedFoo"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@Foo"
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/underscored.c b/clang/test/ExtractAPI/underscored.c
index 204ec36f1fab..30d2b63f763e 100644
--- a/clang/test/ExtractAPI/underscored.c
+++ b/clang/test/ExtractAPI/underscored.c
@@ -1,5 +1,17 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@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 %s -o - -verify | FileCheck %s
+// 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
// Global record
int _HiddenGlobal;
@@ -7,22 +19,399 @@ int exposed_global;
// Record type
struct _HiddenRecord {
- int HiddenRecordMember;
+ int a;
};
struct ExposedRecord {
- int ExposedRecordMember;
+ int a;
};
+// Typedef
+typedef struct {} _HiddenTypedef;
+typedef int ExposedTypedef;
+typedef _HiddenTypedef ExposedTypedefToHidden;
+
// Macros
#define _HIDDEN_MACRO 5
#define EXPOSED_MACRO 5
-// expected-no-diagnostics
-
-// CHECK-NOT: _HiddenRecord
-// CHECK-NOT: HiddenRecordMember
-// CHECK: ExposedRecord
-// CHECK: ExposedRecordMember
-// CHECK-NOT: _HIDDEN_MACRO
-// CHECK: EXPOSED_MACRO
+// 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@ExposedRecord@FI@a",
+ "target": "c:@S@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@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@ExposedRecord@FI@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@335@macro@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@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@_HiddenTypedef",
+ "spelling": "_HiddenTypedef"
+ },
+ {
+ "kind": "text",
+ "spelling": " "
+ },
+ {
+ "kind": "identifier",
+ "spelling": "ExposedTypedefToHidden"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
+ }
+ ],
+ "identifier": {
+ "interfaceLanguage": "c",
+ "precise": "c:input.h@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@_HiddenTypedef"
+ }
+ ]
+}
diff --git a/clang/test/ExtractAPI/union.c b/clang/test/ExtractAPI/union.c
index 8f8300b2c9a5..6ec9fd3ddf6e 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@INPUT_DIR@%{/t:regex_replacement}@g" \
// RUN: %t/reference.output.json.in >> %t/reference.output.json
-// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx -x c-header\
+// RUN: %clang_cc1 -extract-api -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 db0382052ba3..9ba7e1dedb60 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 --pretty-sgf -v --product-name=MyFramework \
+// RUN: %clang_cc1 -extract-api -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 9d9d3a1e40f1..1b27b6f61437 100644
--- a/clang/test/Index/extract-api-cursor.m
+++ b/clang/test/Index/extract-api-cursor.m
@@ -31,8 +31,6 @@ struct Foo {
- (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
@@ -120,10 +118,3 @@ struct Foo {
// 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 d74f3740406c..05098c96829f 100644
--- a/clang/tools/libclang/CXExtractAPI.cpp
+++ b/clang/tools/libclang/CXExtractAPI.cpp
@@ -18,7 +18,6 @@
#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"
@@ -55,20 +54,41 @@ struct LibClangExtractAPIVisitor
if (!shouldDeclBeIncluded(Decl))
return true;
- auto *Interface = Decl->getClassInterface();
+ 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);
+ }
- if (!VisitObjCInterfaceDecl(Interface))
- return false;
+ ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
+ Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
+ Comment, Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
- SmallString<128> USR;
- index::generateUSRForDecl(Interface, USR);
+ // Record all methods (selectors). This doesn't include automatically
+ // synthesized property methods.
+ recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
+ recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
+ recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
- 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;
}
};
@@ -76,14 +96,21 @@ struct LibClangExtractAPIVisitor
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
-// 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));
+ 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;
+}
+
+static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
+ Decl *D) {
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
#define DECL(CLASS, BASE) \
@@ -92,12 +119,20 @@ 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 << llvm::formatv("{0}", Value(std::move(Obj)));
+ OS << Value(std::move(Obj));
return cxstring::createDup(BackingString.str());
}