Refactor manifest module into dedicated submodules#168
Conversation
|
Note Reviews pausedUse the following commands to manage reviews:
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Summary by CodeRabbit
WalkthroughSummarise the refactor: extract diagnostics, foreach expansion, glob handling and rendering from Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Caller
participant Manifest as Manifest API
participant YAML as serde_yaml
participant Diag as diagnostics::map_yaml_error
participant Expand as expand::expand_foreach
participant Render as render::render_manifest
participant Glob as glob::glob_paths
Caller->>Manifest: from_str_named(name, src)
Manifest->>YAML: parse(src)
YAML-->>Manifest: Ok(doc) or Err(err)
alt YAML error
Manifest->>Diag: map_yaml_error(err, src, name)
Diag-->>Manifest: Diagnostic (span, hints)
Manifest-->>Caller: Err(ManifestError::Parse)
else Parsed
Manifest->>Expand: expand_foreach(doc, env)
Expand-->>Manifest: Result<doc>
Manifest->>Render: render_manifest(manifest, env)
note over Render,Glob: Templates call helper to resolve file patterns
Render->>Glob: glob_paths(pattern)
Glob-->>Render: Vec<Path>
Render-->>Manifest: Result<manifest>
Manifest-->>Caller: Ok(manifest)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
🧪 Early access (Sonnet 4.5): enabledWe are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience. Note:
Comment |
Reviewer's GuideThe PR refactors the File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix: Comment on file ❌ New issue: Primitive Obsession |
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai pause |
✅ Actions performedReviews paused. |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix: Comment on lines +247 to +297 fn process_character(
&mut self,
ch: char,
pos: usize,
pattern: &GlobPattern,
) -> std::result::Result<(), Error> {
let context = CharContext {
ch,
position: pos,
in_class: self.state.in_class,
escaped: self.escaped,
};
if context.escaped {
self.escaped = false;
return Ok(());
}
if context.ch == char::from(0x5c) && self.state.escape_active {
self.escaped = true;
return Ok(());
}
if context.ch == '[' && !context.in_class {
self.state.in_class = true;
return Ok(());
}
if context.ch == ']' && context.in_class {
self.state.in_class = false;
return Ok(());
}
if context.ch == '}' && !context.in_class && self.state.depth == 0 {
return Err(create_unmatched_brace_error(&GlobErrorContext {
pattern: pattern.raw.clone(),
error_char: context.ch,
position: context.position,
error_type: GlobErrorType::UnmatchedBrace,
}));
}
if context.ch == '{' && !context.in_class {
self.state.depth += 1;
self.state.last_open_pos = Some(context.position);
} else if context.ch == '}' && !context.in_class {
self.state.depth -= 1;
}
Ok(())
}❌ New issue: Complex Method |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix: Comment on file return Ok(());
}
if context.ch == '}' && !context.in_class && self.state.depth == 0 {❌ New issue: Complex Conditional |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix: Comment on lines +103 to +182 fn render_manifest_renders_targets_and_rules() -> Result<()> {
let env = Environment::new();
let mut target_vars = Vars::new();
target_vars.insert("greet".into(), YamlValue::String("hello".into()));
target_vars.insert("subject".into(), YamlValue::String("world".into()));
target_vars.insert(
"message".into(),
YamlValue::String("{{ greet }} {{ subject }}".into()),
);
let target = Target {
name: StringOrList::String("{{ message }}!".into()),
recipe: Recipe::Command {
command: "{{ message }}".into(),
},
sources: StringOrList::List(vec!["{{ subject }}.txt".into()]),
deps: StringOrList::Empty,
order_only_deps: StringOrList::List(vec!["{{ subject }}.meta".into()]),
vars: target_vars,
phony: false,
always: false,
};
let rule = Rule {
name: "example".into(),
recipe: Recipe::Command {
command: "{{ 2 + 2 }}".into(),
},
description: Some("{{ 1 + 1 }}".into()),
deps: StringOrList::List(vec!["{{ message }}".into()]),
};
let mut manifest_vars = Vars::new();
manifest_vars.insert("message".into(), YamlValue::String("hello world".into()));
let manifest = NetsukeManifest {
netsuke_version: Version::parse("1.0.0")?,
vars: manifest_vars,
rules: vec![rule],
actions: Vec::new(),
targets: vec![target],
defaults: Vec::new(),
};
let rendered = render_manifest(manifest, &env)?;
let rendered_target = rendered.targets.first().expect("rendered target");
let vars = &rendered_target.vars;
let message = vars
.get("message")
.and_then(|v| v.as_str())
.expect("rendered message");
assert_eq!(message, "hello world");
match &rendered_target.name {
StringOrList::String(s) => assert_eq!(s, "hello world!"),
other => panic!("expected string name, got {other:?}"),
}
let rendered_sources = match &rendered_target.sources {
StringOrList::List(items) => items.clone(),
other => panic!("expected list sources, got {other:?}"),
};
assert_eq!(rendered_sources, vec!["world.txt".to_string()]);
match &rendered_target.recipe {
Recipe::Command { command } => assert_eq!(command, "hello world"),
other => panic!("expected command recipe, got {other:?}"),
}
match &rendered_target.order_only_deps {
StringOrList::List(items) => assert_eq!(items, &["world.meta".to_string()]),
other => panic!("expected order-only deps list, got {other:?}"),
}
let rendered_rule = rendered.rules.first().expect("rendered rule");
assert_eq!(rendered_rule.description.as_deref(), Some("2"));
match &rendered_rule.recipe {
Recipe::Command { command } => assert_eq!(command, "4"),
other => panic!("expected command recipe, got {other:?}"),
}
match &rendered_rule.deps {
StringOrList::List(items) => assert_eq!(items, &["hello world".to_string()]),
other => panic!("expected deps list, got {other:?}"),
}
Ok(())
}❌ New issue: Large Method |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Merge the escape, character-class, and brace transitions into a single handler that uses the existing context structs. This keeps the review request satisfied and avoids dead-code warnings from unused context fields.
Document the public manifest error, switch glob entry processing to camino and cap-std metadata, and split the brace validator helpers to lower complexity. Extract reusable helpers in the render manifest test and cover non-UTF glob entries so the suite exercises the capability code paths.
|
@sourcery-ai review |
|
@coderabbitai please create a new GitHub issue for the following:
|
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai GitHub |
|
@coderabbitai please create a new GitHub issue for the following: Review the use of ambient authority for directory access in |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai please create a new GitHub issue for the following: </code_context> <issue_to_address>
</issue_to_address> |
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai Has the following now been resolved? Ensure the top-level |
* expose expand_foreach, render_manifest, glob_paths, and map_yaml_error so the split manifest module retains its original public surface\n* promote helper functions to public and document their error surfaces so clippy continues to pass with the wider visibility
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 1268 @leynos Yes, this has been resolved! ✅ The main pub use diagnostics::{ManifestError, map_yaml_error};
pub use glob::glob_paths;
pub use expand::expand_foreach;
pub use render::render_manifest;Status check:
Each function is properly declared as The refactoring successfully maintains API compatibility whilst achieving better code organisation through the submodule structure. |
Summary
src/manifest.rsinto dedicated diagnostics, glob, expansion, and rendering submodules while preserving the public manifest API surfaceTesting
https://chatgpt.com/codex/tasks/task_e_68d96f5606a48322a56e65a1f89eb3de
Summary by Sourcery
Split the monolithic manifest implementation into dedicated submodules for diagnostics, glob pattern handling, template rendering, and foreach expansion, retaining the existing public API and updating tests accordingly.
Enhancements:
manifest::globsubmodule.manifest::rendersubmodule.foreachexpansion logic in a newmanifest::expandsubmodule.manifest::diagnosticssubmodule.Tests: