Skip to content

Commit

Permalink
backend/sdoc_source_code: C++: recognize functions returning references
Browse files Browse the repository at this point in the history
Closes #2026
  • Loading branch information
stanislaw committed Nov 24, 2024
1 parent 87b7e1b commit 2c7166e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 15 deletions.
39 changes: 24 additions & 15 deletions strictdoc/backend/sdoc_source_code/reader_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,16 @@ def read(
if function_identifier_node.text is None:
continue

assert function_identifier_node.text is not None
assert function_identifier_node.text is not None, node_.text
function_display_name = function_identifier_node.text.decode(
"utf8"
)

assert function_declarator_node.text is not None
assert function_declarator_node.text is not None, node_.text
function_name: str = function_declarator_node.text.decode(
"utf8"
)
assert (
function_name is not None
), "function_name must not be None"
assert function_name is not None, node_.text

parent_names = self.get_node_ns(node_)
if len(parent_names) > 0:
Expand All @@ -169,7 +167,7 @@ def read(
and node_.prev_sibling.type == "comment"
):
function_comment_node = node_.prev_sibling
assert function_comment_node.text is not None
assert function_comment_node.text is not None, node_.text
function_comment_text = function_comment_node.text.decode(
"utf8"
)
Expand Down Expand Up @@ -217,9 +215,24 @@ def read(
function_declarator_node = ts_find_child_node_by_type(
node_, "function_declarator"
)
assert function_declarator_node is not None
# C++ reference declaration wrap the function declaration one time.
if function_declarator_node is None:
# Example: Foo& Foo::operator+(const Foo& c) { return *this; }
reference_declarator_node = ts_find_child_node_by_type(
node_, "reference_declarator"
)
if reference_declarator_node is None:
continue

function_declarator_node = ts_find_child_node_by_type(
reference_declarator_node, "function_declarator"
)
if function_declarator_node is None:
continue

assert function_declarator_node is not None, node_.text

assert function_declarator_node.text is not None
assert function_declarator_node.text is not None, node_.text
function_name = function_declarator_node.text.decode("utf8")

identifier_node = self._get_function_name_node(
Expand All @@ -228,12 +241,10 @@ def read(
if identifier_node is None:
raise NotImplementedError(function_declarator_node)

assert identifier_node.text is not None
assert identifier_node.text is not None, node_.text
function_display_name = identifier_node.text.decode("utf8")

assert (
function_name is not None
), "Could not parse function name"
assert function_name is not None, node_.text
parent_names = self.get_node_ns(node_)
if len(parent_names) > 0:
function_name = (
Expand All @@ -251,9 +262,7 @@ def read(
and node_.prev_sibling.type == "comment"
):
function_comment_node = node_.prev_sibling
assert (
function_comment_node.text is not None
), function_comment_node
assert function_comment_node.text is not None, node_.text
function_comment_text = function_comment_node.text.decode(
"utf8"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,58 @@ class TrkVertex
marker_3: FunctionRangeMarker = info.markers[2]
assert marker_3.ng_range_line_begin == 14
assert marker_3.ng_range_line_end == 17


def test_22_definition_with_reference():
"""
The function returning reference is mostly tested here.
All other members are just for some context around the function.
"""
input_string = b"""\
class Foo
{
int a_, b_;
public:
Foo() {}
Foo(int a, int b) : a_(a), b_(b) {}
/**
* @relation(REQ-1, scope=function)
*/
Foo& operator+(const Foo& c);
};
Foo& Foo::operator+(const Foo& c) { return *this; }
"""

reader = SourceFileTraceabilityReader_C()

info = reader.read(input_string)

assert isinstance(info, SourceFileTraceabilityInfo)
assert len(info.functions) == 4
assert len(info.markers) == 1

function_1: Function = info.functions[0]
assert function_1.name == "Foo::Foo()"
assert function_1.display_name == "Foo::Foo"
assert function_1.line_begin == 6
assert function_1.line_end == 6

function_2: Function = info.functions[1]
assert function_2.name == "Foo::Foo(int a, int b)"
assert function_2.display_name == "Foo::Foo"
assert function_2.line_begin == 7
assert function_2.line_end == 7

function_3: Function = info.functions[2]
assert function_3.name == "Foo::operator+(const Foo& c)"
assert function_3.display_name == "Foo::operator+"
assert function_3.line_begin == 9
assert function_3.line_end == 12

marker_1: FunctionRangeMarker = info.markers[0]
assert marker_1.ng_range_line_begin == 9
assert marker_1.ng_range_line_end == 12

0 comments on commit 2c7166e

Please sign in to comment.