Skip to content
Merged
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
3 changes: 3 additions & 0 deletions bazel/rules/rules_score/examples/seooc/design/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ load(

architectural_design(
name = "sample_seooc_design",
dynamic = [
"dynamic_design.puml",
],
public_api = [
"public_api.puml",
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
' *******************************************************************************
' Copyright (c) 2025 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

participant "Unit 1" as unit_1 <<unit>>
participant "Unit 2" as unit_2 <<unit>>

unit_1 -> unit_2 : callMethod1()
unit_2 -> unit_1 : callMethod2()

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@

namespace unit_1 {
class Foo {
{final}
--
+ GetNumber() : uint8_t
+ SetNumber(value : uint8_t) : void
}
}

namespace unit_2 {
class Bar {
{final}
--
- foo_ : unique_ptr<unit_1::Foo>
--
+ Bar(foo : unique_ptr<unit_1::Foo>)
+ AssertNumber() : bool
}
}
Expand Down
26 changes: 21 additions & 5 deletions bazel/rules/rules_score/private/dependable_element.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -629,13 +629,15 @@ def _collect_architecture_components(ctx):

return all_components

def _run_validation(ctx, arch_json, static_fbs_files):
def _run_validation(ctx, arch_json, static_fbs_files, dynamic_fbs_files, unit_static_fbs_files):
"""Run the architecture verifier tool against a pre-built JSON file.

Args:
ctx: Rule context
arch_json: The architecture JSON File object (already declared and written)
static_fbs_files: List of static FlatBuffer files to verify against
static_fbs_files: List of static component-diagram FlatBuffer files
dynamic_fbs_files: List of dynamic component-diagram FlatBuffer files
unit_static_fbs_files: List of static class-diagram FlatBuffer files

Returns:
validation_log File object
Expand All @@ -645,15 +647,21 @@ def _run_validation(ctx, arch_json, static_fbs_files):

validation_args = ctx.actions.args()
validation_args.add("--architecture-json", arch_json)
validation_args.add_all("--component-fbs", static_fbs_files)
if static_fbs_files:
validation_args.add_all("--component-fbs", static_fbs_files)
if dynamic_fbs_files:
validation_args.add_all("--sequence-fbs", dynamic_fbs_files)

# if unit_static_fbs_files:
# validation_args.add_all("--class-fbs", unit_static_fbs_files)
validation_args.add("--output", validation_log)
validation_args.add("--log-level", get_log_level(ctx))
if ctx.attr.maturity == "development":
validation_args.add("--warn-on-errors")

# ctx.actions.run will fail the build if validation_cli returns non-zero exit code
ctx.actions.run(
inputs = [arch_json] + static_fbs_files,
inputs = [arch_json] + static_fbs_files + dynamic_fbs_files + unit_static_fbs_files,
outputs = [validation_log],
executable = ctx.executable._validation_cli,
arguments = [validation_args],
Expand Down Expand Up @@ -815,12 +823,20 @@ def _dependable_element_index_impl(ctx):
# Collect static FlatBuffers from architectural_design targets (the expected
# static architecture) and verify them against the current architecture.
static_fbs_files = []
dynamic_fbs_files = []
for ad in ctx.attr.architectural_design:
if ArchitecturalDesignInfo in ad:
static_fbs_files.extend(ad[ArchitecturalDesignInfo].static.to_list())
dynamic_fbs_files.extend(ad[ArchitecturalDesignInfo].dynamic.to_list())

# Collect class-diagram FBS files produced by unit_design targets.
unit_static_fbs_files = []
for unit_target in all_units.values():
unit_info = unit_target[UnitInfo]
unit_static_fbs_files.extend(unit_info.unit_design_static_fbs.to_list())

# Run validation; build fails automatically on non-zero exit
validation_log = _run_validation(ctx, arch_json, static_fbs_files)
validation_log = _run_validation(ctx, arch_json, static_fbs_files, dynamic_fbs_files, unit_static_fbs_files)

# Both outputs are included so validation always runs in a default build.
# validation_log is also exposed in the debug output group for explicit access.
Expand Down
11 changes: 3 additions & 8 deletions plantuml/parser/puml_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use puml_parser::{
use puml_resolver::{
ClassResolver, DiagramResolver, ElementResolver, LogicElement, SequenceResolver, SequenceTree,
};
use puml_serializer::{ClassSerializer, ComponentSerializer};
use puml_serializer::{ClassSerializer, ComponentSerializer, SequenceSerializer};
use puml_utils::{write_fbs_to_file, write_json_to_file, LogLevel};

/// CLI wrapper for LogLevel that implements ValueEnum
Expand Down Expand Up @@ -214,13 +214,8 @@ fn serialize_resolved_diagram(resolved_content: &ResolvedDiagram, source_file: &
ResolvedDiagram::Class(resolved_content) => {
ClassSerializer::serialize(resolved_content, source_file)
}
ResolvedDiagram::Sequence(_) => {
log::warn!(
"Sequence diagram serialization is not yet implemented; \
no output will be written for '{}'",
source_file
);
vec![]
ResolvedDiagram::Sequence(resolved_content) => {
SequenceSerializer::serialize(resolved_content, source_file)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions plantuml/parser/puml_serializer/src/fbs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ rust_library(
],
visibility = [
"//plantuml/parser:__subpackages__",
"//validation/core:__subpackages__",
],
deps = [
"@crates//:flatbuffers",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,33 @@

use flatbuffers::FlatBufferBuilder;
use sequence_fbs::sequence_metamodel as fb;
use sequence_logic::{ConditionType, Event, SequenceNode};
use sequence_logic::{ConditionType, Event, SequenceNode, SequenceTree};

pub struct SequenceSerializer;

impl SequenceSerializer {
pub fn serialize(
nodes: &[SequenceNode],
name: Option<&str>,
source_files: &[String],
version: Option<&str>,
) -> Vec<u8> {
pub fn serialize(diagram: &SequenceTree, source_file: &str) -> Vec<u8> {
let mut builder = FlatBufferBuilder::new();

let name_offset = name.map(|n| builder.create_string(n));
let name_offset = diagram.name.as_deref().map(|n| builder.create_string(n));

let node_offsets: Vec<_> = nodes
let node_offsets: Vec<_> = diagram
.root_interactions
.iter()
.map(|node| Self::serialize_node(&mut builder, node))
.collect();
let nodes_offset = builder.create_vector(&node_offsets);

let source_offsets: Vec<_> = source_files
.iter()
.map(|s| builder.create_string(s))
.collect();
let source_offsets = [builder.create_string(source_file)];
let source_files_offset = builder.create_vector(&source_offsets);

let version_offset = version.map(|v| builder.create_string(v));

let root = fb::SequenceDiagram::create(
&mut builder,
&fb::SequenceDiagramArgs {
name: name_offset,
root_interactions: Some(nodes_offset),
source_files: Some(source_files_offset),
version: version_offset,
version: None,
},
);

Expand Down
5 changes: 5 additions & 0 deletions validation/core/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ rust_library(
"src/models/component_diagram_models.rs",
"src/models/error_models.rs",
"src/models/mod.rs",
"src/models/sequence_diagram_models.rs",
"src/models/shared.rs",
"src/readers/bazel_reader.rs",
"src/readers/class_diagram_reader.rs",
"src/readers/component_diagram_reader.rs",
"src/readers/mod.rs",
"src/readers/sequence_diagram_reader.rs",
"src/validators/bazel_component_validator.rs",
"src/validators/component_class_validator.rs",
"src/validators/component_sequence_validator.rs",
Expand All @@ -36,6 +38,9 @@ rust_library(
deps = [
"//plantuml/parser/puml_serializer/src/fbs:class_fbs",
"//plantuml/parser/puml_serializer/src/fbs:component_fbs",
"//plantuml/parser/puml_serializer/src/fbs:sequence_fbs",
"//tools/metamodel:class_diagram",
"//tools/metamodel:sequence_diagram",
"@crates//:flatbuffers",
"@crates//:serde",
"@crates//:serde_json",
Expand Down
10 changes: 8 additions & 2 deletions validation/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ The package contains two public targets:

## What It Validates

The current implementation supports two validation flows:
The current implementation supports three validation flows:

1. `BazelComponent`: compares the indexed Bazel build graph with the indexed
PlantUML component-diagram structure.
2. `ComponentClass`: compares component-diagram unit aliases with enclosing
namespace IDs observed in class diagrams.
3. `ComponentSequence`: compares component-diagram unit aliases with
caller/callee participants observed in sequence diagrams (exact match).

The CLI builds a `ValidationContext` from the provided inputs, infers which of
these flows are executable, and runs all compatible validators in one pass.
Expand Down Expand Up @@ -59,15 +61,18 @@ The CLI accepts the following input families:
- `--architecture-json`: Bazel architecture export consumed by `BazelReader`
- `--component-fbs`: one or more component-diagram FlatBuffers files consumed by
`ComponentDiagramReader`
- `--sequence-fbs`: one or more sequence-diagram FlatBuffers files consumed by
`SequenceDiagramReader`
- `--class-fbs`: one or more class-diagram FlatBuffers files consumed by
`ClassDiagramReader`

The current inference rules are:

- `--architecture-json` + `--component-fbs` enables `BazelComponent`
- `--component-fbs` + `--class-fbs` enables `ComponentClass`
- `--component-fbs` + `--sequence-fbs` enables `ComponentSequence`

If both combinations are present, both validators are executed.
If multiple combinations are present, all compatible validators are executed.

## Run

Expand All @@ -83,6 +88,7 @@ Run it directly:
bazel run //validation/core:validation_cli -- \
--architecture-json path/to/architecture.json \
--component-fbs path/to/component.fbs.bin \
--sequence-fbs path/to/sequence.fbs.bin \
--class-fbs path/to/class.fbs.bin \
--output path/to/validation.log
```
Expand Down
14 changes: 14 additions & 0 deletions validation/core/docs/assets/validation_core_flow.puml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ title Validation Core Runtime Flow
participant "CLI" as cli
participant "BazelReader" as bazel_reader
participant "ComponentDiagramReader" as component_reader
participant "SequenceDiagramReader" as sequence_reader
participant "ClassDiagramReader" as class_reader
participant "ValidationContext" as context
participant "validate_bazel_component()" as bazel_validator
participant "validate_component_sequence()" as sequence_validator
participant "validate_component_class()" as class_validator
participant "Errors" as errors

Expand All @@ -38,6 +40,12 @@ opt component fbs provided
cli -> cli: to_diagram_architecture(&mut base_errors)
end

opt sequence fbs provided
cli -> sequence_reader: read(paths)
sequence_reader --> cli: SequenceDiagramInputs
cli -> cli: to_sequence_diagram_index(&mut base_errors)
end

opt class fbs provided
cli -> class_reader: read(paths)
class_reader --> cli: ClassDiagramInputs
Expand All @@ -53,6 +61,12 @@ opt bazel + component available
cli -> errors: merge_errors(...)
end

opt component + sequence available
cli -> sequence_validator: validate_component_sequence(..., Errors::default())
sequence_validator --> cli: Errors
cli -> errors: merge_errors(...)
end

opt component + class available
cli -> class_validator: validate_component_class(..., Errors::default())
class_validator --> cli: Errors
Expand Down
13 changes: 13 additions & 0 deletions validation/core/docs/assets/validation_core_overview.puml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ package "validation/core" {
package "readers" {
class "BazelReader"
class "ComponentDiagramReader"
class "SequenceDiagramReader"
class "ClassDiagramReader"
}

package "models" {
class "BazelArchitecture"
class "ComponentDiagramArchitecture"
class "SequenceDiagramInputs"
class "SequenceDiagramIndex"
class "ClassDiagramInputs"
class "ClassDiagramIndex"
class "Errors"
Expand All @@ -50,27 +53,33 @@ package "validation/core" {
+base_errors: Errors
+bazel: Option<BazelArchitecture>
+component: Option<ComponentDiagramArchitecture>
+sequence: Option<SequenceDiagramIndex>
+class: Option<ClassDiagramIndex>
}
}

cli --> BazelReader : reads architecture json
cli --> ComponentDiagramReader : reads component fbs
cli --> SequenceDiagramReader : reads sequence fbs
cli --> ClassDiagramReader : reads class fbs

BazelReader --> BazelArchitecture
ComponentDiagramReader --> ComponentDiagramArchitecture
SequenceDiagramReader --> SequenceDiagramInputs
ClassDiagramReader --> ClassDiagramInputs
cli --> SequenceDiagramIndex : to_sequence_diagram_index(...)
cli --> ClassDiagramIndex : to_class_diagram_index(...)

cli --> context : builds
context --> Errors
context --> BazelArchitecture
context --> ComponentDiagramArchitecture
context --> SequenceDiagramIndex
context --> ClassDiagramIndex

cli --> "validate_bazel_component()" : when bazel + component exist
cli --> "validate_component_class()" : when component + class exist
cli --> "validate_component_sequence()" : when component + sequence exist

"validate_bazel_component()" --> BazelArchitecture
"validate_bazel_component()" --> ComponentDiagramArchitecture
Expand All @@ -80,6 +89,10 @@ cli --> "validate_component_class()" : when component + class exist
"validate_component_class()" --> ClassDiagramIndex
"validate_component_class()" --> Errors

"validate_component_sequence()" --> ComponentDiagramArchitecture
"validate_component_sequence()" --> SequenceDiagramIndex
"validate_component_sequence()" --> Errors

note bottom of cli
CLI owns orchestration:
- input loading
Expand Down
21 changes: 11 additions & 10 deletions validation/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@
//! This crate contains the shared models, readers, and validators used by the
//! CLI entrypoints for architecture and design verification.

pub mod models;
pub mod readers;
pub mod validators;
mod models;
mod readers;
mod validators;

pub use models::{
BazelArchitecture, BazelInput, BazelInputEntry, ClassDiagramEntityInput, ClassDiagramIndex,
ClassDiagramInput, ClassDiagramInputs, ClassDiagramRelationshipInput,
ComponentDiagramArchitecture, ComponentDiagramInput, ComponentDiagramInputs, EntityKey, Errors,
BazelArchitecture, BazelInput, ClassDiagramIndex, ClassDiagramInputs,
ComponentDiagramArchitecture, ComponentDiagramInputs, Errors, SequenceDiagramIndex,
SequenceDiagramInputs,
};

pub use readers::{BazelReader, ClassDiagramReader, ComponentDiagramReader, Reader};
pub use readers::{
BazelReader, ClassDiagramReader, ComponentDiagramReader, Reader, SequenceDiagramReader,
};

pub use validators::{
validate_bazel_component, validate_component_class, validate_component_sequence,
BazelComponentValidator, ComponentClassValidator, RequiredInput, SelectedValidator,
ValidatorSpec, ALL_VALIDATORS,
validate_bazel_component, validate_component_class, validate_component_sequence, RequiredInput,
SelectedValidator, ALL_VALIDATORS,
};
Loading
Loading