commit
960ed68785
@ -63,7 +63,7 @@ def gentest(
|
|||||||
popt = ""
|
popt = ""
|
||||||
|
|
||||||
options = ParserOptions(verbose=verbose)
|
options = ParserOptions(verbose=verbose)
|
||||||
if options:
|
if pcpp:
|
||||||
options.preprocessor = make_pcpp_preprocessor()
|
options.preprocessor = make_pcpp_preprocessor()
|
||||||
maybe_options = "options = ParserOptions(preprocessor=make_pcpp_preprocessor())"
|
maybe_options = "options = ParserOptions(preprocessor=make_pcpp_preprocessor())"
|
||||||
popt = ", options=options"
|
popt = ", options=options"
|
||||||
|
@ -58,7 +58,7 @@ from .types import (
|
|||||||
Value,
|
Value,
|
||||||
Variable,
|
Variable,
|
||||||
)
|
)
|
||||||
from .visitor import CxxVisitor
|
from .visitor import CxxVisitor, null_visitor
|
||||||
|
|
||||||
LexTokenList = typing.List[LexToken]
|
LexTokenList = typing.List[LexToken]
|
||||||
T = typing.TypeVar("T")
|
T = typing.TypeVar("T")
|
||||||
@ -114,6 +114,7 @@ class CxxParser:
|
|||||||
|
|
||||||
def _push_state(self, cls: typing.Type[ST], *args) -> ST:
|
def _push_state(self, cls: typing.Type[ST], *args) -> ST:
|
||||||
state = cls(self.state, *args)
|
state = cls(self.state, *args)
|
||||||
|
state._prior_visitor = self.visitor
|
||||||
if isinstance(state, NamespaceBlockState):
|
if isinstance(state, NamespaceBlockState):
|
||||||
self.current_namespace = state.namespace
|
self.current_namespace = state.namespace
|
||||||
self.state = state
|
self.state = state
|
||||||
@ -122,6 +123,7 @@ class CxxParser:
|
|||||||
def _pop_state(self) -> State:
|
def _pop_state(self) -> State:
|
||||||
prev_state = self.state
|
prev_state = self.state
|
||||||
prev_state._finish(self.visitor)
|
prev_state._finish(self.visitor)
|
||||||
|
self.visitor = prev_state._prior_visitor
|
||||||
state = prev_state.parent
|
state = prev_state.parent
|
||||||
if state is None:
|
if state is None:
|
||||||
raise CxxParseError("INTERNAL ERROR: unbalanced state")
|
raise CxxParseError("INTERNAL ERROR: unbalanced state")
|
||||||
@ -454,7 +456,8 @@ class CxxParser:
|
|||||||
ns = NamespaceDecl(names, inline, doxygen)
|
ns = NamespaceDecl(names, inline, doxygen)
|
||||||
state = self._push_state(NamespaceBlockState, ns)
|
state = self._push_state(NamespaceBlockState, ns)
|
||||||
state.location = location
|
state.location = location
|
||||||
self.visitor.on_namespace_start(state)
|
if self.visitor.on_namespace_start(state) is False:
|
||||||
|
self.visitor = null_visitor
|
||||||
|
|
||||||
def _parse_extern(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
|
def _parse_extern(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
|
||||||
etok = self.lex.token_if("STRING_LITERAL", "template")
|
etok = self.lex.token_if("STRING_LITERAL", "template")
|
||||||
@ -463,7 +466,8 @@ class CxxParser:
|
|||||||
if self.lex.token_if("{"):
|
if self.lex.token_if("{"):
|
||||||
state = self._push_state(ExternBlockState, etok.value)
|
state = self._push_state(ExternBlockState, etok.value)
|
||||||
state.location = tok.location
|
state.location = tok.location
|
||||||
self.visitor.on_extern_block_start(state)
|
if self.visitor.on_extern_block_start(state) is False:
|
||||||
|
self.visitor = null_visitor
|
||||||
return
|
return
|
||||||
|
|
||||||
# an extern variable/function with specific linkage
|
# an extern variable/function with specific linkage
|
||||||
@ -508,7 +512,8 @@ class CxxParser:
|
|||||||
self, tok: LexToken, doxygen: typing.Optional[str]
|
self, tok: LexToken, doxygen: typing.Optional[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
state = self._push_state(EmptyBlockState)
|
state = self._push_state(EmptyBlockState)
|
||||||
self.visitor.on_empty_block_start(state)
|
if self.visitor.on_empty_block_start(state) is False:
|
||||||
|
self.visitor = null_visitor
|
||||||
|
|
||||||
def _on_block_end(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
|
def _on_block_end(self, tok: LexToken, doxygen: typing.Optional[str]) -> None:
|
||||||
old_state = self._pop_state()
|
old_state = self._pop_state()
|
||||||
@ -1143,7 +1148,8 @@ class CxxParser:
|
|||||||
ClassBlockState, clsdecl, default_access, typedef, mods
|
ClassBlockState, clsdecl, default_access, typedef, mods
|
||||||
)
|
)
|
||||||
state.location = location
|
state.location = location
|
||||||
self.visitor.on_class_start(state)
|
if self.visitor.on_class_start(state) is False:
|
||||||
|
self.visitor = null_visitor
|
||||||
|
|
||||||
def _finish_class_decl(self, state: ClassBlockState) -> None:
|
def _finish_class_decl(self, state: ClassBlockState) -> None:
|
||||||
self._finish_class_or_enum(
|
self._finish_class_or_enum(
|
||||||
|
@ -46,6 +46,9 @@ class State(typing.Generic[T, PT]):
|
|||||||
#: Approximate location that the parsed element was found at
|
#: Approximate location that the parsed element was found at
|
||||||
location: Location
|
location: Location
|
||||||
|
|
||||||
|
#: internal detail used by parser
|
||||||
|
_prior_visitor: "CxxVisitor"
|
||||||
|
|
||||||
def __init__(self, parent: typing.Optional["State[PT, typing.Any]"]) -> None:
|
def __init__(self, parent: typing.Optional["State[PT, typing.Any]"]) -> None:
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
|
@ -209,22 +209,24 @@ class SimpleCxxVisitor:
|
|||||||
def on_include(self, state: SState, filename: str) -> None:
|
def on_include(self, state: SState, filename: str) -> None:
|
||||||
self.data.includes.append(Include(filename))
|
self.data.includes.append(Include(filename))
|
||||||
|
|
||||||
def on_empty_block_start(self, state: SEmptyBlockState) -> None:
|
def on_empty_block_start(self, state: SEmptyBlockState) -> typing.Optional[bool]:
|
||||||
# this matters for some scope/resolving purposes, but you're
|
# this matters for some scope/resolving purposes, but you're
|
||||||
# probably going to want to use clang if you care about that
|
# probably going to want to use clang if you care about that
|
||||||
# level of detail
|
# level of detail
|
||||||
state.user_data = state.parent.user_data
|
state.user_data = state.parent.user_data
|
||||||
|
return None
|
||||||
|
|
||||||
def on_empty_block_end(self, state: SEmptyBlockState) -> None:
|
def on_empty_block_end(self, state: SEmptyBlockState) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_extern_block_start(self, state: SExternBlockState) -> None:
|
def on_extern_block_start(self, state: SExternBlockState) -> typing.Optional[bool]:
|
||||||
state.user_data = state.parent.user_data
|
state.user_data = state.parent.user_data
|
||||||
|
return None
|
||||||
|
|
||||||
def on_extern_block_end(self, state: SExternBlockState) -> None:
|
def on_extern_block_end(self, state: SExternBlockState) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_namespace_start(self, state: SNamespaceBlockState) -> None:
|
def on_namespace_start(self, state: SNamespaceBlockState) -> typing.Optional[bool]:
|
||||||
parent_ns = state.parent.user_data
|
parent_ns = state.parent.user_data
|
||||||
|
|
||||||
ns = None
|
ns = None
|
||||||
@ -247,6 +249,7 @@ class SimpleCxxVisitor:
|
|||||||
ns.doxygen = state.namespace.doxygen
|
ns.doxygen = state.namespace.doxygen
|
||||||
|
|
||||||
state.user_data = ns
|
state.user_data = ns
|
||||||
|
return None
|
||||||
|
|
||||||
def on_namespace_end(self, state: SNamespaceBlockState) -> None:
|
def on_namespace_end(self, state: SNamespaceBlockState) -> None:
|
||||||
pass
|
pass
|
||||||
@ -299,11 +302,12 @@ class SimpleCxxVisitor:
|
|||||||
# Class/union/struct
|
# Class/union/struct
|
||||||
#
|
#
|
||||||
|
|
||||||
def on_class_start(self, state: SClassBlockState) -> None:
|
def on_class_start(self, state: SClassBlockState) -> typing.Optional[bool]:
|
||||||
parent = state.parent.user_data
|
parent = state.parent.user_data
|
||||||
block = ClassScope(state.class_decl)
|
block = ClassScope(state.class_decl)
|
||||||
parent.classes.append(block)
|
parent.classes.append(block)
|
||||||
state.user_data = block
|
state.user_data = block
|
||||||
|
return None
|
||||||
|
|
||||||
def on_class_field(self, state: SClassBlockState, f: Field) -> None:
|
def on_class_field(self, state: SClassBlockState, f: Field) -> None:
|
||||||
state.user_data.fields.append(f)
|
state.user_data.fields.append(f)
|
||||||
|
@ -52,7 +52,7 @@ class CxxVisitor(Protocol):
|
|||||||
Called once for each ``#include`` directive encountered
|
Called once for each ``#include`` directive encountered
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_empty_block_start(self, state: EmptyBlockState) -> None:
|
def on_empty_block_start(self, state: EmptyBlockState) -> typing.Optional[bool]:
|
||||||
"""
|
"""
|
||||||
Called when a ``{`` is encountered that isn't associated with or
|
Called when a ``{`` is encountered that isn't associated with or
|
||||||
consumed by other declarations.
|
consumed by other declarations.
|
||||||
@ -62,6 +62,9 @@ class CxxVisitor(Protocol):
|
|||||||
{
|
{
|
||||||
// stuff
|
// stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
If this function returns False, the visitor will not be called for any
|
||||||
|
items inside this block (including on_empty_block_end)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_empty_block_end(self, state: EmptyBlockState) -> None:
|
def on_empty_block_end(self, state: EmptyBlockState) -> None:
|
||||||
@ -69,7 +72,7 @@ class CxxVisitor(Protocol):
|
|||||||
Called when an empty block ends
|
Called when an empty block ends
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_extern_block_start(self, state: ExternBlockState) -> None:
|
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
|
||||||
"""
|
"""
|
||||||
.. code-block:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
@ -77,6 +80,8 @@ class CxxVisitor(Protocol):
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
If this function returns False, the visitor will not be called for any
|
||||||
|
items inside this block (including on_extern_block_end)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_extern_block_end(self, state: ExternBlockState) -> None:
|
def on_extern_block_end(self, state: ExternBlockState) -> None:
|
||||||
@ -84,9 +89,12 @@ class CxxVisitor(Protocol):
|
|||||||
Called when an extern block ends
|
Called when an extern block ends
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_namespace_start(self, state: NamespaceBlockState) -> None:
|
def on_namespace_start(self, state: NamespaceBlockState) -> typing.Optional[bool]:
|
||||||
"""
|
"""
|
||||||
Called when a ``namespace`` directive is encountered
|
Called when a ``namespace`` directive is encountered
|
||||||
|
|
||||||
|
If this function returns False, the visitor will not be called for any
|
||||||
|
items inside this namespace (including on_namespace_end)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_namespace_end(self, state: NamespaceBlockState) -> None:
|
def on_namespace_end(self, state: NamespaceBlockState) -> None:
|
||||||
@ -186,7 +194,7 @@ class CxxVisitor(Protocol):
|
|||||||
# Class/union/struct
|
# Class/union/struct
|
||||||
#
|
#
|
||||||
|
|
||||||
def on_class_start(self, state: ClassBlockState) -> None:
|
def on_class_start(self, state: ClassBlockState) -> typing.Optional[bool]:
|
||||||
"""
|
"""
|
||||||
Called when a class/struct/union is encountered
|
Called when a class/struct/union is encountered
|
||||||
|
|
||||||
@ -199,6 +207,9 @@ class CxxVisitor(Protocol):
|
|||||||
This is called first, followed by on_typedef for each typedef instance
|
This is called first, followed by on_typedef for each typedef instance
|
||||||
encountered. The compound type object is passed as the type to the
|
encountered. The compound type object is passed as the type to the
|
||||||
typedef.
|
typedef.
|
||||||
|
|
||||||
|
If this function returns False, the visitor will not be called for any
|
||||||
|
items inside this class (including on_class_end)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_class_field(self, state: ClassBlockState, f: Field) -> None:
|
def on_class_field(self, state: ClassBlockState, f: Field) -> None:
|
||||||
@ -231,3 +242,87 @@ class CxxVisitor(Protocol):
|
|||||||
Then ``on_class_start``, .. ``on_class_end`` are emitted, along with
|
Then ``on_class_start``, .. ``on_class_end`` are emitted, along with
|
||||||
``on_variable`` for each instance declared.
|
``on_variable`` for each instance declared.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class NullVisitor:
|
||||||
|
"""
|
||||||
|
This visitor does nothing
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_parse_start(self, state: NamespaceBlockState) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_pragma(self, state: State, content: Value) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_include(self, state: State, filename: str) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_empty_block_start(self, state: EmptyBlockState) -> typing.Optional[bool]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_empty_block_end(self, state: EmptyBlockState) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_extern_block_end(self, state: ExternBlockState) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_namespace_start(self, state: NamespaceBlockState) -> typing.Optional[bool]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_namespace_end(self, state: NamespaceBlockState) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_template_inst(self, state: State, inst: TemplateInst) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_variable(self, state: State, v: Variable) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_function(self, state: State, fn: Function) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_method_impl(self, state: State, method: Method) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_typedef(self, state: State, typedef: Typedef) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_using_namespace(self, state: State, namespace: typing.List[str]) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_using_alias(self, state: State, using: UsingAlias) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_using_declaration(self, state: State, using: UsingDecl) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_enum(self, state: State, enum: EnumDecl) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_class_start(self, state: ClassBlockState) -> typing.Optional[bool]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_class_field(self, state: ClassBlockState, f: Field) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_class_friend(self, state: ClassBlockState, friend: FriendDecl) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_class_method(self, state: ClassBlockState, method: Method) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def on_class_end(self, state: ClassBlockState) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
null_visitor = NullVisitor()
|
||||||
|
269
tests/test_skip.py
Normal file
269
tests/test_skip.py
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||||
|
# .. and modified
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from cxxheaderparser.parser import CxxParser
|
||||||
|
from cxxheaderparser.simple import (
|
||||||
|
ClassScope,
|
||||||
|
NamespaceScope,
|
||||||
|
ParsedData,
|
||||||
|
SClassBlockState,
|
||||||
|
SEmptyBlockState,
|
||||||
|
SExternBlockState,
|
||||||
|
SNamespaceBlockState,
|
||||||
|
SimpleCxxVisitor,
|
||||||
|
)
|
||||||
|
|
||||||
|
from cxxheaderparser.types import (
|
||||||
|
ClassDecl,
|
||||||
|
Function,
|
||||||
|
FundamentalSpecifier,
|
||||||
|
Method,
|
||||||
|
NameSpecifier,
|
||||||
|
PQName,
|
||||||
|
Type,
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# ensure extern block is skipped
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class SkipExtern(SimpleCxxVisitor):
|
||||||
|
def on_extern_block_start(self, state: SExternBlockState) -> typing.Optional[bool]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_extern():
|
||||||
|
content = """
|
||||||
|
void fn1();
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void fn2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fn3();
|
||||||
|
"""
|
||||||
|
|
||||||
|
v = SkipExtern()
|
||||||
|
parser = CxxParser("<str>", inspect.cleandoc(content), v)
|
||||||
|
parser.parse()
|
||||||
|
data = v.data
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# ensure class block is skipped
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class SkipClass(SimpleCxxVisitor):
|
||||||
|
def on_class_start(self, state: SClassBlockState) -> typing.Optional[bool]:
|
||||||
|
if getattr(state.class_decl.typename.segments[0], "name", None) == "Skip":
|
||||||
|
return False
|
||||||
|
return super().on_class_start(state)
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_class() -> None:
|
||||||
|
content = """
|
||||||
|
void fn1();
|
||||||
|
|
||||||
|
class Skip {
|
||||||
|
void fn2();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Yup {
|
||||||
|
void fn3();
|
||||||
|
};
|
||||||
|
|
||||||
|
void fn5();
|
||||||
|
"""
|
||||||
|
v = SkipClass()
|
||||||
|
parser = CxxParser("<str>", inspect.cleandoc(content), v)
|
||||||
|
parser.parse()
|
||||||
|
data = v.data
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
classes=[
|
||||||
|
ClassScope(
|
||||||
|
class_decl=ClassDecl(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[NameSpecifier(name="Yup")], classkey="class"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
methods=[
|
||||||
|
Method(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[FundamentalSpecifier(name="void")]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
||||||
|
parameters=[],
|
||||||
|
access="private",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn5")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# ensure empty block is skipped
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class SkipEmptyBlock(SimpleCxxVisitor):
|
||||||
|
def on_empty_block_start(self, state: SEmptyBlockState) -> typing.Optional[bool]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_empty_block() -> None:
|
||||||
|
content = """
|
||||||
|
void fn1();
|
||||||
|
|
||||||
|
{
|
||||||
|
void fn2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fn3();
|
||||||
|
"""
|
||||||
|
v = SkipEmptyBlock()
|
||||||
|
parser = CxxParser("<str>", inspect.cleandoc(content), v)
|
||||||
|
parser.parse()
|
||||||
|
data = v.data
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn3")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# ensure namespace 'skip' is skipped
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class SkipNamespace(SimpleCxxVisitor):
|
||||||
|
def on_namespace_start(self, state: SNamespaceBlockState) -> typing.Optional[bool]:
|
||||||
|
if "skip" in state.namespace.names[0]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return super().on_namespace_start(state)
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_namespace():
|
||||||
|
content = """
|
||||||
|
void fn1();
|
||||||
|
|
||||||
|
namespace skip {
|
||||||
|
void fn2();
|
||||||
|
|
||||||
|
namespace thistoo {
|
||||||
|
void fn3();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ok {
|
||||||
|
void fn4();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fn5();
|
||||||
|
"""
|
||||||
|
v = SkipNamespace()
|
||||||
|
parser = CxxParser("<str>", inspect.cleandoc(content), v)
|
||||||
|
parser.parse()
|
||||||
|
data = v.data
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn1")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn5")]),
|
||||||
|
parameters=[],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
namespaces={
|
||||||
|
"ok": NamespaceScope(
|
||||||
|
name="ok",
|
||||||
|
functions=[
|
||||||
|
Function(
|
||||||
|
return_type=Type(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[FundamentalSpecifier(name="void")]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name=PQName(segments=[NameSpecifier(name="fn4")]),
|
||||||
|
parameters=[],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user