Skip to content

Commit 006ab74

Browse files
committed
Feature: Export Doxygen TAGFILE with a map from requirements to StrictDoc documentation
1 parent 32a0ba7 commit 006ab74

File tree

11 files changed

+136
-2
lines changed

11 files changed

+136
-2
lines changed

strictdoc/cli/command_parser_builder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"reqif-sdoc",
1717
"reqifz-sdoc",
1818
"sdoc",
19+
"doxygen",
1920
"spdx",
2021
]
2122
EXCEL_PARSERS = ["basic"]

strictdoc/core/actions/export_action.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from strictdoc.core.project_config import ProjectConfig
1313
from strictdoc.core.traceability_index import TraceabilityIndex
1414
from strictdoc.core.traceability_index_builder import TraceabilityIndexBuilder
15+
from strictdoc.export.doxygen.doxygen_generator import DoxygenGenerator
1516
from strictdoc.export.html.document_type import DocumentType
1617
from strictdoc.export.html.html_generator import HTMLGenerator
1718
from strictdoc.export.html.html_templates import HTMLTemplates
@@ -153,6 +154,18 @@ def export(self) -> None:
153154
if "sdoc" in self.project_config.export_formats:
154155
self.export_sdoc()
155156

157+
if "doxygen" in self.project_config.export_formats:
158+
output_doxygen_root = os.path.join(
159+
self.project_config.output_dir, "doxygen"
160+
)
161+
doxygen_generator = DoxygenGenerator(
162+
project_config=self.project_config
163+
)
164+
doxygen_generator.export(
165+
traceability_index=self.traceability_index,
166+
path_to_output_dir=output_doxygen_root,
167+
)
168+
156169
if "spdx" in self.project_config.export_formats:
157170
output_dot_root = os.path.join(
158171
self.project_config.output_dir, "spdx"
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import os
2+
from pathlib import Path
3+
4+
from strictdoc.backend.sdoc.models.document import SDocDocument
5+
from strictdoc.backend.sdoc.models.node import SDocNode
6+
from strictdoc.core.document_iterator import DocumentCachingIterator
7+
from strictdoc.core.project_config import ProjectConfig
8+
from strictdoc.core.traceability_index import TraceabilityIndex
9+
from strictdoc.export.html.renderers.link_renderer import LinkRenderer
10+
11+
12+
class DoxygenGenerator:
13+
def __init__(self, project_config: ProjectConfig):
14+
self.project_config: ProjectConfig = project_config
15+
16+
def export(
17+
self,
18+
*,
19+
traceability_index: TraceabilityIndex,
20+
path_to_output_dir: str,
21+
) -> None:
22+
Path(path_to_output_dir).mkdir(parents=True, exist_ok=True)
23+
output_path = os.path.join(path_to_output_dir, "strictdoc.xml")
24+
25+
link_renderer = LinkRenderer(
26+
root_path="NOT_RELEVANT", static_path="NOT_RELEVANT"
27+
)
28+
29+
def template_node(node_uid: str, path_to_html: str) -> str:
30+
return f"""\
31+
<compound kind="page">
32+
<name>{node_uid}</name>
33+
<filename>html/{path_to_html}</filename>
34+
</compound>
35+
"""
36+
37+
template_all_nodes = ""
38+
39+
assert traceability_index.document_tree is not None
40+
assert traceability_index.document_tree.document_list is not None
41+
42+
document_: SDocDocument
43+
for document_ in traceability_index.document_tree.document_list:
44+
document_iterator = DocumentCachingIterator(document_)
45+
46+
for node in document_iterator.all_content(
47+
print_fragments=False,
48+
print_fragments_from_files=False,
49+
):
50+
if isinstance(node, SDocNode) and node.reserved_uid is not None:
51+
path_to_html = link_renderer.render_node_doxygen_link(node)
52+
template_all_nodes += template_node(
53+
node.reserved_uid, path_to_html
54+
)
55+
56+
template_xml = f"""\
57+
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
58+
<tagfile doxygen_version="1.9.8">
59+
{template_all_nodes.rstrip()}
60+
</tagfile>
61+
"""
62+
with open(output_path, "w", encoding="utf8") as file:
63+
file.write(template_xml)

strictdoc/export/html/renderers/link_renderer.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ def render_node_link(
139139
self.req_link_cache[link_cache_key][node] = requirement_link
140140
return requirement_link
141141

142+
def render_node_doxygen_link(
143+
self,
144+
node: Union[SDocDocument, SDocNode, SDocSection, Anchor],
145+
):
146+
"""
147+
allow_local: used on the DTR screen where we want to ensure that only
148+
full paths are used when jumping to the DOC screen.
149+
"""
150+
151+
assert isinstance(node, (SDocNode, SDocSection, Anchor)), node
152+
local_link = self.render_local_anchor(node)
153+
document_link = (
154+
node.parent_or_including_document.meta.get_html_doc_link()
155+
)
156+
requirement_link = f"{document_link}#{local_link}"
157+
return requirement_link
158+
142159
def render_requirement_link_from_source_file(self, node, source_file):
143160
assert isinstance(node, SDocNode)
144161
assert isinstance(source_file, SourceFile)

tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import re
66
import sys
77
from enum import Enum
8-
from typing import Optional, Dict
8+
from typing import Dict, Optional
99

1010
if not hasattr(inspect, "getargspec"):
1111
inspect.getargspec = inspect.getfullargspec
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
RUN: %expect_exit 2 %strictdoc export --formats=foo %S | filecheck %s --dump-input=fail
22

3-
CHECK: {{.*}} export: error: argument --formats: invalid choice: 'foo' (choose from 'html', 'html2pdf', 'rst', 'json', 'excel', 'reqif-sdoc', 'reqifz-sdoc', 'sdoc', 'spdx')
3+
CHECK: {{.*}} export: error: argument --formats: invalid choice: 'foo' (choose from 'html', 'html2pdf', 'rst', 'json', 'excel', 'reqif-sdoc', 'reqifz-sdoc', 'sdoc', 'doxygen', 'spdx')
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[DOCUMENT]
2+
TITLE: Hello world doc
3+
4+
[REQUIREMENT]
5+
UID: REQ-2
6+
TITLE: Title #2
7+
STATEMENT: System shall do foo.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[DOCUMENT]
2+
TITLE: Hello world doc
3+
4+
[REQUIREMENT]
5+
UID: REQ-3
6+
TITLE: Title #3
7+
STATEMENT: System shall do foo.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[DOCUMENT]
2+
TITLE: Hello world doc
3+
4+
[REQUIREMENT]
5+
UID: REQ-1
6+
TITLE: Title #1
7+
STATEMENT: System shall do foo.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
2+
<tagfile doxygen_version="1.9.8">
3+
<compound kind="page">
4+
<name>REQ-1</name>
5+
<filename>html/01_basic_export/input1.html#1-REQ-1</filename>
6+
</compound>
7+
<compound kind="page">
8+
<name>REQ-2</name>
9+
<filename>html/01_basic_export/folder/input2.html#1-REQ-2</filename>
10+
</compound>
11+
<compound kind="page">
12+
<name>REQ-3</name>
13+
<filename>html/01_basic_export/folder/subfolder/input3.html#1-REQ-3</filename>
14+
</compound>
15+
</tagfile>

0 commit comments

Comments
 (0)