from clang.cindex import CursorKind
from .predicates import *
from .internal import *
__all__ = [
'allOf', 'anyOf', 'hasType', 'anything', 'hasAnyParameter', 'builtinType',
'classTemplateDecl', 'cxxRecordDecl', 'cxxConstructorDecl',
'cxxDestructorDecl', 'cxxMethodDecl', 'decl', 'enumDecl', 'fieldDecl',
'functionDecl', 'has', 'hasName', 'hasReturnType', 'hasStaticStorageDuration',
'hasTypename', 'isDerivedFrom', 'isSameOrDerivedFrom', 'namespaceDecl',
'recordDecl', 'stmt', 'typedefDecl', 'unless', 'isDefinition', 'hasAncestor',
'isExpansionInFileMatching', 'varDecl', 'hasParent', 'parameterCountIs',
'hasCanonicalType', 'isStruct', 'isClass', 'isPublic', 'isProtected', 'isPrivate',
'pointerType', 'pointee', 'hasParameter'
]
[docs]def allOf(*args):
"""Matches if all of the argument matchers match
>>> from glud import *
>>> config = '''
... class X;
... class Y;
... '''
>>> m = allOf(cxxRecordDecl(), hasName('X'))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return AllOfMatcher(*args)
def makeKindMatcher(kinds, *args):
inner = [ PredMatcher(is_kind(k)) for k in kinds ]
inner += list(args)
return allOf(*inner)
[docs]def anyOf(*args):
"""Matches if any of the argument matchers match
>>> from glud import *
>>> config = '''
... int x;
... class Y {};
... enum Z {};
... '''
>>> m = anyOf(varDecl(), isClass())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
x
Y
"""
return AnyOfMatcher(*args)
[docs]def anything():
"""Matches anything
>>> from glud import *
>>> config = '''
... namespace W {
... int x;
... class Y;
... enum Z {};
... }
... '''
>>> m = allOf(anything(), hasParent(namespaceDecl()))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
x
Y
Z
"""
return TrueMatcher()
[docs]def builtinType(*args):
"""Matches builtin primitive types (eg/ integers, booleans and float)
>>> from glud import *
>>> config = '''
... int x;
... bool y;
... '''
>>> m = varDecl(hasType(builtinType()))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
x
y
"""
return AllOfTypeMatcher(is_builtin, *args)
[docs]def classTemplateDecl(*args):
"""Match C++ template class declarations
>>> from glud import *
>>> config = '''
... template<typename T> class X {};
... class Y {};
... '''
>>> m = classTemplateDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return makeKindMatcher([CursorKind.CLASS_TEMPLATE], *args)
[docs]def cxxConstructorDecl(*args):
"""Match C++ constructors
>>> from glud import *
>>> config = '''
... class X {
... X();
... };
... class Y {};
... '''
>>> m = cxxConstructorDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return makeKindMatcher([CursorKind.CONSTRUCTOR], *args)
[docs]def cxxDestructorDecl(*args):
"""Match C++ destructors
>>> from glud import *
>>> config = '''
... class X {
... ~X();
... };
... class Y {};
... '''
>>> m = cxxDestructorDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
~X
"""
return makeKindMatcher([CursorKind.DESTRUCTOR], *args)
[docs]def cxxMethodDecl(*args):
"""Match C++ methods
>>> from glud import *
>>> config = '''
... class X {
... void u();
... void v();
... };
... '''
>>> m = cxxMethodDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
u
v
"""
return makeKindMatcher([CursorKind.CXX_METHOD], *args)
[docs]def cxxRecordDecl(*args):
"""Matches C++ class declarations.
>>> from glud import *
>>> config = '''
... class W;
... template<typename T> class X {};
... struct Y {};
... union Z {};
... '''
>>> m = cxxRecordDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
W
X
"""
kinds = [
CursorKind.CLASS_DECL,
CursorKind.CLASS_TEMPLATE,
]
inner = [ PredMatcher(is_kind(k)) for k in kinds ]
return allOf(anyOf(*inner), *args)
[docs]def decl(*args):
"""Match any declaration
>>> from glud import *
>>> config = '''
... class X {};
... struct Y {};
... enum Z {};
... '''
>>> m = decl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
Y
Z
"""
return allOf(PredMatcher(is_decl), *args)
[docs]def enumDecl(*args):
"""Match enumerations
>>> from glud import *
>>> config = '''
... enum X {};
... enum class Y {};
... '''
>>> m = enumDecl()
>>> args = '-x c++ -std=c++11'.split()
>>> for c in walk(m, parse_string(config, args=args).cursor):
... print(c.spelling)
X
Y
"""
return makeKindMatcher([CursorKind.ENUM_DECL], *args)
[docs]def fieldDecl(*args):
"""Match struct / class fields
>>> from glud import *
>>> config = '''
... struct X {
... int u;
... int v;
... };
... '''
>>> m = fieldDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
u
v
"""
return makeKindMatcher([CursorKind.FIELD_DECL], *args)
[docs]def functionDecl(*args):
"""Match function declarations
>>> from glud import *
>>> config = '''
... int u();
... int v();
... '''
>>> m = functionDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
u
v
"""
return makeKindMatcher([CursorKind.FUNCTION_DECL], *args)
[docs]def has(*args):
"""Match if a cursor has a child that matches
>>> from glud import *
>>> config = '''
... class X {
... void f();
... };
... class Y;
... '''
>>> m = cxxRecordDecl(has(cxxMethodDecl()))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return ChildAnyOfMatcher(*args)
[docs]def hasAncestor(matcher):
"""Matches if the current cursor has an ancestor that matches
>>> from glud import *
>>> config = '''
... namespace X {
... class Y {};
... }
... class Z {};
... '''
>>> m = cxxRecordDecl(
... hasName('Y'),
... hasAncestor(namespaceDecl(hasName('X'))))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
Y
"""
return AncestorMatcher(matcher)
[docs]def hasAnyParameter(matcher):
"""Match if any method or function argument matches
>>> from glud import *
>>> config = '''
... void f();
... void g(int);
... '''
>>> m = functionDecl(hasAnyParameter(hasType(builtinType())))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
g
"""
return AnyParameterMatcher(matcher)
[docs]def hasCanonicalType(m):
"""Matches if a cursor has the specified number of arguments
>>> from glud import *
>>> config = '''
... namespace X {
... struct Y;
... Y f();
... }
... '''
>>> m = functionDecl(hasReturnType(hasCanonicalType(hasName('X::Y'))))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
f
"""
return CanonicalTypeTraversalMatcher(m)
[docs]def hasName(name):
"""Match a cursors spelling against a pattern
>>> from glud import *
>>> config = '''
... class X {};
... class Y {};
... '''
>>> m = cxxRecordDecl(hasName('X'))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return NameMatcher(name)
[docs]def hasParameter(N, inner):
"""Matches if the N-th parameter matches the inner matcher
>>> from glud import *
>>> config = '''
... void f(int x);
... void g(int y, int x);
... void h();
... '''
>>> m = functionDecl(hasParameter(1, hasName('x')))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
g
"""
return ParameterMatcher(N, inner)
[docs]def hasParent(*args):
"""Matches if the direct parent node matches
>>> from glud import *
>>> config = '''
... namespace X {
... int a;
... }
... int b;
... '''
>>> m = varDecl(hasParent(namespaceDecl(hasName('X'))))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
a
"""
return ParentMatcher(*args)
[docs]def hasReturnType(matcher):
"""Match a function/method with a specified return type
>>> from glud import *
>>> config = '''
... class X {};
... X u();
... int v();
... '''
>>> m = functionDecl(hasReturnType(builtinType()))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
v
"""
return ReturnTypeTraversalMatcher(matcher)
[docs]def hasStaticStorageDuration():
"""Match an item has static storage duration
>>> from glud import *
>>> config = '''
... class X {
... static void u();
... void v();
... };
... '''
>>> m = cxxMethodDecl(
... hasStaticStorageDuration())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
u
"""
return PredMatcher(has_storage_class(clang.cindex.StorageClass.STATIC))
[docs]def hasType(matcher):
"""Matches if the type associated with the current cursor matches
>>> from glud import *
>>> config = '''
... int x;
... long y;
... '''
>>> m = varDecl(hasType(hasName('int')))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
x
"""
return TypeTraversalMatcher(matcher)
[docs]def hasTypename(typename):
"""Match if the spelling of the type of a cursor matches a pattern
>>> from glud import *
>>> config = '''
... namespace X {
... class Y {};
... }
... class Y {};
... '''
>>> m = cxxRecordDecl(hasTypename('X::Y'))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.type.spelling)
X::Y
"""
return TypenameMatcher(typename)
[docs]def isClass():
"""Matches if a cursor is a class
>>> from glud import *
>>> config = '''
... class X;
... struct Y;
... '''
>>> m = isClass()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return PredMatcher(is_kind(CursorKind.CLASS_DECL))
[docs]def isDefinition():
"""Matches if the cursor is a definition
>>> from glud import *
>>> config = '''
... class X {};
... class Y;
... '''
>>> m = cxxRecordDecl(isDefinition())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return PredMatcher(is_definition)
[docs]def isDerivedFrom(name):
"""Match if a C++ type inherits from a named class
>>> from glud import *
>>> config = '''
... class X {};
... class Y : public X {};
... class Z : public Y {};
... '''
>>> m = cxxRecordDecl(isDerivedFrom('X'))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
Y
Z
"""
return AnyBaseClassMatcher(hasTypename(name))
[docs]def isExpansionInFileMatching(pattern):
"""Matches if the nodes location matches a pattern
>>> from glud import *
>>> config = '''
... class X;
... '''
>>> m = isExpansionInFileMatching('tmp.cpp')
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return LocationMatcher(pattern)
[docs]def isPrivate():
"""Test if a cursor is private
>>> from glud import *
>>> config = '''
... class X {
... private:
... int y;
... };
... '''
>>> m = fieldDecl(isPrivate())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
y
"""
return PredMatcher(has_access(AccessSpecifier.PRIVATE))
[docs]def isProtected():
"""Test if a cursor is protected
>>> from glud import *
>>> config = '''
... class X {
... protected:
... int y;
... };
... '''
>>> m = fieldDecl(isProtected())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
y
"""
return PredMatcher(has_access(AccessSpecifier.PROTECTED))
[docs]def isPublic():
"""Test if a cursor is public
>>> from glud import *
>>> config = '''
... class X {
... public:
... int y;
... };
... '''
>>> m = fieldDecl(isPublic())
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
y
"""
return PredMatcher(has_access(AccessSpecifier.PUBLIC))
[docs]def isSameOrDerivedFrom(name):
"""Match if derives-from (or is-a) class with a given name
>>> from glud import *
>>> config = '''
... class X {};
... class Y : public X {};
... class Z : public Y {};
... '''
>>> m = cxxRecordDecl(isSameOrDerivedFrom('X'))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
Y
Z
"""
return anyOf(hasTypename(name), isDerivedFrom(name))
[docs]def isStruct():
"""Matches if a cursor is a struct
>>> from glud import *
>>> config = '''
... class X;
... struct Y;
... '''
>>> m = isStruct()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
Y
"""
return PredMatcher(is_kind(CursorKind.STRUCT_DECL))
[docs]def namespaceDecl(*args):
"""Match a C++ namespace declaration
>>> from glud import *
>>> config = '''
... namespace X { }
... '''
>>> m = namespaceDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return allOf(PredMatcher(is_kind(CursorKind.NAMESPACE)), *args)
[docs]def parameterCountIs(N):
"""Matches if a cursor has the specified number of arguments
>>> from glud import *
>>> config = '''
... int f();
... int g(int);
... int h(int, int);
... '''
>>> m = functionDecl(parameterCountIs(1))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
g
"""
return ParameterCountMatcher(N)
[docs]def pointee(inner):
"""Traverse from a pointer to the dereferenced type
>>> from glud import *
>>> config = '''
... int *x;
... void *y;
... '''
>>> m = varDecl(hasType(pointerType(pointee(hasName('int')))))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
x
"""
return PointeeTypeTraversalMatcher(inner)
[docs]def pointerType(*args):
"""Test if a cursor has pointer type
>>> from glud import *
>>> config = '''
... int w;
... int* x;
... int** y;
... int& z = w;
... '''
>>> m = varDecl(hasType(pointerType()))
>>> for c in parse_string(config, args='-x c++ -std=c++11'.split()).cursor.walk_preorder():
... if m(c):
... print(c.spelling)
x
y
"""
return AllOfTypeMatcher(is_kind(TypeKind.POINTER), *args)
[docs]def recordDecl(*args):
"""Matches class, struct, and union declarations.
>>> from glud import *
>>> config = '''
... class W;
... template<typename T> class X {};
... struct Y {};
... union Z {};
... '''
>>> m = recordDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
W
X
Y
Z
"""
kinds = [
CursorKind.STRUCT_DECL,
CursorKind.UNION_DECL,
CursorKind.CLASS_DECL,
CursorKind.CLASS_TEMPLATE,
]
inner = [ PredMatcher(is_kind(k)) for k in kinds ]
return allOf(anyOf(*inner), *args)
[docs]def stmt(*args):
"""Matches statements
>>> from glud import *
>>> config = '''
... void f() { }
... '''
>>> m = stmt()
>>> i = 0
>>> for c in parse_string(config).cursor.walk_preorder():
... if m(c):
... i += 1
>>> print(i)
1
"""
return allOf(PredMatcher(is_stmt), *args)
[docs]def typedefDecl(*args):
"""Matches typedef declarations
>>> from glud import *
>>> config = '''
... typedef int X;
... '''
>>> m = typedefDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
"""
return allOf(PredMatcher(is_kind(CursorKind.TYPEDEF_DECL)), *args)
[docs]def unless(*args):
"""Inverts the match of the children
>>> from glud import *
>>> config = '''
... class X { };
... class Y {};
... class Z {};
... '''
>>> m = cxxRecordDecl(unless(hasName('Y')))
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
X
Z
"""
return UnlessMatcher(*args)
[docs]def varDecl(*args):
"""Matches variable declarations
>>> from glud import *
>>> config = '''
... int a;
... '''
>>> m = varDecl()
>>> for c in walk(m, parse_string(config).cursor):
... print(c.spelling)
a
"""
return allOf(PredMatcher(is_kind(CursorKind.VAR_DECL)), *args)