Skip to content

Commit 9b36e12

Browse files
committed
[clang][extract-api] Add Objective-C interface support
Add support for Objective-C interface declarations in ExtractAPI. Depends on D122495 Differential Revision: https://reviews.llvm.org/D122446
1 parent 686dcbe commit 9b36e12

File tree

8 files changed

+1146
-18
lines changed

8 files changed

+1146
-18
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define LLVM_CLANG_EXTRACTAPI_API_H
2020

2121
#include "clang/AST/Decl.h"
22+
#include "clang/AST/DeclObjC.h"
2223
#include "clang/AST/RawCommentList.h"
2324
#include "clang/Basic/SourceLocation.h"
2425
#include "clang/ExtractAPI/AvailabilityInfo.h"
@@ -77,6 +78,10 @@ struct APIRecord {
7778
RK_Enum,
7879
RK_StructField,
7980
RK_Struct,
81+
RK_ObjCProperty,
82+
RK_ObjCIvar,
83+
RK_ObjCMethod,
84+
RK_ObjCInterface,
8085
};
8186

8287
private:
@@ -201,6 +206,154 @@ struct StructRecord : APIRecord {
201206
virtual void anchor();
202207
};
203208

209+
/// This holds information associated with Objective-C properties.
210+
struct ObjCPropertyRecord : APIRecord {
211+
/// The attributes associated with an Objective-C property.
212+
enum AttributeKind : unsigned {
213+
NoAttr = 0,
214+
ReadOnly = 1,
215+
Class = 1 << 1,
216+
Dynamic = 1 << 2,
217+
};
218+
219+
AttributeKind Attributes;
220+
StringRef GetterName;
221+
StringRef SetterName;
222+
bool IsOptional;
223+
224+
ObjCPropertyRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
225+
const AvailabilityInfo &Availability,
226+
const DocComment &Comment,
227+
DeclarationFragments Declaration,
228+
DeclarationFragments SubHeading, AttributeKind Attributes,
229+
StringRef GetterName, StringRef SetterName,
230+
bool IsOptional)
231+
: APIRecord(RK_ObjCProperty, Name, USR, Loc, Availability,
232+
LinkageInfo::none(), Comment, Declaration, SubHeading),
233+
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
234+
IsOptional(IsOptional) {}
235+
236+
bool isReadOnly() const { return Attributes & ReadOnly; }
237+
bool isDynamic() const { return Attributes & Dynamic; }
238+
bool isClassProperty() const { return Attributes & Class; }
239+
240+
static bool classof(const APIRecord *Record) {
241+
return Record->getKind() == RK_ObjCProperty;
242+
}
243+
244+
private:
245+
virtual void anchor();
246+
};
247+
248+
/// This holds information associated with Objective-C instance variables.
249+
struct ObjCInstanceVariableRecord : APIRecord {
250+
using AccessControl = ObjCIvarDecl::AccessControl;
251+
AccessControl Access;
252+
253+
ObjCInstanceVariableRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
254+
const AvailabilityInfo &Availability,
255+
const DocComment &Comment,
256+
DeclarationFragments Declaration,
257+
DeclarationFragments SubHeading,
258+
AccessControl Access)
259+
: APIRecord(RK_ObjCIvar, Name, USR, Loc, Availability,
260+
LinkageInfo::none(), Comment, Declaration, SubHeading),
261+
Access(Access) {}
262+
263+
static bool classof(const APIRecord *Record) {
264+
return Record->getKind() == RK_ObjCIvar;
265+
}
266+
267+
private:
268+
virtual void anchor();
269+
};
270+
271+
/// This holds information associated with Objective-C methods.
272+
struct ObjCMethodRecord : APIRecord {
273+
FunctionSignature Signature;
274+
bool IsInstanceMethod;
275+
276+
ObjCMethodRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
277+
const AvailabilityInfo &Availability,
278+
const DocComment &Comment, DeclarationFragments Declaration,
279+
DeclarationFragments SubHeading, FunctionSignature Signature,
280+
bool IsInstanceMethod)
281+
: APIRecord(RK_ObjCMethod, Name, USR, Loc, Availability,
282+
LinkageInfo::none(), Comment, Declaration, SubHeading),
283+
Signature(Signature), IsInstanceMethod(IsInstanceMethod) {}
284+
285+
static bool classof(const APIRecord *Record) {
286+
return Record->getKind() == RK_ObjCMethod;
287+
}
288+
289+
private:
290+
virtual void anchor();
291+
};
292+
293+
/// This represents a reference to another symbol that might come from external
294+
/// sources.
295+
struct SymbolReference {
296+
StringRef Name;
297+
StringRef USR;
298+
299+
/// The source project/module/product of the referred symbol.
300+
StringRef Source;
301+
302+
SymbolReference() = default;
303+
SymbolReference(StringRef Name, StringRef USR = "", StringRef Source = "")
304+
: Name(Name), USR(USR), Source(Source) {}
305+
SymbolReference(const APIRecord &Record)
306+
: Name(Record.Name), USR(Record.USR) {}
307+
308+
/// Determine if this SymbolReference is empty.
309+
///
310+
/// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
311+
bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
312+
};
313+
314+
/// The base representation of an Objective-C container record. Holds common
315+
/// information associated with Objective-C containers.
316+
struct ObjCContainerRecord : APIRecord {
317+
SmallVector<std::unique_ptr<ObjCMethodRecord>> Methods;
318+
SmallVector<std::unique_ptr<ObjCPropertyRecord>> Properties;
319+
SmallVector<std::unique_ptr<ObjCInstanceVariableRecord>> Ivars;
320+
SmallVector<SymbolReference> Protocols;
321+
322+
ObjCContainerRecord() = delete;
323+
324+
ObjCContainerRecord(RecordKind Kind, StringRef Name, StringRef USR,
325+
PresumedLoc Loc, const AvailabilityInfo &Availability,
326+
LinkageInfo Linkage, const DocComment &Comment,
327+
DeclarationFragments Declaration,
328+
DeclarationFragments SubHeading)
329+
: APIRecord(Kind, Name, USR, Loc, Availability, Linkage, Comment,
330+
Declaration, SubHeading) {}
331+
332+
virtual ~ObjCContainerRecord() = 0;
333+
};
334+
335+
/// This holds information associated with Objective-C interfaces/classes.
336+
struct ObjCInterfaceRecord : ObjCContainerRecord {
337+
SymbolReference SuperClass;
338+
339+
ObjCInterfaceRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
340+
const AvailabilityInfo &Availability, LinkageInfo Linkage,
341+
const DocComment &Comment,
342+
DeclarationFragments Declaration,
343+
DeclarationFragments SubHeading,
344+
SymbolReference SuperClass)
345+
: ObjCContainerRecord(RK_ObjCInterface, Name, USR, Loc, Availability,
346+
Linkage, Comment, Declaration, SubHeading),
347+
SuperClass(SuperClass) {}
348+
349+
static bool classof(const APIRecord *Record) {
350+
return Record->getKind() == RK_ObjCInterface;
351+
}
352+
353+
private:
354+
virtual void anchor();
355+
};
356+
204357
/// APISet holds the set of API records collected from given inputs.
205358
class APISet {
206359
public:
@@ -292,6 +445,58 @@ class APISet {
292445
DeclarationFragments Declaration,
293446
DeclarationFragments SubHeading);
294447

448+
/// Create and add an Objective-C interface record into the API set.
449+
///
450+
/// Note: the caller is responsible for keeping the StringRef \p Name and
451+
/// \p USR alive. APISet::copyString provides a way to copy strings into
452+
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
453+
/// to generate the USR for \c D and keep it alive in APISet.
454+
ObjCInterfaceRecord *
455+
addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
456+
const AvailabilityInfo &Availability, LinkageInfo Linkage,
457+
const DocComment &Comment, DeclarationFragments Declaration,
458+
DeclarationFragments SubHeading, SymbolReference SuperClass);
459+
460+
/// Create and add an Objective-C method record into the API set.
461+
///
462+
/// Note: the caller is responsible for keeping the StringRef \p Name and
463+
/// \p USR alive. APISet::copyString provides a way to copy strings into
464+
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
465+
/// to generate the USR for \c D and keep it alive in APISet.
466+
ObjCMethodRecord *
467+
addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
468+
PresumedLoc Loc, const AvailabilityInfo &Availability,
469+
const DocComment &Comment, DeclarationFragments Declaration,
470+
DeclarationFragments SubHeading, FunctionSignature Signature,
471+
bool IsInstanceMethod);
472+
473+
/// Create and add an Objective-C property record into the API set.
474+
///
475+
/// Note: the caller is responsible for keeping the StringRef \p Name and
476+
/// \p USR alive. APISet::copyString provides a way to copy strings into
477+
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
478+
/// to generate the USR for \c D and keep it alive in APISet.
479+
ObjCPropertyRecord *
480+
addObjCProperty(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
481+
PresumedLoc Loc, const AvailabilityInfo &Availability,
482+
const DocComment &Comment, DeclarationFragments Declaration,
483+
DeclarationFragments SubHeading,
484+
ObjCPropertyRecord::AttributeKind Attributes,
485+
StringRef GetterName, StringRef SetterName, bool IsOptional);
486+
487+
/// Create and add an Objective-C instance variable record into the API set.
488+
///
489+
/// Note: the caller is responsible for keeping the StringRef \p Name and
490+
/// \p USR alive. APISet::copyString provides a way to copy strings into
491+
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
492+
/// to generate the USR for \c D and keep it alive in APISet.
493+
ObjCInstanceVariableRecord *addObjCInstanceVariable(
494+
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
495+
PresumedLoc Loc, const AvailabilityInfo &Availability,
496+
const DocComment &Comment, DeclarationFragments Declaration,
497+
DeclarationFragments SubHeading,
498+
ObjCInstanceVariableRecord::AccessControl Access);
499+
295500
/// A map to store the set of GlobalRecord%s with the declaration name as the
296501
/// key.
297502
using GlobalRecordMap =
@@ -306,6 +511,11 @@ class APISet {
306511
using StructRecordMap =
307512
llvm::MapVector<StringRef, std::unique_ptr<StructRecord>>;
308513

514+
/// A map to store the set of ObjCInterfaceRecord%s with the declaration name
515+
/// as the key.
516+
using ObjCInterfaceRecordMap =
517+
llvm::MapVector<StringRef, std::unique_ptr<ObjCInterfaceRecord>>;
518+
309519
/// Get the target triple for the ExtractAPI invocation.
310520
const llvm::Triple &getTarget() const { return Target; }
311521

@@ -315,6 +525,9 @@ class APISet {
315525
const GlobalRecordMap &getGlobals() const { return Globals; }
316526
const EnumRecordMap &getEnums() const { return Enums; }
317527
const StructRecordMap &getStructs() const { return Structs; }
528+
const ObjCInterfaceRecordMap &getObjCInterfaces() const {
529+
return ObjCInterfaces;
530+
}
318531

319532
/// Generate and store the USR of declaration \p D.
320533
///
@@ -343,6 +556,7 @@ class APISet {
343556
GlobalRecordMap Globals;
344557
EnumRecordMap Enums;
345558
StructRecordMap Structs;
559+
ObjCInterfaceRecordMap ObjCInterfaces;
346560
};
347561

348562
} // namespace extractapi

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "clang/AST/ASTContext.h"
2222
#include "clang/AST/Decl.h"
2323
#include "clang/AST/DeclCXX.h"
24+
#include "clang/AST/DeclObjC.h"
2425
#include "llvm/ADT/StringRef.h"
2526
#include <vector>
2627

@@ -202,11 +203,34 @@ class DeclarationFragmentsBuilder {
202203
/// Build DeclarationFragments for a struct record declaration RecordDecl.
203204
static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
204205

206+
/// Build DeclarationFragments for an Objective-C interface declaration
207+
/// ObjCInterfaceDecl.
208+
static DeclarationFragments
209+
getFragmentsForObjCInterface(const ObjCInterfaceDecl *);
210+
211+
/// Build DeclarationFragments for an Objective-C method declaration
212+
/// ObjCMethodDecl.
213+
static DeclarationFragments getFragmentsForObjCMethod(const ObjCMethodDecl *);
214+
215+
/// Build DeclarationFragments for an Objective-C property declaration
216+
/// ObjCPropertyDecl.
217+
static DeclarationFragments
218+
getFragmentsForObjCProperty(const ObjCPropertyDecl *);
219+
205220
/// Build sub-heading fragments for a NamedDecl.
206221
static DeclarationFragments getSubHeading(const NamedDecl *);
207222

208-
/// Build FunctionSignature for a function declaration FunctionDecl.
209-
static FunctionSignature getFunctionSignature(const FunctionDecl *);
223+
/// Build sub-heading fragments for an Objective-C method.
224+
static DeclarationFragments getSubHeading(const ObjCMethodDecl *);
225+
226+
/// Build FunctionSignature for a function-like declaration \c FunctionT like
227+
/// FunctionDecl or ObjCMethodDecl.
228+
///
229+
/// The logic and implementation of building a signature for a FunctionDecl
230+
/// and an ObjCMethodDecl are exactly the same, but they do not share a common
231+
/// base. This template helps reuse the code.
232+
template <typename FunctionT>
233+
static FunctionSignature getFunctionSignature(const FunctionT *);
210234

211235
private:
212236
DeclarationFragmentsBuilder() = delete;

clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ class SymbolGraphSerializer : public APISerializer {
6262
/// For example enum constants are members of the enum, class/instance
6363
/// methods are members of the class, etc.
6464
MemberOf,
65+
66+
/// The source symbol is inherited from the target symbol.
67+
InheritsFrom,
68+
69+
/// The source symbol conforms to the target symbol.
70+
/// For example Objective-C protocol conformances.
71+
ConformsTo,
6572
};
6673

6774
/// Get the string representation of the relationship kind.
@@ -101,8 +108,8 @@ class SymbolGraphSerializer : public APISerializer {
101108
///
102109
/// Record the relationship between the two symbols in
103110
/// SymbolGraphSerializer::Relationships.
104-
void serializeRelationship(RelationshipKind Kind, const APIRecord &Source,
105-
const APIRecord &Target);
111+
void serializeRelationship(RelationshipKind Kind, SymbolReference Source,
112+
SymbolReference Target);
106113

107114
/// Serialize a global record.
108115
void serializeGlobalRecord(const GlobalRecord &Record);
@@ -113,6 +120,9 @@ class SymbolGraphSerializer : public APISerializer {
113120
/// Serialize a struct record.
114121
void serializeStructRecord(const StructRecord &Record);
115122

123+
/// Serialize an Objective-C container record.
124+
void serializeObjCContainerRecord(const ObjCContainerRecord &Record);
125+
116126
public:
117127
SymbolGraphSerializer(const APISet &API, StringRef ProductName,
118128
APISerializerOption Options = {})

0 commit comments

Comments
 (0)