Skip to content

Commit ab5a1fd

Browse files
committed
inputs: handle deeply nested inputs
Handle follows inputs of the form: ` inputs = { nixpkgs = { follows = "nixpkgs"; }; }; `
1 parent 725b457 commit ab5a1fd

9 files changed

+202
-16
lines changed

src/walk/inputs.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -718,22 +718,53 @@ fn handle_url_attr(
718718
&& SyntaxKind::NODE_ATTR_SET == attr_set.kind()
719719
{
720720
for nested_attr in attr_set.children() {
721-
let is_follows = nested_attr
722-
.first_child()
723-
.unwrap()
724-
.first_child()
725-
.unwrap()
726-
.next_sibling()
727-
.unwrap();
728-
729-
if is_follows.to_string() == "follows" {
730-
let id = is_follows.prev_sibling().unwrap();
731-
let follows = nested_attr.first_child().unwrap().next_sibling().unwrap();
732-
let input =
733-
Input::with_url(id.to_string(), follows.to_string(), follows.text_range());
734-
insert_with_ctx(inputs, id.to_string(), input, ctx);
735-
if should_remove_nested_input(change, ctx, &follows.to_string()) {
736-
return Some(empty_node());
721+
let Some(attrpath) = nested_attr.first_child() else {
722+
continue;
723+
};
724+
let Some(first_ident) = attrpath.first_child() else {
725+
continue;
726+
};
727+
728+
if let Some(follows_ident) = first_ident.next_sibling() {
729+
// Flat attrpath style: `nixpkgs.follows = "nixpkgs"`
730+
if follows_ident.to_string() == "follows" {
731+
let id = &first_ident;
732+
let Some(follows) = attrpath.next_sibling() else {
733+
continue;
734+
};
735+
let input =
736+
Input::with_url(id.to_string(), follows.to_string(), follows.text_range());
737+
insert_with_ctx(inputs, id.to_string(), input, ctx);
738+
if should_remove_nested_input(change, ctx, &follows.to_string()) {
739+
return Some(empty_node());
740+
}
741+
}
742+
} else if let Some(value_node) = attrpath.next_sibling()
743+
&& SyntaxKind::NODE_ATTR_SET == value_node.kind()
744+
{
745+
// Deeply nested attrset style: `nixpkgs = { follows = "nixpkgs"; }`
746+
let id = &first_ident;
747+
for inner_attr in value_node.children() {
748+
let Some(inner_path) = inner_attr.first_child() else {
749+
continue;
750+
};
751+
let Some(inner_ident) = inner_path.first_child() else {
752+
continue;
753+
};
754+
if inner_ident.to_string() == "follows" {
755+
let Some(follows) = inner_path.next_sibling() else {
756+
continue;
757+
};
758+
let input = Input::with_url(
759+
id.to_string(),
760+
follows.to_string(),
761+
follows.text_range(),
762+
);
763+
insert_with_ctx(inputs, id.to_string(), input, ctx);
764+
if should_remove_nested_input(change, ctx, &follows.to_string()) {
765+
return Some(empty_node());
766+
}
767+
}
737768
}
738769
}
739770
}

tests/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ fn stderr_path_filters(settings: &mut insta::Settings) {
6161
#[case("one_level_nesting_flat")]
6262
#[case("flat_nested_flat")]
6363
#[case("first_nested_node")]
64+
#[case("deeply_nested_inputs")]
6465
#[case("follows_cycle")]
6566
fn test_list(#[case] fixture: &str) {
6667
let mut settings = insta::Settings::clone_current();
@@ -104,6 +105,7 @@ fn test_list_format(#[case] fixture: &str, #[case] format: &str) {
104105
#[case("first_nested_node", "vmsh", "github:mic92/vmsh")]
105106
#[case("comments_before_brace", "vmsh", "github:mic92/vmsh")]
106107
#[case("all_blanks", "vmsh", "github:mic92/vmsh")]
108+
#[case("deeply_nested_inputs", "vmsh", "github:mic92/vmsh")]
107109
fn test_add(#[case] fixture: &str, #[case] id: &str, #[case] uri: &str) {
108110
let mut settings = insta::Settings::clone_current();
109111
path_redactions(&mut settings);
@@ -221,6 +223,7 @@ fn test_add_infer_id(#[case] fixture: &str) {
221223
#[case("flat_nested_flat", "nixpkgs")]
222224
#[case("first_nested_node", "nixpkgs")]
223225
#[case("comments_before_brace", "nixpkgs")]
226+
#[case("deeply_nested_inputs", "nixpkgs")]
224227
#[case("root", "rust-overlay")]
225228
#[case("outputs_leading_comma_remove_first", "nixpkgs-unstable")]
226229
fn test_remove(#[case] fixture: &str, #[case] id: &str) {
@@ -261,6 +264,7 @@ fn test_remove(#[case] fixture: &str, #[case] id: &str) {
261264
)]
262265
#[case("flat_nested_flat", "nixpkgs", "github:nixos/nixpkgs/nixos-24.05")]
263266
#[case("first_nested_node", "nixpkgs", "github:nixos/nixpkgs/nixos-24.05")]
267+
#[case("deeply_nested_inputs", "nixpkgs", "github:nixos/nixpkgs/nixos-24.05")]
264268
fn test_change(#[case] fixture: &str, #[case] id: &str, #[case] uri: &str) {
265269
let mut settings = insta::Settings::clone_current();
266270
path_redactions(&mut settings);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
description = "Deeply nested inputs attrset";
3+
4+
inputs = {
5+
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
6+
7+
disko = {
8+
url = "github:nix-community/disko";
9+
inputs = {
10+
nixpkgs = {
11+
follows = "nixpkgs";
12+
};
13+
};
14+
};
15+
};
16+
17+
outputs = _: { };
18+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
source: tests/cli.rs
3+
info:
4+
program: flake-edit
5+
args:
6+
- "--flake"
7+
- "[FIXTURES]/deeply_nested_inputs.flake.nix"
8+
- "--diff"
9+
- add
10+
- vmsh
11+
- "github:mic92/vmsh"
12+
env:
13+
NO_COLOR: "1"
14+
---
15+
success: true
16+
exit_code: 0
17+
----- stdout -----
18+
--- original
19+
+++ modified
20+
@@ -12,6 +12,7 @@
21+
};
22+
};
23+
};
24+
+ vmsh.url = "github:mic92/vmsh";
25+
};
26+
27+
outputs = _: { };
28+
29+
----- stderr -----
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: tests/cli.rs
3+
info:
4+
program: flake-edit
5+
args:
6+
- "--flake"
7+
- "[FIXTURES]/deeply_nested_inputs.flake.nix"
8+
- "--diff"
9+
- change
10+
- nixpkgs
11+
- "github:nixos/nixpkgs/nixos-24.05"
12+
env:
13+
NO_COLOR: "1"
14+
---
15+
success: true
16+
exit_code: 0
17+
----- stdout -----
18+
--- original
19+
+++ modified
20+
@@ -2,7 +2,7 @@
21+
description = "Deeply nested inputs attrset";
22+
23+
inputs = {
24+
- nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
25+
+ nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
26+
27+
disko = {
28+
url = "github:nix-community/disko";
29+
30+
----- stderr -----
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
source: tests/cli.rs
3+
info:
4+
program: flake-edit
5+
args:
6+
- "--flake"
7+
- "[FIXTURES]/deeply_nested_inputs.flake.nix"
8+
- list
9+
env:
10+
NO_COLOR: "1"
11+
---
12+
success: true
13+
exit_code: 0
14+
----- stdout -----
15+
· disko - "github:nix-community/disko"
16+
nixpkgs => "nixpkgs"
17+
· nixpkgs - "github:nixos/nixpkgs/nixos-unstable"
18+
19+
----- stderr -----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
source: tests/cli.rs
3+
info:
4+
program: flake-edit
5+
args:
6+
- "--flake"
7+
- "[FIXTURES]/deeply_nested_inputs.flake.nix"
8+
- "--diff"
9+
- rm
10+
- nixpkgs
11+
env:
12+
NO_COLOR: "1"
13+
---
14+
success: true
15+
exit_code: 0
16+
----- stdout -----
17+
--- original
18+
+++ modified
19+
@@ -2,7 +2,6 @@
20+
description = "Deeply nested inputs attrset";
21+
22+
inputs = {
23+
- nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
24+
25+
disko = {
26+
url = "github:nix-community/disko";
27+
28+
----- stderr -----
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
source: tests/walker.rs
3+
expression: walker.inputs
4+
info:
5+
flake_nix: ""
6+
changes: []
7+
---
8+
disko:
9+
id: disko
10+
flake: true
11+
url: "\"github:nix-community/disko\""
12+
follows:
13+
- Indirect:
14+
- nixpkgs
15+
- "\"nixpkgs\""
16+
range:
17+
start: 148
18+
end: 176
19+
nixpkgs:
20+
id: nixpkgs
21+
flake: true
22+
url: "\"github:nixos/nixpkgs/nixos-unstable\""
23+
follows: []
24+
range:
25+
start: 82
26+
end: 119

tests/walker.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rstest::rstest;
1313
#[case("completely_flat_toplevel_alt")]
1414
#[case("one_level_nesting_flat")]
1515
#[case("flat_nested_flat")]
16+
#[case("deeply_nested_inputs")]
1617
fn test_walker_list_inputs(#[case] fixture: &str) {
1718
let content = load_flake(fixture);
1819
let mut walker = Walker::new(&content);

0 commit comments

Comments
 (0)