Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: ci

on:
push:
branches:
- main
pull_request:
branches:
- main
Expand Down
62 changes: 60 additions & 2 deletions src/mkdocstrings_handlers/zig/_internal/zig_docs_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,20 @@ def _parse_function(self, node: Node) -> dict | None:
fn_name = self._get_node_name(node)
doc_comment = self._get_doc_comments(node)
if fn_name and doc_comment:
return {
result = {
"node_type": "function",
"name": fn_name,
"doc": doc_comment,
"signature": self._get_function_signature(node),
"short_signature": self._get_short_function_signature(node),
}

return_struct = self._get_return_struct(node)
if return_struct:
result["return_struct"] = return_struct

return result

return None

def _get_function_signature(self, node: Node) -> str:
Expand Down Expand Up @@ -172,7 +178,7 @@ def _parse_field(self, node: Node) -> dict | None:
field_name = None
field_type = None
for child in node.children:
if child.type == "identifier":
if child.type == "identifier" and not field_name:
field_name = self._get_node_text(child)
elif child.type == ":":
continue
Expand All @@ -189,6 +195,50 @@ def _parse_field(self, node: Node) -> dict | None:

return None

def _get_return_struct(self, node: Node) -> dict | None:
"""
Parse structure returned from a function.
Probably recursive search for return is needed, but for we support only basic case.
"""
function_body = self._get_function_body(node)
if not function_body:
return None

for child in function_body.children:
if child.type == "expression_statement":
return_expression = self._get_return_expression(child)
if not return_expression:
continue

struct = self._get_struct_declaration(return_expression)
if not struct:
continue

parsed_struct = self._parse_structure(struct)
if not parsed_struct:
continue

parsed_struct["node_type"] = "struct"
return parsed_struct

return None

def _get_function_body(self, node: Node) -> Node | None:
"""Get the block which represents the function's body"""
for child in node.children:
if child.type == "block":
return child

return None

def _get_return_expression(self, node: Node) -> Node | None:
"""Check if the statement is return and return the return value"""
for child in node.children:
if child.type == "return_expression":
return child

return None


def _main() -> None:
import json # noqa: PLC0415
Expand Down Expand Up @@ -217,6 +267,14 @@ def _main() -> None:
.y = std.math.maxInt(u32),
};
};

/// Generic structure factory example
fn GenericStructure(comptime T: type) type {
return struct {
/// Contained value
value: T,
};
}
"""

extractor = _ZigDocsExtractor(code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
</div>
{% endif %}

{% include "partials/parameters.html.jinja" %}
{% include "parameters.html.jinja" %}

{% with parent = parent.return_struct %}
{% include "struct.html.jinja" %}
{% endwith %}
</div>
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

<div class="doc doc-object doc-data">
{% with obj = data, html_id = data.path %}
{% include "partials/heading.html.jinja" %}
{% include "heading.html.jinja" %}

{% with heading_level=heading_level+1 %}
<div class="doc doc-contents {% if root %}first{% endif %}">
{% block contents scoped %}
{% include "partials/docstring.html.jinja" %}
{% include "docstring.html.jinja" %}
{% for child in data.children %}
{% with parent=child %}
{% include "partials/fields.html.jinja" %}
{% include "partials/constant.html.jinja" %}
{% include "partials/struct.html.jinja" %}
{% include "partials/function.html.jinja" %}
{% include "fields.html.jinja" %}
{% include "constant.html.jinja" %}
{% include "struct.html.jinja" %}
{% include "function.html.jinja" %}
{% endwith %}
{% endfor %}
{% endblock contents %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{% include "partials/modules.html.jinja" %}
{% for child in data %}
{% with data=child %}
{% include "module.html.jinja" %}
{% endwith %}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{% if parent.node_type == "struct" %}
{% if parent and parent.node_type == "struct" %}
<div class="struct" id="struct-{{ parent.name }}">
{% if parent.name %}
{% filter heading(heading_level, id=html_id ~ parent.name) %}{{ parent.short_signature }}{% endfilter %}

{% endif %}

{% if parent.doc %}
<div class="docstring">
{% with heading_level=heading_level + 1 %}
Expand All @@ -12,10 +14,10 @@

{% for child in parent.children %}
{% with parent = child, heading_level = heading_level + 1 %}
{% include "partials/fields.html.jinja" %}
{% include "partials/constant.html.jinja" %}
{% include "partials/struct.html.jinja" %}
{% include "partials/function.html.jinja" %}
{% include "fields.html.jinja" %}
{% include "constant.html.jinja" %}
{% include "struct.html.jinja" %}
{% include "function.html.jinja" %}
{% endwith %}
{% endfor %}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/constant.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/docstring.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/fields.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/function.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/heading.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/module.html.jinja" %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/parameters.html.jinja" %}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "_base/struct.html.jinja" %}
8 changes: 8 additions & 0 deletions test_zig_project/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ const std = @import("std");

/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details.
const lib = @import("test_zig_project_lib");

/// Generic structure factory example
fn GenericStructure(comptime T: type) type {
return struct {
/// Contained value
value: T,
};
}
32 changes: 31 additions & 1 deletion tests/test_zig_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def test_parser() -> None:

/// Adds two numbers.
fn add(a: i32, b: i32) i32 {
return a b;
return a + b;
}

/// A constant named PI.
Expand All @@ -33,6 +33,14 @@ def test_parser() -> None:
pub fn main() void {
std.print("Hello, world!\n");
}

/// Generic structure factory example
fn GenericStructure(comptime T: type) type {
return struct {
/// Contained value
value: T,
};
}
"""

parsed = ZigDocsExtractor(zig_code).get_docs()
Expand Down Expand Up @@ -88,5 +96,27 @@ def test_parser() -> None:
"signature": "pub fn main() void",
"short_signature": "pub fn main",
},
{
"node_type": "function",
"name": "GenericStructure",
"doc": "Generic structure factory example",
"signature": "fn GenericStructure(comptime T: type) type",
"short_signature": "fn GenericStructure",
"return_struct": {
"node_type": "struct",
"children": [
{
"node_type": "fields",
"children": [
{
"doc": "Contained value",
"name": "value",
"type": "T",
},
],
},
],
},
},
],
}
Loading