summaryrefslogtreecommitdiff
path: root/bindings
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
committerDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
commit9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch)
tree47df2c12b57214af6c31e47404b005675b8b7ffc /bindings
parentf73d5f23a889b93d89ddef61ac0995df40286bb8 (diff)
downloadsrc-test2-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz
src-test2-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip
Notes
Diffstat (limited to 'bindings')
-rw-r--r--bindings/python/clang/cindex.py123
-rw-r--r--bindings/python/examples/cindex/cindex-dump.py4
-rw-r--r--bindings/python/tests/cindex/test_access_specifiers.py34
-rw-r--r--bindings/python/tests/cindex/test_cdb.py21
-rw-r--r--bindings/python/tests/cindex/test_cursor.py9
-rw-r--r--bindings/python/tests/cindex/test_translation_unit.py11
-rw-r--r--bindings/python/tests/cindex/util.py40
-rw-r--r--bindings/xml/comment-xml-schema.rng8
8 files changed, 183 insertions, 67 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index c103c7078003..517b3c1bac6e 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -272,7 +272,7 @@ class SourceRange(Structure):
return False
if other.file is None and self.start.file is None:
pass
- elif ( self.start.file.name != other.file.name or
+ elif ( self.start.file.name != other.file.name or
other.file.name != self.end.file.name):
# same file name
return False
@@ -361,13 +361,13 @@ class Diagnostic(object):
@property
def category_number(self):
- """The category number for this diagnostic."""
+ """The category number for this diagnostic or 0 if unavailable."""
return conf.lib.clang_getDiagnosticCategory(self)
@property
def category_name(self):
"""The string name of the category for this diagnostic."""
- return conf.lib.clang_getDiagnosticCategoryName(self.category_number)
+ return conf.lib.clang_getDiagnosticCategoryText(self)
@property
def option(self):
@@ -748,7 +748,7 @@ CursorKind.LABEL_REF = CursorKind(48)
# that has not yet been resolved to a specific function or function template.
CursorKind.OVERLOADED_DECL_REF = CursorKind(49)
-# A reference to a variable that occurs in some non-expression
+# A reference to a variable that occurs in some non-expression
# context, e.g., a C++ lambda capture list.
CursorKind.VARIABLE_REF = CursorKind(50)
@@ -937,7 +937,7 @@ CursorKind.SIZE_OF_PACK_EXPR = CursorKind(143)
# Represents a C++ lambda expression that produces a local function
# object.
-#
+#
# \code
# void abssort(float *x, unsigned N) {
# std::sort(x, x + N,
@@ -947,7 +947,7 @@ CursorKind.SIZE_OF_PACK_EXPR = CursorKind(143)
# }
# \endcode
CursorKind.LAMBDA_EXPR = CursorKind(144)
-
+
# Objective-c Boolean Literal.
CursorKind.OBJ_BOOL_LITERAL_EXPR = CursorKind(145)
@@ -1079,6 +1079,13 @@ CursorKind.CXX_OVERRIDE_ATTR = CursorKind(405)
CursorKind.ANNOTATE_ATTR = CursorKind(406)
CursorKind.ASM_LABEL_ATTR = CursorKind(407)
CursorKind.PACKED_ATTR = CursorKind(408)
+CursorKind.PURE_ATTR = CursorKind(409)
+CursorKind.CONST_ATTR = CursorKind(410)
+CursorKind.NODUPLICATE_ATTR = CursorKind(411)
+CursorKind.CUDACONSTANT_ATTR = CursorKind(412)
+CursorKind.CUDADEVICE_ATTR = CursorKind(413)
+CursorKind.CUDAGLOBAL_ATTR = CursorKind(414)
+CursorKind.CUDAHOST_ATTR = CursorKind(415)
###
# Preprocessing
@@ -1159,10 +1166,6 @@ class Cursor(Structure):
@property
def spelling(self):
"""Return the spelling of the entity pointed at by the cursor."""
- if not self.kind.is_declaration():
- # FIXME: clang_getCursorSpelling should be fixed to not assert on
- # this, for consistency with clang_getCursorUSR.
- return None
if not hasattr(self, '_spelling'):
self._spelling = conf.lib.clang_getCursorSpelling(self)
@@ -1205,6 +1208,17 @@ class Cursor(Structure):
return self._extent
@property
+ def access_specifier(self):
+ """
+ Retrieves the access specifier (if any) of the entity pointed at by the
+ cursor.
+ """
+ if not hasattr(self, '_access_specifier'):
+ self._access_specifier = conf.lib.clang_getCXXAccessSpecifier(self)
+
+ return AccessSpecifier.from_id(self._access_specifier)
+
+ @property
def type(self):
"""
Retrieve the Type (if any) of the entity pointed at by the cursor.
@@ -1331,7 +1345,7 @@ class Cursor(Structure):
@property
def referenced(self):
"""
- For a cursor that is a reference, returns a cursor
+ For a cursor that is a reference, returns a cursor
representing the entity that it references.
"""
if not hasattr(self, '_referenced'):
@@ -1343,7 +1357,7 @@ class Cursor(Structure):
def brief_comment(self):
"""Returns the brief comment text associated with that Cursor"""
return conf.lib.clang_Cursor_getBriefCommentText(self)
-
+
@property
def raw_comment(self):
"""Returns the raw comment text associated with that Cursor"""
@@ -1373,6 +1387,16 @@ class Cursor(Structure):
children)
return iter(children)
+ def walk_preorder(self):
+ """Depth-first preorder walk over the cursor and its descendants.
+
+ Yields cursors.
+ """
+ yield self
+ for child in self.get_children():
+ for descendant in child.walk_preorder():
+ yield descendant
+
def get_tokens(self):
"""Obtain Token instances formulating that compose this Cursor.
@@ -1426,6 +1450,54 @@ class Cursor(Structure):
res._tu = args[0]._tu
return res
+### C++ access specifiers ###
+
+class AccessSpecifier(object):
+ """
+ Describes the access of a C++ class member
+ """
+
+ # The unique kind objects, index by id.
+ _kinds = []
+ _name_map = None
+
+ def __init__(self, value):
+ if value >= len(AccessSpecifier._kinds):
+ AccessSpecifier._kinds += [None] * (value - len(AccessSpecifier._kinds) + 1)
+ if AccessSpecifier._kinds[value] is not None:
+ raise ValueError,'AccessSpecifier already loaded'
+ self.value = value
+ AccessSpecifier._kinds[value] = self
+ AccessSpecifier._name_map = None
+
+ def from_param(self):
+ return self.value
+
+ @property
+ def name(self):
+ """Get the enumeration name of this access specifier."""
+ if self._name_map is None:
+ self._name_map = {}
+ for key,value in AccessSpecifier.__dict__.items():
+ if isinstance(value,AccessSpecifier):
+ self._name_map[value] = key
+ return self._name_map[self]
+
+ @staticmethod
+ def from_id(id):
+ if id >= len(AccessSpecifier._kinds) or not AccessSpecifier._kinds[id]:
+ raise ValueError,'Unknown access specifier %d' % id
+ return AccessSpecifier._kinds[id]
+
+ def __repr__(self):
+ return 'AccessSpecifier.%s' % (self.name,)
+
+AccessSpecifier.INVALID = AccessSpecifier(0)
+AccessSpecifier.PUBLIC = AccessSpecifier(1)
+AccessSpecifier.PROTECTED = AccessSpecifier(2)
+AccessSpecifier.PRIVATE = AccessSpecifier(3)
+AccessSpecifier.NONE = AccessSpecifier(4)
+
### Type Kinds ###
class TypeKind(object):
@@ -1820,7 +1892,7 @@ SpellingCache = {
# 5 : CompletionChunk.Kind("CurrentParameter"),
6: '(', # CompletionChunk.Kind("LeftParen"),
7: ')', # CompletionChunk.Kind("RightParen"),
- 8: ']', # CompletionChunk.Kind("LeftBracket"),
+ 8: '[', # CompletionChunk.Kind("LeftBracket"),
9: ']', # CompletionChunk.Kind("RightBracket"),
10: '{', # CompletionChunk.Kind("LeftBrace"),
11: '}', # CompletionChunk.Kind("RightBrace"),
@@ -1934,7 +2006,7 @@ class CompletionString(ClangObject):
return "<Availability: %s>" % self
def __len__(self):
- self.num_chunks
+ return self.num_chunks
@CachedProperty
def num_chunks(self):
@@ -2501,7 +2573,7 @@ class CompilationDatabaseError(Exception):
constants in this class.
"""
- # An unknown error occured
+ # An unknown error occurred
ERROR_UNKNOWN = 0
# The database could not be loaded
@@ -2607,6 +2679,14 @@ class CompilationDatabase(ClangObject):
return conf.lib.clang_CompilationDatabase_getCompileCommands(self,
filename)
+ def getAllCompileCommands(self):
+ """
+ Get an iterable object providing all the CompileCommands available from
+ the database.
+ """
+ return conf.lib.clang_CompilationDatabase_getAllCompileCommands(self)
+
+
class Token(Structure):
"""Represents a single token from the preprocessor.
@@ -2673,6 +2753,11 @@ functionList = [
c_object_p,
CompilationDatabase.from_result),
+ ("clang_CompilationDatabase_getAllCompileCommands",
+ [c_object_p],
+ c_object_p,
+ CompileCommands.from_result),
+
("clang_CompilationDatabase_getCompileCommands",
[c_object_p, c_char_p],
c_object_p,
@@ -2909,8 +2994,8 @@ functionList = [
[Diagnostic],
c_uint),
- ("clang_getDiagnosticCategoryName",
- [c_uint],
+ ("clang_getDiagnosticCategoryText",
+ [Diagnostic],
_CXString,
_CXString.from_result),
@@ -3329,8 +3414,8 @@ class Config:
python bindings can disable the compatibility check. This will cause
the python bindings to load, even though they are written for a newer
version of libclang. Failures now arise if unsupported or incompatible
- features are accessed. The user is required to test himself if the
- features he is using are available and compatible between different
+ features are accessed. The user is required to test themselves if the
+ features they are using are available and compatible between different
libclang versions.
"""
if Config.loaded:
diff --git a/bindings/python/examples/cindex/cindex-dump.py b/bindings/python/examples/cindex/cindex-dump.py
index af7ddab6ea53..5556ad121a3e 100644
--- a/bindings/python/examples/cindex/cindex-dump.py
+++ b/bindings/python/examples/cindex/cindex-dump.py
@@ -63,8 +63,8 @@ def main():
parser = OptionParser("usage: %prog [options] {filename} [clang-args*]")
parser.add_option("", "--show-ids", dest="showIDs",
- help="Don't compute cursor IDs (very slow)",
- default=False)
+ help="Compute cursor IDs (very slow)",
+ action="store_true", default=False)
parser.add_option("", "--max-depth", dest="maxDepth",
help="Limit cursor expansion to depth N",
metavar="N", type=int, default=None)
diff --git a/bindings/python/tests/cindex/test_access_specifiers.py b/bindings/python/tests/cindex/test_access_specifiers.py
new file mode 100644
index 000000000000..cfa04dc86574
--- /dev/null
+++ b/bindings/python/tests/cindex/test_access_specifiers.py
@@ -0,0 +1,34 @@
+
+from clang.cindex import AccessSpecifier
+from clang.cindex import Cursor
+from clang.cindex import TranslationUnit
+
+from .util import get_cursor
+from .util import get_tu
+
+def test_access_specifiers():
+ """Ensure that C++ access specifiers are available on cursors"""
+
+ tu = get_tu("""
+class test_class {
+public:
+ void public_member_function();
+protected:
+ void protected_member_function();
+private:
+ void private_member_function();
+};
+""", lang = 'cpp')
+
+ test_class = get_cursor(tu, "test_class")
+ assert test_class.access_specifier == AccessSpecifier.INVALID;
+
+ public = get_cursor(tu.cursor, "public_member_function")
+ assert public.access_specifier == AccessSpecifier.PUBLIC
+
+ protected = get_cursor(tu.cursor, "protected_member_function")
+ assert protected.access_specifier == AccessSpecifier.PROTECTED
+
+ private = get_cursor(tu.cursor, "private_member_function")
+ assert private.access_specifier == AccessSpecifier.PRIVATE
+
diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py
index d0f580ea9f47..e1f824f797f2 100644
--- a/bindings/python/tests/cindex/test_cdb.py
+++ b/bindings/python/tests/cindex/test_cdb.py
@@ -32,6 +32,27 @@ def test_lookup_succeed():
cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp')
assert len(cmds) != 0
+def test_all_compilecommand():
+ """Check we get all results from the db"""
+ cdb = CompilationDatabase.fromDirectory(kInputsDir)
+ cmds = cdb.getAllCompileCommands()
+ assert len(cmds) == 3
+ expected = [
+ { 'wd': '/home/john.doe/MyProjectA',
+ 'line': ['clang++', '-o', 'project2.o', '-c',
+ '/home/john.doe/MyProject/project2.cpp']},
+ { 'wd': '/home/john.doe/MyProjectB',
+ 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
+ '/home/john.doe/MyProject/project2.cpp']},
+ { 'wd': '/home/john.doe/MyProject',
+ 'line': ['clang++', '-o', 'project.o', '-c',
+ '/home/john.doe/MyProject/project.cpp']}
+ ]
+ for i in range(len(cmds)):
+ assert cmds[i].directory == expected[i]['wd']
+ for arg, exp in zip(cmds[i].arguments, expected[i]['line']):
+ assert arg == exp
+
def test_1_compilecommand():
"""Check file with single compile command"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index a27525cfe553..431504502245 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -8,9 +8,6 @@ from .util import get_cursors
from .util import get_tu
kInput = """\
-// FIXME: Find nicer way to drop builtins and other cruft.
-int start_decl;
-
struct s0 {
int a;
int b;
@@ -33,11 +30,7 @@ void f0(int a0, int a1) {
def test_get_children():
tu = get_tu(kInput)
- # Skip until past start_decl.
it = tu.cursor.get_children()
- while it.next().spelling != 'start_decl':
- pass
-
tu_nodes = list(it)
assert len(tu_nodes) == 3
@@ -49,7 +42,7 @@ def test_get_children():
assert tu_nodes[0].spelling == 's0'
assert tu_nodes[0].is_definition() == True
assert tu_nodes[0].location.file.name == 't.c'
- assert tu_nodes[0].location.line == 4
+ assert tu_nodes[0].location.line == 1
assert tu_nodes[0].location.column == 8
assert tu_nodes[0].hash > 0
assert tu_nodes[0].translation_unit is not None
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
index f77998e52457..be6cd671ae0c 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -1,5 +1,6 @@
import gc
import os
+import tempfile
from clang.cindex import CursorKind
from clang.cindex import Cursor
@@ -93,15 +94,7 @@ def save_tu(tu):
Returns the filename it was saved to.
"""
-
- # FIXME Generate a temp file path using system APIs.
- base = 'TEMP_FOR_TRANSLATIONUNIT_SAVE.c'
- path = os.path.join(kInputsDir, base)
-
- # Just in case.
- if os.path.exists(path):
- os.unlink(path)
-
+ _, path = tempfile.mkstemp()
tu.save(path)
return path
diff --git a/bindings/python/tests/cindex/util.py b/bindings/python/tests/cindex/util.py
index 8614b02ad258..c53ba7c81bde 100644
--- a/bindings/python/tests/cindex/util.py
+++ b/bindings/python/tests/cindex/util.py
@@ -39,52 +39,34 @@ def get_cursor(source, spelling):
If the cursor is not found, None is returned.
"""
- children = []
- if isinstance(source, Cursor):
- children = source.get_children()
- else:
- # Assume TU
- children = source.cursor.get_children()
-
- for cursor in children:
+ # Convenience for calling on a TU.
+ root_cursor = source if isinstance(source, Cursor) else source.cursor
+
+ for cursor in root_cursor.walk_preorder():
if cursor.spelling == spelling:
return cursor
- # Recurse into children.
- result = get_cursor(cursor, spelling)
- if result is not None:
- return result
-
return None
-
+
def get_cursors(source, spelling):
"""Obtain all cursors from a source object with a specific spelling.
- This provides a convenient search mechanism to find all cursors with specific
- spelling within a source. The first argument can be either a
+ This provides a convenient search mechanism to find all cursors with
+ specific spelling within a source. The first argument can be either a
TranslationUnit or Cursor instance.
If no cursors are found, an empty list is returned.
"""
+ # Convenience for calling on a TU.
+ root_cursor = source if isinstance(source, Cursor) else source.cursor
+
cursors = []
- children = []
- if isinstance(source, Cursor):
- children = source.get_children()
- else:
- # Assume TU
- children = source.cursor.get_children()
-
- for cursor in children:
+ for cursor in root_cursor.walk_preorder():
if cursor.spelling == spelling:
cursors.append(cursor)
- # Recurse into children.
- cursors.extend(get_cursors(cursor, spelling))
-
return cursors
-
-
__all__ = [
'get_cursor',
diff --git a/bindings/xml/comment-xml-schema.rng b/bindings/xml/comment-xml-schema.rng
index a8913a360b79..43f3e54c2863 100644
--- a/bindings/xml/comment-xml-schema.rng
+++ b/bindings/xml/comment-xml-schema.rng
@@ -580,6 +580,14 @@
</data>
</element>
<element name="rawHTML">
+ <optional>
+ <!-- If not specified, the default value is 'false'. -->
+ <!-- The value 'false' or absence of the attribute does not imply
+ that the HTML is actually well-formed. -->
+ <attribute name="isMalformed">
+ <data type="boolean" />
+ </attribute>
+ </optional>
<!-- Non-empty text content. -->
<data type="string">
<param name="pattern">.*\S.*</param>