forked from OSchip/llvm-project
Introduce a new libclang API to determine the platform availability of
a given entity, so that we can tell when the entity was introduced/deprecated/obsoleted on each platform for which we have an annotation. Addresses <rdar://problem/11365715>. llvm-svn: 156347
This commit is contained in:
parent
ececf9f0ae
commit
d6225d304e
|
@ -132,6 +132,29 @@ enum CXAvailabilityKind {
|
||||||
*/
|
*/
|
||||||
CXAvailability_NotAccessible
|
CXAvailability_NotAccessible
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Describes a version number of the form major.minor.subminor.
|
||||||
|
*/
|
||||||
|
typedef struct CXVersion {
|
||||||
|
/**
|
||||||
|
* \brief The major version number, e.g., the '10' in '10.7.3'. A negative
|
||||||
|
* value indicates that there is no version number at all.
|
||||||
|
*/
|
||||||
|
int Major;
|
||||||
|
/**
|
||||||
|
* \brief The minor version number, e.g., the '7' in '10.7.3'. This value
|
||||||
|
* will be negative if no minor version number was provided, e.g., for
|
||||||
|
* version '10'.
|
||||||
|
*/
|
||||||
|
int Minor;
|
||||||
|
/**
|
||||||
|
* \brief The subminor version number, e.g., the '3' in '10.7.3'. This value
|
||||||
|
* will be negative if no minor or subminor version number was provided,
|
||||||
|
* e.g., in version '10' or '10.7'.
|
||||||
|
*/
|
||||||
|
int Subminor;
|
||||||
|
} CXVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup CINDEX_STRING String manipulation routines
|
* \defgroup CINDEX_STRING String manipulation routines
|
||||||
|
@ -2165,7 +2188,8 @@ enum CXLinkageKind {
|
||||||
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Determine the availability of the entity that this cursor refers to.
|
* \brief Determine the availability of the entity that this cursor refers to,
|
||||||
|
* taking the current target platform into account.
|
||||||
*
|
*
|
||||||
* \param cursor The cursor to query.
|
* \param cursor The cursor to query.
|
||||||
*
|
*
|
||||||
|
@ -2174,6 +2198,94 @@ CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
||||||
CINDEX_LINKAGE enum CXAvailabilityKind
|
CINDEX_LINKAGE enum CXAvailabilityKind
|
||||||
clang_getCursorAvailability(CXCursor cursor);
|
clang_getCursorAvailability(CXCursor cursor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the availability of a given entity on a particular platform, e.g.,
|
||||||
|
* a particular class might only be available on Mac OS 10.7 or newer.
|
||||||
|
*/
|
||||||
|
typedef struct CXPlatformAvailability {
|
||||||
|
/**
|
||||||
|
* \brief A string that describes the platform for which this structure
|
||||||
|
* provides availability information.
|
||||||
|
*
|
||||||
|
* Possible values are "ios" or "macosx".
|
||||||
|
*/
|
||||||
|
CXString Platform;
|
||||||
|
/**
|
||||||
|
* \brief The version number in which this entity was introduced.
|
||||||
|
*/
|
||||||
|
CXVersion Introduced;
|
||||||
|
/**
|
||||||
|
* \brief The version number in which this entity was deprecated (but is
|
||||||
|
* still available).
|
||||||
|
*/
|
||||||
|
CXVersion Deprecated;
|
||||||
|
/**
|
||||||
|
* \brief The version number in which this entity was obsoleted, and therefore
|
||||||
|
* is no longer available.
|
||||||
|
*/
|
||||||
|
CXVersion Obsoleted;
|
||||||
|
/**
|
||||||
|
* \brief Whether the entity is unconditionally unavailable on this platform.
|
||||||
|
*/
|
||||||
|
int Unavailable;
|
||||||
|
/**
|
||||||
|
* \brief An optional message to provide to a user of this API, e.g., to
|
||||||
|
* suggest replacement APIs.
|
||||||
|
*/
|
||||||
|
CXString Message;
|
||||||
|
} CXPlatformAvailability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Determine the availability of the entity that this cursor refers to
|
||||||
|
* on any platforms for which availability information is known.
|
||||||
|
*
|
||||||
|
* \param cursor The cursor to query.
|
||||||
|
*
|
||||||
|
* \param always_deprecated If non-NULL, will be set to indicate whether the
|
||||||
|
* entity is deprecated on all platforms.
|
||||||
|
*
|
||||||
|
* \param deprecated_message If non-NULL, will be set to the message text
|
||||||
|
* provided along with the unconditional deprecation of this entity. The client
|
||||||
|
* is responsible for deallocating this string.
|
||||||
|
*
|
||||||
|
* \param always_unavailabile If non-NULL, will be set to indicate whether the
|
||||||
|
* entity is unavailable on all platforms.
|
||||||
|
*
|
||||||
|
* \param unavailable_message If non-NULL, will be set to the message text
|
||||||
|
* provided along with the unconditional unavailability of this entity. The
|
||||||
|
* client is responsible for deallocating this string.
|
||||||
|
*
|
||||||
|
* \param availability If non-NULL, an array of CXPlatformAvailability instances
|
||||||
|
* that will be populated with platform availability information, up to either
|
||||||
|
* the number of platforms for which availability information is available (as
|
||||||
|
* returned by this function) or \c availability_size, whichever is smaller.
|
||||||
|
*
|
||||||
|
* \param availability_size The number of elements available in the
|
||||||
|
* \c availability array.
|
||||||
|
*
|
||||||
|
* \returns The number of platforms (N) for which availability information is
|
||||||
|
* available (which is unrelated to \c availability_size).
|
||||||
|
*
|
||||||
|
* Note that the client is responsible for calling
|
||||||
|
* \c clang_disposeCXPlatformAvailability to free each of the
|
||||||
|
* platform-availability structures returned. There are
|
||||||
|
* \c min(N, availability_size) such structures.
|
||||||
|
*/
|
||||||
|
CINDEX_LINKAGE int
|
||||||
|
clang_getCursorPlatformAvailability(CXCursor cursor,
|
||||||
|
int *always_deprecated,
|
||||||
|
CXString *deprecated_message,
|
||||||
|
int *always_unavailable,
|
||||||
|
CXString *unavailable_message,
|
||||||
|
CXPlatformAvailability *availability,
|
||||||
|
int availability_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free the memory associated with a \c CXPlatformAvailability structure.
|
||||||
|
*/
|
||||||
|
CINDEX_LINKAGE void
|
||||||
|
clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Describe the "language" of the entity referred to by a cursor.
|
* \brief Describe the "language" of the entity referred to by a cursor.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Run lines below; this test is line- and column-sensitive.
|
||||||
|
|
||||||
|
void foo(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7), availability(ios,introduced=3.2,deprecated=4.1)));
|
||||||
|
|
||||||
|
// RUN: c-index-test -test-load-source all %s | FileCheck %s
|
||||||
|
// CHECK: (ios, introduced=3.2, deprecated=4.1) (macosx, introduced=10.4, deprecated=10.5, obsoleted=10.7)
|
|
@ -83,7 +83,7 @@ struct X0 {};
|
||||||
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
|
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
|
||||||
// CHECK: c-index-api-loadTU-test.m:8:50: ParmDecl=msg:8:50 (Definition) Extent=[8:47 - 8:53]
|
// CHECK: c-index-api-loadTU-test.m:8:50: ParmDecl=msg:8:50 (Definition) Extent=[8:47 - 8:53]
|
||||||
// CHECK: c-index-api-loadTU-test.m:8:47: TypeRef=id:0:0 Extent=[8:47 - 8:49]
|
// CHECK: c-index-api-loadTU-test.m:8:47: TypeRef=id:0:0 Extent=[8:47 - 8:49]
|
||||||
// CHECK: c-index-api-loadTU-test.m:9:3: ObjCInstanceMethodDecl=foo:9:3 (deprecated) Extent=[9:1 - 9:35]
|
// CHECK: c-index-api-loadTU-test.m:9:3: ObjCInstanceMethodDecl=foo:9:3 (deprecated) (always deprecated: "") Extent=[9:1 - 9:35]
|
||||||
// CHECK: c-index-api-loadTU-test.m:10:3: ObjCClassMethodDecl=fooC:10:3 Extent=[10:1 - 10:8]
|
// CHECK: c-index-api-loadTU-test.m:10:3: ObjCClassMethodDecl=fooC:10:3 Extent=[10:1 - 10:8]
|
||||||
// CHECK: c-index-api-loadTU-test.m:14:12: ObjCInterfaceDecl=Bar:14:12 Extent=[14:1 - 18:5]
|
// CHECK: c-index-api-loadTU-test.m:14:12: ObjCInterfaceDecl=Bar:14:12 Extent=[14:1 - 18:5]
|
||||||
// CHECK: c-index-api-loadTU-test.m:14:18: ObjCSuperClassRef=Foo:4:12 Extent=[14:18 - 14:21]
|
// CHECK: c-index-api-loadTU-test.m:14:18: ObjCSuperClassRef=Foo:4:12 Extent=[14:18 - 14:21]
|
||||||
|
|
|
@ -180,6 +180,20 @@ static void PrintRange(CXSourceRange R, const char *str) {
|
||||||
|
|
||||||
int want_display_name = 0;
|
int want_display_name = 0;
|
||||||
|
|
||||||
|
static void printVersion(const char *Prefix, CXVersion Version) {
|
||||||
|
if (Version.Major < 0)
|
||||||
|
return;
|
||||||
|
printf("%s%d", Prefix, Version.Major);
|
||||||
|
|
||||||
|
if (Version.Minor < 0)
|
||||||
|
return;
|
||||||
|
printf(".%d", Version.Minor);
|
||||||
|
|
||||||
|
if (Version.Subminor < 0)
|
||||||
|
return;
|
||||||
|
printf(".%d", Version.Subminor);
|
||||||
|
}
|
||||||
|
|
||||||
static void PrintCursor(CXCursor Cursor) {
|
static void PrintCursor(CXCursor Cursor) {
|
||||||
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
|
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
|
||||||
if (clang_isInvalid(Cursor.kind)) {
|
if (clang_isInvalid(Cursor.kind)) {
|
||||||
|
@ -197,7 +211,14 @@ static void PrintCursor(CXCursor Cursor) {
|
||||||
unsigned RefNameRangeNr;
|
unsigned RefNameRangeNr;
|
||||||
CXSourceRange CursorExtent;
|
CXSourceRange CursorExtent;
|
||||||
CXSourceRange RefNameRange;
|
CXSourceRange RefNameRange;
|
||||||
|
int AlwaysUnavailable;
|
||||||
|
int AlwaysDeprecated;
|
||||||
|
CXString UnavailableMessage;
|
||||||
|
CXString DeprecatedMessage;
|
||||||
|
CXPlatformAvailability PlatformAvailability[2];
|
||||||
|
int NumPlatformAvailability;
|
||||||
|
int I;
|
||||||
|
|
||||||
ks = clang_getCursorKindSpelling(Cursor.kind);
|
ks = clang_getCursorKindSpelling(Cursor.kind);
|
||||||
string = want_display_name? clang_getCursorDisplayName(Cursor)
|
string = want_display_name? clang_getCursorDisplayName(Cursor)
|
||||||
: clang_getCursorSpelling(Cursor);
|
: clang_getCursorSpelling(Cursor);
|
||||||
|
@ -249,6 +270,47 @@ static void PrintCursor(CXCursor Cursor) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NumPlatformAvailability
|
||||||
|
= clang_getCursorPlatformAvailability(Cursor,
|
||||||
|
&AlwaysDeprecated,
|
||||||
|
&DeprecatedMessage,
|
||||||
|
&AlwaysUnavailable,
|
||||||
|
&UnavailableMessage,
|
||||||
|
PlatformAvailability, 2);
|
||||||
|
if (AlwaysUnavailable) {
|
||||||
|
printf(" (always unavailable: \"%s\")",
|
||||||
|
clang_getCString(UnavailableMessage));
|
||||||
|
} else if (AlwaysDeprecated) {
|
||||||
|
printf(" (always deprecated: \"%s\")",
|
||||||
|
clang_getCString(DeprecatedMessage));
|
||||||
|
} else {
|
||||||
|
for (I = 0; I != NumPlatformAvailability; ++I) {
|
||||||
|
if (I >= 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf(" (%s", clang_getCString(PlatformAvailability[I].Platform));
|
||||||
|
if (PlatformAvailability[I].Unavailable)
|
||||||
|
printf(", unavailable");
|
||||||
|
else {
|
||||||
|
printVersion(", introduced=", PlatformAvailability[I].Introduced);
|
||||||
|
printVersion(", deprecated=", PlatformAvailability[I].Deprecated);
|
||||||
|
printVersion(", obsoleted=", PlatformAvailability[I].Obsoleted);
|
||||||
|
}
|
||||||
|
if (clang_getCString(PlatformAvailability[I].Message)[0])
|
||||||
|
printf(", message=\"%s\"",
|
||||||
|
clang_getCString(PlatformAvailability[I].Message));
|
||||||
|
printf(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (I = 0; I != NumPlatformAvailability; ++I) {
|
||||||
|
if (I >= 2)
|
||||||
|
break;
|
||||||
|
clang_disposeCXPlatformAvailability(PlatformAvailability + I);
|
||||||
|
}
|
||||||
|
|
||||||
|
clang_disposeString(DeprecatedMessage);
|
||||||
|
clang_disposeString(UnavailableMessage);
|
||||||
|
|
||||||
if (clang_CXXMethod_isStatic(Cursor))
|
if (clang_CXXMethod_isStatic(Cursor))
|
||||||
printf(" (static)");
|
printf(" (static)");
|
||||||
if (clang_CXXMethod_isVirtual(Cursor))
|
if (clang_CXXMethod_isVirtual(Cursor))
|
||||||
|
|
|
@ -5489,6 +5489,90 @@ enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
|
||||||
return CXAvailability_Available;
|
return CXAvailability_Available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CXVersion convertVersion(VersionTuple In) {
|
||||||
|
CXVersion Out = { -1, -1, -1 };
|
||||||
|
if (In.empty())
|
||||||
|
return Out;
|
||||||
|
|
||||||
|
Out.Major = In.getMajor();
|
||||||
|
|
||||||
|
if (llvm::Optional<unsigned> Minor = In.getMinor())
|
||||||
|
Out.Minor = *Minor;
|
||||||
|
else
|
||||||
|
return Out;
|
||||||
|
|
||||||
|
if (llvm::Optional<unsigned> Subminor = In.getSubminor())
|
||||||
|
Out.Subminor = *Subminor;
|
||||||
|
|
||||||
|
return Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clang_getCursorPlatformAvailability(CXCursor cursor,
|
||||||
|
int *always_deprecated,
|
||||||
|
CXString *deprecated_message,
|
||||||
|
int *always_unavailable,
|
||||||
|
CXString *unavailable_message,
|
||||||
|
CXPlatformAvailability *availability,
|
||||||
|
int availability_size) {
|
||||||
|
if (always_deprecated)
|
||||||
|
*always_deprecated = 0;
|
||||||
|
if (deprecated_message)
|
||||||
|
*deprecated_message = cxstring::createCXString("", /*DupString=*/false);
|
||||||
|
if (always_unavailable)
|
||||||
|
*always_unavailable = 0;
|
||||||
|
if (unavailable_message)
|
||||||
|
*unavailable_message = cxstring::createCXString("", /*DupString=*/false);
|
||||||
|
|
||||||
|
if (!clang_isDeclaration(cursor.kind))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Decl *D = cxcursor::getCursorDecl(cursor);
|
||||||
|
if (!D)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int N = 0;
|
||||||
|
for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;
|
||||||
|
++A) {
|
||||||
|
if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
|
||||||
|
if (always_deprecated)
|
||||||
|
*always_deprecated = 1;
|
||||||
|
if (deprecated_message)
|
||||||
|
*deprecated_message = cxstring::createCXString(Deprecated->getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
|
||||||
|
if (always_unavailable)
|
||||||
|
*always_unavailable = 1;
|
||||||
|
if (unavailable_message) {
|
||||||
|
*unavailable_message
|
||||||
|
= cxstring::createCXString(Unavailable->getMessage());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
|
||||||
|
if (N < availability_size) {
|
||||||
|
availability[N].Platform
|
||||||
|
= cxstring::createCXString(Avail->getPlatform()->getName());
|
||||||
|
availability[N].Introduced = convertVersion(Avail->getIntroduced());
|
||||||
|
availability[N].Deprecated = convertVersion(Avail->getDeprecated());
|
||||||
|
availability[N].Obsoleted = convertVersion(Avail->getObsoleted());
|
||||||
|
availability[N].Unavailable = Avail->getUnavailable();
|
||||||
|
availability[N].Message = cxstring::createCXString(Avail->getMessage());
|
||||||
|
}
|
||||||
|
++N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
|
||||||
|
clang_disposeString(availability->Platform);
|
||||||
|
clang_disposeString(availability->Message);
|
||||||
|
}
|
||||||
|
|
||||||
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
|
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
|
||||||
if (clang_isDeclaration(cursor.kind))
|
if (clang_isDeclaration(cursor.kind))
|
||||||
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
|
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
|
||||||
|
|
|
@ -43,6 +43,7 @@ clang_disposeDiagnostic
|
||||||
clang_disposeDiagnosticSet
|
clang_disposeDiagnosticSet
|
||||||
clang_disposeIndex
|
clang_disposeIndex
|
||||||
clang_disposeOverriddenCursors
|
clang_disposeOverriddenCursors
|
||||||
|
clang_disposeCXPlatformAvailability
|
||||||
clang_disposeString
|
clang_disposeString
|
||||||
clang_disposeTokens
|
clang_disposeTokens
|
||||||
clang_disposeTranslationUnit
|
clang_disposeTranslationUnit
|
||||||
|
@ -85,6 +86,7 @@ clang_getCursorLanguage
|
||||||
clang_getCursorLexicalParent
|
clang_getCursorLexicalParent
|
||||||
clang_getCursorLinkage
|
clang_getCursorLinkage
|
||||||
clang_getCursorLocation
|
clang_getCursorLocation
|
||||||
|
clang_getCursorPlatformAvailability
|
||||||
clang_getCursorReferenceNameRange
|
clang_getCursorReferenceNameRange
|
||||||
clang_getCursorReferenced
|
clang_getCursorReferenced
|
||||||
clang_getCursorResultType
|
clang_getCursorResultType
|
||||||
|
|
Loading…
Reference in New Issue