-
Notifications
You must be signed in to change notification settings - Fork 20
Source links as Bazel target #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f6991e9
61dad86
d31a8fc
ac852e5
69991f3
740c4e2
c4d8950
2842afb
502f550
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,14 +2,65 @@ Reference Docs in Source Code | |||||||||||||||||
| ============================= | ||||||||||||||||||
|
|
||||||||||||||||||
| In your C++/Rust/Python source code, you want to reference requirements (needs). | ||||||||||||||||||
| The docs-as-code tool will create backlinks in the documentation. | ||||||||||||||||||
| The docs-as-code tool will create backlinks in the documentation in two steps: | ||||||||||||||||||
|
|
||||||||||||||||||
| 1. You add a special comment in your source code that references the need ID. | ||||||||||||||||||
| 2. Scan for those comments and provide needs links to your documentation. | ||||||||||||||||||
|
|
||||||||||||||||||
| For an example result, look at the attribute ``source_code_link`` | ||||||||||||||||||
| of :need:`tool_req__docs_common_attr_title`. | ||||||||||||||||||
|
|
||||||||||||||||||
| Comments in Source Code | ||||||||||||||||||
| ----------------------- | ||||||||||||||||||
|
|
||||||||||||||||||
| Use a comment and start with ``req-Id:`` or ``req-traceability:`` followed by the need ID. | ||||||||||||||||||
|
|
||||||||||||||||||
| .. code-block:: python | ||||||||||||||||||
|
|
||||||||||||||||||
| # req-Id: TOOL_REQ__EXAMPLE_ID | ||||||||||||||||||
| # req-traceability: TOOL_REQ__EXAMPLE_ID | ||||||||||||||||||
| # req-Id: TOOL_REQ__EXAMPLE_ID | ||||||||||||||||||
| # req-traceability: TOOL_REQ__EXAMPLE_ID | ||||||||||||||||||
|
|
||||||||||||||||||
| For an example, look at the attribute ``source_code_link`` | ||||||||||||||||||
| of :need:`tool_req__docs_common_attr_title`. | ||||||||||||||||||
| For other languages (C++, Rust, etc.), use the appropriate comment syntax. | ||||||||||||||||||
|
|
||||||||||||||||||
| Scanning Source Code for Links | ||||||||||||||||||
| ------------------------------ | ||||||||||||||||||
|
|
||||||||||||||||||
| In you ``BUILD`` files, you specify which source files to scan | ||||||||||||||||||
| with ``filegroup`` or ``glob`` or whatever Bazel mechanism you prefer. | ||||||||||||||||||
| Then, you use the ``sourcelinks_json`` rule to scan those files. | ||||||||||||||||||
| Finally, pass the scan results to the ``docs`` rule as ``sourcelinks`` attribute. | ||||||||||||||||||
|
Comment on lines
+28
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I remember correctly it was requested that we use non direct language (like you etc.) Here is a suggestion how that could look like:
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| .. code-block:: starlark | ||||||||||||||||||
| :emphasize-lines: 1, 12, 26 | ||||||||||||||||||
| :linenos: | ||||||||||||||||||
|
|
||||||||||||||||||
| load("//:docs.bzl", "docs", "sourcelinks_json") | ||||||||||||||||||
|
|
||||||||||||||||||
| filegroup( | ||||||||||||||||||
| name = "some_sources", | ||||||||||||||||||
| srcs = [ | ||||||||||||||||||
| "foo.py", | ||||||||||||||||||
| "bar.cpp", | ||||||||||||||||||
| "data.yaml", | ||||||||||||||||||
| ] + glob(["subdir/**/.py"]), | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| sourcelinks_json( | ||||||||||||||||||
| name = "my_source_links", | ||||||||||||||||||
| srcs = [ | ||||||||||||||||||
| ":some_sources", | ||||||||||||||||||
| "//src:all_sources", | ||||||||||||||||||
| # whatever | ||||||||||||||||||
| ], | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| docs( | ||||||||||||||||||
| data = [ | ||||||||||||||||||
| "@score_process//:needs_json", | ||||||||||||||||||
| ], | ||||||||||||||||||
| source_dir = "docs", | ||||||||||||||||||
| sourcelinks = [":my_source_links"], | ||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. up to now docs() is defining internal targets like needs_json itself. All in one command. Can we do the same with sourcelinks_json? |
||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| Since the source links are Bazel targets, you can easily reference other modules as well. | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # ******************************************************************************* | ||
| # Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| # | ||
| # See the NOTICE file(s) distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the Apache License Version 2.0 which is available at | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # ******************************************************************************* | ||
|
|
||
| load("@aspect_rules_py//py:defs.bzl", "py_binary") | ||
| load("@pip_process//:requirements.bzl", "all_requirements") | ||
|
|
||
| py_binary( | ||
| name = "generate_sourcelinks", | ||
| srcs = ["generate_sourcelinks_cli.py"], | ||
| main = "generate_sourcelinks_cli.py", | ||
| visibility = ["//visibility:public"], | ||
| deps = [ | ||
| "//src/extensions/score_source_code_linker", | ||
| ] + all_requirements, | ||
| ) | ||
|
|
||
| py_binary( | ||
| name = "merge_sourcelinks", | ||
| srcs = ["merge_sourcelinks.py"], | ||
| main = "merge_sourcelinks.py", | ||
| visibility = ["//visibility:public"], | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # ******************************************************************************* | ||
a-zw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| # | ||
| # See the NOTICE file(s) distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the Apache License Version 2.0 which is available at | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # ******************************************************************************* | ||
|
|
||
| """ | ||
| CLI tool to generate source code links JSON from source files. | ||
| This is used by the Bazel sourcelinks_json rule to create a JSON file | ||
| with all source code links for documentation needs. | ||
| """ | ||
|
|
||
| import argparse | ||
| import logging | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| from src.extensions.score_source_code_linker.generate_source_code_links_json import ( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might need to either make this function public or make a public counterpart.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure yet. Eventually, we should be able to extract it from the Sphinx extension, because the extension shall only consume the json files. |
||
| _extract_references_from_file, | ||
| ) | ||
| from src.extensions.score_source_code_linker.needlinks import ( | ||
| store_source_code_links_json, | ||
| ) | ||
|
|
||
| logging.basicConfig(level=logging.INFO, format="%(message)s") | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser( | ||
| description="Generate source code links JSON from source files" | ||
| ) | ||
| parser.add_argument( | ||
| "--output", | ||
| required=True, | ||
| type=Path, | ||
| help="Output JSON file path", | ||
| ) | ||
| parser.add_argument( | ||
| "files", | ||
| nargs="*", | ||
| type=Path, | ||
| help="Source files to scan for traceability tags", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| all_need_references = [] | ||
| for file_path in args.files: | ||
| abs_file_path = file_path.resolve() | ||
| if abs_file_path.exists(): | ||
| references = _extract_references_from_file( | ||
| abs_file_path.parent, Path(abs_file_path.name) | ||
| ) | ||
| all_need_references.extend(references) | ||
MaximilianSoerenPollak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| store_source_code_links_json(args.output, all_need_references) | ||
| logger.info( | ||
| f"Found {len(all_need_references)} need references in {len(args.files)} files" | ||
| ) | ||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all following items are already included in src:all_sources?