from clang.cindex import *
from .traversal import *
import re
__all__ = [
'Matcher', 'TrueMatcher', 'PredMatcher', 'UnlessMatcher', 'AllOfMatcher',
'AllOfTypeMatcher', 'AnyOfMatcher', 'ChildAnyOfMatcher', 'AnyBaseClassMatcher',
'NameMatcher', 'TypenameMatcher', 'TypeTraversalMatcher',
'ReturnTypeTraversalMatcher', 'AnyParameterMatcher', 'AncestorMatcher',
'LocationMatcher', 'ParentMatcher', 'ParameterMatcher',
'ParameterCountMatcher', 'CanonicalTypeTraversalMatcher',
'PointeeTypeTraversalMatcher',
]
[docs]class Matcher(object):
"""Base class for matchers
"""
def __init__(self):
pass
def __call__(self, cursor):
raise NotImplemented
[docs]class TrueMatcher(Matcher):
"""Matcher that always returns true
"""
def __init__(self):
super(TrueMatcher, self).__init__()
def __call__(self, cursor):
return True
[docs]class PredMatcher(Matcher):
def __init__(self, pred):
super(PredMatcher, self).__init__()
self.pred = pred
def __call__(self, cursor):
return self.pred(cursor)
[docs]class UnlessMatcher(Matcher):
"""Inverts the match of the children
"""
def __init__(self, innerMatcher):
super(UnlessMatcher, self).__init__()
self.innerMatcher = innerMatcher
def __call__(self, cursor):
return not self.innerMatcher(cursor)
[docs]class AllOfMatcher(Matcher):
"""Matches if all inner matchers match
"""
def __init__(self, *innerMatchers):
super(AllOfMatcher, self).__init__()
self.innerMatchers = list(innerMatchers)
[docs] def matchNode(self, cursor):
ms = (m(cursor) for m in self.innerMatchers)
return all(ms)
def __call__(self, cursor):
return self.matchNode(cursor)
[docs]class AnyOfMatcher(Matcher):
"""Matches if any of the inner matchers match
"""
def __init__(self, *args):
super(AnyOfMatcher, self).__init__()
self.matchers = list(args)
[docs] def matchNode(self, cursor):
ms = (m(cursor) for m in self.matchers)
return any(ms)
def __call__(self, cursor):
return self.matchNode(cursor)
[docs]class ChildAnyOfMatcher(AnyOfMatcher):
def __init__(self, *args):
super(ChildAnyOfMatcher, self).__init__(*args)
[docs] def children(self, cursor):
return cursor.get_children()
def __call__(self, cursor):
for c in self.children(cursor):
if self.matchNode(c):
return True
return False
[docs]class AnyBaseClassMatcher(AnyOfMatcher):
def __init__(self, *args):
super(AnyBaseClassMatcher, self).__init__(*args)
[docs] def traverse(self, cursor):
for c in iter_base_classes(cursor):
yield c
def __call__(self, cursor):
for c in self.traverse(cursor):
if self.matchNode(c):
return True
return False
[docs]class NameMatcher(Matcher):
def __init__(self, pattern):
super(NameMatcher, self).__init__()
self.pattern = pattern
[docs] def name(self, cursor):
return cursor.spelling or ''
def __call__(self, cursor):
name = self.name(cursor)
return re.match(self.pattern + '$', name) is not None
[docs]class TypenameMatcher(NameMatcher):
def __init__(self, pattern):
super(TypenameMatcher, self).__init__(pattern)
[docs] def name(self, cursor):
if cursor is None or cursor.type is None:
return ''
return cursor.type.spelling or ''
[docs]class AllOfTypeMatcher(AllOfMatcher):
def __init__(self, *args):
super(AllOfTypeMatcher, self).__init__(*args)
class TraversalMatcher(Matcher):
def __init__(self, innerMatcher):
super(TraversalMatcher, self).__init__()
self.innerMatcher = innerMatcher
def traverse(self, cursor):
return cursor.type
def matchNode(self, n):
if n is None:
return False
return self.innerMatcher(n)
def __call__(self, cursor):
c = self.traverse(cursor)
return self.matchNode(c)
[docs]class TypeTraversalMatcher(TraversalMatcher):
def __init__(self, innerMatcher):
super(TypeTraversalMatcher, self).__init__(innerMatcher)
[docs] def traverse(self, cursor):
assert(type(cursor) == Cursor), str(type(cursor))
return cursor.type
[docs]class PointeeTypeTraversalMatcher(TraversalMatcher):
def __init__(self, innerMatcher):
super(PointeeTypeTraversalMatcher, self).__init__(innerMatcher)
[docs] def traverse(self, t):
return t.get_pointee()
[docs]class ReturnTypeTraversalMatcher(TypeTraversalMatcher):
def __init__(self, matcher):
super(ReturnTypeTraversalMatcher, self).__init__(matcher)
[docs] def traverse(self, cursor):
return cursor.result_type
[docs]class AnyParameterMatcher(Matcher):
def __init__(self, innerMatcher):
super(AnyParameterMatcher, self).__init__()
self.innerMatcher = innerMatcher
[docs] def traverse(self, cursor):
return cursor.get_arguments()
[docs] def matchNode(self, cursor):
return self.innerMatcher(cursor)
def __call__(self, cursor):
for a in self.traverse(cursor):
if self.matchNode(a):
return True
return False
[docs]class AncestorMatcher(Matcher):
def __init__(self, innerMatcher):
super(AncestorMatcher, self).__init__()
self.innerMatcher = innerMatcher
[docs] def traverse(self, cursor):
c = cursor.semantic_parent
while c is not None:
yield c
c = c.semantic_parent
[docs] def matchNode(self, cursor):
return self.innerMatcher(cursor)
def __call__(self, cursor):
for a in self.traverse(cursor):
if self.matchNode(a):
return True
return False
[docs]class ParentMatcher(Matcher):
def __init__(self, innerMatcher):
super(ParentMatcher, self).__init__()
self.innerMatcher = innerMatcher
[docs] def traverse(self, cursor):
return cursor.semantic_parent
[docs] def matchNode(self, cursor):
if cursor is None:
return False
return self.innerMatcher(cursor)
def __call__(self, cursor):
c = self.traverse(cursor)
return self.matchNode(c)
[docs]class LocationMatcher(Matcher):
def __init__(self, pattern):
super(LocationMatcher, self).__init__()
self.pattern = pattern
def __call__(self, cursor):
try:
fname = cursor.location.file.name
return re.match(self.pattern, fname)
except:
return False
[docs]class ParameterCountMatcher(Matcher):
def __init__(self, N):
super(ParameterCountMatcher, self).__init__()
self.N = N
def __call__(self, cursor):
return self.N == len(list(cursor.get_arguments()))
[docs]class CanonicalTypeTraversalMatcher(TypeTraversalMatcher):
def __init__(self, matcher):
super(CanonicalTypeTraversalMatcher, self).__init__(matcher)
[docs] def traverse(self, t):
return t.get_canonical()
[docs]class ParameterMatcher(Matcher):
def __init__(self, N, innerMatcher):
super(ParameterMatcher, self).__init__()
self.innerMatcher = innerMatcher
self.N = N
[docs] def matchNode(self, cursor):
return self.innerMatcher(cursor)
def __call__(self, cursor):
args = list(cursor.get_arguments())
return (len(args) > self.N) and self.matchNode(args[self.N])