Add support for inline namespaces

This commit is contained in:
Dustin Spicuzza 2022-12-09 00:20:09 -05:00
parent 305312b095
commit dc76328bd5
3 changed files with 57 additions and 0 deletions

View File

@ -284,6 +284,7 @@ class CxxParser:
"alignas": self._consume_attribute_specifier_seq,
"extern": self._parse_extern,
"friend": self._parse_friend_decl,
"inline": self._parse_inline,
"namespace": self._parse_namespace,
"private": self._process_access_specifier,
"protected": self._process_access_specifier,
@ -398,6 +399,9 @@ class CxxParser:
tok = self._next_token_must_be("NAME")
if inline and len(names) > 1:
raise CxxParseError("a nested namespace definition cannot be inline")
# TODO: namespace_alias_definition
ns = NamespaceDecl(names, inline)

View File

@ -91,6 +91,7 @@ class NamespaceScope:
"""
name: str = ""
inline: bool = False
classes: typing.List["ClassScope"] = field(default_factory=list)
enums: typing.List[EnumDecl] = field(default_factory=list)
@ -248,6 +249,9 @@ class SimpleCxxVisitor:
assert ns is not None
# only set inline on inner namespace
ns.inline = state.namespace.inline
self.block = ns
self.namespace = ns

View File

@ -1,6 +1,8 @@
# Note: testcases generated via `python -m cxxheaderparser.gentest`
from cxxheaderparser.errors import CxxParseError
from cxxheaderparser.types import (
ForwardDecl,
FundamentalSpecifier,
NameSpecifier,
PQName,
@ -15,6 +17,9 @@ from cxxheaderparser.simple import (
ParsedData,
)
import pytest
import re
def test_dups_in_different_ns() -> None:
content = """
@ -119,3 +124,47 @@ def test_correct_ns() -> None:
}
)
)
def test_inline_namespace() -> None:
content = """
namespace Lib {
inline namespace Lib_1 {
class A;
}
}
"""
data = parse_string(content, cleandoc=True)
assert data == ParsedData(
namespace=NamespaceScope(
namespaces={
"Lib": NamespaceScope(
name="Lib",
namespaces={
"Lib_1": NamespaceScope(
name="Lib_1",
inline=True,
forward_decls=[
ForwardDecl(
typename=PQName(
segments=[NameSpecifier(name="A")],
classkey="class",
)
)
],
)
},
)
}
)
)
def test_invalid_inline_namespace() -> None:
content = """
inline namespace a::b {}
"""
err = "<str>:1: parse error evaluating 'inline': a nested namespace definition cannot be inline"
with pytest.raises(CxxParseError, match=re.escape(err)):
parse_string(content, cleandoc=True)