1
1
mirror of https://github.com/casey/just.git synced 2024-11-25 07:06:23 +03:00

Add source information as path of the information

Motivation: To add support for module integration in justl which is an
Emacs extension for driving justfiles within Emacs.

This would allow me to easily discover the file locations of different
just modules and allow the ability to individually open justl buffers
for them within the editor.
This commit is contained in:
Sibi Prabakaran 2024-11-16 17:42:17 +05:30
parent 084a2d2de3
commit 516fac504c
No known key found for this signature in database
GPG Key ID: D19E3E0EBB557613
4 changed files with 1036 additions and 894 deletions

View File

@ -182,6 +182,7 @@ impl<'run, 'src> Analyzer<'run, 'src> {
unstable_features.insert(UnstableFeature::ScriptInterpreterSetting); unstable_features.insert(UnstableFeature::ScriptInterpreterSetting);
} }
let source = root.canonicalize().unwrap();
let root = paths.get(root).unwrap(); let root = paths.get(root).unwrap();
Ok(Justfile { Ok(Justfile {
@ -205,7 +206,7 @@ impl<'run, 'src> Analyzer<'run, 'src> {
name, name,
recipes, recipes,
settings, settings,
source: root.into(), source,
unexports: self.unexports, unexports: self.unexports,
unstable_features, unstable_features,
warnings: self.warnings, warnings: self.warnings,

View File

@ -23,7 +23,6 @@ pub(crate) struct Justfile<'src> {
pub(crate) name: Option<Name<'src>>, pub(crate) name: Option<Name<'src>>,
pub(crate) recipes: Table<'src, Rc<Recipe<'src>>>, pub(crate) recipes: Table<'src, Rc<Recipe<'src>>>,
pub(crate) settings: Settings<'src>, pub(crate) settings: Settings<'src>,
#[serde(skip)]
pub(crate) source: PathBuf, pub(crate) source: PathBuf,
pub(crate) unexports: HashSet<String>, pub(crate) unexports: HashSet<String>,
#[serde(skip)] #[serde(skip)]

View File

@ -1,22 +1,30 @@
use super::*; use super::*;
fn case(justfile: &str, value: Value) { fn case<F: Fn(&Path) -> Value>(justfile: &str, value: F) {
Test::new() Test::new()
.justfile(justfile) .justfile(justfile)
.args(["--dump", "--dump-format", "json"]) .args(["--dump", "--dump-format", "json"])
.stdout(format!("{}\n", serde_json::to_string(&value).unwrap())) .stdout_with_tempdir(|dir| format!("{}\n", serde_json::to_string(&value(dir.path())).unwrap()))
.run(); .run();
} }
#[test] #[test]
fn alias() { fn alias() {
case( let test = Test::new().justfile(
" "
alias f := foo alias f := foo
foo: foo:
", ",
json!({ );
let source = test
.tempdir
.path()
.join("justfile")
.to_str()
.unwrap()
.to_owned();
let json = json!({
"first": "foo", "first": "foo",
"doc": null, "doc": null,
"aliases": { "aliases": {
@ -66,14 +74,18 @@ fn alias() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); });
test
.args(["--dump", "--dump-format", "json"])
.stdout(format!("{}\n", serde_json::to_string(&json).unwrap()))
.run();
} }
#[test] #[test]
fn assignment() { fn assignment() {
case( case("foo := 'bar'", |dir| {
"foo := 'bar'", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": { "assignments": {
@ -110,8 +122,9 @@ fn assignment() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
@ -122,6 +135,8 @@ fn private_assignment() {
[private] [private]
bar := 'bar' bar := 'bar'
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": { "assignments": {
@ -164,7 +179,9 @@ fn private_assignment() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -176,6 +193,8 @@ fn body() {
bar bar
abc{{ 'xyz' }}def abc{{ 'xyz' }}def
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -222,7 +241,9 @@ fn body() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -233,6 +254,8 @@ fn dependencies() {
foo: foo:
bar: foo bar: foo
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -292,7 +315,9 @@ fn dependencies() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -316,6 +341,8 @@ fn dependency_argument() {
replace('a', 'b', 'c') replace('a', 'b', 'c')
) )
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"first": "foo", "first": "foo",
@ -400,7 +427,9 @@ fn dependency_argument() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -414,6 +443,8 @@ fn duplicate_recipes() {
foo: foo:
foo bar: foo bar:
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"first": "foo", "first": "foo",
"doc": null, "doc": null,
@ -470,7 +501,9 @@ fn duplicate_recipes() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -482,6 +515,8 @@ fn duplicate_variables() {
x := 'foo' x := 'foo'
x := 'bar' x := 'bar'
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": { "assignments": {
@ -518,14 +553,16 @@ fn duplicate_variables() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
#[test] #[test]
fn doc_comment() { fn doc_comment() {
case( case("# hello\nfoo:", |dir| {
"# hello\nfoo:", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"first": "foo", "first": "foo",
@ -569,14 +606,15 @@ fn doc_comment() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
fn empty_justfile() { fn empty_justfile() {
case( case("", |dir| {
"", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -606,8 +644,9 @@ fn empty_justfile() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
@ -621,6 +660,8 @@ fn parameters() {
e *x: e *x:
f $x: f $x:
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"first": "a", "first": "a",
@ -764,7 +805,9 @@ fn parameters() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -776,6 +819,8 @@ fn priors() {
b: a && c b: a && c
c: c:
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -855,14 +900,16 @@ fn priors() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
#[test] #[test]
fn private() { fn private() {
case( case("_foo:", |dir| {
"_foo:", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -906,14 +953,15 @@ fn private() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
fn quiet() { fn quiet() {
case( case("@foo:", |dir| {
"@foo:", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -957,8 +1005,9 @@ fn quiet() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
@ -977,6 +1026,8 @@ fn settings() {
foo: foo:
#!bar #!bar
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -1023,7 +1074,9 @@ fn settings() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -1034,6 +1087,8 @@ fn shebang() {
foo: foo:
#!bar #!bar
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -1077,14 +1132,16 @@ fn shebang() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
#[test] #[test]
fn simple() { fn simple() {
case( case("foo:", |dir| {
"foo:", let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -1128,8 +1185,9 @@ fn simple() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
); })
});
} }
#[test] #[test]
@ -1139,6 +1197,8 @@ fn attribute() {
[no-exit-message] [no-exit-message]
foo: foo:
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -1182,7 +1242,9 @@ fn attribute() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
); );
} }
@ -1199,7 +1261,10 @@ fn module() {
"foo.just": "bar:", "foo.just": "bar:",
}) })
.args(["--dump", "--dump-format", "json"]) .args(["--dump", "--dump-format", "json"])
.stdout(format!( .stdout_with_tempdir(|dir| {
let source = dir.path().join("justfile").to_str().unwrap().to_owned();
let foo_just = dir.path().join("foo.just").to_str().unwrap().to_owned();
format!(
"{}\n", "{}\n",
serde_json::to_string(&json!({ serde_json::to_string(&json!({
"aliases": {}, "aliases": {},
@ -1251,6 +1316,7 @@ fn module() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
"source": foo_just
}, },
}, },
"recipes": {}, "recipes": {},
@ -1275,9 +1341,11 @@ fn module() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
"source": source
})) }))
.unwrap() .unwrap()
)) )
})
.run(); .run();
} }
@ -1294,7 +1362,10 @@ fn module_group() {
"foo.just": "bar:", "foo.just": "bar:",
}) })
.args(["--dump", "--dump-format", "json"]) .args(["--dump", "--dump-format", "json"])
.stdout(format!( .stdout_with_tempdir(|dir| {
let source = dir.path().join("justfile").to_str().unwrap().to_owned();
let foo_just = dir.path().join("foo.just").to_str().unwrap().to_owned();
format!(
"{}\n", "{}\n",
serde_json::to_string(&json!({ serde_json::to_string(&json!({
"aliases": {}, "aliases": {},
@ -1346,6 +1417,7 @@ fn module_group() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
"source": foo_just,
}, },
}, },
"recipes": {}, "recipes": {},
@ -1370,9 +1442,11 @@ fn module_group() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
"source": source,
})) }))
.unwrap() .unwrap()
)) )
})
.run(); .run();
} }
@ -1383,6 +1457,8 @@ fn recipes_with_private_attribute_are_private() {
[private] [private]
foo: foo:
", ",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({ json!({
"aliases": {}, "aliases": {},
"assignments": {}, "assignments": {},
@ -1426,7 +1502,68 @@ fn recipes_with_private_attribute_are_private() {
}, },
"unexports": [], "unexports": [],
"warnings": [], "warnings": [],
}), "source": source,
})
},
);
}
#[test]
fn doc_attribute_overrides_comment() {
case(
"
# COMMENT
[doc('ATTRIBUTE')]
foo:
",
|dir| {
let source = dir.join("justfile").to_str().unwrap().to_owned();
json!({
"aliases": {},
"assignments": {},
"first": "foo",
"doc": null,
"groups": [],
"modules": {},
"recipes": {
"foo": {
"attributes": [{"doc": "ATTRIBUTE"}],
"body": [],
"dependencies": [],
"doc": "ATTRIBUTE",
"name": "foo",
"namepath": "foo",
"parameters": [],
"priors": 0,
"private": false,
"quiet": false,
"shebang": false,
}
},
"settings": {
"allow_duplicate_recipes": false,
"allow_duplicate_variables": false,
"dotenv_filename": null,
"dotenv_load": false,
"dotenv_path": null,
"dotenv_required": false,
"export": false,
"fallback": false,
"ignore_comments": false,
"positional_arguments": false,
"quiet": false,
"shell": null,
"tempdir" : null,
"unstable": false,
"windows_powershell": false,
"windows_shell": null,
"working_directory" : null,
},
"unexports": [],
"warnings": [],
"source": source
})
},
); );
} }

View File

@ -167,6 +167,11 @@ impl Test {
self self
} }
pub(crate) fn stdout_with_tempdir(mut self, stdout_fn: impl Fn(&TempDir) -> String) -> Self {
self.stdout = stdout_fn(&self.tempdir);
self
}
pub(crate) fn stdout_regex(mut self, stdout_regex: impl AsRef<str>) -> Self { pub(crate) fn stdout_regex(mut self, stdout_regex: impl AsRef<str>) -> Self {
self.stdout_regex = Some(Regex::new(&format!("^{}$", stdout_regex.as_ref())).unwrap()); self.stdout_regex = Some(Regex::new(&format!("^{}$", stdout_regex.as_ref())).unwrap());
self self