# Note: testcases generated via `python -m cxxheaderparser.gentest` from cxxheaderparser.types import ( Array, AutoSpecifier, ClassDecl, Function, FunctionType, FundamentalSpecifier, Method, MoveReference, NameSpecifier, PQName, Parameter, Pointer, Reference, TemplateArgument, TemplateDecl, TemplateSpecialization, TemplateTypeParam, Token, Type, Typedef, Value, ) from cxxheaderparser.simple import ( ClassScope, NamespaceScope, parse_string, ParsedData, ) def test_fn_returns_class() -> None: content = """ class X *fn1(); struct Y fn2(); enum E fn3(); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Pointer( ptr_to=Type( typename=PQName( segments=[NameSpecifier(name="X")], classkey="class" ) ) ), name=PQName(segments=[NameSpecifier(name="fn1")]), parameters=[], ), Function( return_type=Type( typename=PQName( segments=[NameSpecifier(name="Y")], classkey="struct" ) ), name=PQName(segments=[NameSpecifier(name="fn2")]), parameters=[], ), Function( return_type=Type( typename=PQName( segments=[NameSpecifier(name="E")], classkey="enum" ) ), name=PQName(segments=[NameSpecifier(name="fn3")]), parameters=[], ), ] ) ) def test_fn_returns_typename() -> None: content = """ typename ns::X fn(); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="ns"), NameSpecifier(name="X"), ], has_typename=True, ) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], ) ] ) ) def test_fn_returns_typename_const() -> None: content = """ const typename ns::X fn(); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="ns"), NameSpecifier(name="X"), ], has_typename=True, ), const=True, ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], ) ] ) ) def test_fn_pointer_params() -> None: content = """ int fn1(int *); int fn2(int *p); int fn3(int(*p)); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn1")]), parameters=[ Parameter( type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ) ), ) ], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn2")]), parameters=[ Parameter( name="p", type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ) ), ) ], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn3")]), parameters=[ Parameter( name="p", type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ) ), ) ], ), ] ) ) def test_fn_void_is_no_params() -> None: content = """ int fn(void); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], ) ] ) ) def test_fn_array_param() -> None: content = """ void fn(int array[]); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[ Parameter( name="array", type=Array( array_of=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), size=None, ), ) ], ) ] ) ) def test_fn_typename_param() -> None: content = """ void MethodA(const mynamespace::SomeObject &x, typename mynamespace::SomeObject * = 0); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="MethodA")]), parameters=[ Parameter( type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier(name="mynamespace"), NameSpecifier(name="SomeObject"), ] ), const=True, ) ), name="x", ), Parameter( type=Pointer( ptr_to=Type( typename=PQName( segments=[ NameSpecifier(name="mynamespace"), NameSpecifier(name="SomeObject"), ], has_typename=True, ) ) ), default=Value(tokens=[Token(value="0")]), ), ], ) ] ) ) def test_fn_weird_refs() -> None: content = """ int aref(int(&x)); void ptr_ref(int(*&name)); void ref_to_array(int (&array)[]); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="aref")]), parameters=[ Parameter( name="x", type=Reference( ref_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ) ), ) ], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="ptr_ref")]), parameters=[ Parameter( name="name", type=Reference( ref_to=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ) ) ), ) ], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="ref_to_array")]), parameters=[ Parameter( name="array", type=Reference( ref_to=Array( array_of=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), size=None, ) ), ) ], ), ] ) ) def test_fn_too_many_parens() -> None: content = """ int fn1(int (x)); void (fn2 (int (*const (name)))); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn1")]), parameters=[ Parameter( name="x", type=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), ) ], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn2")]), parameters=[ Parameter( name="name", type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ) ), const=True, ), ) ], ), ] ) ) # TODO calling conventions """ void __stdcall fn(); void (__stdcall * fn) """ def test_fn_same_line() -> None: # multiple functions on the same line content = """ void fn1(), fn2(); void *fn3(), fn4(); """ data = parse_string(content, cleandoc=True) 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="fn2")]), parameters=[], ), Function( return_type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="void")] ) ) ), name=PQName(segments=[NameSpecifier(name="fn3")]), parameters=[], ), Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn4")]), parameters=[], ), ] ) ) def test_fn_auto_template() -> None: content = """ template auto add(T t, U u) { return t + u; } """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type(typename=PQName(segments=[AutoSpecifier()])), name=PQName(segments=[NameSpecifier(name="add")]), parameters=[ Parameter( type=Type( typename=PQName(segments=[NameSpecifier(name="T")]) ), name="t", ), Parameter( type=Type( typename=PQName(segments=[NameSpecifier(name="U")]) ), name="u", ), ], has_body=True, template=TemplateDecl( params=[ TemplateTypeParam(typekey="class", name="T"), TemplateTypeParam(typekey="class", name="U"), ] ), ) ] ) ) def test_fn_template_ptr() -> None: content = """ std::vector *fn(std::vector *ps); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Pointer( ptr_to=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="vector", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Pointer( ptr_to=Type( typename=PQName( segments=[ NameSpecifier( name="Pointer" ) ] ) ) ) ) ] ), ), ] ) ) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[ Parameter( type=Pointer( ptr_to=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="vector", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=Pointer( ptr_to=Type( typename=PQName( segments=[ NameSpecifier( name="Pointer" ) ] ) ) ) ) ] ), ), ] ) ) ), name="ps", ) ], ) ] ) ) def test_fn_with_impl() -> None: content = """ // clang-format off void termite(void) { return ((structA*) (Func())->element); } """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="termite")]), parameters=[], has_body=True, ) ] ) ) def test_fn_return_std_function() -> None: content = """ std::function fn(); """ data1 = parse_string(content, cleandoc=True) content = """ std::function fn(); """ data2 = parse_string(content, cleandoc=True) expected = ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="function", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=FunctionType( return_type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="void" ) ] ) ), parameters=[ Parameter( type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ) ], ) ) ] ), ), ] ) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], ) ] ) ) assert data1 == expected assert data2 == expected def test_fn_return_std_function_trailing() -> None: content = """ std::functionint> fn(); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="function", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=FunctionType( return_type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ), parameters=[ Parameter( type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ) ) ], has_trailing_return=True, ) ) ] ), ), ] ) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], ) ] ) ) def test_fn_trailing_return_simple() -> None: content = """ auto fn() -> int; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], has_trailing_return=True, ) ] ) ) def test_fn_trailing_return_std_function() -> None: content = """ auto fn() -> std::function; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="function", specialization=TemplateSpecialization( args=[ TemplateArgument( arg=FunctionType( return_type=Type( typename=PQName( segments=[ FundamentalSpecifier( name="int" ) ] ) ), parameters=[], ) ) ] ), ), ] ) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], has_trailing_return=True, ) ] ) ) def test_inline_volatile_fn() -> None: content = """ inline int Standard_Atomic_Increment (volatile int* theValue); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="int")]) ), name=PQName( segments=[NameSpecifier(name="Standard_Atomic_Increment")] ), parameters=[ Parameter( type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="int")] ), volatile=True, ) ), name="theValue", ) ], inline=True, ) ] ) ) def test_method_w_reference() -> None: content = """ struct StreamBuffer { StreamBuffer &operator<<(std::ostream &(*fn)(std::ostream &)) { return *this; } }; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( classes=[ ClassScope( class_decl=ClassDecl( typename=PQName( segments=[NameSpecifier(name="StreamBuffer")], classkey="struct", ) ), methods=[ Method( return_type=Reference( ref_to=Type( typename=PQName( segments=[NameSpecifier(name="StreamBuffer")] ) ) ), name=PQName(segments=[NameSpecifier(name="operator<<")]), parameters=[ Parameter( type=Pointer( ptr_to=FunctionType( return_type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier(name="std"), NameSpecifier( name="ostream" ), ] ) ) ), parameters=[ Parameter( type=Reference( ref_to=Type( typename=PQName( segments=[ NameSpecifier( name="std" ), NameSpecifier( name="ostream" ), ] ) ) ) ) ], ) ), name="fn", ) ], has_body=True, access="public", operator="<<", ) ], ) ] ) ) def test_fn_w_mvreference() -> None: content = """ void fn1(int && (*)(int)); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn1")]), parameters=[ Parameter( type=Pointer( ptr_to=FunctionType( return_type=MoveReference( moveref_to=Type( typename=PQName( segments=[ FundamentalSpecifier(name="int") ] ) ) ), parameters=[ Parameter( type=Type( typename=PQName( segments=[ FundamentalSpecifier(name="int") ] ) ) ) ], ) ) ) ], ) ] ) ) def test_msvc_conventions() -> None: content = """ void __cdecl fn(); typedef const char* (__stdcall *wglGetExtensionsStringARB_t)(HDC theDeviceContext); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="fn")]), parameters=[], msvc_convention="__cdecl", ) ], typedefs=[ Typedef( type=Pointer( ptr_to=FunctionType( return_type=Pointer( ptr_to=Type( typename=PQName( segments=[FundamentalSpecifier(name="char")] ), const=True, ) ), parameters=[ Parameter( type=Type( typename=PQName( segments=[NameSpecifier(name="HDC")] ) ), name="theDeviceContext", ) ], msvc_convention="__stdcall", ) ), name="wglGetExtensionsStringARB_t", ) ], ) ) def test_throw_empty() -> None: content = """ void foo() throw() { throw std::runtime_error("foo"); } """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="foo")]), parameters=[], has_body=True, throw=Value(tokens=[]), ) ] ) ) def test_throw_dynamic() -> None: content = """ void foo() throw(std::exception) { throw std::runtime_error("foo"); } """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="foo")]), parameters=[], has_body=True, throw=Value( tokens=[ Token(value="std"), Token(value="::"), Token(value="exception"), ] ), ) ] ) ) def test_noexcept_empty() -> None: content = """ void foo() noexcept; """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="foo")]), parameters=[], noexcept=Value(tokens=[]), ) ] ) ) def test_noexcept_contents() -> None: content = """ void foo() noexcept(false); """ data = parse_string(content, cleandoc=True) assert data == ParsedData( namespace=NamespaceScope( functions=[ Function( return_type=Type( typename=PQName(segments=[FundamentalSpecifier(name="void")]) ), name=PQName(segments=[NameSpecifier(name="foo")]), parameters=[], noexcept=Value(tokens=[Token(value="false")]), ) ] ) )