Initial commit
This commit is contained in:
25
tests/README.md
Normal file
25
tests/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
Tests
|
||||
=====
|
||||
|
||||
To run the tests, install `cxxheaderparser` and `pytest`, then just run:
|
||||
|
||||
pytest
|
||||
|
||||
Adding new tests
|
||||
----------------
|
||||
|
||||
There's a helper script in cxxheaderparser explicitly for generating many of the
|
||||
unit tests in this directory. To run it:
|
||||
|
||||
* Create a file with your C++ content in it
|
||||
* Run `python -m cxxheaderparser.gentest FILENAME.h some_name`
|
||||
* Copy the stdout to one of these `test_*.py` files
|
||||
|
||||
Content origin
|
||||
--------------
|
||||
|
||||
* Some are scraps of real code derived from various sources
|
||||
* Some were derived from the original `CppHeaderParser` tests
|
||||
* Some have been derived from examples found on https://en.cppreference.com,
|
||||
which are available under Creative Commons Attribution-Sharealike 3.0
|
||||
Unported License (CC-BY-SA)
|
||||
148
tests/test_attributes.py
Normal file
148
tests/test_attributes.py
Normal file
@@ -0,0 +1,148 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
ClassDecl,
|
||||
EnumDecl,
|
||||
Enumerator,
|
||||
Field,
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Pointer,
|
||||
Token,
|
||||
Type,
|
||||
Typedef,
|
||||
Value,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_attributes_everywhere():
|
||||
# TODO: someday we'll actually support storing attributes,
|
||||
# but for now just make sure they don't get in the way
|
||||
|
||||
content = """
|
||||
struct [[deprecated]] S {};
|
||||
[[deprecated]] typedef S *PS;
|
||||
|
||||
[[deprecated]] int x;
|
||||
union U {
|
||||
[[deprecated]] int n;
|
||||
};
|
||||
[[deprecated]] void f();
|
||||
|
||||
enum [[deprecated]] E{A [[deprecated]], B [[deprecated]] = 42};
|
||||
|
||||
struct alignas(8) AS {};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="S")], classkey="struct"
|
||||
)
|
||||
)
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="U")], classkey="union"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="n",
|
||||
)
|
||||
],
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="AS")], classkey="struct"
|
||||
)
|
||||
)
|
||||
),
|
||||
],
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
values=[
|
||||
Enumerator(name="A"),
|
||||
Enumerator(name="B", value=Value(tokens=[Token(value="42")])),
|
||||
],
|
||||
)
|
||||
],
|
||||
functions=[
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="f")]),
|
||||
parameters=[],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(typename=PQName(segments=[NameSpecifier(name="S")]))
|
||||
),
|
||||
name="PS",
|
||||
)
|
||||
],
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_attributes_gcc_enum_packed():
|
||||
content = """
|
||||
enum Wheat {
|
||||
w1,
|
||||
w2,
|
||||
w3,
|
||||
} __attribute__((packed));
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Wheat")], classkey="enum"
|
||||
),
|
||||
values=[
|
||||
Enumerator(name="w1"),
|
||||
Enumerator(name="w2"),
|
||||
Enumerator(name="w3"),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
2843
tests/test_class.py
Normal file
2843
tests/test_class.py
Normal file
File diff suppressed because it is too large
Load Diff
247
tests/test_class_base.py
Normal file
247
tests/test_class_base.py
Normal file
@@ -0,0 +1,247 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
BaseClass,
|
||||
ClassDecl,
|
||||
Field,
|
||||
FundamentalSpecifier,
|
||||
Method,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
TemplateArgument,
|
||||
TemplateSpecialization,
|
||||
Token,
|
||||
Type,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_class_private_base():
|
||||
content = """
|
||||
namespace Citrus
|
||||
{
|
||||
class BloodOrange { };
|
||||
}
|
||||
|
||||
class Bananna: public Citrus::BloodOrange
|
||||
{
|
||||
};
|
||||
|
||||
class ExcellentCake: private Citrus::BloodOrange, Convoluted::Nested::Mixin
|
||||
{
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Bananna")], classkey="class"
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="Citrus"),
|
||||
NameSpecifier(name="BloodOrange"),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="ExcellentCake")],
|
||||
classkey="class",
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="private",
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="Citrus"),
|
||||
NameSpecifier(name="BloodOrange"),
|
||||
]
|
||||
),
|
||||
),
|
||||
BaseClass(
|
||||
access="private",
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="Convoluted"),
|
||||
NameSpecifier(name="Nested"),
|
||||
NameSpecifier(name="Mixin"),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
namespaces={
|
||||
"Citrus": NamespaceScope(
|
||||
name="Citrus",
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BloodOrange")],
|
||||
classkey="class",
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_class_virtual_base():
|
||||
content = """
|
||||
class BaseMangoClass {};
|
||||
class MangoClass : virtual public BaseMangoClass {};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BaseMangoClass")],
|
||||
classkey="class",
|
||||
)
|
||||
)
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="MangoClass")],
|
||||
classkey="class",
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BaseMangoClass")]
|
||||
),
|
||||
virtual=True,
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_class_multiple_base_with_virtual():
|
||||
content = """
|
||||
class BlueJay : public Bird, public virtual Food {
|
||||
public:
|
||||
BlueJay() {}
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BlueJay")], classkey="class"
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(segments=[NameSpecifier(name="Bird")]),
|
||||
),
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(segments=[NameSpecifier(name="Food")]),
|
||||
virtual=True,
|
||||
),
|
||||
],
|
||||
),
|
||||
methods=[
|
||||
Method(
|
||||
return_type=None,
|
||||
name=PQName(segments=[NameSpecifier(name="BlueJay")]),
|
||||
parameters=[],
|
||||
has_body=True,
|
||||
access="public",
|
||||
constructor=True,
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_class_base_specialized():
|
||||
content = """
|
||||
class Pea : public Vegetable<Green> {
|
||||
int i;
|
||||
};
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Pea")], classkey="class"
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(
|
||||
name="Vegetable",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(
|
||||
tokens=[Token(value="Green")]
|
||||
)
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="private",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="i",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
221
tests/test_doxygen.py
Normal file
221
tests/test_doxygen.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
AnonymousName,
|
||||
Array,
|
||||
BaseClass,
|
||||
ClassDecl,
|
||||
EnumDecl,
|
||||
Enumerator,
|
||||
Field,
|
||||
ForwardDecl,
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
Method,
|
||||
MoveReference,
|
||||
NameSpecifier,
|
||||
Operator,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Reference,
|
||||
TemplateArgument,
|
||||
TemplateDecl,
|
||||
TemplateSpecialization,
|
||||
TemplateTypeParam,
|
||||
Token,
|
||||
Type,
|
||||
Typedef,
|
||||
UsingDecl,
|
||||
Value,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
r"""
|
||||
class SampleClass: public BaseSampleClass
|
||||
{
|
||||
public:
|
||||
enum Elephant
|
||||
{
|
||||
EL_ONE = 1,
|
||||
EL_TWO = 2,
|
||||
EL_NINE = 9,
|
||||
EL_TEN,
|
||||
};
|
||||
|
||||
SampleClass();
|
||||
/*!
|
||||
* Method 1
|
||||
*/
|
||||
string meth1();
|
||||
|
||||
///
|
||||
/// Method 2 description
|
||||
///
|
||||
/// @param v1 Variable 1
|
||||
///
|
||||
int meth2(int v1);
|
||||
|
||||
/**
|
||||
* Method 3 description
|
||||
*
|
||||
* \param v1 Variable 1 with a really long
|
||||
* wrapping description
|
||||
* \param v2 Variable 2
|
||||
*/
|
||||
void meth3(const string & v1, vector<string> & v2);
|
||||
|
||||
/**********************************
|
||||
* Method 4 description
|
||||
*
|
||||
* @return Return value
|
||||
*********************************/
|
||||
unsigned int meth4();
|
||||
private:
|
||||
void * meth5(){return NULL;}
|
||||
|
||||
/// prop1 description
|
||||
string prop1;
|
||||
//! prop5 description
|
||||
int prop5;
|
||||
|
||||
bool prop6; /*!< prop6 description */
|
||||
|
||||
double prop7; //!< prop7 description
|
||||
//!< with two lines
|
||||
|
||||
/// prop8 description
|
||||
int prop8;
|
||||
};
|
||||
namespace Alpha
|
||||
{
|
||||
class AlphaClass
|
||||
{
|
||||
public:
|
||||
AlphaClass();
|
||||
|
||||
void alphaMethod();
|
||||
|
||||
string alphaString;
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
Z_A,
|
||||
Z_B = 0x2B,
|
||||
Z_C = 'j',
|
||||
Z_D,
|
||||
} Zebra;
|
||||
};
|
||||
|
||||
namespace Omega
|
||||
{
|
||||
class OmegaClass
|
||||
{
|
||||
public:
|
||||
OmegaClass();
|
||||
|
||||
string omegaString;
|
||||
protected:
|
||||
///
|
||||
/// @brief Rino Numbers, not that that means anything
|
||||
///
|
||||
typedef enum
|
||||
{
|
||||
RI_ZERO, /// item zero
|
||||
RI_ONE, /** item one */
|
||||
RI_TWO, //!< item two
|
||||
RI_THREE,
|
||||
/// item four
|
||||
RI_FOUR,
|
||||
} Rino;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# def test_doxygen_messy():
|
||||
# content = """
|
||||
# // clang-format off
|
||||
|
||||
# /// fn comment
|
||||
# void
|
||||
# fn();
|
||||
|
||||
# /// var comment
|
||||
# int
|
||||
# v1 = 0;
|
||||
|
||||
# int
|
||||
# v2 = 0; /// var2 comment
|
||||
|
||||
# /// cls comment
|
||||
# class
|
||||
# C {};
|
||||
|
||||
# /// template comment
|
||||
# template <typename T>
|
||||
# class
|
||||
# C2 {};
|
||||
# """
|
||||
# data = parse_string(content, cleandoc=True)
|
||||
|
||||
# assert data == ParsedData(
|
||||
# namespace=NamespaceScope(
|
||||
# classes=[
|
||||
# ClassScope(
|
||||
# class_decl=ClassDecl(
|
||||
# typename=PQName(
|
||||
# segments=[NameSpecifier(name="C")], classkey="class"
|
||||
# ),
|
||||
# doxygen="/// cls comment",
|
||||
# )
|
||||
# ),
|
||||
# ClassScope(
|
||||
# class_decl=ClassDecl(
|
||||
# typename=PQName(
|
||||
# segments=[NameSpecifier(name="C2")], classkey="class"
|
||||
# ),
|
||||
# template=TemplateDecl(
|
||||
# params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||
# ),
|
||||
# doxygen="/// template comment",
|
||||
# )
|
||||
# ),
|
||||
# ],
|
||||
# functions=[
|
||||
# Function(
|
||||
# return_type=Type(
|
||||
# typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||
# ),
|
||||
# name=PQName(segments=[NameSpecifier(name="fn")]),
|
||||
# parameters=[],
|
||||
# doxygen="/// fn comment",
|
||||
# )
|
||||
# ],
|
||||
# variables=[
|
||||
# Variable(
|
||||
# name=PQName(segments=[NameSpecifier(name="v1")]),
|
||||
# type=Type(
|
||||
# typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
# ),
|
||||
# value=Value(tokens=[Token(value="0")]),
|
||||
# doxygen="/// var comment",
|
||||
# ),
|
||||
# Variable(
|
||||
# name=PQName(segments=[NameSpecifier(name="v2")]),
|
||||
# type=Type(
|
||||
# typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
# ),
|
||||
# value=Value(tokens=[Token(value="0")]),
|
||||
# ),
|
||||
# ],
|
||||
# )
|
||||
# )
|
||||
649
tests/test_enum.py
Normal file
649
tests/test_enum.py
Normal file
@@ -0,0 +1,649 @@
|
||||
from cxxheaderparser.types import (
|
||||
AnonymousName,
|
||||
ClassDecl,
|
||||
EnumDecl,
|
||||
Enumerator,
|
||||
Field,
|
||||
ForwardDecl,
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Token,
|
||||
Type,
|
||||
Typedef,
|
||||
Value,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_basic_enum():
|
||||
content = """
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Foo")], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="A"), Enumerator(name="B")],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_w_expr():
|
||||
content = """
|
||||
enum Foo {
|
||||
A = (1 / 2),
|
||||
B = 3,
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Foo")], classkey="enum"
|
||||
),
|
||||
values=[
|
||||
Enumerator(
|
||||
name="A",
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="("),
|
||||
Token(value="1"),
|
||||
Token(value="/"),
|
||||
Token(value="2"),
|
||||
Token(value=")"),
|
||||
]
|
||||
),
|
||||
),
|
||||
Enumerator(name="B", value=Value(tokens=[Token(value="3")])),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_w_multiline_expr():
|
||||
content = r"""
|
||||
// clang-format off
|
||||
enum Author
|
||||
{
|
||||
NAME = ('J' << 24 | \
|
||||
'A' << 16 | \
|
||||
'S' << 8 | \
|
||||
'H'),
|
||||
};
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Author")], classkey="enum"
|
||||
),
|
||||
values=[
|
||||
Enumerator(
|
||||
name="NAME",
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="("),
|
||||
Token(value="'J'"),
|
||||
Token(value="<<"),
|
||||
Token(value="24"),
|
||||
Token(value="|"),
|
||||
Token(value="\\"),
|
||||
Token(value="'A'"),
|
||||
Token(value="<<"),
|
||||
Token(value="16"),
|
||||
Token(value="|"),
|
||||
Token(value="\\"),
|
||||
Token(value="'S'"),
|
||||
Token(value="<<"),
|
||||
Token(value="8"),
|
||||
Token(value="|"),
|
||||
Token(value="\\"),
|
||||
Token(value="'H'"),
|
||||
Token(value=")"),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_basic_enum_class():
|
||||
content = """
|
||||
enum class BE { BEX };
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
),
|
||||
values=[Enumerator(name="BEX")],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_basic_enum_struct():
|
||||
content = """
|
||||
enum struct BE { BEX };
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum struct"
|
||||
),
|
||||
values=[Enumerator(name="BEX")],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_base():
|
||||
content = """
|
||||
enum class E : int {};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum class"
|
||||
),
|
||||
values=[],
|
||||
base=PQName(segments=[FundamentalSpecifier(name="int")]),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# instances
|
||||
|
||||
|
||||
def test_enum_instance_1():
|
||||
content = """
|
||||
enum class BE { BEX } be1;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
),
|
||||
values=[Enumerator(name="BEX")],
|
||||
)
|
||||
],
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="be1")]),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_instance_2():
|
||||
content = """
|
||||
enum class BE { BEX } be1, *be2;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
),
|
||||
values=[Enumerator(name="BEX")],
|
||||
)
|
||||
],
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="be1")]),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
)
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="be2")]),
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")],
|
||||
classkey="enum class",
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# bases in namespaces
|
||||
|
||||
|
||||
def test_enum_base_in_ns():
|
||||
content = """
|
||||
namespace EN {
|
||||
typedef int EINT;
|
||||
};
|
||||
|
||||
enum class BE : EN::EINT { BEX };
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum class"
|
||||
),
|
||||
values=[Enumerator(name="BEX")],
|
||||
base=PQName(
|
||||
segments=[NameSpecifier(name="EN"), NameSpecifier(name="EINT")]
|
||||
),
|
||||
)
|
||||
],
|
||||
namespaces={
|
||||
"EN": NamespaceScope(
|
||||
name="EN",
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="EINT",
|
||||
)
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# forward declarations
|
||||
|
||||
|
||||
def test_enum_fwd():
|
||||
content = """
|
||||
enum class BE1;
|
||||
enum class BE2 : EN::EINT;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
forward_decls=[
|
||||
ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE1")], classkey="enum class"
|
||||
)
|
||||
),
|
||||
ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE2")], classkey="enum class"
|
||||
),
|
||||
enum_base=PQName(
|
||||
segments=[NameSpecifier(name="EN"), NameSpecifier(name="EINT")]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_private_in_class():
|
||||
content = """
|
||||
|
||||
class C {
|
||||
enum E { E1 };
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="C")], classkey="class"
|
||||
)
|
||||
),
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="E1")],
|
||||
access="private",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_public_in_class():
|
||||
content = """
|
||||
|
||||
class C {
|
||||
public:
|
||||
enum E { E1 };
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="C")], classkey="class"
|
||||
)
|
||||
),
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="E1")],
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_default_enum():
|
||||
content = """
|
||||
class A {
|
||||
enum {
|
||||
v1,
|
||||
v2,
|
||||
} m_v1 = v1;
|
||||
|
||||
enum { vv1, vv2, vv3 } m_v2 = vv2, m_v3 = vv3;
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="A")], classkey="class"
|
||||
)
|
||||
),
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="v1"), Enumerator(name="v2")],
|
||||
access="private",
|
||||
),
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=2)], classkey="enum"
|
||||
),
|
||||
values=[
|
||||
Enumerator(name="vv1"),
|
||||
Enumerator(name="vv2"),
|
||||
Enumerator(name="vv3"),
|
||||
],
|
||||
access="private",
|
||||
),
|
||||
],
|
||||
fields=[
|
||||
Field(
|
||||
access="private",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="enum"
|
||||
)
|
||||
),
|
||||
name="m_v1",
|
||||
value=Value(tokens=[Token(value="v1")]),
|
||||
),
|
||||
Field(
|
||||
access="private",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=2)], classkey="enum"
|
||||
)
|
||||
),
|
||||
name="m_v2",
|
||||
value=Value(tokens=[Token(value="vv2")]),
|
||||
),
|
||||
Field(
|
||||
access="private",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=2)], classkey="enum"
|
||||
)
|
||||
),
|
||||
name="m_v3",
|
||||
value=Value(tokens=[Token(value="vv3")]),
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_template_vals():
|
||||
content = """
|
||||
enum {
|
||||
IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
|
||||
IteratorCategoryT>::value,
|
||||
IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag,
|
||||
IteratorCategoryT>::value,
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[
|
||||
Enumerator(
|
||||
name="IsRandomAccess",
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="std"),
|
||||
Token(value="::"),
|
||||
Token(value="is_base_of"),
|
||||
Token(value="<"),
|
||||
Token(value="std"),
|
||||
Token(value="::"),
|
||||
Token(value="random_access_iterator_tag"),
|
||||
Token(value=","),
|
||||
Token(value="IteratorCategoryT"),
|
||||
Token(value=">"),
|
||||
Token(value="::"),
|
||||
Token(value="value"),
|
||||
]
|
||||
),
|
||||
),
|
||||
Enumerator(
|
||||
name="IsBidirectional",
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="std"),
|
||||
Token(value="::"),
|
||||
Token(value="is_base_of"),
|
||||
Token(value="<"),
|
||||
Token(value="std"),
|
||||
Token(value="::"),
|
||||
Token(value="bidirectional_iterator_tag"),
|
||||
Token(value=","),
|
||||
Token(value="IteratorCategoryT"),
|
||||
Token(value=">"),
|
||||
Token(value="::"),
|
||||
Token(value="value"),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_fn():
|
||||
content = """
|
||||
enum E {
|
||||
VALUE,
|
||||
};
|
||||
|
||||
void fn_with_enum_param1(const enum E e);
|
||||
|
||||
void fn_with_enum_param2(const enum E e) {
|
||||
// code here
|
||||
}
|
||||
|
||||
enum E fn_with_enum_retval1(void);
|
||||
|
||||
enum E fn_with_enum_retval2(void) {
|
||||
// code here
|
||||
}
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="VALUE")],
|
||||
)
|
||||
],
|
||||
functions=[
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn_with_enum_param1")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
const=True,
|
||||
),
|
||||
name="e",
|
||||
)
|
||||
],
|
||||
),
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="void")])
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn_with_enum_param2")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
const=True,
|
||||
),
|
||||
name="e",
|
||||
)
|
||||
],
|
||||
has_body=True,
|
||||
),
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn_with_enum_retval1")]),
|
||||
parameters=[],
|
||||
),
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn_with_enum_retval2")]),
|
||||
parameters=[],
|
||||
has_body=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
506
tests/test_fn.py
Normal file
506
tests/test_fn.py
Normal file
@@ -0,0 +1,506 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
Array,
|
||||
AutoSpecifier,
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Reference,
|
||||
TemplateArgument,
|
||||
TemplateDecl,
|
||||
TemplateSpecialization,
|
||||
TemplateTypeParam,
|
||||
Token,
|
||||
Type,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_fn_returns_class():
|
||||
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_pointer_params():
|
||||
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():
|
||||
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():
|
||||
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_weird_refs():
|
||||
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():
|
||||
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():
|
||||
# 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():
|
||||
content = """
|
||||
template<class T, class U>
|
||||
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():
|
||||
content = """
|
||||
std::vector<Pointer *> *fn(std::vector<Pointer *> *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(
|
||||
tokens=[
|
||||
Token(value="Pointer"),
|
||||
Token(value="*"),
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
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(
|
||||
tokens=[
|
||||
Token(value="Pointer"),
|
||||
Token(value="*"),
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="ps",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_fn_with_impl():
|
||||
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,
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
382
tests/test_friends.py
Normal file
382
tests/test_friends.py
Normal file
@@ -0,0 +1,382 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
ClassDecl,
|
||||
Field,
|
||||
ForwardDecl,
|
||||
FriendDecl,
|
||||
FundamentalSpecifier,
|
||||
Method,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Reference,
|
||||
TemplateDecl,
|
||||
TemplateTypeParam,
|
||||
Type,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
# friends
|
||||
def test_various_friends():
|
||||
content = """
|
||||
class FX {
|
||||
public:
|
||||
FX(char);
|
||||
~FX();
|
||||
void fn() const;
|
||||
};
|
||||
|
||||
class FF {
|
||||
friend class FX;
|
||||
friend FX::FX(char), FX::~FX();
|
||||
friend void FX::fn() const;
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="FX")], classkey="class"
|
||||
)
|
||||
),
|
||||
methods=[
|
||||
Method(
|
||||
return_type=None,
|
||||
name=PQName(segments=[NameSpecifier(name="FX")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="char")]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
access="public",
|
||||
constructor=True,
|
||||
),
|
||||
Method(
|
||||
return_type=None,
|
||||
name=PQName(segments=[NameSpecifier(name="~FX")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
destructor=True,
|
||||
),
|
||||
Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
const=True,
|
||||
),
|
||||
],
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="FF")], classkey="class"
|
||||
)
|
||||
),
|
||||
friends=[
|
||||
FriendDecl(
|
||||
cls=ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="FX")],
|
||||
classkey="class",
|
||||
),
|
||||
access="private",
|
||||
)
|
||||
),
|
||||
FriendDecl(
|
||||
fn=Method(
|
||||
return_type=None,
|
||||
name=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="FX"),
|
||||
NameSpecifier(name="FX"),
|
||||
]
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="char")
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
access="private",
|
||||
constructor=True,
|
||||
)
|
||||
),
|
||||
FriendDecl(
|
||||
fn=Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="FX"),
|
||||
NameSpecifier(name="FX"),
|
||||
]
|
||||
)
|
||||
),
|
||||
name=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="FX"),
|
||||
NameSpecifier(name="~FX"),
|
||||
]
|
||||
),
|
||||
parameters=[],
|
||||
access="private",
|
||||
)
|
||||
),
|
||||
FriendDecl(
|
||||
fn=Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="FX"),
|
||||
NameSpecifier(name="fn"),
|
||||
]
|
||||
),
|
||||
parameters=[],
|
||||
access="private",
|
||||
const=True,
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_more_friends():
|
||||
content = """
|
||||
template <typename T> struct X { static int x; };
|
||||
|
||||
struct BFF {
|
||||
void fn() const;
|
||||
};
|
||||
|
||||
struct F {
|
||||
friend enum B;
|
||||
friend void BFF::fn() const;
|
||||
|
||||
template <typename T> friend 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="struct"
|
||||
),
|
||||
template=TemplateDecl(
|
||||
params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||
),
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
name="x",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
static=True,
|
||||
)
|
||||
],
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BFF")], classkey="struct"
|
||||
)
|
||||
),
|
||||
methods=[
|
||||
Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
const=True,
|
||||
)
|
||||
],
|
||||
),
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="F")], classkey="struct"
|
||||
)
|
||||
),
|
||||
friends=[
|
||||
FriendDecl(
|
||||
cls=ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="B")], classkey="enum"
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
),
|
||||
FriendDecl(
|
||||
fn=Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="BFF"),
|
||||
NameSpecifier(name="fn"),
|
||||
]
|
||||
),
|
||||
parameters=[],
|
||||
access="public",
|
||||
const=True,
|
||||
)
|
||||
),
|
||||
FriendDecl(
|
||||
cls=ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="X")], classkey="class"
|
||||
),
|
||||
template=TemplateDecl(
|
||||
params=[
|
||||
TemplateTypeParam(typekey="typename", name="T")
|
||||
]
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_friend_type_no_class():
|
||||
content = """
|
||||
class DogClass;
|
||||
class CatClass {
|
||||
friend DogClass;
|
||||
};
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="CatClass")], classkey="class"
|
||||
)
|
||||
),
|
||||
friends=[
|
||||
FriendDecl(
|
||||
cls=ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="DogClass")]
|
||||
),
|
||||
access="private",
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
forward_decls=[
|
||||
ForwardDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="DogClass")], classkey="class"
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_friend_with_impl():
|
||||
content = """
|
||||
// clang-format off
|
||||
class Garlic {
|
||||
public:
|
||||
friend int genNum(C& a)
|
||||
{
|
||||
return obj.meth().num();
|
||||
}
|
||||
};
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Garlic")], classkey="class"
|
||||
)
|
||||
),
|
||||
friends=[
|
||||
FriendDecl(
|
||||
fn=Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="genNum")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="C")]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="a",
|
||||
)
|
||||
],
|
||||
has_body=True,
|
||||
access="public",
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
170
tests/test_misc.py
Normal file
170
tests/test_misc.py
Normal file
@@ -0,0 +1,170 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Type,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
Include,
|
||||
NamespaceScope,
|
||||
Pragma,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
Define,
|
||||
)
|
||||
|
||||
#
|
||||
# minimal preprocessor support
|
||||
#
|
||||
|
||||
|
||||
def test_define():
|
||||
content = """
|
||||
#define simple
|
||||
#define complex(thing) stuff(thing)
|
||||
# define spaced
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
defines=[
|
||||
Define(content="simple"),
|
||||
Define(content="complex(thing) stuff(thing)"),
|
||||
Define(content="spaced"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def test_includes():
|
||||
content = """
|
||||
#include <global.h>
|
||||
#include "local.h"
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(includes=[Include("<global.h>"), Include('"local.h"')])
|
||||
|
||||
|
||||
def test_pragma():
|
||||
content = """
|
||||
|
||||
#pragma once
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(pragmas=[Pragma(content="once")])
|
||||
|
||||
|
||||
#
|
||||
# extern "C"
|
||||
#
|
||||
|
||||
|
||||
def test_extern_c():
|
||||
content = """
|
||||
extern "C" {
|
||||
int x;
|
||||
};
|
||||
|
||||
int y;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="y")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_misc_extern_inline():
|
||||
content = """
|
||||
extern "C++" {
|
||||
inline HAL_Value HAL_GetSimValue(HAL_SimValueHandle handle) {
|
||||
HAL_Value v;
|
||||
return v;
|
||||
}
|
||||
} // extern "C++"
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
functions=[
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(segments=[NameSpecifier(name="HAL_Value")])
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="HAL_GetSimValue")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="HAL_SimValueHandle")]
|
||||
)
|
||||
),
|
||||
name="handle",
|
||||
)
|
||||
],
|
||||
inline=True,
|
||||
has_body=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Misc
|
||||
#
|
||||
|
||||
|
||||
def test_static_assert_1():
|
||||
# static_assert should be ignored
|
||||
content = """
|
||||
static_assert(x == 1);
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData()
|
||||
|
||||
|
||||
def test_static_assert_2():
|
||||
# static_assert should be ignored
|
||||
content = """
|
||||
static_assert(sizeof(int) == 4,
|
||||
"integer size is wrong"
|
||||
"for some reason");
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData()
|
||||
|
||||
|
||||
def test_comment_eof():
|
||||
content = """
|
||||
namespace a {} // namespace a"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(namespaces={"a": NamespaceScope(name="a")})
|
||||
)
|
||||
121
tests/test_namespaces.py
Normal file
121
tests/test_namespaces.py
Normal file
@@ -0,0 +1,121 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Token,
|
||||
Type,
|
||||
Value,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_dups_in_different_ns():
|
||||
content = """
|
||||
|
||||
namespace {
|
||||
int x = 4;
|
||||
}
|
||||
|
||||
int x = 5;
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
value=Value(tokens=[Token(value="5")]),
|
||||
)
|
||||
],
|
||||
namespaces={
|
||||
"": NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
value=Value(tokens=[Token(value="4")]),
|
||||
)
|
||||
]
|
||||
)
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_correct_ns():
|
||||
content = """
|
||||
namespace a::b::c {
|
||||
int i1;
|
||||
}
|
||||
|
||||
namespace a {
|
||||
namespace b {
|
||||
namespace c {
|
||||
int i2;
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
namespaces={
|
||||
"a": NamespaceScope(
|
||||
name="a",
|
||||
namespaces={
|
||||
"b": NamespaceScope(
|
||||
name="b",
|
||||
namespaces={
|
||||
"c": NamespaceScope(
|
||||
name="c",
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(
|
||||
segments=[NameSpecifier(name="i1")]
|
||||
),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
)
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(
|
||||
segments=[NameSpecifier(name="i2")]
|
||||
),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
554
tests/test_operators.py
Normal file
554
tests/test_operators.py
Normal file
@@ -0,0 +1,554 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
ClassDecl,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
Operator,
|
||||
PQName,
|
||||
Parameter,
|
||||
Reference,
|
||||
Type,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_class_operators():
|
||||
content = r"""
|
||||
class OperatorClass {
|
||||
public:
|
||||
void operator=(const Sample25Class &);
|
||||
void operator-=(const Sample25Class &);
|
||||
void operator+=();
|
||||
void operator[]();
|
||||
bool operator==(const int &b);
|
||||
OperatorClass &operator+();
|
||||
void operator-();
|
||||
void operator*();
|
||||
void operator\();
|
||||
void operator%();
|
||||
void operator^();
|
||||
void operator|();
|
||||
void operator&();
|
||||
void operator~();
|
||||
void operator<<();
|
||||
void operator>>();
|
||||
void operator!=();
|
||||
void operator<();
|
||||
void operator>();
|
||||
void operator>=();
|
||||
void operator<=();
|
||||
void operator!();
|
||||
void operator&&();
|
||||
void operator||();
|
||||
void operator+=();
|
||||
void operator-=();
|
||||
void operator*=();
|
||||
void operator\=();
|
||||
void operator%=();
|
||||
void operator&=();
|
||||
void operator|=();
|
||||
void operator^=();
|
||||
void operator<<=();
|
||||
void operator>>=();
|
||||
void operator++();
|
||||
void operator--();
|
||||
void operator()();
|
||||
void operator->();
|
||||
void operator,();
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="OperatorClass")],
|
||||
classkey="class",
|
||||
)
|
||||
),
|
||||
methods=[
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator=")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="Sample25Class")
|
||||
]
|
||||
),
|
||||
const=True,
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
access="public",
|
||||
operator="=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator-=")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="Sample25Class")
|
||||
]
|
||||
),
|
||||
const=True,
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
access="public",
|
||||
operator="-=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator+=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="+=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator[]")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="[]",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="bool")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator==")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
),
|
||||
const=True,
|
||||
)
|
||||
),
|
||||
name="b",
|
||||
)
|
||||
],
|
||||
access="public",
|
||||
operator="==",
|
||||
),
|
||||
Operator(
|
||||
return_type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="OperatorClass")]
|
||||
)
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator+")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="+",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator-")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="-",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator*")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="*",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator\\")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="\\",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator%")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="%",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator^")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="^",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator|")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="|",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator&")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="&",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator~")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="~",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator<<")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="<<",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator>>")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator=">>",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator!=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="!=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator<")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="<",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator>")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator=">",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator>=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator=">=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator<=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="<=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator!")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="!",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator&&")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="&&",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator||")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="||",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator+=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="+=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator-=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="-=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator*=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="*=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator\\=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="\\=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator%=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="%=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator&=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="&=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator|=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="|=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator^=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="^=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator<<=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="<<=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator>>=")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator=">>=",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator++")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="++",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator--")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="--",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator()")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="()",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator->")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator="->",
|
||||
),
|
||||
Operator(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="operator,")]),
|
||||
parameters=[],
|
||||
access="public",
|
||||
operator=",",
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
1290
tests/test_template.py
Normal file
1290
tests/test_template.py
Normal file
File diff suppressed because it is too large
Load Diff
52
tests/test_tokfmt.py
Normal file
52
tests/test_tokfmt.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import pytest
|
||||
|
||||
from cxxheaderparser.lexer import Lexer
|
||||
from cxxheaderparser.tokfmt import tokfmt
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"instr",
|
||||
[
|
||||
"int",
|
||||
"unsigned int",
|
||||
"::uint8_t",
|
||||
"void *",
|
||||
"const char *",
|
||||
"const char[]",
|
||||
"void * (*)()",
|
||||
"void (*)(void * buf, int buflen)",
|
||||
"void (* fnType)(void * buf, int buflen)",
|
||||
"TypeName<int, void>& x",
|
||||
"vector<string>&",
|
||||
"std::vector<Pointer *> *",
|
||||
"Alpha::Omega",
|
||||
"Convoluted::Nested::Mixin",
|
||||
"std::function<void ()>",
|
||||
"std::shared_ptr<std::function<void (void)>>",
|
||||
"tr1::shared_ptr<SnailTemplateClass<SnailNamespace::SnailClass>>",
|
||||
"std::map<unsigned, std::pair<unsigned, SnailTemplateClass<SnailNamespace::SnailClass>>>",
|
||||
"std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value",
|
||||
"const char&&",
|
||||
"something<T, U>{1, 2, 3}",
|
||||
"operator-=",
|
||||
"operator[]",
|
||||
"operator*",
|
||||
"operator>=",
|
||||
],
|
||||
)
|
||||
def test_tokfmt(instr):
|
||||
"""
|
||||
Each input string is exactly what the output of tokfmt should be
|
||||
"""
|
||||
toks = []
|
||||
lexer = Lexer("")
|
||||
lexer.input(instr)
|
||||
|
||||
while True:
|
||||
tok = lexer.token_eof_ok()
|
||||
if not tok:
|
||||
break
|
||||
|
||||
toks.append(tok)
|
||||
|
||||
assert tokfmt(toks) == instr
|
||||
870
tests/test_typedef.py
Normal file
870
tests/test_typedef.py
Normal file
@@ -0,0 +1,870 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
AnonymousName,
|
||||
Array,
|
||||
BaseClass,
|
||||
ClassDecl,
|
||||
EnumDecl,
|
||||
Enumerator,
|
||||
Field,
|
||||
FunctionType,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Reference,
|
||||
TemplateArgument,
|
||||
TemplateSpecialization,
|
||||
Token,
|
||||
Type,
|
||||
Typedef,
|
||||
Value,
|
||||
)
|
||||
from cxxheaderparser.simple import ClassScope, NamespaceScope, ParsedData, parse_string
|
||||
|
||||
|
||||
def test_simple_typedef():
|
||||
content = """
|
||||
typedef std::vector<int> IntVector;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="std"),
|
||||
NameSpecifier(
|
||||
name="vector",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(
|
||||
tokens=[Token(value="int")]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
name="IntVector",
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_struct_typedef_1():
|
||||
content = """
|
||||
typedef struct {
|
||||
int m;
|
||||
} unnamed_struct, *punnamed_struct;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
name="m",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="unnamed_struct",
|
||||
),
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="punnamed_struct",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_struct_typedef_2():
|
||||
content = """
|
||||
typedef struct {
|
||||
int m;
|
||||
} * punnamed_struct, unnamed_struct;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
name="m",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="punnamed_struct",
|
||||
),
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="unnamed_struct",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_array():
|
||||
content = """
|
||||
typedef char TenCharArray[10];
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="char")]
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="10")]),
|
||||
),
|
||||
name="TenCharArray",
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_array_of_struct():
|
||||
content = """
|
||||
typedef struct{} tx[3], ty;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
),
|
||||
name="tx",
|
||||
),
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="ty",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_class_w_base():
|
||||
content = """
|
||||
typedef class XX : public F {} G;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="XX")], classkey="class"
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(segments=[NameSpecifier(name="F")]),
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="XX")], classkey="class"
|
||||
)
|
||||
),
|
||||
name="G",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_complicated_typedef():
|
||||
content = """
|
||||
typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10];
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
name="int_t",
|
||||
),
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
)
|
||||
),
|
||||
name="intp_t",
|
||||
),
|
||||
Typedef(
|
||||
type=Reference(
|
||||
ref_to=FunctionType(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
)
|
||||
),
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="ulong")]
|
||||
)
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
name="fp",
|
||||
),
|
||||
Typedef(
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
size=Value(tokens=[Token(value="10")]),
|
||||
),
|
||||
name="arr_t",
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_c_struct_idiom():
|
||||
content = """
|
||||
// common C idiom to avoid having to write "struct S"
|
||||
typedef struct {int a; int b;} S, *pS;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
name="a",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
),
|
||||
Field(
|
||||
name="b",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="S",
|
||||
),
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="pS",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_struct_same_name():
|
||||
content = """
|
||||
typedef struct Fig {
|
||||
int a;
|
||||
} Fig;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Fig")], classkey="struct"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="a",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Fig")], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="Fig",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_struct_w_enum():
|
||||
content = """
|
||||
typedef struct {
|
||||
enum BeetEnum : int { FAIL = 0, PASS = 1 };
|
||||
} BeetStruct;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BeetEnum")],
|
||||
classkey="enum",
|
||||
),
|
||||
values=[
|
||||
Enumerator(
|
||||
name="FAIL", value=Value(tokens=[Token(value="0")])
|
||||
),
|
||||
Enumerator(
|
||||
name="PASS", value=Value(tokens=[Token(value="1")])
|
||||
),
|
||||
],
|
||||
base=PQName(segments=[FundamentalSpecifier(name="int")]),
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="struct"
|
||||
)
|
||||
),
|
||||
name="BeetStruct",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_union():
|
||||
content = """
|
||||
typedef union apricot_t {
|
||||
int i;
|
||||
float f;
|
||||
char s[20];
|
||||
} Apricot;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="apricot_t")], classkey="union"
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="i",
|
||||
),
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="float")]
|
||||
)
|
||||
),
|
||||
name="f",
|
||||
),
|
||||
Field(
|
||||
access="public",
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="char")]
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="20")]),
|
||||
),
|
||||
name="s",
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="apricot_t")], classkey="union"
|
||||
)
|
||||
),
|
||||
name="Apricot",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_fnptr():
|
||||
content = """
|
||||
typedef void *(*fndef)(int);
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
name="fndef",
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_const():
|
||||
content = """
|
||||
typedef int theint, *const ptheint;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
name="theint",
|
||||
),
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
const=True,
|
||||
),
|
||||
name="ptheint",
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_1():
|
||||
content = """
|
||||
typedef enum {} E;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="E",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_2():
|
||||
content = """
|
||||
typedef enum { E1 } BE;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[Enumerator(name="E1")],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="BE",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_3():
|
||||
content = """
|
||||
typedef enum { E1, E2, } E;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[Enumerator(name="E1"), Enumerator(name="E2")],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="E",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_3():
|
||||
content = """
|
||||
typedef enum { E1 } * PBE;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[Enumerator(name="E1")],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="enum"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="PBE",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_4():
|
||||
content = """
|
||||
typedef enum { E1 } * PBE, BE;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[Enumerator(name="E1")],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="enum"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="PBE",
|
||||
),
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="BE",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_5():
|
||||
content = """
|
||||
typedef enum { E1 } BE, *PBE;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[Enumerator(name="E1")],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="BE",
|
||||
),
|
||||
Typedef(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="enum"
|
||||
)
|
||||
)
|
||||
),
|
||||
name="PBE",
|
||||
),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_enum_typedef_fwd():
|
||||
content = """
|
||||
typedef enum BE BET;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="BE")], classkey="enum"
|
||||
)
|
||||
),
|
||||
name="BET",
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_typedef_enum_expr():
|
||||
content = """
|
||||
typedef enum { StarFruit = (2 + 2) / 2 } Carambola;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum"),
|
||||
values=[
|
||||
Enumerator(
|
||||
name="StarFruit",
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="("),
|
||||
Token(value="2"),
|
||||
Token(value="+"),
|
||||
Token(value="2"),
|
||||
Token(value=")"),
|
||||
Token(value="/"),
|
||||
Token(value="2"),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
typedefs=[
|
||||
Typedef(
|
||||
type=Type(
|
||||
typename=PQName(segments=[AnonymousName(id=1)], classkey="enum")
|
||||
),
|
||||
name="Carambola",
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
154
tests/test_union.py
Normal file
154
tests/test_union.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
AnonymousName,
|
||||
ClassDecl,
|
||||
Field,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Type,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_union_basic():
|
||||
content = """
|
||||
|
||||
struct HAL_Value {
|
||||
union {
|
||||
int v_int;
|
||||
HAL_Bool v_boolean;
|
||||
} data;
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="HAL_Value")],
|
||||
classkey="struct",
|
||||
)
|
||||
),
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="union"
|
||||
),
|
||||
access="public",
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="v_int",
|
||||
),
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="HAL_Bool")]
|
||||
)
|
||||
),
|
||||
name="v_boolean",
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="union"
|
||||
)
|
||||
),
|
||||
name="data",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_union_anon_in_struct():
|
||||
content = """
|
||||
struct Outer {
|
||||
union {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
int z;
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="Outer")], classkey="struct"
|
||||
)
|
||||
),
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[AnonymousName(id=1)], classkey="union"
|
||||
),
|
||||
access="public",
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="x",
|
||||
),
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="y",
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="z",
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
511
tests/test_using.py
Normal file
511
tests/test_using.py
Normal file
@@ -0,0 +1,511 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
BaseClass,
|
||||
ClassDecl,
|
||||
Function,
|
||||
FundamentalSpecifier,
|
||||
Method,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Reference,
|
||||
TemplateArgument,
|
||||
TemplateDecl,
|
||||
TemplateSpecialization,
|
||||
TemplateTypeParam,
|
||||
Token,
|
||||
Type,
|
||||
UsingAlias,
|
||||
UsingDecl,
|
||||
)
|
||||
from cxxheaderparser.simple import (
|
||||
ClassScope,
|
||||
NamespaceScope,
|
||||
UsingNamespace,
|
||||
parse_string,
|
||||
ParsedData,
|
||||
)
|
||||
|
||||
|
||||
def test_using_namespace():
|
||||
content = """
|
||||
using namespace foo;
|
||||
using namespace foo::bar;
|
||||
using namespace ::foo;
|
||||
using namespace ::foo::bar;
|
||||
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_ns=[
|
||||
UsingNamespace(ns="foo"),
|
||||
UsingNamespace(ns="foo::bar"),
|
||||
UsingNamespace(ns="::foo"),
|
||||
UsingNamespace(ns="::foo::bar"),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_using_declaration():
|
||||
content = """
|
||||
using ::foo;
|
||||
using foo::bar;
|
||||
using ::foo::bar;
|
||||
using typename ::foo::bar;
|
||||
using typename foo::bar;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using=[
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name=""), NameSpecifier(name="foo")]
|
||||
)
|
||||
),
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="foo"), NameSpecifier(name="bar")]
|
||||
)
|
||||
),
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name=""),
|
||||
NameSpecifier(name="foo"),
|
||||
NameSpecifier(name="bar"),
|
||||
]
|
||||
)
|
||||
),
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name=""),
|
||||
NameSpecifier(name="foo"),
|
||||
NameSpecifier(name="bar"),
|
||||
]
|
||||
)
|
||||
),
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="foo"), NameSpecifier(name="bar")]
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# alias-declaration
|
||||
def test_alias_declaration_1():
|
||||
content = """
|
||||
using alias = foo;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(typename=PQName(segments=[NameSpecifier(name="foo")])),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_alias_declaration_2():
|
||||
content = """
|
||||
template <typename T> using alias = foo<T>;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(
|
||||
name="foo",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(tokens=[Token(value="T")])
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
template=TemplateDecl(
|
||||
params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_alias_declaration_3():
|
||||
content = """
|
||||
using alias = ::foo::bar;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name=""),
|
||||
NameSpecifier(name="foo"),
|
||||
NameSpecifier(name="bar"),
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_alias_declaration_4():
|
||||
content = """
|
||||
template <typename T> using alias = ::foo::bar<T>;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name=""),
|
||||
NameSpecifier(name="foo"),
|
||||
NameSpecifier(
|
||||
name="bar",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(tokens=[Token(value="T")])
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
template=TemplateDecl(
|
||||
params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_alias_declaration_5():
|
||||
content = """
|
||||
using alias = foo::bar;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="foo"),
|
||||
NameSpecifier(name="bar"),
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_alias_declaration_6():
|
||||
content = """
|
||||
template <typename T> using alias = foo<T>::bar;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="alias",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(
|
||||
name="foo",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(tokens=[Token(value="T")])
|
||||
]
|
||||
),
|
||||
),
|
||||
NameSpecifier(name="bar"),
|
||||
]
|
||||
)
|
||||
),
|
||||
template=TemplateDecl(
|
||||
params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_using_many_things():
|
||||
content = """
|
||||
// clang-format off
|
||||
|
||||
using std::thing;
|
||||
using MyThing = SomeThing;
|
||||
namespace a {
|
||||
using std::string;
|
||||
using VoidFunction = std::function<void()>;
|
||||
|
||||
void fn(string &s, VoidFunction fn, thing * t);
|
||||
|
||||
class A : public B {
|
||||
public:
|
||||
using B::B;
|
||||
using IntFunction = std::function<int()>;
|
||||
|
||||
void a(string &s, IntFunction fn, thing * t);
|
||||
};
|
||||
}
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
using=[
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="std"),
|
||||
NameSpecifier(name="thing"),
|
||||
]
|
||||
)
|
||||
)
|
||||
],
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="MyThing",
|
||||
type=Type(
|
||||
typename=PQName(segments=[NameSpecifier(name="SomeThing")])
|
||||
),
|
||||
)
|
||||
],
|
||||
namespaces={
|
||||
"a": NamespaceScope(
|
||||
name="a",
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="A")], classkey="class"
|
||||
),
|
||||
bases=[
|
||||
BaseClass(
|
||||
access="public",
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="B")]
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
methods=[
|
||||
Method(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="a")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="string")
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="s",
|
||||
),
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(
|
||||
name="IntFunction"
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
name="fn",
|
||||
),
|
||||
Parameter(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="thing")
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="t",
|
||||
),
|
||||
],
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
using=[
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="B"),
|
||||
NameSpecifier(name="B"),
|
||||
]
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="IntFunction",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="std"),
|
||||
NameSpecifier(
|
||||
name="function",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(
|
||||
tokens=[
|
||||
Token(value="int"),
|
||||
Token(value="("),
|
||||
Token(value=")"),
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
access="public",
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
functions=[
|
||||
Function(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
name=PQName(segments=[NameSpecifier(name="fn")]),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Reference(
|
||||
ref_to=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="string")]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="s",
|
||||
),
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="VoidFunction")
|
||||
]
|
||||
)
|
||||
),
|
||||
name="fn",
|
||||
),
|
||||
Parameter(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="thing")]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="t",
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
using=[
|
||||
UsingDecl(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="std"),
|
||||
NameSpecifier(name="string"),
|
||||
]
|
||||
)
|
||||
)
|
||||
],
|
||||
using_alias=[
|
||||
UsingAlias(
|
||||
alias="VoidFunction",
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
NameSpecifier(name="std"),
|
||||
NameSpecifier(
|
||||
name="function",
|
||||
specialization=TemplateSpecialization(
|
||||
args=[
|
||||
TemplateArgument(
|
||||
tokens=[
|
||||
Token(value="void"),
|
||||
Token(value="("),
|
||||
Token(value=")"),
|
||||
]
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
},
|
||||
)
|
||||
)
|
||||
768
tests/test_var.py
Normal file
768
tests/test_var.py
Normal file
@@ -0,0 +1,768 @@
|
||||
# Note: testcases generated via `python -m cxxheaderparser.gentest`
|
||||
|
||||
|
||||
from cxxheaderparser.types import (
|
||||
Array,
|
||||
ClassDecl,
|
||||
EnumDecl,
|
||||
Enumerator,
|
||||
Field,
|
||||
FunctionType,
|
||||
FundamentalSpecifier,
|
||||
NameSpecifier,
|
||||
PQName,
|
||||
Parameter,
|
||||
Pointer,
|
||||
Reference,
|
||||
Token,
|
||||
Type,
|
||||
Value,
|
||||
Variable,
|
||||
)
|
||||
from cxxheaderparser.simple import ClassScope, NamespaceScope, ParsedData, parse_string
|
||||
|
||||
|
||||
def test_var_unixwiz_ridiculous():
|
||||
# http://unixwiz.net/techtips/reading-cdecl.html
|
||||
#
|
||||
# .. "we have no idea how this variable is useful, but at least we can
|
||||
# describe the type correctly"
|
||||
|
||||
content = """
|
||||
char *(*(**foo[][8])())[];
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="foo")]),
|
||||
type=Array(
|
||||
array_of=Array(
|
||||
array_of=Pointer(
|
||||
ptr_to=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Pointer(
|
||||
ptr_to=Array(
|
||||
array_of=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(
|
||||
name="char"
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
size=None,
|
||||
)
|
||||
),
|
||||
parameters=[],
|
||||
)
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="8")]),
|
||||
),
|
||||
size=None,
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ptr_to_array15_of_ptr_to_int():
|
||||
content = """
|
||||
int *(*crocodile)[15];
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="crocodile")]),
|
||||
type=Pointer(
|
||||
ptr_to=Array(
|
||||
array_of=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="15")]),
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ref_to_array():
|
||||
content = """
|
||||
int abase[3];
|
||||
int (&aname)[3] = abase;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="abase")]),
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="aname")]),
|
||||
type=Reference(
|
||||
ref_to=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
)
|
||||
),
|
||||
value=Value(tokens=[Token(value="abase")]),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ptr_to_array():
|
||||
content = """
|
||||
int zz, (*aname)[3] = &abase;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="zz")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="aname")]),
|
||||
type=Pointer(
|
||||
ptr_to=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
)
|
||||
),
|
||||
value=Value(tokens=[Token(value="&"), Token(value="abase")]),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_multi_1():
|
||||
content = """
|
||||
int zz, (&aname)[3] = abase;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="zz")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
),
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="aname")]),
|
||||
type=Reference(
|
||||
ref_to=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
)
|
||||
),
|
||||
value=Value(tokens=[Token(value="abase")]),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_array_of_fnptr_varargs():
|
||||
content = """
|
||||
void (*a3[3])(int, ...);
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="a3")]),
|
||||
type=Array(
|
||||
array_of=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
vararg=True,
|
||||
)
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_double_fnptr_varargs():
|
||||
content = """
|
||||
void (*(*a4))(int, ...);
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="a4")]),
|
||||
type=Pointer(
|
||||
ptr_to=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
vararg=True,
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_fnptr_voidstar():
|
||||
content = """
|
||||
void(*(*a5)(int));
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="a5")]),
|
||||
type=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_fnptr_moreparens():
|
||||
content = """
|
||||
void (*x)(int(p1), int);
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
),
|
||||
name="p1",
|
||||
),
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="int")]
|
||||
)
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# From pycparser:
|
||||
# Pointer decls nest from inside out. This is important when different
|
||||
# levels have different qualifiers. For example:
|
||||
#
|
||||
# char * const * p;
|
||||
#
|
||||
# Means "pointer to const pointer to char"
|
||||
#
|
||||
# While:
|
||||
#
|
||||
# char ** const p;
|
||||
#
|
||||
# Means "const pointer to pointer to char"
|
||||
|
||||
|
||||
def test_var_ptr_to_const_ptr_to_char():
|
||||
content = """
|
||||
char *const *p;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="p")]),
|
||||
type=Pointer(
|
||||
ptr_to=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="char")]
|
||||
)
|
||||
),
|
||||
const=True,
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_const_ptr_to_ptr_to_char():
|
||||
content = """
|
||||
char **const p;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="p")]),
|
||||
type=Pointer(
|
||||
ptr_to=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="char")]
|
||||
)
|
||||
)
|
||||
),
|
||||
const=True,
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_array_initializer1():
|
||||
content = """
|
||||
int x[3]{1, 2, 3};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
),
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="{"),
|
||||
Token(value="1"),
|
||||
Token(value=","),
|
||||
Token(value="2"),
|
||||
Token(value=","),
|
||||
Token(value="3"),
|
||||
Token(value="}"),
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_array_initializer2():
|
||||
content = """
|
||||
int x[3] = {1, 2, 3};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Array(
|
||||
array_of=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
size=Value(tokens=[Token(value="3")]),
|
||||
),
|
||||
value=Value(
|
||||
tokens=[
|
||||
Token(value="{"),
|
||||
Token(value="1"),
|
||||
Token(value=","),
|
||||
Token(value="2"),
|
||||
Token(value=","),
|
||||
Token(value="3"),
|
||||
Token(value="}"),
|
||||
]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_extern_c():
|
||||
content = """
|
||||
extern "C" int x;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="x")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
# TODO: store linkage
|
||||
extern=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ns_1():
|
||||
content = """
|
||||
int N::x;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(
|
||||
segments=[NameSpecifier(name="N"), NameSpecifier(name="x")]
|
||||
),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ns_2():
|
||||
content = """
|
||||
int N::x = 4;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(
|
||||
segments=[NameSpecifier(name="N"), NameSpecifier(name="x")]
|
||||
),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
value=Value(tokens=[Token(value="4")]),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_ns_3():
|
||||
content = """
|
||||
int N::x{4};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(
|
||||
segments=[NameSpecifier(name="N"), NameSpecifier(name="x")]
|
||||
),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
value=Value(
|
||||
tokens=[Token(value="{"), Token(value="4"), Token(value="}")]
|
||||
),
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_static_struct():
|
||||
content = """
|
||||
constexpr static struct SS {} s;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="SS")], classkey="struct"
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="s")]),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="SS")], classkey="struct"
|
||||
)
|
||||
),
|
||||
constexpr=True,
|
||||
static=True,
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_constexpr_enum():
|
||||
content = """
|
||||
constexpr enum E { EE } e = EE;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
enums=[
|
||||
EnumDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
),
|
||||
values=[Enumerator(name="EE")],
|
||||
)
|
||||
],
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="e")]),
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="E")], classkey="enum"
|
||||
)
|
||||
),
|
||||
value=Value(tokens=[Token(value="EE")]),
|
||||
constexpr=True,
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_fnptr_in_class():
|
||||
content = """
|
||||
struct DriverFuncs {
|
||||
void *(*init)();
|
||||
void (*write)(void *buf, int buflen);
|
||||
};
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
classes=[
|
||||
ClassScope(
|
||||
class_decl=ClassDecl(
|
||||
typename=PQName(
|
||||
segments=[NameSpecifier(name="DriverFuncs")],
|
||||
classkey="struct",
|
||||
)
|
||||
),
|
||||
fields=[
|
||||
Field(
|
||||
access="public",
|
||||
type=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="void")
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
parameters=[],
|
||||
)
|
||||
),
|
||||
name="init",
|
||||
),
|
||||
Field(
|
||||
access="public",
|
||||
type=Pointer(
|
||||
ptr_to=FunctionType(
|
||||
return_type=Type(
|
||||
typename=PQName(
|
||||
segments=[FundamentalSpecifier(name="void")]
|
||||
)
|
||||
),
|
||||
parameters=[
|
||||
Parameter(
|
||||
type=Pointer(
|
||||
ptr_to=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(
|
||||
name="void"
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
name="buf",
|
||||
),
|
||||
Parameter(
|
||||
type=Type(
|
||||
typename=PQName(
|
||||
segments=[
|
||||
FundamentalSpecifier(name="int")
|
||||
]
|
||||
)
|
||||
),
|
||||
name="buflen",
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
name="write",
|
||||
),
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_var_extern():
|
||||
content = """
|
||||
extern int externVar;
|
||||
"""
|
||||
data = parse_string(content, cleandoc=True)
|
||||
|
||||
assert data == ParsedData(
|
||||
namespace=NamespaceScope(
|
||||
variables=[
|
||||
Variable(
|
||||
name=PQName(segments=[NameSpecifier(name="externVar")]),
|
||||
type=Type(
|
||||
typename=PQName(segments=[FundamentalSpecifier(name="int")])
|
||||
),
|
||||
extern=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user