Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

@startuml

participant "Unit 1" as unit_1 <<unit>>
participant "Unit 2" as unit_2 <<unit>>
participant "Unit 1 : safety_software_seooc_example::component_example::unit_1" as unit_1 <<unit>>
participant "Unit 2 : safety_software_seooc_example::component_example::unit_2" as unit_2 <<unit>>

unit_1 -> unit_2 : GetData()
return Data*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@

@startuml

namespace safety_software_seooc_example {
interface "SampleLibraryAPI" as SampleLibraryAPI {
+ GetNumber(): int
}
interface "SampleLibraryAPI" as SampleLibraryAPI <<interface>> {
+ GetNumber(): int
}

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ package "Safety Software SEooC Example" as safety_software_seooc_example <<SEooC

interface "InternalInterface" as InternalInterface
unit_1 -l-( InternalInterface
unit_2 -r- InternalInterface
unit_2 )-r- InternalInterface
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ScoreReq.FailureMode SampleFailureMode{
failureeffect = "The world as we know it will end"
version = 1
safety = ScoreReq.Asil.B
interface = "safety_software_seooc_example.SampleLibraryAPI.GetNumber"
interface = "design.SampleLibraryAPI.GetNumber"
}

ScoreReq.FailureMode SampleFailureMode2{
Expand All @@ -29,5 +29,5 @@ ScoreReq.FailureMode SampleFailureMode2{
failureeffect = "Downstream consumers time out"
version = 1
safety = ScoreReq.Asil.D
interface = "safety_software_seooc_example.SampleLibraryAPI.GetNumber"
interface = "design.SampleLibraryAPI.GetNumber"
}
4 changes: 3 additions & 1 deletion bazel/rules/rules_score/private/architectural_design.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ to produce FlatBuffers binary representations of the parsed diagrams.

load("@bazel_skylib//lib:paths.bzl", "paths")
load("//bazel/rules/rules_score:providers.bzl", "ArchitecturalDesignInfo", "SphinxSourcesInfo")
load("//bazel/rules/rules_score/private:puml_utils.bzl", "emit_view_navigation", "plan_view_layout", "relative_source_path")
load("//bazel/rules/rules_score/private:puml_utils.bzl", "emit_view_navigation", "package_root_anchor", "plan_view_layout", "relative_source_path")
load("//bazel/rules/rules_score/private:validation.bzl", "PROFILES", "VALIDATION_ATTRS", "run_validation")
load("//bazel/rules/rules_score/private:verbosity.bzl", "VERBOSITY_ATTR", "get_log_level")
load("//bazel/rules/rules_score/private:views.bzl", "ARCH_VIEWS")
Expand Down Expand Up @@ -138,6 +138,8 @@ def _run_puml_parser(ctx, puml_file, file_stem):
puml_file.short_path,
"--output-stem",
file_stem,
"--root-anchor",
package_root_anchor(ctx),
"--log-level",
get_log_level(ctx),
],
Expand Down
15 changes: 15 additions & 0 deletions bazel/rules/rules_score/private/puml_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ indexes for one architectural design view (static/dynamic/public_api/internal_ap

load("@bazel_skylib//lib:paths.bzl", "paths")

def package_root_anchor(ctx):
"""Return the resolver root anchor derived from the owning Bazel package.

The resolver uid model uses dot-separated package segments, while Bazel
labels use `/` between package path elements.

Args:
ctx: Rule context.

Returns:
Dot-separated package path string, or the empty string for repo-root
targets.
"""
return ctx.label.package.replace("/", ".")

def relative_source_path(file, package, own_repo = None):
"""Return `file`'s path relative to `package`, or its full workspace-relative
short_path when it doesn't live under `package` -- never just the bare
Expand Down
2 changes: 2 additions & 0 deletions bazel/rules/rules_score/private/unit.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ load("@rules_rust//rust:defs.bzl", "rust_common")
load("//bazel/rules/rules_score:providers.bzl", "CcDependencyInfo", "CertifiedScope", "SphinxSourcesInfo", "UnitDesignInfo", "UnitInfo")
load("//cpp/libclang:cpp_parser.bzl", "cpp_parser_action_internal_attrs", "cpp_parser_action_toolchains", "cpp_parser_target_aspects", "has_cpp_parser_inputs", "run_cpp_parser_action")
load(":cc_dependency_aspect.bzl", "cc_dependencies_aspect")
load(":puml_utils.bzl", "package_root_anchor")
load(":validation.bzl", "PROFILES", "VALIDATION_ATTRS", "run_validation")
load(":verbosity.bzl", "VERBOSITY_ATTR", "get_log_level")

Expand All @@ -36,6 +37,7 @@ def _run_implementation_cpp_parser(ctx, impl, output_prefix):
output_prefix = output_prefix,
tool = ctx.attr._tool,
log_level = ctx.attr._log_level[BuildSettingInfo].value,
root_anchor = package_root_anchor(ctx),
)

def _target_output_prefix(ctx, target):
Expand Down
3 changes: 3 additions & 0 deletions bazel/rules/rules_score/private/unit_design.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ verification tooling.
"""

load("//bazel/rules/rules_score:providers.bzl", "SphinxSourcesInfo", "UnitDesignInfo")
load("//bazel/rules/rules_score/private:puml_utils.bzl", "package_root_anchor")
load("//bazel/rules/rules_score/private:verbosity.bzl", "VERBOSITY_ATTR", "get_log_level")

# ============================================================================
Expand Down Expand Up @@ -68,6 +69,8 @@ def _run_puml_parser(ctx, puml_file):
idmap_output.dirname,
"--source-name",
puml_file.short_path,
"--root-anchor",
package_root_anchor(ctx),
"--log-level",
get_log_level(ctx),
],
Expand Down
7 changes: 7 additions & 0 deletions cpp/libclang/cpp_parser.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ def run_cpp_parser_action(
output_prefix,
tool,
log_level,
root_anchor = "",
extra_args = [],
emit_debug_json = False):
"""Register the libclang parser action and return its declared outputs.
Expand Down Expand Up @@ -315,6 +316,12 @@ def run_cpp_parser_action(
debug_json_output.path,
]

if root_anchor:
args += [
"--root-anchor",
root_anchor,
]

target_compilation_flags_list = target[CompilationFlagsInfo].flags.to_list()

target_source_files_info = target[SourceFilesInfo]
Expand Down
41 changes: 40 additions & 1 deletion cpp/libclang/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ struct Args {
/// Debug JSON output path (internal use only)
#[arg(long, hide = true)]
debug_json_output: Option<PathBuf>,

/// Resolver root anchor for IDs emitted by this parser (internal use only)
#[arg(long, hide = true, default_value = "")]
root_anchor: String,
}

#[derive(Default)]
Expand Down Expand Up @@ -210,6 +214,37 @@ fn serialize_class_diagram(
Ok(())
}

fn apply_root_anchor(
entities: &mut BTreeMap<String, SimpleEntity>,
free_functions: &mut [FreeFunctionDecl],
root_anchor: &str,
) {
if root_anchor.is_empty() {
return;
}

let mut anchored_entities = BTreeMap::new();
for (_, mut entity) in std::mem::take(entities) {
entity.id = format!("{root_anchor}::{}", entity.id);
entity.enclosing_namespace_id = entity
.enclosing_namespace_id
.map(|namespace| format!("{root_anchor}::{namespace}"));
for relationship in &mut entity.relationships {
relationship.source = format!("{root_anchor}::{}", relationship.source);
relationship.target = format!("{root_anchor}::{}", relationship.target);
}
anchored_entities.insert(entity.id.clone(), entity);
}
*entities = anchored_entities;

for free_function in free_functions {
free_function.enclosing_namespace_id = Some(match &free_function.enclosing_namespace_id {
Some(namespace) if !namespace.is_empty() => format!("{root_anchor}::{namespace}"),
_ => root_anchor.to_string(),
});
}
}

fn ensure_output_parent_exists(path: &Path) -> Result<(), std::io::Error> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
Expand Down Expand Up @@ -251,6 +286,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
}

apply_root_anchor(
&mut outputs.types,
&mut outputs.free_function_declarations,
&command_line_args.root_anchor,
);
if let Some(debug_json_output) = &command_line_args.debug_json_output {
write_debug_json(
debug_json_output,
Expand All @@ -260,7 +300,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
&outputs.functions,
)?;
}

serialize_class_diagram(
&command_line_args.class_fbs_output,
outputs.types,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
}
},
{
"id": "sample.file_level.<<template>>\\nTest<T>",
"id": "sample.file_level.TestTemplate",
"name": "TestTemplate",
"enclosing_namespace_id": "sample.file_level",
"stereotypes": ["service"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@
}
},
{
"id": "sample.newline.<<template>>\\nTest<T>",
"id": "sample.newline.TestTemplate",
"name": "TestTemplate",
"enclosing_namespace_id": "sample.newline",
"stereotypes": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
should_pass: true
qualified_name_does_not_search_descendants.puml:
error:
type: "UnresolvedReference"
fields:
reference: "A.B"
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@
'
' SPDX-License-Identifier: Apache-2.0
' *******************************************************************************
@startuml "Qualified Name Does Not Search Descendants"

@startuml class_diagram

namespace unit_1 {
class Controller {
+ Execute() : void
package "Root" as Root {
component "Group" as Group {
component "A" as A {
component "B" as B
}
}
}

namespace unit_2 {
class Controller {
+ Execute() : void
}
component "Target" as Target

A.B --> Target
}

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"stereotype": null,
"relations": [
{
"target": "score::mw::log",
"target": "score.mw.log",
"annotation": "verbose",
"relation_type": "Dependency",
"source_role": "None",
Expand All @@ -24,8 +24,8 @@
"line": 14
}
},
"score::mw::log": {
"id": "score::mw::log",
"score.mw.log": {
"id": "score.mw.log",
"name": "score::mw::log",
"alias": null,
"parent_id": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"file": "",
"line": 16
},
"stereotype": null
"stereotype": null,
"uid": "alice"
},
{
"display_name": "bob",
Expand All @@ -20,7 +21,8 @@
"file": "",
"line": 16
},
"stereotype": null
"stereotype": null,
"uid": "bob"
}
],
"root": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"file": "",
"line": 16
},
"stereotype": null
"stereotype": null,
"uid": "Client"
},
{
"display_name": "Service",
Expand All @@ -20,7 +21,8 @@
"file": "",
"line": 18
},
"stereotype": null
"stereotype": null,
"uid": "Service"
}
],
"root": {
Expand All @@ -39,4 +41,4 @@
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
' *******************************************************************************
' 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
' *******************************************************************************

@startuml invalid_duplicate_participant_id

participant "svc:billing::InvoiceService" as inv1
participant "billing::InvoiceService" as inv2

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
should_pass: true
invalid_duplicate_participant_id.puml:
error:
type: DuplicateParticipantId
fields:
participant_id: billing.InvoiceService
line: "17"
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
' SPDX-License-Identifier: Apache-2.0
' *******************************************************************************

@startuml sequence_diagram
@startuml invalid_free_text_participant_identifier

participant "<u><size:14>unit_1::Controller</size></u>" as controller
participant Caller
participant "Display Service" as Service

controller -> controller : Execute()
Caller -> "Display Service": invalidReference

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
should_pass: true
invalid_free_text_participant_identifier.puml:
error:
type: InvalidParticipantIdentifier
fields:
participant: Display Service
reason: free-text participant display names require an alias for uid derivation
line: "19"
Loading
Loading