Merge pull request #68 from robotpy/simplify-blocks
breaking change: remove empty block state and update visitor types
This commit is contained in:
commit
bdcee6f9c0
@ -10,9 +10,9 @@ from .lexer import LexToken, Location, PhonyEnding
|
|||||||
from .options import ParserOptions
|
from .options import ParserOptions
|
||||||
from .parserstate import (
|
from .parserstate import (
|
||||||
ClassBlockState,
|
ClassBlockState,
|
||||||
EmptyBlockState,
|
|
||||||
ExternBlockState,
|
ExternBlockState,
|
||||||
NamespaceBlockState,
|
NamespaceBlockState,
|
||||||
|
NonClassBlockState,
|
||||||
ParsedTypeModifiers,
|
ParsedTypeModifiers,
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
@ -62,7 +62,6 @@ from .visitor import CxxVisitor, null_visitor
|
|||||||
LexTokenList = typing.List[LexToken]
|
LexTokenList = typing.List[LexToken]
|
||||||
T = typing.TypeVar("T")
|
T = typing.TypeVar("T")
|
||||||
|
|
||||||
ST = typing.TypeVar("ST", bound=State)
|
|
||||||
PT = typing.TypeVar("PT", Parameter, TemplateNonTypeParam)
|
PT = typing.TypeVar("PT", Parameter, TemplateNonTypeParam)
|
||||||
|
|
||||||
|
|
||||||
@ -90,7 +89,9 @@ class CxxParser:
|
|||||||
global_ns = NamespaceDecl([], False)
|
global_ns = NamespaceDecl([], False)
|
||||||
self.current_namespace = global_ns
|
self.current_namespace = global_ns
|
||||||
|
|
||||||
self.state: State = NamespaceBlockState(None, global_ns)
|
self.state: State = NamespaceBlockState(
|
||||||
|
None, self.lex.current_location(), global_ns
|
||||||
|
)
|
||||||
self.anon_id = 0
|
self.anon_id = 0
|
||||||
|
|
||||||
self.verbose = True if self.options.verbose else False
|
self.verbose = True if self.options.verbose else False
|
||||||
@ -111,13 +112,9 @@ class CxxParser:
|
|||||||
# State management
|
# State management
|
||||||
#
|
#
|
||||||
|
|
||||||
def _push_state(self, cls: typing.Type[ST], *args) -> ST:
|
def _setup_state(self, state: State):
|
||||||
state = cls(self.state, *args)
|
|
||||||
state._prior_visitor = self.visitor
|
state._prior_visitor = self.visitor
|
||||||
if isinstance(state, NamespaceBlockState):
|
|
||||||
self.current_namespace = state.namespace
|
|
||||||
self.state = state
|
self.state = state
|
||||||
return state
|
|
||||||
|
|
||||||
def _pop_state(self) -> State:
|
def _pop_state(self) -> State:
|
||||||
prev_state = self.state
|
prev_state = self.state
|
||||||
@ -447,24 +444,37 @@ class CxxParser:
|
|||||||
if inline and len(names) > 1:
|
if inline and len(names) > 1:
|
||||||
raise CxxParseError("a nested namespace definition cannot be inline")
|
raise CxxParseError("a nested namespace definition cannot be inline")
|
||||||
|
|
||||||
|
state = self.state
|
||||||
|
if not isinstance(state, (NamespaceBlockState, ExternBlockState)):
|
||||||
|
raise CxxParseError("namespace cannot be defined in a class")
|
||||||
|
|
||||||
if ns_alias:
|
if ns_alias:
|
||||||
alias = NamespaceAlias(ns_alias.value, names)
|
alias = NamespaceAlias(ns_alias.value, names)
|
||||||
self.visitor.on_namespace_alias(self.state, alias)
|
self.visitor.on_namespace_alias(state, alias)
|
||||||
return
|
return
|
||||||
|
|
||||||
ns = NamespaceDecl(names, inline, doxygen)
|
ns = NamespaceDecl(names, inline, doxygen)
|
||||||
state = self._push_state(NamespaceBlockState, ns)
|
|
||||||
state.location = location
|
state = NamespaceBlockState(state, location, ns)
|
||||||
|
self._setup_state(state)
|
||||||
|
self.current_namespace = state.namespace
|
||||||
|
|
||||||
if self.visitor.on_namespace_start(state) is False:
|
if self.visitor.on_namespace_start(state) is False:
|
||||||
self.visitor = null_visitor
|
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")
|
||||||
if etok:
|
if etok:
|
||||||
|
# classes cannot contain extern blocks/templates
|
||||||
|
state = self.state
|
||||||
|
if isinstance(state, ClassBlockState):
|
||||||
|
raise self._parse_error(tok)
|
||||||
|
|
||||||
if etok.type == "STRING_LITERAL":
|
if etok.type == "STRING_LITERAL":
|
||||||
if self.lex.token_if("{"):
|
if self.lex.token_if("{"):
|
||||||
state = self._push_state(ExternBlockState, etok.value)
|
state = ExternBlockState(state, tok.location, etok.value)
|
||||||
state.location = tok.location
|
self._setup_state(state)
|
||||||
|
|
||||||
if self.visitor.on_extern_block_start(state) is False:
|
if self.visitor.on_extern_block_start(state) is False:
|
||||||
self.visitor = null_visitor
|
self.visitor = null_visitor
|
||||||
return
|
return
|
||||||
@ -510,9 +520,7 @@ class CxxParser:
|
|||||||
def _on_empty_block_start(
|
def _on_empty_block_start(
|
||||||
self, tok: LexToken, doxygen: typing.Optional[str]
|
self, tok: LexToken, doxygen: typing.Optional[str]
|
||||||
) -> None:
|
) -> None:
|
||||||
state = self._push_state(EmptyBlockState)
|
raise self._parse_error(tok)
|
||||||
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()
|
||||||
@ -822,7 +830,7 @@ class CxxParser:
|
|||||||
# Using directive/declaration/typealias
|
# Using directive/declaration/typealias
|
||||||
#
|
#
|
||||||
|
|
||||||
def _parse_using_directive(self) -> None:
|
def _parse_using_directive(self, state: NonClassBlockState) -> None:
|
||||||
"""
|
"""
|
||||||
using_directive: [attribute_specifier_seq] "using" "namespace" ["::"] [nested_name_specifier] IDENTIFIER ";"
|
using_directive: [attribute_specifier_seq] "using" "namespace" ["::"] [nested_name_specifier] IDENTIFIER ";"
|
||||||
"""
|
"""
|
||||||
@ -841,7 +849,7 @@ class CxxParser:
|
|||||||
if not names:
|
if not names:
|
||||||
raise self._parse_error(None, "NAME")
|
raise self._parse_error(None, "NAME")
|
||||||
|
|
||||||
self.visitor.on_using_namespace(self.state, names)
|
self.visitor.on_using_namespace(state, names)
|
||||||
|
|
||||||
def _parse_using_declaration(self, tok: LexToken) -> None:
|
def _parse_using_declaration(self, tok: LexToken) -> None:
|
||||||
"""
|
"""
|
||||||
@ -893,10 +901,11 @@ class CxxParser:
|
|||||||
raise CxxParseError(
|
raise CxxParseError(
|
||||||
"unexpected using-directive when parsing alias-declaration", tok
|
"unexpected using-directive when parsing alias-declaration", tok
|
||||||
)
|
)
|
||||||
if isinstance(self.state, ClassBlockState):
|
state = self.state
|
||||||
|
if not isinstance(state, (NamespaceBlockState, ExternBlockState)):
|
||||||
raise self._parse_error(tok)
|
raise self._parse_error(tok)
|
||||||
|
|
||||||
self._parse_using_directive()
|
self._parse_using_directive(state)
|
||||||
elif tok.type in ("DBL_COLON", "typename") or not self.lex.token_if("="):
|
elif tok.type in ("DBL_COLON", "typename") or not self.lex.token_if("="):
|
||||||
if template:
|
if template:
|
||||||
raise CxxParseError(
|
raise CxxParseError(
|
||||||
@ -1143,10 +1152,11 @@ class CxxParser:
|
|||||||
clsdecl = ClassDecl(
|
clsdecl = ClassDecl(
|
||||||
typename, bases, template, explicit, final, doxygen, self._current_access
|
typename, bases, template, explicit, final, doxygen, self._current_access
|
||||||
)
|
)
|
||||||
state = self._push_state(
|
state: ClassBlockState = ClassBlockState(
|
||||||
ClassBlockState, clsdecl, default_access, typedef, mods
|
self.state, location, clsdecl, default_access, typedef, mods
|
||||||
)
|
)
|
||||||
state.location = location
|
self._setup_state(state)
|
||||||
|
|
||||||
if self.visitor.on_class_start(state) is False:
|
if self.visitor.on_class_start(state) is False:
|
||||||
self.visitor = null_visitor
|
self.visitor = null_visitor
|
||||||
|
|
||||||
@ -1853,6 +1863,7 @@ class CxxParser:
|
|||||||
|
|
||||||
self.visitor.on_class_method(state, method)
|
self.visitor.on_class_method(state, method)
|
||||||
else:
|
else:
|
||||||
|
assert isinstance(state, (ExternBlockState, NamespaceBlockState))
|
||||||
if not method.has_body:
|
if not method.has_body:
|
||||||
raise self._parse_error(None, expected="Method body")
|
raise self._parse_error(None, expected="Method body")
|
||||||
self.visitor.on_method_impl(state, method)
|
self.visitor.on_method_impl(state, method)
|
||||||
@ -1912,6 +1923,9 @@ class CxxParser:
|
|||||||
self.visitor.on_typedef(state, typedef)
|
self.visitor.on_typedef(state, typedef)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
if not isinstance(state, (ExternBlockState, NamespaceBlockState)):
|
||||||
|
raise CxxParseError("internal error")
|
||||||
|
|
||||||
self.visitor.on_function(state, fn)
|
self.visitor.on_function(state, fn)
|
||||||
return fn.has_body or fn.has_trailing_return
|
return fn.has_body or fn.has_trailing_return
|
||||||
|
|
||||||
|
@ -35,13 +35,13 @@ T = typing.TypeVar("T")
|
|||||||
PT = typing.TypeVar("PT")
|
PT = typing.TypeVar("PT")
|
||||||
|
|
||||||
|
|
||||||
class State(typing.Generic[T, PT]):
|
class BaseState(typing.Generic[T, PT]):
|
||||||
#: Uninitialized user data available for use by visitor implementations. You
|
#: Uninitialized user data available for use by visitor implementations. You
|
||||||
#: should set this in a ``*_start`` method.
|
#: should set this in a ``*_start`` method.
|
||||||
user_data: T
|
user_data: T
|
||||||
|
|
||||||
#: parent state
|
#: parent state
|
||||||
parent: typing.Optional["State[PT, typing.Any]"]
|
parent: typing.Optional["State"]
|
||||||
|
|
||||||
#: Approximate location that the parsed element was found at
|
#: Approximate location that the parsed element was found at
|
||||||
location: Location
|
location: Location
|
||||||
@ -49,52 +49,51 @@ class State(typing.Generic[T, PT]):
|
|||||||
#: internal detail used by parser
|
#: internal detail used by parser
|
||||||
_prior_visitor: "CxxVisitor"
|
_prior_visitor: "CxxVisitor"
|
||||||
|
|
||||||
def __init__(self, parent: typing.Optional["State[PT, typing.Any]"]) -> None:
|
def __init__(self, parent: typing.Optional["State"], location: Location) -> None:
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.location = location
|
||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
def _finish(self, visitor: "CxxVisitor") -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EmptyBlockState(State[T, PT]):
|
class ExternBlockState(BaseState[T, PT]):
|
||||||
parent: State[PT, typing.Any]
|
parent: "NonClassBlockState"
|
||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
|
||||||
visitor.on_empty_block_end(self)
|
|
||||||
|
|
||||||
|
|
||||||
class ExternBlockState(State[T, PT]):
|
|
||||||
parent: State[PT, typing.Any]
|
|
||||||
|
|
||||||
#: The linkage for this extern block
|
#: The linkage for this extern block
|
||||||
linkage: str
|
linkage: str
|
||||||
|
|
||||||
def __init__(self, parent: typing.Optional[State], linkage: str) -> None:
|
def __init__(
|
||||||
super().__init__(parent)
|
self, parent: "NonClassBlockState", location: Location, linkage: str
|
||||||
|
) -> None:
|
||||||
|
super().__init__(parent, location)
|
||||||
self.linkage = linkage
|
self.linkage = linkage
|
||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
def _finish(self, visitor: "CxxVisitor") -> None:
|
||||||
visitor.on_extern_block_end(self)
|
visitor.on_extern_block_end(self)
|
||||||
|
|
||||||
|
|
||||||
class NamespaceBlockState(State[T, PT]):
|
class NamespaceBlockState(BaseState[T, PT]):
|
||||||
parent: State[PT, typing.Any]
|
parent: "NonClassBlockState"
|
||||||
|
|
||||||
#: The incremental namespace for this block
|
#: The incremental namespace for this block
|
||||||
namespace: NamespaceDecl
|
namespace: NamespaceDecl
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, parent: typing.Optional[State], namespace: NamespaceDecl
|
self,
|
||||||
|
parent: typing.Optional["NonClassBlockState"],
|
||||||
|
location: Location,
|
||||||
|
namespace: NamespaceDecl,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent, location)
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
def _finish(self, visitor: "CxxVisitor") -> None:
|
||||||
visitor.on_namespace_end(self)
|
visitor.on_namespace_end(self)
|
||||||
|
|
||||||
|
|
||||||
class ClassBlockState(State[T, PT]):
|
class ClassBlockState(BaseState[T, PT]):
|
||||||
parent: State[PT, typing.Any]
|
parent: "State"
|
||||||
|
|
||||||
#: class decl block being processed
|
#: class decl block being processed
|
||||||
class_decl: ClassDecl
|
class_decl: ClassDecl
|
||||||
@ -110,13 +109,14 @@ class ClassBlockState(State[T, PT]):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
parent: typing.Optional[State],
|
parent: typing.Optional["State"],
|
||||||
|
location: Location,
|
||||||
class_decl: ClassDecl,
|
class_decl: ClassDecl,
|
||||||
access: str,
|
access: str,
|
||||||
typedef: bool,
|
typedef: bool,
|
||||||
mods: ParsedTypeModifiers,
|
mods: ParsedTypeModifiers,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent, location)
|
||||||
self.class_decl = class_decl
|
self.class_decl = class_decl
|
||||||
self.access = access
|
self.access = access
|
||||||
self.typedef = typedef
|
self.typedef = typedef
|
||||||
@ -127,3 +127,9 @@ class ClassBlockState(State[T, PT]):
|
|||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
def _finish(self, visitor: "CxxVisitor") -> None:
|
||||||
visitor.on_class_end(self)
|
visitor.on_class_end(self)
|
||||||
|
|
||||||
|
|
||||||
|
State = typing.Union[
|
||||||
|
NamespaceBlockState[T, PT], ExternBlockState[T, PT], ClassBlockState[T, PT]
|
||||||
|
]
|
||||||
|
NonClassBlockState = typing.Union[ExternBlockState[T, PT], NamespaceBlockState[T, PT]]
|
||||||
|
@ -51,7 +51,6 @@ from .types import (
|
|||||||
|
|
||||||
from .parserstate import (
|
from .parserstate import (
|
||||||
State,
|
State,
|
||||||
EmptyBlockState,
|
|
||||||
ClassBlockState,
|
ClassBlockState,
|
||||||
ExternBlockState,
|
ExternBlockState,
|
||||||
NamespaceBlockState,
|
NamespaceBlockState,
|
||||||
@ -180,11 +179,12 @@ class ParsedData:
|
|||||||
#
|
#
|
||||||
|
|
||||||
# define what user data we store in each state type
|
# define what user data we store in each state type
|
||||||
SState = State[Block, Block]
|
|
||||||
SEmptyBlockState = EmptyBlockState[Block, Block]
|
|
||||||
SExternBlockState = ExternBlockState[Block, Block]
|
|
||||||
SNamespaceBlockState = NamespaceBlockState[NamespaceScope, NamespaceScope]
|
|
||||||
SClassBlockState = ClassBlockState[ClassScope, Block]
|
SClassBlockState = ClassBlockState[ClassScope, Block]
|
||||||
|
SExternBlockState = ExternBlockState[NamespaceScope, NamespaceScope]
|
||||||
|
SNamespaceBlockState = NamespaceBlockState[NamespaceScope, NamespaceScope]
|
||||||
|
|
||||||
|
SState = typing.Union[SClassBlockState, SExternBlockState, SNamespaceBlockState]
|
||||||
|
SNonClassBlockState = typing.Union[SExternBlockState, SNamespaceBlockState]
|
||||||
|
|
||||||
|
|
||||||
class SimpleCxxVisitor:
|
class SimpleCxxVisitor:
|
||||||
@ -209,16 +209,6 @@ 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) -> typing.Optional[bool]:
|
|
||||||
# this matters for some scope/resolving purposes, but you're
|
|
||||||
# probably going to want to use clang if you care about that
|
|
||||||
# level of detail
|
|
||||||
state.user_data = state.parent.user_data
|
|
||||||
return None
|
|
||||||
|
|
||||||
def on_empty_block_end(self, state: SEmptyBlockState) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_extern_block_start(self, state: SExternBlockState) -> typing.Optional[bool]:
|
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
|
return None
|
||||||
@ -254,8 +244,9 @@ class SimpleCxxVisitor:
|
|||||||
def on_namespace_end(self, state: SNamespaceBlockState) -> None:
|
def on_namespace_end(self, state: SNamespaceBlockState) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_namespace_alias(self, state: SState, alias: NamespaceAlias) -> None:
|
def on_namespace_alias(
|
||||||
assert isinstance(state.user_data, NamespaceScope)
|
self, state: SNonClassBlockState, alias: NamespaceAlias
|
||||||
|
) -> None:
|
||||||
state.user_data.ns_alias.append(alias)
|
state.user_data.ns_alias.append(alias)
|
||||||
|
|
||||||
def on_forward_decl(self, state: SState, fdecl: ForwardDecl) -> None:
|
def on_forward_decl(self, state: SState, fdecl: ForwardDecl) -> None:
|
||||||
@ -269,19 +260,18 @@ class SimpleCxxVisitor:
|
|||||||
assert isinstance(state.user_data, NamespaceScope)
|
assert isinstance(state.user_data, NamespaceScope)
|
||||||
state.user_data.variables.append(v)
|
state.user_data.variables.append(v)
|
||||||
|
|
||||||
def on_function(self, state: SState, fn: Function) -> None:
|
def on_function(self, state: SNonClassBlockState, fn: Function) -> None:
|
||||||
assert isinstance(state.user_data, NamespaceScope)
|
|
||||||
state.user_data.functions.append(fn)
|
state.user_data.functions.append(fn)
|
||||||
|
|
||||||
def on_method_impl(self, state: SState, method: Method) -> None:
|
def on_method_impl(self, state: SNonClassBlockState, method: Method) -> None:
|
||||||
assert isinstance(state.user_data, NamespaceScope)
|
|
||||||
state.user_data.method_impls.append(method)
|
state.user_data.method_impls.append(method)
|
||||||
|
|
||||||
def on_typedef(self, state: SState, typedef: Typedef) -> None:
|
def on_typedef(self, state: SState, typedef: Typedef) -> None:
|
||||||
state.user_data.typedefs.append(typedef)
|
state.user_data.typedefs.append(typedef)
|
||||||
|
|
||||||
def on_using_namespace(self, state: SState, namespace: typing.List[str]) -> None:
|
def on_using_namespace(
|
||||||
assert isinstance(state.user_data, NamespaceScope)
|
self, state: SNonClassBlockState, namespace: typing.List[str]
|
||||||
|
) -> None:
|
||||||
ns = UsingNamespace("::".join(namespace))
|
ns = UsingNamespace("::".join(namespace))
|
||||||
state.user_data.using_ns.append(ns)
|
state.user_data.using_ns.append(ns)
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ from .types import (
|
|||||||
|
|
||||||
from .parserstate import (
|
from .parserstate import (
|
||||||
State,
|
State,
|
||||||
EmptyBlockState,
|
|
||||||
ClassBlockState,
|
ClassBlockState,
|
||||||
ExternBlockState,
|
ExternBlockState,
|
||||||
NamespaceBlockState,
|
NamespaceBlockState,
|
||||||
|
NonClassBlockState,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -52,26 +52,6 @@ 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) -> typing.Optional[bool]:
|
|
||||||
"""
|
|
||||||
Called when a ``{`` is encountered that isn't associated with or
|
|
||||||
consumed by other declarations.
|
|
||||||
|
|
||||||
.. code-block:: c++
|
|
||||||
|
|
||||||
{
|
|
||||||
// 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:
|
|
||||||
"""
|
|
||||||
Called when an empty block ends
|
|
||||||
"""
|
|
||||||
|
|
||||||
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
|
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
|
||||||
"""
|
"""
|
||||||
.. code-block:: c++
|
.. code-block:: c++
|
||||||
@ -102,7 +82,9 @@ class CxxVisitor(Protocol):
|
|||||||
Called at the end of a ``namespace`` block
|
Called at the end of a ``namespace`` block
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
|
def on_namespace_alias(
|
||||||
|
self, state: NonClassBlockState, alias: NamespaceAlias
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Called when a ``namespace`` alias is encountered
|
Called when a ``namespace`` alias is encountered
|
||||||
"""
|
"""
|
||||||
@ -122,12 +104,12 @@ class CxxVisitor(Protocol):
|
|||||||
Called when a global variable is encountered
|
Called when a global variable is encountered
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_function(self, state: State, fn: Function) -> None:
|
def on_function(self, state: NonClassBlockState, fn: Function) -> None:
|
||||||
"""
|
"""
|
||||||
Called when a function is encountered that isn't part of a class
|
Called when a function is encountered that isn't part of a class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_method_impl(self, state: State, method: Method) -> None:
|
def on_method_impl(self, state: NonClassBlockState, method: Method) -> None:
|
||||||
"""
|
"""
|
||||||
Called when a method implementation is encountered outside of a class
|
Called when a method implementation is encountered outside of a class
|
||||||
declaration. For example:
|
declaration. For example:
|
||||||
@ -155,7 +137,9 @@ class CxxVisitor(Protocol):
|
|||||||
once for ``*PT``
|
once for ``*PT``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_using_namespace(self, state: State, namespace: typing.List[str]) -> None:
|
def on_using_namespace(
|
||||||
|
self, state: NonClassBlockState, namespace: typing.List[str]
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
.. code-block:: c++
|
.. code-block:: c++
|
||||||
|
|
||||||
@ -258,12 +242,6 @@ class NullVisitor:
|
|||||||
def on_include(self, state: State, filename: str) -> None:
|
def on_include(self, state: State, filename: str) -> None:
|
||||||
return 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]:
|
def on_extern_block_start(self, state: ExternBlockState) -> typing.Optional[bool]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -276,7 +254,9 @@ class NullVisitor:
|
|||||||
def on_namespace_end(self, state: NamespaceBlockState) -> None:
|
def on_namespace_end(self, state: NamespaceBlockState) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_namespace_alias(self, state: State, alias: NamespaceAlias) -> None:
|
def on_namespace_alias(
|
||||||
|
self, state: NonClassBlockState, alias: NamespaceAlias
|
||||||
|
) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
def on_forward_decl(self, state: State, fdecl: ForwardDecl) -> None:
|
||||||
@ -288,16 +268,18 @@ class NullVisitor:
|
|||||||
def on_variable(self, state: State, v: Variable) -> None:
|
def on_variable(self, state: State, v: Variable) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_function(self, state: State, fn: Function) -> None:
|
def on_function(self, state: NonClassBlockState, fn: Function) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_method_impl(self, state: State, method: Method) -> None:
|
def on_method_impl(self, state: NonClassBlockState, method: Method) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_typedef(self, state: State, typedef: Typedef) -> None:
|
def on_typedef(self, state: State, typedef: Typedef) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_using_namespace(self, state: State, namespace: typing.List[str]) -> None:
|
def on_using_namespace(
|
||||||
|
self, state: NonClassBlockState, namespace: typing.List[str]
|
||||||
|
) -> None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def on_using_alias(self, state: State, using: UsingAlias) -> None:
|
def on_using_alias(self, state: State, using: UsingAlias) -> None:
|
||||||
|
@ -351,29 +351,3 @@ def test_warning_directive() -> None:
|
|||||||
data = parse_string(content, cleandoc=True)
|
data = parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
assert data == ParsedData()
|
assert data == ParsedData()
|
||||||
|
|
||||||
|
|
||||||
def test_empty_block() -> None:
|
|
||||||
"""
|
|
||||||
Ensure the simple visitor doesn't break with an empty block
|
|
||||||
"""
|
|
||||||
content = """
|
|
||||||
{
|
|
||||||
class X {};
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
data = parse_string(content, cleandoc=True)
|
|
||||||
|
|
||||||
assert data == ParsedData(
|
|
||||||
namespace=NamespaceScope(
|
|
||||||
classes=[
|
|
||||||
ClassScope(
|
|
||||||
class_decl=ClassDecl(
|
|
||||||
typename=PQName(
|
|
||||||
segments=[NameSpecifier(name="X")], classkey="class"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
@ -10,7 +10,6 @@ from cxxheaderparser.simple import (
|
|||||||
NamespaceScope,
|
NamespaceScope,
|
||||||
ParsedData,
|
ParsedData,
|
||||||
SClassBlockState,
|
SClassBlockState,
|
||||||
SEmptyBlockState,
|
|
||||||
SExternBlockState,
|
SExternBlockState,
|
||||||
SNamespaceBlockState,
|
SNamespaceBlockState,
|
||||||
SimpleCxxVisitor,
|
SimpleCxxVisitor,
|
||||||
@ -148,53 +147,6 @@ def test_skip_class() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# 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
|
# ensure namespace 'skip' is skipped
|
||||||
#
|
#
|
||||||
|
Loading…
x
Reference in New Issue
Block a user