Skip to content

Commit

Permalink
Forward functions: Search all parent classes
Browse files Browse the repository at this point in the history
  • Loading branch information
haxtibal committed Nov 2, 2024
1 parent 5ac32b9 commit 5f237e4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 30 deletions.
52 changes: 32 additions & 20 deletions strictdoc/backend/sdoc_source_code/reader_python.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# mypy: disable-error-code="no-redef,no-untyped-call,no-untyped-def,type-arg,var-annotated"
import sys
import traceback
from typing import List, Optional, Union
from typing import List, Optional, Sequence, Union

import tree_sitter_python
from tree_sitter import Language, Node, Parser
Expand Down Expand Up @@ -119,25 +119,9 @@ def read(self, input_buffer: bytes, file_path=None):

assert function_name is not None, "Function name"

parent_class_name: Optional[str] = None
if (function_parent_node := node_.parent) is not None and (
class_node_or_node := function_parent_node.parent
) is not None:
if (
class_node_or_node.type == "class_definition"
and len(class_node_or_node.children) > 1
):
second_node_or_none = class_node_or_node.children[1]
if (
second_node_or_none.type == "identifier"
and second_node_or_none.text is not None
):
parent_class_name = second_node_or_none.text.decode(
"utf8"
)

if parent_class_name is not None:
function_name = parent_class_name + "." + function_name
parent_names = self.get_node_ns(node_)
if parent_names:
function_name = f"{'.'.join(parent_names)}.{function_name}"

block_comment = None
if (
Expand Down Expand Up @@ -271,3 +255,31 @@ def read_from_file(self, file_path):
# TODO: when --debug is provided
# traceback.print_exc() # noqa: ERA001
sys.exit(1)

@staticmethod
def get_node_ns(node: Node) -> Sequence[str]:
"""Walk up the tree and find parent classes"""
parent_scopes = []
cursor: Optional[Node] = node
while cursor:
if (block_node := cursor.parent) is not None and (
class_node_or_node := block_node.parent
) is not None:
cursor = class_node_or_node
if (
class_node_or_node.type == "class_definition"
and len(class_node_or_node.children) > 1
):
second_node_or_none = class_node_or_node.children[1]
if (
second_node_or_none.type == "identifier"
and second_node_or_none.text is not None
):
parent_class_name = second_node_or_none.text.decode(
"utf8"
)
parent_scopes.append(parent_class_name)
else:
cursor = None
parent_scopes.reverse()
return parent_scopes
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
class Foo:
class Bar:
class Baz:
def hello_world(self):
print("hello world") # noqa: T201

def hello_world(self):
"""
@relation(REQ-1, scope=function)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ STATEMENT: Requirement Statement
RELATIONS:
- TYPE: File
VALUE: file.py
FUNCTION: Foo.hello_world
FUNCTION: Foo.Bar.Baz.hello_world
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ CHECK: Published: Hello world doc
RUN: %check_exists --file "%S/Output/html/_source_files/file.py.html"

RUN: %cat %S/Output/html/%THIS_TEST_FOLDER/input.html | filecheck %s --dump-input=fail --check-prefix CHECK-HTML
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#2#11">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#6#11">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#8#8">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#2#11">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#7#16">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#11#16">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#13#13">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-1#7#16">
CHECK-HTML: <a{{.*}}href="../_source_files/file.py.html#REQ-2#4#5">

RUN: %cat %S/Output/html/_source_files/file.py.html | filecheck %s --dump-input=fail --check-prefix CHECK-SOURCE-FILE
CHECK-SOURCE-FILE: def</span> <span class="nf">hello_world</span>
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-1#2#11"
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-2#2#11"
CHECK-SOURCE-FILE: <div data-line=3 class="source__line-content">
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-1#2#11"
CHECK-SOURCE-FILE: def</span> <span class="nf">hello_world</span>
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-2#4#5"
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-1#7#16"
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-1#11#16"
CHECK-SOURCE-FILE: href="../_source_files/file.py.html#REQ-1#13#13"

RUN: %cat %S/Output/html/source_coverage.html | filecheck %s --dump-input=fail --check-prefix CHECK-SOURCE-COVERAGE
CHECK-SOURCE-COVERAGE: 71.4%
CHECK-SOURCE-COVERAGE: 63.2%

0 comments on commit 5f237e4

Please sign in to comment.