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
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"skinparam_and_legend.puml": {
"name": "skinparam_and_legend",
"statements": [
{
"Start": {
"source": {
"start_line": 19,
"start_column": 1
}
}
},
{
"Action": {
"label": "do something",
"source": {
"start_line": 20,
"start_column": 1
}
}
},
{
"Stop": {
"source": {
"start_line": 21,
"start_column": 1
}
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
' *******************************************************************************
' 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 skinparam_and_legend

skinparam activity {
BackgroundColor Red
}

start
:do something;
stop

legend
hi
endlegend

@enduml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
' *******************************************************************************
' 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 anonymous_frame

component ExternalCaller

frame {
node AdaptiveApplication {
component ApplicationLogic
}
}

ExternalCaller --> ApplicationLogic : call

@enduml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"anonymous_frame.puml": {
"ExternalCaller": {
"id": "ExternalCaller",
"name": "ExternalCaller",
"alias": null,
"parent_id": null,
"element_type": "Component",
"stereotype": null,
"relations": [
{
"target": "AdaptiveApplication.ApplicationLogic",
"annotation": "call",
"relation_type": "Dependency",
"source_role": "None",
"source_location": {
"file": "",
"line": 23
}
}
],
"source_location": {
"file": "",
"line": 15
}
},
"AdaptiveApplication": {
"id": "AdaptiveApplication",
"name": "AdaptiveApplication",
"alias": null,
"parent_id": null,
"element_type": "Node",
"stereotype": null,
"relations": [],
"source_location": {
"file": "",
"line": 18
}
},
"AdaptiveApplication.ApplicationLogic": {
"id": "AdaptiveApplication.ApplicationLogic",
"name": "ApplicationLogic",
"alias": null,
"parent_id": "AdaptiveApplication",
"element_type": "Component",
"stereotype": null,
"relations": [],
"source_location": {
"file": "",
"line": 19
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
' *******************************************************************************
' 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

hide empty members
show empty methods
hide empty attributes
show empty fields

component A
component B

@enduml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"hide_show_empty_members.puml": {
"name": null,
"statements": [
{
"Element": {
"identity": {
"name": "A",
"alias": null,
"stereotype": null,
"element_kind": "component",
"source_location": {
"file": "",
"line": 20
}
},
"style": null,
"statements": []
}
},
{
"Element": {
"identity": {
"name": "B",
"alias": null,
"stereotype": null,
"element_kind": "component",
"source_location": {
"file": "",
"line": 21
}
},
"style": null,
"statements": []
}
}
]
}
}
5 changes: 5 additions & 0 deletions plantuml/parser/integration_test/src/test_error_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ impl ErrorView for ComponentResolverError {
} => ProjectedError::new("AmbiguousReference")
.with_field("reference", reference.clone())
.with_field("candidates", candidates.join(", ")),

ComponentResolverError::MissingElementIdentity { source_location } => {
ProjectedError::new("MissingElementIdentity")
.with_field("source_location", format!("{:?}", source_location))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ fn test_start_stop() {
run_activity_diagram_parser_case("start_stop");
}

#[test]
fn test_skinparam_and_legend() {
run_activity_diagram_parser_case("skinparam_and_legend");
}

#[test]
fn test_if() {
run_activity_diagram_parser_case("if");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ impl PumlComponentParser {
match inner.as_rule() {
Rule::element => {
let element = Self::parse_element(inner, source_file, ignored_notes)?;
if element.identity.name.is_none() && element.identity.alias.is_none() {
// Anonymous container (e.g. bare `frame { ... }`) has no identity to
// resolve against; flatten it like `together` instead of keeping a
// nameless wrapper the resolver can't build an FQN for.
return Ok(element.statements);
}
return Ok(vec![Statement::Element(element)]);
}
Rule::relation => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,8 @@ fn test_relation_quoted_name() {
fn test_component_note_alias_hidden_relation() {
run_component_diagram_parser_case("component_note_alias_hidden_relation");
}

#[test]
fn test_hide_show_empty_members() {
run_component_diagram_parser_case("hide_show_empty_members");
}
2 changes: 1 addition & 1 deletion plantuml/parser/puml_parser/src/grammar/activity.pest
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ activity_diagram = {
SOI
~ empty_line*
~ startuml
~ (statement | empty_line)*
~ (ignored_block | ignored_stmt | statement | empty_line)*
~ activity_enduml
~ EOI
}
Expand Down
6 changes: 5 additions & 1 deletion plantuml/parser/puml_parser/src/grammar/component.pest
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

diagram_start = { empty_line* ~ startuml ~ (ignored_block | diagram_statement | empty_line)* ~ enduml }

diagram_statement = { ((ignored_stmt | relation | together_block | port_declaration | element | footer_line) ~ EOL) }
diagram_statement = { ((ignored_stmt | component_ignored_stmt | relation | together_block | port_declaration | element | footer_line) ~ EOL) }

component_ignored_stmt = _{
shared_hide_show_empty_member_core
}

port_declaration = { port_keyword ~ port_name ~ alias_clause? }
port_keyword = @{ "portin" | "portout" | "port" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::collections::{BTreeSet, HashMap};

use component_diagram::{
ComponentRelationType, ComponentType, EndpointRole, LogicComponent, LogicRelation,
SourceLocation,
};
use component_parser::{Arrow, CompPumlDocument, Element, Port, PortType, Relation, Statement};
use resolver_traits::DiagramResolver;
Expand All @@ -37,6 +38,9 @@ pub enum ComponentResolverError {
#[error("Unknown element type: {element_type}")]
UnknownElementType { element_type: String },

#[error("Element at {source_location:?} has neither a name nor an alias")]
MissingElementIdentity { source_location: SourceLocation },

#[error("Invalid relationship: {from} -> {to}: {reason}")]
InvalidRelationship {
from: String,
Expand Down Expand Up @@ -796,7 +800,9 @@ impl ComponentResolver {
.alias
.as_deref()
.or(element.identity.name.as_deref())
.expect("Element must have name or alias (guaranteed by grammar)");
.ok_or_else(|| ComponentResolverError::MissingElementIdentity {
source_location: element.identity.source_location.clone(),
})?;

let fqn = self.make_fqn(local_id);
if self.elements.contains_key(&fqn) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ fn test_relation_quoted_name() {
run_component_resolver_case("relation_quoted_name");
}

#[test]
fn test_anonymous_frame() {
run_component_resolver_case("anonymous_frame");
}

#[test]
fn test_invalid_unresolved_reference() {
run_component_resolver_case("invalid_unresolved_reference");
Expand Down
Loading