Skip to content

Commit

Permalink
doc: extensions: Navigate to DTS entries from supported hardware list
Browse files Browse the repository at this point in the history
Update the gen_board_catalog.py logic to also capture lineno for
each devicetree node. Use that info in the supported hardware list to
create clickable elements that directly take the user to the
corresponding line in the devicetree file on Github.

Signed-off-by: Benjamin Cabé <[email protected]>
  • Loading branch information
kartben committed Feb 28, 2025
1 parent 8db6fa8 commit 4f77244
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 28 deletions.
50 changes: 34 additions & 16 deletions doc/_extensions/zephyr/domain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

from anytree import ChildResolverError, Node, PreOrderIter, Resolver, search
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.parsers.rst import directives, roles
from docutils.statemachine import StringList
from sphinx import addnodes
from sphinx.application import Sphinx
Expand Down Expand Up @@ -811,7 +811,8 @@ def run(self):
<span class="count disabled-count">2</span>
</dt>
<dd>
Number of instances that are enabled / disabled.
Number of instances that are enabled / disabled. <br/>
Click on the label to see the first instance of this feature in the board/SoC DTS files.
</dd>
<dt>
<code class="docutils literal notranslate"><span class="pre">vnd,foo</span></code>
Expand Down Expand Up @@ -870,7 +871,7 @@ def feature_sort_key(feature):

for i, (key, value) in enumerate(items):
row = nodes.row()
if value.get("disabled_count", 0) > 0 and value.get("okay_count", 0) == 0:
if value.get("disabled_nodes", []) and not value.get("okay_nodes", []):
row["classes"].append("disabled")

# TYPE column
Expand Down Expand Up @@ -911,22 +912,39 @@ def feature_sort_key(feature):
desc_para += nodes.Text(value["description"])

# Add count indicators for okay and not-okay instances
okay_count = value.get("okay_count", 0)
disabled_count = value.get("disabled_count", 0)
okay_nodes = value.get("okay_nodes", [])
disabled_nodes = value.get("disabled_nodes", [])

if okay_count > 0:
okay_count_indicator = nodes.inline(
classes=["count", "okay-count"],
text=str(okay_count),
)
desc_para += okay_count_indicator
role_fn, _ = roles.role(
"zephyr_file", self.state_machine.language, self.lineno, self.state.reporter
)

def create_count_indicator(nodes_list, class_type, role_function=role_fn):
if not nodes_list:
return None

count = len(nodes_list)

if role_function is None:
return nodes.inline(
classes=["count", f"{class_type}-count"], text=str(count)
)

if disabled_count > 0:
disabled_count_indicator = nodes.inline(
classes=["count", "disabled-count"],
text=str(disabled_count),
# Create a reference to the first node in the list
first_node = nodes_list[0]
file_ref = f"{count} <{first_node['filename']}#L{first_node['lineno']}>"

role_nodes, _ = role_function(
"zephyr_file", file_ref, file_ref, self.lineno, self.state.inliner
)
desc_para += disabled_count_indicator

count_node = role_nodes[0]
count_node["classes"] = ["count", f"{class_type}-count"]

return count_node

desc_para += create_count_indicator(okay_nodes, "okay")
desc_para += create_count_indicator(disabled_nodes, "disabled")

desc_entry += desc_para
row += desc_entry
Expand Down
1 change: 1 addition & 0 deletions doc/_extensions/zephyr/domain/static/css/board.css
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
font-size: 0.7em;
font-weight: 600;
margin-left: 4px;
padding-right: 6px !important;

&::before {
content: "×";
Expand Down
32 changes: 20 additions & 12 deletions doc/_scripts/gen_boards_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def get_catalog(generate_hw_features=False):
# Use pre-gathered build info and DTS files
if board.name in board_devicetrees:
for board_target, edt in board_devicetrees[board.name].items():
target_features = {}
features = {}
for node in edt.nodes:
if node.binding_path is None:
continue
Expand All @@ -271,6 +271,7 @@ def get_catalog(generate_hw_features=False):

description = DeviceTreeUtils.get_cached_description(node)
filename = node.filename
lineno = node.lineno
locations = set()
if Path(filename).is_relative_to(ZEPHYR_BASE):
filename = Path(filename).relative_to(ZEPHYR_BASE)
Expand All @@ -279,23 +280,30 @@ def get_catalog(generate_hw_features=False):
else:
locations.add("soc")

existing_feature = target_features.get(binding_type, {}).get(
existing_feature = features.get(binding_type, {}).get(
node.matching_compat
)

node_info = {"filename": str(filename), "lineno": lineno}
node_list_key = "okay_nodes" if node.status == "okay" else "disabled_nodes"

if existing_feature:
locations.update(existing_feature["locations"])
key = "okay_count" if node.status == "okay" else "disabled_count"
existing_feature[key] = existing_feature.get(key, 0) + 1
else:
key = "okay_count" if node.status == "okay" else "disabled_count"
target_features.setdefault(binding_type, {})[node.matching_compat] = {
"description": description,
"locations": locations,
key: 1
}
existing_feature.setdefault(node_list_key, []).append(node_info)
continue

feature_data = {
"description": description,
"locations": locations,
"okay_nodes": [],
"disabled_nodes": [],
}
feature_data[node_list_key].append(node_info)

features.setdefault(binding_type, {})[node.matching_compat] = feature_data

# Store features for this specific target
supported_features[board_target] = target_features
supported_features[board_target] = features

# Grab all the twister files for this board and use them to figure out all the archs it
# supports.
Expand Down

0 comments on commit 4f77244

Please sign in to comment.