Improve the Python bindings for libclang in a few ways, from Eli

Bendersky. Specifically: 

* Implemented a new function in libclang: clang_isAttribute

* Fixing TranslationUnit.get_includes to only go through the argument
* buffer when it contains something. This fixed a crash on Windows 

* clang_getFileName returns CXString, not char*. Made appropriate
* fixes in cindex.py - now the relevant tests pass and we can see the
* full locations correctly again (previously there was garbage in
* place of the file name) 
* Exposed clang_getCursorDisplayName to the python bindings

llvm-svn: 134460
This commit is contained in:
Douglas Gregor 2011-07-06 03:00:34 +00:00
parent 75bc773be5
commit a98034a25e
7 changed files with 44 additions and 12 deletions

View File

@ -321,6 +321,10 @@ class CursorKind(object):
"""Test if this is a statement kind."""
return CursorKind_is_stmt(self)
def is_attribute(self):
"""Test if this is an attribute kind."""
return CursorKind_is_attribute(self)
def is_invalid(self):
"""Test if this is an invalid kind."""
return CursorKind_is_inv(self)
@ -978,8 +982,9 @@ class TranslationUnit(ClangObject):
headers.
"""
def visitor(fobj, lptr, depth, includes):
loc = lptr.contents
includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
if depth > 0:
loc = lptr.contents
includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
# Automatically adapt CIndex/ctype pointers to python objects
includes = []
@ -1074,7 +1079,7 @@ class File(ClangObject):
@property
def name(self):
"""Return the complete file and path name of the file."""
return File_name(self)
return _CXString_getCString(File_name(self))
@property
def time(self):
@ -1147,6 +1152,10 @@ CursorKind_is_stmt = lib.clang_isStatement
CursorKind_is_stmt.argtypes = [CursorKind]
CursorKind_is_stmt.restype = bool
CursorKind_is_attribute = lib.clang_isAttribute
CursorKind_is_attribute.argtypes = [CursorKind]
CursorKind_is_attribute.restype = bool
CursorKind_is_inv = lib.clang_isInvalid
CursorKind_is_inv.argtypes = [CursorKind]
CursorKind_is_inv.restype = bool
@ -1183,6 +1192,11 @@ Cursor_spelling.argtypes = [Cursor]
Cursor_spelling.restype = _CXString
Cursor_spelling.errcheck = _CXString.from_result
Cursor_displayname = lib.clang_getCursorDisplayName
Cursor_displayname.argtypes = [Cursor]
Cursor_displayname.restype = _CXString
Cursor_displayname.errcheck = _CXString.from_result
Cursor_loc = lib.clang_getCursorLocation
Cursor_loc.argtypes = [Cursor]
Cursor_loc.restype = SourceLocation
@ -1253,7 +1267,7 @@ TranslationUnit_includes.argtypes = [TranslationUnit,
# File Functions
File_name = lib.clang_getFileName
File_name.argtypes = [File]
File_name.restype = c_char_p
File_name.restype = _CXString
File_time = lib.clang_getFileTime
File_time.argtypes = [File]

View File

@ -18,10 +18,14 @@ def test_kind_groups():
for k in CursorKind.get_all_kinds():
group = [n for n in ('is_declaration', 'is_reference', 'is_expression',
'is_statement', 'is_invalid')
'is_statement', 'is_invalid', 'is_attribute')
if getattr(k, n)()]
if k == CursorKind.TRANSLATION_UNIT:
if k in ( CursorKind.TRANSLATION_UNIT,
CursorKind.MACRO_DEFINITION,
CursorKind.MACRO_INSTANTIATION,
CursorKind.INCLUSION_DIRECTIVE,
CursorKind.PREPROCESSING_DIRECTIVE):
assert len(group) == 0
else:
assert len(group) == 1

View File

@ -58,24 +58,27 @@ def test_unsaved_files_2():
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'
def normpaths_equal(path1, path2):
""" Compares two paths for equality after normalizing them with
os.path.normpath
"""
return os.path.normpath(path1) == os.path.normpath(path2)
def test_includes():
def eq(expected, actual):
if not actual.is_input_file:
return expected[0] == actual.source.name and \
expected[1] == actual.include.name
return normpaths_equal(expected[0], actual.source.name) and \
normpaths_equal(expected[1], actual.include.name)
else:
return expected[1] == actual.include.name
return normpaths_equal(expected[1], actual.include.name)
src = os.path.join(kInputsDir, 'include.cpp')
h1 = os.path.join(kInputsDir, "header1.h")
h2 = os.path.join(kInputsDir, "header2.h")
h3 = os.path.join(kInputsDir, "header3.h")
inc = [(None, src), (src, h1), (h1, h3), (src, h2), (h2, h3)]
inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)]
index = Index.create()
tu = index.parse(src)
for i in zip(inc, tu.get_includes()):
assert eq(i[0], i[1])

View File

@ -1473,6 +1473,11 @@ CINDEX_LINKAGE unsigned clang_isExpression(enum CXCursorKind);
*/
CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind);
/**
* \brief Determine whether the given cursor kind represents an attribute.
*/
CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind);
/**
* \brief Determine whether the given cursor kind represents an invalid
* cursor.

View File

@ -3562,6 +3562,10 @@ unsigned clang_isStatement(enum CXCursorKind K) {
return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
}
unsigned clang_isAttribute(enum CXCursorKind K) {
return K >= CXCursor_FirstAttr && K <= CXCursor_LastAttr;
}
unsigned clang_isTranslationUnit(enum CXCursorKind K) {
return K == CXCursor_TranslationUnit;
}

View File

@ -112,6 +112,7 @@ _clang_getTranslationUnitSpelling
_clang_getTypeDeclaration
_clang_getTypeKindSpelling
_clang_hashCursor
_clang_isAttribute
_clang_isConstQualifiedType
_clang_isCursorDefinition
_clang_isDeclaration

View File

@ -112,6 +112,7 @@ clang_getTranslationUnitSpelling
clang_getTypeDeclaration
clang_getTypeKindSpelling
clang_hashCursor
clang_isAttribute
clang_isConstQualifiedType
clang_isCursorDefinition
clang_isDeclaration