mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-10 03:30:59 +00:00
Classify graph attributes with a graph-only reference kind
reference_kind_for_attribute returned the full ReferenceKind, which includes the config-sourced Dockerfile kind the classifier can never yield, so the shared graph walker carried a silent `continue` and an `unreachable!` for impossible kinds; each new config-sourced kind widens those filler arms, and a classifier extension that reuses an existing kind would be dropped by the walker without validation, visitation, or a compiler error. Return a GraphReferenceKind subset instead (converting into ReferenceKind for validation), making the walker's matches total with every arm meaningful. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4e48d2887e
commit
8dfbfb9aa5
3 changed files with 43 additions and 20 deletions
|
|
@ -519,7 +519,7 @@ impl TemplateTransform {
|
|||
continue;
|
||||
}
|
||||
if let Some(kind) = reference_kind_for_attribute(scope, attr_name, text) {
|
||||
validate_static_reference(text, kind)
|
||||
validate_static_reference(text, kind.into())
|
||||
.map_err(|error| Error::Validation(error.to_string()))?;
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
//! reference-bearing attribute is added here once instead of drifting between
|
||||
//! per-crate walkers.
|
||||
|
||||
use fabro_types::graph::{AttributeScope, Graph, ReferenceKind, reference_kind_for_attribute};
|
||||
use fabro_types::graph::{
|
||||
AttributeScope, Graph, GraphReferenceKind, ReferenceKind, reference_kind_for_attribute,
|
||||
};
|
||||
|
||||
use crate::contains_template_syntax;
|
||||
|
||||
|
|
@ -119,20 +121,19 @@ pub fn visit_graph_references<'graph, E>(
|
|||
continue;
|
||||
};
|
||||
let reference = match kind {
|
||||
ReferenceKind::Import | ReferenceKind::ChildWorkflow => value,
|
||||
// Classification only yields FileInline for `@` values.
|
||||
ReferenceKind::FileInline => value
|
||||
GraphReferenceKind::Import | GraphReferenceKind::ChildWorkflow => value,
|
||||
// Classification only yields these kinds for `@` values.
|
||||
GraphReferenceKind::FileInline | GraphReferenceKind::GraphGoalFile => value
|
||||
.strip_prefix('@')
|
||||
.expect("file inline classification requires a leading '@'"),
|
||||
ReferenceKind::Dockerfile | ReferenceKind::GraphGoalFile => continue,
|
||||
.expect("file reference classification requires a leading '@'"),
|
||||
};
|
||||
validate_static_reference(reference, kind)
|
||||
validate_static_reference(reference, kind.into())
|
||||
.map_err(GraphReferenceError::StaticReference)?;
|
||||
let event = match kind {
|
||||
ReferenceKind::Import => GraphReference::Import { reference },
|
||||
ReferenceKind::ChildWorkflow => GraphReference::ChildWorkflow { reference },
|
||||
ReferenceKind::FileInline => GraphReference::FileInline { key, reference },
|
||||
ReferenceKind::Dockerfile | ReferenceKind::GraphGoalFile => unreachable!(),
|
||||
GraphReferenceKind::Import => GraphReference::Import { reference },
|
||||
GraphReferenceKind::ChildWorkflow => GraphReference::ChildWorkflow { reference },
|
||||
GraphReferenceKind::FileInline => GraphReference::FileInline { key, reference },
|
||||
GraphReferenceKind::GraphGoalFile => GraphReference::GoalFile { reference },
|
||||
};
|
||||
visit(event).map_err(GraphReferenceError::Visit)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,8 +598,7 @@ pub enum AttributeScope {
|
|||
Edge,
|
||||
}
|
||||
|
||||
/// Kinds of static (non-templated) file references a graph attribute can
|
||||
/// carry.
|
||||
/// Kinds of static (non-templated) workflow-owned file references.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, strum::Display)]
|
||||
pub enum ReferenceKind {
|
||||
#[strum(to_string = "file inline reference")]
|
||||
|
|
@ -614,25 +613,48 @@ pub enum ReferenceKind {
|
|||
GraphGoalFile,
|
||||
}
|
||||
|
||||
/// Kinds of static file references that graph attributes can carry: the
|
||||
/// subset of [`ReferenceKind`] that [`reference_kind_for_attribute`] can
|
||||
/// classify. Config-sourced kinds (Dockerfiles) are unrepresentable here by
|
||||
/// construction.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum GraphReferenceKind {
|
||||
FileInline,
|
||||
Import,
|
||||
ChildWorkflow,
|
||||
GraphGoalFile,
|
||||
}
|
||||
|
||||
impl From<GraphReferenceKind> for ReferenceKind {
|
||||
fn from(kind: GraphReferenceKind) -> Self {
|
||||
match kind {
|
||||
GraphReferenceKind::FileInline => Self::FileInline,
|
||||
GraphReferenceKind::Import => Self::Import,
|
||||
GraphReferenceKind::ChildWorkflow => Self::ChildWorkflow,
|
||||
GraphReferenceKind::GraphGoalFile => Self::GraphGoalFile,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Classify a graph attribute as a static file reference, if it is one.
|
||||
#[must_use]
|
||||
pub fn reference_kind_for_attribute(
|
||||
scope: AttributeScope,
|
||||
key: &str,
|
||||
value: &str,
|
||||
) -> Option<ReferenceKind> {
|
||||
) -> Option<GraphReferenceKind> {
|
||||
match key {
|
||||
"import" if matches!(scope, AttributeScope::Node) => Some(ReferenceKind::Import),
|
||||
"import" if matches!(scope, AttributeScope::Node) => Some(GraphReferenceKind::Import),
|
||||
"stack.child_workflow" if matches!(scope, AttributeScope::Node) => {
|
||||
Some(ReferenceKind::ChildWorkflow)
|
||||
Some(GraphReferenceKind::ChildWorkflow)
|
||||
}
|
||||
"goal" if matches!(scope, AttributeScope::Graph) && value.starts_with('@') => {
|
||||
Some(ReferenceKind::GraphGoalFile)
|
||||
Some(GraphReferenceKind::GraphGoalFile)
|
||||
}
|
||||
"prompt" | "output_schema"
|
||||
if matches!(scope, AttributeScope::Node) && value.starts_with('@') =>
|
||||
{
|
||||
Some(ReferenceKind::FileInline)
|
||||
Some(GraphReferenceKind::FileInline)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -1168,7 +1190,7 @@ mod tests {
|
|||
"output_schema",
|
||||
"@schemas/result.schema.json",
|
||||
),
|
||||
Some(ReferenceKind::FileInline),
|
||||
Some(GraphReferenceKind::FileInline),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue