Score Source Code Linker#

A Sphinx extension for enabling source code and test traceability for requirements.
This extension integrates with Bazel and sphinx-needs to automatically generate traceability links between implementation, tests, and documentation.


Overview#

The extension is split into two main components:

  • CodeLink – Parses source files for template strings and links them to needs.

  • TestLink – Parses test.xml outputs inside bazel-testlogs to link test cases to requirements.

Each component stores intermediate data in JSON caches under _build/ to optimize performance and speed up incremental builds.


How It Works#




⚠️ Known Limitations#


🏗️ Internal Module Overview#

score_source_code_linker/
├── __init__.py                   # Main Sphinx extension; combines CodeLinks + TestLinks
├── generate_source_code_links_json.py  # Parses source files for tags
├── need_source_links.py         # Data model for combined links
├── needlinks.py                 # CodeLink dataclass & JSON encoder/decoder
├── testlink.py                  # DataForTestLink definition & logic
├── xml_parser.py                # Parses XML files into test case data
├── tests/                       # Testsuite, containing unit & integration tests
│   └── ...

Clearing Cache Manually#

To clear the build cache, run:

rm -rf _build/

Examples:#

To see working examples for CodeLinks & TestLinks, take a look at the Docs-As-Code documentation.

Example CodeLink Example CodeLink

Example TestLink

Flow-Overview#

        flowchart TD
    %% Entry Point
    A[source_code_linker] --> B{Check for Grouped JSON Cache}

    %% If cache exists
    B --> |✅| C[Load Grouped JSON Cache]
    B --> |🔴| N9[Proceed Without Cache]

    %% --- NeedLink Path ---
    N9 --> D1[needslink.py<br/><b>NeedLink</b>]
    D1 --> E1{Check for CodeLink JSON Cache}

    E1 --> |✅| F1[Load CodeLink JSON Cache]
    F1 --> Z[Grouped JSON Cache]

    E1 --> |🔴| G1[Parse all files in repository]
    G1 --> H1[Build & Save<br/>CodeLink JSON Cache]
    H1 --> Z

    %% --- TestLink Path ---
    N9 --> D2[testlink.py<br/><b>DFTL</b>]
    D2 --> E2{Check for DFTL JSON Cache}

    E2 --> |✅| F2[Load DFTL JSON Cache]
    F2 --> J2[Load DOTC JSON Cache]
    J2 --> K2[Add as External Needs]

    E2 --> |🔴| G2[Parse test.xml Files]
    G2 --> H2[Convert TestCases<br/>to DOTC]
    H2 --> I2[Build & Save<br/>DOTC JSON Cache]
    I2 --> K2

    H2 --> M2[Convert to DFTL]
    M2 --> N2[Build & Save<br/>DFTL JSON Cache]
    N2 --> Z

    %% Final step
    Z --> FINAL[<b>Add links to needs</b>]

    %% Legend
    subgraph Legend["Legend"]
        direction TB
        L1[NeedLink Operations]
        L2[TestLink Operations]
        L4[DTFL = DataForTestLink]
        L3[TestCaseNeed Operations]
        L5[DOTC = DataOfTestCase]
        L1 ~~~ L2 
        L2 ~~~ L4 
        L4 ~~~ L3 
        L3 ~~~ L5
    end

    %% Node Styling
    classDef needlink fill:#3b82f6,color:#ffffff,stroke:#1d4ed8,stroke-width:2px
    classDef testlink fill:#8b5cf6,color:#ffffff,stroke:#6d28d9,stroke-width:2px
    classDef dotc fill:#f59e0b,color:#ffffff,stroke:#b45309,stroke-width:2px
    classDef grouped fill:#10b981,color:#ffffff,stroke:#047857,stroke-width:2px
    classDef final fill:#f43f5e,color:#ffffff,stroke:#be123c,stroke-width:2px

    %% Class assignments
    class D1,E1,F1,G1,H1 needlink
    class D2,E2,F2,G2,M2,N2 testlink
    class J2,H2,I2,K2 dotc
    class Z grouped
    class FINAL final
    class L1 needlink
    class L2,L4 testlink
    class L3,L5 dotc

    %% Edge/Arrow Styling
    linkStyle default stroke:#22d3ee,stroke-width:2px,color:#22d3ee
    %% Ensure links in the Legend do not show up
    linkStyle 23,24,25,26 opacity:0