Remove EmptyBlockState
- Turns out you can't put an empty block except in code
This commit is contained in:
parent
8c69970857
commit
326da6112c
@ -10,7 +10,6 @@ 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,
|
||||||
ParsedTypeModifiers,
|
ParsedTypeModifiers,
|
||||||
@ -510,9 +509,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()
|
||||||
|
@ -56,13 +56,6 @@ class State(typing.Generic[T, PT]):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class EmptyBlockState(State[T, PT]):
|
|
||||||
parent: State[PT, typing.Any]
|
|
||||||
|
|
||||||
def _finish(self, visitor: "CxxVisitor") -> None:
|
|
||||||
visitor.on_empty_block_end(self)
|
|
||||||
|
|
||||||
|
|
||||||
class ExternBlockState(State[T, PT]):
|
class ExternBlockState(State[T, PT]):
|
||||||
parent: State[PT, typing.Any]
|
parent: State[PT, typing.Any]
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ from .types import (
|
|||||||
|
|
||||||
from .parserstate import (
|
from .parserstate import (
|
||||||
State,
|
State,
|
||||||
EmptyBlockState,
|
|
||||||
ClassBlockState,
|
ClassBlockState,
|
||||||
ExternBlockState,
|
ExternBlockState,
|
||||||
NamespaceBlockState,
|
NamespaceBlockState,
|
||||||
@ -181,7 +180,6 @@ 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]
|
SState = State[Block, Block]
|
||||||
SEmptyBlockState = EmptyBlockState[Block, Block]
|
|
||||||
SExternBlockState = ExternBlockState[Block, Block]
|
SExternBlockState = ExternBlockState[Block, Block]
|
||||||
SNamespaceBlockState = NamespaceBlockState[NamespaceScope, NamespaceScope]
|
SNamespaceBlockState = NamespaceBlockState[NamespaceScope, NamespaceScope]
|
||||||
SClassBlockState = ClassBlockState[ClassScope, Block]
|
SClassBlockState = ClassBlockState[ClassScope, Block]
|
||||||
@ -209,16 +207,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
|
||||||
|
@ -25,7 +25,6 @@ from .types import (
|
|||||||
|
|
||||||
from .parserstate import (
|
from .parserstate import (
|
||||||
State,
|
State,
|
||||||
EmptyBlockState,
|
|
||||||
ClassBlockState,
|
ClassBlockState,
|
||||||
ExternBlockState,
|
ExternBlockState,
|
||||||
NamespaceBlockState,
|
NamespaceBlockState,
|
||||||
@ -52,26 +51,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++
|
||||||
@ -258,12 +237,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
|
||||||
|
|
||||||
|
@ -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