From e38adb6a0ade0c79336acab5c94b2fe616ae0f58 Mon Sep 17 00:00:00 2001 From: Jonathan Coe Date: Mon, 16 Oct 2017 23:46:02 +0000 Subject: [PATCH] [libclang] Add support for querying cursor availability MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315959 91177308-0d34-0410-b5e6-96231b3b80d8 --- bindings/python/clang/cindex.py | 33 +++++++++++++++++++++ bindings/python/tests/cindex/test_cursor.py | 25 ++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index c236a47651..1dc1760e4f 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -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', diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py index 4dd42fc84b..8ff0695154 100644 --- a/bindings/python/tests/cindex/test_cursor.py +++ b/bindings/python/tests/cindex/test_cursor.py @@ -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);') -- 2.40.0