Skip to content

Commit ca6f40e

Browse files
authored
Merge pull request #660 from kkoomen/feature/python-classes
Implement class docstrings
2 parents 39b42ec + 40422f2 commit ca6f40e

11 files changed

+234
-0
lines changed

Diff for: helper/src/python/docs/doxygen.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# https://www.woolseyworkshop.com/2020/06/25/documenting-python-programs-with-doxygen/
22

33
templates:
4+
class:
5+
node_types:
6+
- class_definition
7+
template: |
8+
"""! @brief [TODO:description]"""
9+
410
function:
511
node_types:
612
- function_definition

Diff for: helper/src/python/docs/google.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# https://github.com/google/styleguide/blob/gh-pages/pyguide.md
22

33
templates:
4+
class:
5+
node_types:
6+
- class_definition
7+
template: |
8+
"""
9+
[TODO:description]
10+
{% if attributes %}
11+
~
12+
Attributes:
13+
{% for attribute in attributes %}
14+
<INDENT>{{ attribute.name }}{% if show_types or not attribute.type %} ({{ attribute.type | default(value="[TODO:type]") }}){% endif %}: [TODO:description]
15+
{% endfor %}
16+
{% endif %}
17+
"""
18+
419
function:
520
node_types:
621
- function_definition

Diff for: helper/src/python/docs/numpy.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
# http://daouzli.com/blog/docstring.html#numpydoc
22

33
templates:
4+
class:
5+
node_types:
6+
- class_definition
7+
template: |
8+
"""
9+
[TODO:description]
10+
{% if attributes %}
11+
~
12+
Attributes
13+
----------
14+
{% for attribute in attributes %}
15+
{{ attribute.name }}{% if show_types or not attribute.type %} : {{ attribute.type | default(value="[TODO:type]") }}{% endif %}
16+
<INDENT>[TODO:description]
17+
{% endfor %}
18+
{% endif %}
19+
"""
20+
421
function:
522
node_types:
623
- function_definition

Diff for: helper/src/python/docs/reST.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# http://daouzli.com/blog/docstring.html#restructuredtext
22

33
templates:
4+
class:
5+
node_types:
6+
- class_definition
7+
template: |
8+
"""
9+
[TODO:description]
10+
{% if attributes %}
11+
~
12+
Attributes:
13+
{% for attribute in attributes %}
14+
<INDENT>{{ attribute.name }}{% if show_types or not attribute.type %} ({{ attribute.type | default(value="[TODO:type]") }}){% endif %}: [TODO:description]
15+
{% endfor %}
16+
{% endif %}
17+
"""
18+
419
function:
520
node_types:
621
- function_definition

Diff for: helper/src/python/docs/sphinx.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html
22

33
templates:
4+
class:
5+
node_types:
6+
- class_definition
7+
template: |
8+
"""
9+
[TODO:description]
10+
{% if attributes %}
11+
~
12+
Attributes:
13+
{% for attribute in attributes %}
14+
<INDENT>{{ attribute.name }}{% if show_types or not attribute.type %} ({{ attribute.type | default(value="[TODO:type]") }}){% endif %}: [TODO:description]
15+
{% endfor %}
16+
{% endif %}
17+
"""
18+
419
function:
520
node_types:
621
- function_definition

Diff for: helper/src/python/parser.rs

+55
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl<'a> PythonParser<'a> {
6464
for child_node in traverse::PreOrder::new(node.walk()) {
6565
if child_node.start_position().row + 1 == *self.line && self.node_types.contains(&child_node.kind()) {
6666
return match child_node.kind() {
67+
"class_definition" => Some(self.parse_class(&child_node)),
6768
"function_definition" => Some(self.parse_function(&child_node)),
6869
_ => None,
6970
};
@@ -73,6 +74,60 @@ impl<'a> PythonParser<'a> {
7374
None
7475
}
7576

77+
fn parse_class(&self, node: &Node) -> Result<Map<String, Value>, String> {
78+
let mut tokens = Map::new();
79+
80+
for child_node in node.children(&mut node.walk()) {
81+
match child_node.kind() {
82+
"identifier" => {
83+
tokens.insert("name".to_string(), Value::String(self.get_node_text(&child_node)));
84+
},
85+
"block" => {
86+
let attributes = self.parse_class_attributes(&child_node);
87+
if !attributes.is_empty() {
88+
tokens.insert("attributes".to_string(), Value::Array(attributes));
89+
}
90+
}
91+
_ => {},
92+
}
93+
}
94+
95+
Ok(tokens)
96+
}
97+
98+
fn parse_class_attributes(&self, node: &Node) -> Vec<Value> {
99+
let mut attributes = Vec::new();
100+
101+
node
102+
.children(&mut node.walk())
103+
.filter(|node| node.kind() == "expression_statement")
104+
.for_each(|node| {
105+
let mut attr = Map::new();
106+
107+
node
108+
.children(&mut node.walk())
109+
.filter(|node| node.kind() == "assignment")
110+
.for_each(|node|
111+
for child_node in node.children(&mut node.walk()) {
112+
match child_node.kind() {
113+
"identifier" => {
114+
attr.insert("name".to_string(), Value::String(self.get_node_text(&child_node)));
115+
},
116+
"type" => {
117+
attr.insert("type".to_string(), Value::String(self.get_node_text(&child_node)));
118+
},
119+
_ => {}
120+
}
121+
}
122+
);
123+
124+
attributes.push(Value::Object(attr));
125+
});
126+
127+
attributes
128+
}
129+
130+
76131
fn parse_function(&self, node: &Node) -> Result<Map<String, Value>, String> {
77132
let mut tokens = Map::new();
78133

Diff for: test/filetypes/python/classes-doc-doxygen.vader

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ==============================================================================
2+
# Classes with attributes
3+
# ==============================================================================
4+
Given python (class with two attributes):
5+
class Foo:
6+
bar = 1
7+
baz: int = 2
8+
9+
Do (run doge):
10+
:let b:doge_doc_standard='doxygen'\<CR>
11+
\<C-d>
12+
13+
Expect python (class with docstring describing all attributes):
14+
class Foo:
15+
"""! @brief [TODO:description]"""
16+
bar = 1
17+
baz: int = 2

Diff for: test/filetypes/python/classes-doc-google.vader

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ==============================================================================
2+
# Classes with attributes
3+
# ==============================================================================
4+
Given python (class with two attributes):
5+
class Foo:
6+
bar = 1
7+
baz: int = 2
8+
9+
Do (run doge):
10+
:let b:doge_doc_standard='google'\<CR>
11+
\<C-d>
12+
13+
Expect python (class with docstring describing all attributes):
14+
class Foo:
15+
"""
16+
[TODO:description]
17+
18+
Attributes:
19+
bar ([TODO:type]): [TODO:description]
20+
baz: [TODO:description]
21+
"""
22+
bar = 1
23+
baz: int = 2

Diff for: test/filetypes/python/classes-doc-numpy.vader

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# ==============================================================================
2+
# Classes with attributes
3+
# ==============================================================================
4+
Given python (class with two attributes):
5+
class Foo:
6+
bar = 1
7+
baz: int = 2
8+
9+
Do (run doge):
10+
:let b:doge_doc_standard='numpy'\<CR>
11+
\<C-d>
12+
13+
Expect python (class with docstring describing all attributes):
14+
class Foo:
15+
"""
16+
[TODO:description]
17+
18+
Attributes
19+
----------
20+
bar : [TODO:type]
21+
[TODO:description]
22+
baz
23+
[TODO:description]
24+
"""
25+
bar = 1
26+
baz: int = 2

Diff for: test/filetypes/python/classes-doc-sphinx.vader

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ==============================================================================
2+
# Classes with attributes
3+
# ==============================================================================
4+
Given python (class with two attributes):
5+
class Foo:
6+
bar = 1
7+
baz: int = 2
8+
9+
Do (run doge):
10+
:let b:doge_doc_standard='sphinx'\<CR>
11+
\<C-d>
12+
13+
Expect python (class with docstring describing all attributes):
14+
class Foo:
15+
"""
16+
[TODO:description]
17+
18+
Attributes:
19+
bar ([TODO:type]): [TODO:description]
20+
baz: [TODO:description]
21+
"""
22+
bar = 1
23+
baz: int = 2

Diff for: test/filetypes/python/classes.vader

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# ==============================================================================
2+
# Classes with attributes
3+
# ==============================================================================
4+
Given python (class with two attributes):
5+
class Foo:
6+
bar = 1
7+
baz: int = 2
8+
9+
Do (run doge):
10+
\<C-d>
11+
12+
Expect python (class with docstring describing all attributes):
13+
class Foo:
14+
"""
15+
[TODO:description]
16+
17+
Attributes:
18+
bar ([TODO:type]): [TODO:description]
19+
baz: [TODO:description]
20+
"""
21+
bar = 1
22+
baz: int = 2

0 commit comments

Comments
 (0)