diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
commit | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch) | |
tree | 47df2c12b57214af6c31e47404b005675b8b7ffc /bindings | |
parent | f73d5f23a889b93d89ddef61ac0995df40286bb8 (diff) | |
download | src-test2-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz src-test2-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip |
Notes
Diffstat (limited to 'bindings')
-rw-r--r-- | bindings/python/clang/cindex.py | 123 | ||||
-rw-r--r-- | bindings/python/examples/cindex/cindex-dump.py | 4 | ||||
-rw-r--r-- | bindings/python/tests/cindex/test_access_specifiers.py | 34 | ||||
-rw-r--r-- | bindings/python/tests/cindex/test_cdb.py | 21 | ||||
-rw-r--r-- | bindings/python/tests/cindex/test_cursor.py | 9 | ||||
-rw-r--r-- | bindings/python/tests/cindex/test_translation_unit.py | 11 | ||||
-rw-r--r-- | bindings/python/tests/cindex/util.py | 40 | ||||
-rw-r--r-- | bindings/xml/comment-xml-schema.rng | 8 |
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> |