Clean up fabro-validate extraction

- Add From<ValidationError> for FabroError to eliminate duplicated
  .map_err(|e| FabroError::Validation(e.0)) at call sites
- Use top-level `use` imports for stylesheet types in rules.rs
  instead of verbose fully-qualified paths
- Remove duplicate parse_condition tests from fabro-workflows
  (already covered by fabro-graphviz)
- Use //! inner doc comments in context/keys.rs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-17 13:42:54 -04:00
parent addbf0563e
commit 3d981ea25d
6 changed files with 20 additions and 25 deletions

View file

@ -3,6 +3,7 @@ use std::str::FromStr;
use fabro_graphviz::condition::parse_condition;
use fabro_graphviz::graph::{is_llm_handler_type, AttrValue, Graph};
use fabro_graphviz::stylesheet::{parse_stylesheet, Selector};
use crate::{Diagnostic, LintRule, Severity};
@ -348,7 +349,7 @@ impl LintRule for StylesheetSyntaxRule {
if stylesheet.is_empty() {
return Vec::new();
}
match fabro_graphviz::stylesheet::parse_stylesheet(stylesheet) {
match parse_stylesheet(stylesheet) {
Ok(_) => Vec::new(),
Err(e) => vec![Diagnostic {
rule: self.name().to_string(),
@ -902,12 +903,12 @@ impl LintRule for ScriptAbsoluteCdRule {
struct StylesheetModelKnownRule;
impl StylesheetModelKnownRule {
fn selector_label(selector: &fabro_graphviz::stylesheet::Selector) -> String {
fn selector_label(selector: &Selector) -> String {
match selector {
fabro_graphviz::stylesheet::Selector::Universal => "*".to_string(),
fabro_graphviz::stylesheet::Selector::Shape(s) => s.clone(),
fabro_graphviz::stylesheet::Selector::Class(c) => format!(".{c}"),
fabro_graphviz::stylesheet::Selector::Id(id) => format!("#{id}"),
Selector::Universal => "*".to_string(),
Selector::Shape(s) => s.clone(),
Selector::Class(c) => format!(".{c}"),
Selector::Id(id) => format!("#{id}"),
}
}
}
@ -922,7 +923,7 @@ impl LintRule for StylesheetModelKnownRule {
if stylesheet_str.is_empty() {
return Vec::new();
}
let stylesheet = match fabro_graphviz::stylesheet::parse_stylesheet(stylesheet_str) {
let stylesheet = match parse_stylesheet(stylesheet_str) {
Ok(ss) => ss,
Err(_) => return Vec::new(), // syntax errors caught by stylesheet_syntax rule
};

View file

@ -261,18 +261,6 @@ mod tests {
));
}
#[test]
fn parse_condition_validates() {
assert!(parse_condition("outcome=success").is_ok());
assert!(parse_condition("outcome=success && context.x=y").is_ok());
assert!(parse_condition("").is_ok());
}
#[test]
fn parse_condition_accepts_bare_key() {
assert!(parse_condition("some_flag").is_ok());
}
#[test]
fn context_dotted_fallback() {
let outcome = make_outcome(StageStatus::Success);

View file

@ -1,7 +1,7 @@
// Static context key constants and helper functions for dynamic keys.
//
// All context keys used across the engine, handlers, and preamble are
// defined here to prevent typos and improve discoverability.
//! Static context key constants and helper functions for dynamic keys.
//!
//! All context keys used across the engine, handlers, and preamble are
//! defined here to prevent typos and improve discoverability.
// --- Top-level keys ---
pub const CURRENT_NODE: &str = "current_node";

View file

@ -426,6 +426,12 @@ impl From<fabro_graphviz::error::GraphvizError> for FabroError {
}
}
impl From<fabro_validate::ValidationError> for FabroError {
fn from(e: fabro_validate::ValidationError) -> Self {
Self::Validation(e.0)
}
}
pub type Result<T> = std::result::Result<T, FabroError>;
#[cfg(test)]

View file

@ -61,7 +61,7 @@ fn parse_child_graph(node: &Node) -> Result<Graph, FabroError> {
.and_then(|v| v.as_str())
{
let (graph, diagnostics) = prepare_from_file(std::path::Path::new(path))?;
fabro_validate::raise_on_errors(&diagnostics).map_err(|e| FabroError::Validation(e.0))?;
fabro_validate::raise_on_errors(&diagnostics)?;
return Ok(graph);
}
Err(FabroError::handler("No child workflow source".to_string()))

View file

@ -106,7 +106,7 @@ pub fn prepare_from_file(path: &Path) -> Result<(Graph, Vec<Diagnostic>), FabroE
pub fn prepare_from_source(dot_source: &str) -> Result<Graph, FabroError> {
let builder = WorkflowBuilder::new();
let (graph, diagnostics) = builder.prepare(dot_source)?;
fabro_validate::raise_on_errors(&diagnostics).map_err(|e| FabroError::Validation(e.0))?;
fabro_validate::raise_on_errors(&diagnostics)?;
Ok(graph)
}