From 919e35e45fd35199471d4a1e7c68406bf0a33bce Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Thu, 8 Dec 2022 02:00:05 -0500 Subject: [PATCH] Correctly parse constructor implementations outside of a class - Fixes #32 --- cxxheaderparser/parser.py | 18 ++++++++++++++---- tests/test_class.py | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cxxheaderparser/parser.py b/cxxheaderparser/parser.py index 1ae710f..0e3dbc5 100644 --- a/cxxheaderparser/parser.py +++ b/cxxheaderparser/parser.py @@ -2131,12 +2131,22 @@ class CxxParser: tok = self.lex.token_if("(") if tok: - # Check to see if this is a constructor/destructor - if isinstance(state, ClassBlockState) and isinstance(dtype, Type): - + dsegments: typing.List[PQNameSegment] = [] + if isinstance(dtype, Type): dsegments = dtype.typename.segments - if not is_friend: + # Check to see if this is a constructor/destructor by matching + # the method name to the class name + is_class_block = isinstance(state, ClassBlockState) + if (is_class_block or len(dsegments) > 1) and isinstance(dtype, Type): + + if not is_class_block: + # must be an instance of a class + cls_name = getattr(dsegments[-2], "name", None) + + elif not is_friend: + assert isinstance(state, ClassBlockState) + # class name to match against is this class cls_name = getattr( state.class_decl.typename.segments[-1], "name", None diff --git a/tests/test_class.py b/tests/test_class.py index 2815209..c8ec97d 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -3236,3 +3236,27 @@ def test_method_outside_class() -> None: ] ) ) + + +def test_constructor_outside_class() -> None: + content = """ + inline foo::foo() {} + """ + data = parse_string(content, cleandoc=True) + + assert data == ParsedData( + namespace=NamespaceScope( + method_impls=[ + Method( + return_type=None, + name=PQName( + segments=[NameSpecifier(name="foo"), NameSpecifier(name="foo")] + ), + parameters=[], + inline=True, + has_body=True, + constructor=True, + ) + ] + ) + )