[libclang] Add support for querying cursor availability

Summary:
This patch allows checking the availability of cursors through libclang and clang.cindex (Python).
This e.g. allows to check whether a C++ member function has been marked as deleted.

Reviewers: arphaman, jbcoe

Reviewed By: jbcoe

Subscribers: cfe-commits

Tags: #clang

Patch by jklaehn (Johann Klähn)

Differential Revision: https://reviews.llvm.org/D36973

llvm-svn: 315959
This commit is contained in:
Jonathan Coe 2017-10-16 23:46:02 +00:00
parent 578ac7a2ec
commit 1fada3b90a
2 changed files with 58 additions and 0 deletions

View File

@ -1586,6 +1586,16 @@ class Cursor(Structure):
return StorageClass.from_id(self._storage_class)
@property
def availability(self):
"""
Retrieves the availability of the entity pointed at by the cursor.
"""
if not hasattr(self, '_availability'):
self._availability = conf.lib.clang_getCursorAvailability(self)
return AvailabilityKind.from_id(self._availability)
@property
def access_specifier(self):
"""
@ -1923,6 +1933,24 @@ StorageClass.OPENCLWORKGROUPLOCAL = StorageClass(5)
StorageClass.AUTO = StorageClass(6)
StorageClass.REGISTER = StorageClass(7)
### Availability Kinds ###
class AvailabilityKind(BaseEnumeration):
"""
Describes the availability of an entity.
"""
# The unique kind objects, indexed by id.
_kinds = []
_name_map = None
def __repr__(self):
return 'AvailabilityKind.%s' % (self.name,)
AvailabilityKind.AVAILABLE = AvailabilityKind(0)
AvailabilityKind.DEPRECATED = AvailabilityKind(1)
AvailabilityKind.NOT_AVAILABLE = AvailabilityKind(2)
AvailabilityKind.NOT_ACCESSIBLE = AvailabilityKind(3)
### C++ access specifiers ###
@ -3491,6 +3519,10 @@ functionList = [
[TranslationUnit, SourceLocation],
Cursor),
("clang_getCursorAvailability",
[Cursor],
c_int),
("clang_getCursorDefinition",
[Cursor],
Cursor,
@ -4106,6 +4138,7 @@ conf = Config()
register_enumerations()
__all__ = [
'AvailabilityKind',
'Config',
'CodeCompletionResults',
'CompilationDatabase',

View File

@ -1,6 +1,7 @@
import ctypes
import gc
from clang.cindex import AvailabilityKind
from clang.cindex import CursorKind
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
@ -405,6 +406,30 @@ def test_result_type():
t = foo.result_type
assert t.kind == TypeKind.INT
def test_availability():
tu = get_tu('class A { A(A const&) = delete; };', lang='cpp')
# AvailabilityKind.AVAILABLE
cursor = get_cursor(tu, 'A')
assert cursor.kind == CursorKind.CLASS_DECL
assert cursor.availability == AvailabilityKind.AVAILABLE
# AvailabilityKind.NOT_AVAILABLE
cursors = get_cursors(tu, 'A')
for c in cursors:
if c.kind == CursorKind.CONSTRUCTOR:
assert c.availability == AvailabilityKind.NOT_AVAILABLE
break
else:
assert False, "Could not find cursor for deleted constructor"
# AvailabilityKind.DEPRECATED
tu = get_tu('void test() __attribute__((deprecated));', lang='cpp')
cursor = get_cursor(tu, 'test')
assert cursor.availability == AvailabilityKind.DEPRECATED
# AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results
def test_get_tokens():
"""Ensure we can map cursors back to tokens."""
tu = get_tu('int foo(int i);')