Skip to content

5 REQ lang

Manuel Hatzl edited this page Sep 5, 2025 · 7 revisions

lang: Conventions for integrated programming languages

Sub-requirements of lang define conventions and syntax constructs that must be followed by users that want to use mantra's built-in automatic trace, test, and coverage collection for supported programming languages.

lang.rust: Conventions for Rust

Contains conventions for Rust code to allow automated collection of traceability information by mantra.

lang.rust.tracing: Rules to detect traces in Rust code

  • Parents: [lang.rust, trace.collect.auto.ast, trace.collect.auto.pattern, trace.kind]

Sub-requirements describe patterns that must be recognized as requirements traces in Rust code.

Note: <requirement IDs> is used in this section as placeholder for the pattern or parts of the pattern defined in [req("trace.collect.auto.pattern")].

lang.rust.tracing.attribute_macros: Detectable attribute macros

These traces have an associated line span of the element the attribute macro is set on.

The module path must be irrelevant for the detection to allow different macro implementations.

mantra must be able to detect the attribute macro inside a cfg_attr attribute macro independent of the currently active features.

  • Clarify Requirement Macro:

    The attribute macro #[req_note()] may be used to mark code that adds clarification for one or more requirements. Therefore, mantra must detect this macro as a trace of kind clarify.

    Examples:

    #[req_note(<requirement IDs>)]
    fn foo() {}
  • Satisfy Requirement Macro:

    The attribute macro #[req()] may be used to mark code that satisfies one or more requirements. Therefore, mantra must detect this macro as a trace of kind satisfy.

    Examples:

    #[req(<requirement IDs>)]
    fn foo() {}
    #[mod_path::req(<requirement IDs>)]
    fn foo() {}
    #[cfg_attr(<some condition>, mod_path::req(<requirement IDs>))]
    fn foo() {}
    #[req(<requirement IDs>; { prop_key: "custom-prop-1" }, "custom-prop-2")]
    fn foo() {}
  • Verify Requirement Macro:

    The attribute macro #[req_test()] may be used to mark code that verifies one or more requirements. Therefore, mantra must detect this macro as a trace of kind verify.

    Examples:

    #[req_test(<requirement IDs>)]
    fn foo() {}
  • Link Requirement Macro:

    The attribute macro #[req_link()] may be used to mark code that links to one or more requirements. Therefore, mantra must detect this macro as a trace of kind links.

    Examples:

    #[req_link(<requirement IDs>)]
    fn foo() {}

lang.rust.tracing.fn_macros: Detectable function-like macros

These traces only link to the lines the macro itself spans.

The module path must be irrelevant for the detection to allow different macro implementations.

  • Satisfy Requirement Macro:

    fn foo() {
        satisfy_req!(<requirement IDs>; <some code that is passed through>);
        mod_path::satisfy_req!(<requirement IDs>; { some_key: "custom-prop" }; <some code that is passed through>);
    }
  • Verify Requirement Macro:

    fn foo() {
        assert_req!(<requirement IDs>; <some boolean expression that must evaluate to "true">, <some message explaining the assertion>);
        assert_req_eq!(<requirement IDs>; <left side>, <right side>);
    }

Detectable traces in comments

These traces have an associated line span of the element the comment is referred to. The trace syntax is similar to the one for attribute macros except the missing # at the start.

Note: Traces in block comments are not supported to reduce the potential of false trace detection.

  • Doc-Comments:

    /// [req(<requirement IDs>)]
    fn foo() {}
  • Line Comments:

    For traces in regular line comments, several restrictions apply to prevent false detection:

    • Traces must be on a separate commented line without any other content except whitespace
    • The line directly below a trace must contain a non-commented element to which the trace is linked to
    • The affected line span depends on the non-commented element the trace is linked to
    fn foo() {
        // [req(<requirement IDs>)]
        let x = 5;
    }

lang.rust.tracing.span: Line span of elements and code blocks in Rust code

Line spans of elements in Rust code must include the element header, element body, doc comments, and attribute macros set on an element, because code generated by attribute macros has the line the macro is set at. To properly map covered statements to traces, the line span of elements must therefore cover more lines than just the body.

e.g. all lines of the example below are part of the element span

/// Some doc comment for the function.
#[req(<requirement IDs>)]
fn foo() { // <- element header up until `{`
    // some body content
}

Line spans of code blocks must include the span of the code block and the optional line comments directly above a code block if no blank line is between the last line comment and the code block start.

Clone this wiki locally