Skip to content

[plantuml tooling] prepare uid refactor - #489

Merged
castler merged 4 commits into
mainfrom
joho_prepare_integration_testing
Sep 30, 2026
Merged

castler merged 4 commits into
mainfrom
joho_prepare_integration_testing

Conversation

@hoe-jo

@hoe-jo hoe-jo commented Sep 30, 2026

Copy link
Copy Markdown
Contributor
  • create common helper functions for naming
  • implement cross diagram test suite
  • update docs

… checks in CI

- Add tools/metamodel/common/uid_utils crate: dependency-free identifier
  normalization primitives (normalize, normalized_segments, join,
  is_identifier_path, strip_anchor), with unit tests.
- Replace the duplicated normalize_fqn implementations in
  class_parser.rs (IgnoredObjectRegistry) and class_resolver.rs
  (ClassResolver) with calls to uid_utils::normalize. No behavior change.
- Give is_identifier_path its first real caller: class_resolver.rs's FQN
  check now uses it instead of an ad hoc `name.contains('.') ||
  name.contains("::")`. No behavior change.
- join() now filters out empty parts before allocating, instead of
  joining them in as empty segments.
- strip_anchor() is rewritten to compare normalized path segments
  instead of doing a raw string strip_prefix, fixing a bug where an
  interior empty segment (e.g. "score.logging..x" with anchor
  "score.logging") produced ".x" instead of "x".
- Add //tools/... to the tooling_checks CI job (clippy + test), which was
  previously not covered by CI.
- Fix a pre-existing clippy::redundant_field_names in
  sequence_serializer.rs, required for the new //tools/... clippy step
  to pass cleanly.
- Add puml_utils::label_markup: single source of truth for recognizing
  and stripping PlantUML inline style markup (<b>, <i>, <color:...>,
  </color>, etc.) and decoding \n escapes, with unit tests.
- creole_tag_length() in the activity-diagram normalizer now delegates
  to puml_utils::style_markup_tag_length instead of its own ~20-line
  duplicate, which only matched opening color:/back:/size: forms. The
  now-redundant wrapper function is removed; the call site calls
  puml_utils::style_markup_tag_length directly.
- is_style_markup_tag is private to the module (no longer re-exported);
  no caller outside label_markup needs it.
- normalize_rule_b_label is renamed to normalize_identity_label, since no
  caller of it exists yet in this PR and "Rule B" is premature
  terminology to expose at the module boundary.
- KNOWN_TAGS/STYLED_TAGS are declared as `&[&str]` instead of
  `[&str; N]`, so their length doesn't need to be kept in sync manually.

Behavior change (bug fix): closing style tags such as </color>,
</back>, </size> used to leak into normalized activity labels as
literal text; they are now correctly stripped. Added regression tests
covering this and case-insensitivity/whitespace handling around style
tags, and non-ASCII text in labels. No other diagram type is affected.
Add plantuml/parser/integration_test/cross_diagram: an end-to-end suite
that shells out to the puml_cli binary and asserts on its
--idmap-output-dir JSON output.

Seed cases pin down today's idmap behavior with goldens, so later
changes to identifier derivation show up as a readable golden-file diff
instead of silent regressions:

- component_nesting: nested package/component ids, including an
  unaliased nested component and a same-named sequence participant that
  today does not accidentally link to it
- class_alias_wins: today's class id is the label, not the alias
- namespace_and_package: namespace and package both contribute
  dotted scope
- sequence_forms: sequence participants are always references,
  id == alias verbatim, independent of the display label
- prose_without_alias: a prose participant label with no alias and
  an implicit participant created by referencing a display name in an
  arrow are both accepted today (no diagnostic yet)
- linking_three_diagrams: component/class/sequence linking by
  matching alias at the top level
- qualified_reference: a `::`-qualified relationship endpoint
  (e.g. `A --> a::B`) is rejected today instead of being resolved

Cases requiring not-yet-implemented behavior (root anchor, sequence
Rule B forms, qualified reference resolution, ExternalEndpoint) are
intentionally deferred to the PRs that implement them.

Harness hardening:
- Golden entries are keyed by an IdSet (one or more ids per alias)
  instead of a single id, so an alias that resolves to more than one id
  can be expressed in a golden instead of silently collapsing.
- resolve_ref() panics if a reference resolves to more than one id, or
  appears in both defines and references, instead of picking one
  silently.
- validate_case_config() checks that every diagram_types key and every
  links/distinct file#Alias reference names a real file, and that every
  links/distinct group has at least two entries.
- The suite is driven by test_framework::run_case (the same driver used
  by the other diagram parser/resolver suites): a PumlCliIdmapRunner
  (DiagramProcessor) shells out to puml_cli per file, and a
  CrossDiagramChecker (ExpectationChecker) adds the links/distinct
  cross-file id assertions via the new check_case hook on top of the
  framework's default per-file checks. Golden files follow the shared
  convention: output.json for success cases, output.yaml for cases where
  the file is expected to fail.
- A cross_diagram_cases! macro generates one #[test] per case plus a
  guard test that compares the registered case names against the case
  directories actually on disk, so an added directory can't be
  forgotten. discover_case_names() only counts a directory as a case if
  it directly contains a .puml file, so it doesn't get confused by
  sibling directories the test runner places alongside the case
  directories at runtime.
- element-identifiers.md: add an 'Implementation status' section (new
  section 0) that tracks, per topic, whether main implements the target
  design described in the rest of the guide, with a Test case column
  pointing at the corresponding cross_diagram case:
  - Id normalization is implemented for scope paths inside one class
    diagram, but `::` in class/component relationship endpoints (e.g.
    `A --> ns::B`) is rejected rather than normalized.
  - Label markup stripping is implemented for activity diagram labels
    only, not yet for sequence participant labels.
  - Sequence <-> component/class linking only works today when both
    sides use a plain, un-nested alias, not "at the Bazel-package root"
    as previously stated.
  - Root anchor, class alias-wins, sequence Rule B, qualified reference
    resolution, ExternalEndpoint, and the new diagnostics remain not
    implemented.
- Fold section 9 ("Current limitations") into section 0: its two bug
  entries (qualified name inside a nested declaration, non-identifier-
  based sequence hyperlinks) now live in the status table, and section 9
  is reduced to a pointer at section 0 instead of a second, divergent
  list. The unsubstantiated "Cross-diagrams in Class Diagrams also have
  a bug currently" bullet is dropped.
- Rename "The four forms" heading to "The label forms": the table under
  it has five rows, not four.
- sequence-diagram.md: mark the two claims that describe rejection
  behavior which does not exist yet (free-text participant without an
  alias, and referencing a declared participant by its display name) as
  not yet implemented, with a pointer to the new status section.

Docs only, no code change.
@castler
castler merged commit 100352d into main Sep 30, 2026
15 checks passed
@castler
castler deleted the joho_prepare_integration_testing branch September 30, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants