Skip to content

Commit

Permalink
Add support to variable with [] inside type (#85)
Browse files Browse the repository at this point in the history
* Add support to variable with [] inside type

std::unique_ptr<int[]> variable;

* Type of "array_size" should always be the same

* Add test for std::unique_ptr<int[]>

* Add support for initialization with {}

int double {0};
int double {(1.2+3.2)};

* Fix format
  • Loading branch information
bansan85 committed May 22, 2024
1 parent 7595d33 commit 8a2caee
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 28 deletions.
88 changes: 61 additions & 27 deletions CppHeaderParser/CppHeaderParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def trace_print(*args):
_BRACE_REASON_OTHER = 0
_BRACE_REASON_NS = 1
_BRACE_REASON_EXTERN = 2
_BRACE_REASON_VARIABLE = 3

# Track what was added in what order and at what depth
parseHistory = []
Expand Down Expand Up @@ -239,10 +240,13 @@ def is_property_namestack(nameStack):
r = False
if "(" not in nameStack and ")" not in nameStack:
r = True
elif (
"(" in nameStack
and "=" in nameStack
and nameStack.index("=") < nameStack.index("(")
elif "(" in nameStack and (
( # = initialization
"=" in nameStack and nameStack.index("=") < nameStack.index("(")
)
or ( # {} initialization
"{" in nameStack and nameStack.index("{") < nameStack.index("(")
)
):
r = True
# See if we are a function pointer
Expand Down Expand Up @@ -1217,29 +1221,48 @@ def __init__(self, nameStack, doxygen, location, is_var=True, **kwargs):
else:
self["extern"] = False

if "=" in nameStack:
self["type"] = " ".join(nameStack[: nameStack.index("=") - 1])
self["name"] = nameStack[nameStack.index("=") - 1]
default = " ".join(nameStack[nameStack.index("=") + 1 :])
nameStack = nameStack[: nameStack.index("=")]
default = self._filter_name(default)
self["default"] = default
# backwards compat; deprecate camelCase in dicts
self["defaultValue"] = default
elif "{" in nameStack and "}" in nameStack:
posBracket = nameStack.index("{")
self["type"] = " ".join(nameStack[: posBracket - 1])
self["name"] = nameStack[posBracket - 1]
default = " ".join(nameStack[posBracket + 1 : -1])
nameStack = nameStack[:posBracket]
default = self._filter_name(default)
self["default"] = default
# backwards compat; deprecate camelCase in dicts
self["defaultValue"] = default

_stack_ = nameStack
if "[" in nameStack: # strip off array informatin
arrayStack = nameStack[nameStack.index("[") :]
if nameStack.count("[") > 1:
self["array"] = 0
while "]" in nameStack[-1]: # strip off array information
arrayPos = len(nameStack) - 1 - nameStack[::-1].index("[")
arrayStack = nameStack[arrayPos:]
if self["array"] == 1:
debug_print("Multi dimensional array")
debug_print("arrayStack=%s", arrayStack)
nums = [x for x in arrayStack if x.isdigit()]
# Calculate size by multiplying all dimensions
p = 1
for n in nums:
p *= int(n)
if len(arrayStack) == 3:
n = arrayStack[1]
# Multi dimensional array
self["array_size"] = p
if not "multi_dimensional_array_size" in self:
self["multi_dimensional_array_size"] = self["array_size"]
self["multi_dimensional_array_size"] += "x" + n
self["array_size"] = str(int(self["array_size"]) * int(n))
self["multi_dimensional_array"] = 1
self["multi_dimensional_array_size"] = "x".join(nums)
else:
debug_print("Array")
if len(arrayStack) == 3:
self["array_size"] = arrayStack[1]
nameStack = nameStack[: nameStack.index("[")]
nameStack = nameStack[:arrayPos]
self["array"] = 1
else:
self["array"] = 0
nameStack = self._name_stack_helper(nameStack)

if doxygen:
Expand Down Expand Up @@ -1268,15 +1291,6 @@ def __init__(self, nameStack, doxygen, location, is_var=True, **kwargs):
)
self["function_pointer"] = 1

elif "=" in nameStack:
self["type"] = " ".join(nameStack[: nameStack.index("=") - 1])
self["name"] = nameStack[nameStack.index("=") - 1]
default = " ".join(nameStack[nameStack.index("=") + 1 :])
default = self._filter_name(default)
self["default"] = default
# backwards compat; deprecate camelCase in dicts
self["defaultValue"] = default

elif (
is_fundamental(nameStack[-1])
or nameStack[-1] in [">", "<", ":", "."]
Expand Down Expand Up @@ -2931,7 +2945,23 @@ def __init__(
continue

if parenDepth == 0 and tok.type == "{":
self.lastBraceReason = _BRACE_REASON_OTHER
if self.nameStack[0] in (
"class",
"struct",
"union",
"namespace",
"enum",
"extern",
"typedef",
) or (is_method_namestack(self.stack) or (not self.curClass)):
self.lastBraceReason = _BRACE_REASON_OTHER
else:
# Case : type variable {init};
self.lastBraceReason = _BRACE_REASON_VARIABLE
self.braceDepth += 1
self.braceReason.append(self.lastBraceReason)
self.nameStack.append(tok.value)
continue
if len(self.nameStack) >= 2 and is_namespace(
self.nameStack
): # namespace {} with no name used in boost, this sets default?
Expand Down Expand Up @@ -2991,6 +3021,10 @@ def __init__(
self.linkage_stack.pop()
self.stack = [] # clear stack when linkage ends?
self.stmtTokens = []
# Case : type variable {init};
elif reason == _BRACE_REASON_VARIABLE:
self.nameStack.append(tok.value)
continue
else:
self._evaluate_stack()
self.braceDepth -= 1
Expand Down
85 changes: 84 additions & 1 deletion test/test_CppHeaderParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2359,7 +2359,7 @@ def setUp(self):
def test_array_size(self):
self.assertEqual(
self.cppHeader.classes["Picture"]["properties"]["public"][1]["array_size"],
16384,
"16384",
)

def test_multi_dimensional_array_size(self):
Expand Down Expand Up @@ -4222,5 +4222,88 @@ def test_fn(self):
self.assertEqual(fn["linkage"], "")


# Github PR 85
class ContainerOfArray_TestCase(unittest.TestCase):
def setUp(self):
self.cppHeader = CppHeaderParser.CppHeader(
"""
class ContainerOfArray {
public:
std::unique_ptr<int[]> variable;
std::unique_ptr<int[]> function(std::unique_ptr<int[]> param1);
};
""",
"string",
)

def test_rtntype(self):
self.assertEqual(
self.cppHeader.classes["ContainerOfArray"]["methods"]["public"][0][
"rtnType"
],
"std::unique_ptr<int [ ] >",
)

def test_parameters(self):
self.assertEqual(
filter_pameters(
self.cppHeader.classes["ContainerOfArray"]["methods"]["public"][0][
"parameters"
]
),
[{"name": "param1", "desc": None, "type": "std::unique_ptr<int [ ] >"}],
)

def test_member(self):
self.assertEqual(
self.cppHeader.classes["ContainerOfArray"]["properties"]["public"][0][
"name"
],
"variable",
)
self.assertEqual(
self.cppHeader.classes["ContainerOfArray"]["properties"]["public"][0][
"type"
],
"std::unique_ptr<int [ ] >",
)


class InitBracket_TestCase(unittest.TestCase):
def setUp(self):
self.cppHeader = CppHeaderParser.CppHeader(
"""
class InitBracket {
public:
int variable{10};
std::shared_ptr<int> variable2 {std::make_shared<int>(150)};
};
""",
"string",
)

def test_member(self):
self.assertEqual(
self.cppHeader.classes["InitBracket"]["properties"]["public"][0]["name"],
"variable",
)
self.assertEqual(
self.cppHeader.classes["InitBracket"]["properties"]["public"][0][
"defaultValue"
],
"10",
)
self.assertEqual(
self.cppHeader.classes["InitBracket"]["properties"]["public"][1]["name"],
"variable2",
)
self.assertEqual(
self.cppHeader.classes["InitBracket"]["properties"]["public"][1][
"defaultValue"
],
"std::make_shared<int> ( 150 )",
)


if __name__ == "__main__":
unittest.main()

0 comments on commit 8a2caee

Please sign in to comment.