Skip to content

Commit

Permalink
Allow [private] attribute on assignments (#2300)
Browse files Browse the repository at this point in the history
  • Loading branch information
adsnaider authored Aug 10, 2024
1 parent a9ac91b commit f25e2d7
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 30 deletions.
8 changes: 3 additions & 5 deletions src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,9 @@ impl<'src> Analyzer<'src> {
return Err(assignment.name.token.error(DuplicateVariable { variable }));
}

if self
.assignments
.get(variable)
.map_or(true, |original| assignment.depth <= original.depth)
{
if self.assignments.get(variable).map_or(true, |original| {
assignment.file_depth <= original.file_depth
}) {
self.assignments.insert(assignment.clone());
}

Expand Down
8 changes: 3 additions & 5 deletions src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ use super::*;
/// A binding of `name` to `value`
#[derive(Debug, Clone, PartialEq, Serialize)]
pub(crate) struct Binding<'src, V = String> {
/// Module depth where binding appears
pub(crate) depth: u32,
/// Export binding as an environment variable to child processes
pub(crate) export: bool,
/// Binding name
#[serde(skip)]
pub(crate) file_depth: u32,
pub(crate) name: Name<'src>,
/// Binding value
pub(crate) private: bool,
pub(crate) value: V,
}

Expand Down
16 changes: 13 additions & 3 deletions src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ impl<'src, 'run> Evaluator<'src, 'run> {

for (name, value) in overrides {
if let Some(assignment) = module.assignments.get(name) {
scope.bind(assignment.export, assignment.name, value.clone());
scope.bind(
assignment.export,
assignment.name,
assignment.private,
value.clone(),
);
} else {
unknown_overrides.push(name.clone());
}
Expand Down Expand Up @@ -63,7 +68,12 @@ impl<'src, 'run> Evaluator<'src, 'run> {

if !self.scope.bound(name) {
let value = self.evaluate_expression(&assignment.value)?;
self.scope.bind(assignment.export, assignment.name, value);
self.scope.bind(
assignment.export,
assignment.name,
assignment.private,
value,
);
}

Ok(self.scope.value(name).unwrap())
Expand Down Expand Up @@ -321,7 +331,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
};
evaluator
.scope
.bind(parameter.export, parameter.name, value);
.bind(parameter.export, parameter.name, false, value);
}

Ok((evaluator.scope, positional))
Expand Down
14 changes: 8 additions & 6 deletions src/justfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,14 @@ impl<'src> Justfile<'src> {
let width = scope.names().fold(0, |max, name| name.len().max(max));

for binding in scope.bindings() {
println!(
"{0:1$} := \"{2}\"",
binding.name.lexeme(),
width,
binding.value
);
if !binding.private {
println!(
"{0:1$} := \"{2}\"",
binding.name.lexeme(),
width,
binding.value
);
}
}
}

Expand Down
37 changes: 32 additions & 5 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ impl<'run, 'src> Parser<'run, 'src> {
}
Some(Keyword::Export) if self.next_are(&[Identifier, Identifier, ColonEquals]) => {
self.presume_keyword(Keyword::Export)?;
items.push(Item::Assignment(self.parse_assignment(true)?));
items.push(Item::Assignment(
self.parse_assignment(true, take_attributes())?,
));
}
Some(Keyword::Unexport)
if self.next_are(&[Identifier, Identifier, Eof])
Expand Down Expand Up @@ -412,7 +414,9 @@ impl<'run, 'src> Parser<'run, 'src> {
}
_ => {
if self.next_are(&[Identifier, ColonEquals]) {
items.push(Item::Assignment(self.parse_assignment(false)?));
items.push(Item::Assignment(
self.parse_assignment(false, take_attributes())?,
));
} else {
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
items.push(Item::Recipe(self.parse_recipe(
Expand Down Expand Up @@ -473,16 +477,21 @@ impl<'run, 'src> Parser<'run, 'src> {
}

/// Parse an assignment, e.g. `foo := bar`
fn parse_assignment(&mut self, export: bool) -> CompileResult<'src, Assignment<'src>> {
fn parse_assignment(
&mut self,
export: bool,
attributes: BTreeSet<Attribute<'_>>,
) -> CompileResult<'src, Assignment<'src>> {
let name = self.parse_name()?;
self.presume_any(&[Equals, ColonEquals])?;
self.presume(ColonEquals)?;
let value = self.parse_expression()?;
self.expect_eol()?;
Ok(Assignment {
depth: self.file_depth,
file_depth: self.file_depth,
export,
name,
value,
private: name.lexeme().starts_with('_') || attributes.contains(&Attribute::Private),
})
}

Expand Down Expand Up @@ -1237,6 +1246,15 @@ mod tests {
tree: (justfile (assignment #export x "hello")),
}

test! {
name: private_export,
text: "
[private]
export x := 'hello'
",
tree: (justfile (assignment #export x "hello")),
}

test! {
name: export_equals,
text: r#"export x := "hello""#,
Expand All @@ -1251,6 +1269,15 @@ mod tests {
tree: (justfile (assignment x "hello")),
}

test! {
name: private_assignment,
text: "
[private]
x := 'hello'
",
tree: (justfile (assignment x "hello")),
}

test! {
name: assignment_equals,
text: r#"x := "hello""#,
Expand Down
6 changes: 4 additions & 2 deletions src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ impl<'src, 'run> Scope<'src, 'run> {
src: key,
},
},
false,
(*value).into(),
);
}

root
}

pub(crate) fn bind(&mut self, export: bool, name: Name<'src>, value: String) {
pub(crate) fn bind(&mut self, export: bool, name: Name<'src>, private: bool, value: String) {
self.bindings.insert(Binding {
depth: 0,
export,
file_depth: 0,
name,
private,
value,
});
}
Expand Down
7 changes: 6 additions & 1 deletion src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,12 @@ impl Subcommand {
}

fn variables(justfile: &Justfile) {
for (i, (_, assignment)) in justfile.assignments.iter().enumerate() {
for (i, (_, assignment)) in justfile
.assignments
.iter()
.filter(|(_, binding)| !binding.private)
.enumerate()
{
if i > 0 {
print!(" ");
}
Expand Down
26 changes: 26 additions & 0 deletions tests/evaluate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,29 @@ test! {
",
status: EXIT_FAILURE,
}

test! {
name: evaluate_private,
justfile: "
[private]
foo := 'one'
bar := 'two'
_baz := 'three'
",
args: ("--evaluate"),
stdout: "bar := \"two\"\n",
status: EXIT_SUCCESS,
}

test! {
name: evaluate_single_private,
justfile: "
[private]
foo := 'one'
bar := 'two'
_baz := 'three'
",
args: ("--evaluate", "foo"),
stdout: "one",
status: EXIT_SUCCESS,
}
60 changes: 57 additions & 3 deletions tests/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn assignment() {
"export": false,
"name": "foo",
"value": "bar",
"depth": 0,
"private": false,
}
},
"first": null,
Expand Down Expand Up @@ -114,6 +114,60 @@ fn assignment() {
);
}

#[test]
fn private_assignment() {
case(
"
_foo := 'foo'
[private]
bar := 'bar'
",
json!({
"aliases": {},
"assignments": {
"_foo": {
"export": false,
"name": "_foo",
"value": "foo",
"private": true,
},
"bar": {
"export": false,
"name": "bar",
"value": "bar",
"private": true,
},
},
"first": null,
"doc": null,
"groups": [],
"modules": {},
"recipes": {},
"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": [],
}),
);
}

#[test]
fn body() {
case(
Expand Down Expand Up @@ -271,7 +325,7 @@ fn dependency_argument() {
"export": false,
"name": "x",
"value": "foo",
"depth": 0,
"private": false,
},
},
"groups": [],
Expand Down Expand Up @@ -435,7 +489,7 @@ fn duplicate_variables() {
"export": false,
"name": "x",
"value": "bar",
"depth": 0,
"private": false,
}
},
"first": null,
Expand Down
16 changes: 16 additions & 0 deletions tests/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,19 @@ fn private_attribute_for_alias() {
)
.run();
}

#[test]
fn private_variables_are_not_listed() {
Test::new()
.justfile(
"
[private]
foo := 'one'
bar := 'two'
_baz := 'three'
",
)
.args(["--variables"])
.stdout("bar\n")
.run();
}

0 comments on commit f25e2d7

Please sign in to comment.