-
Notifications
You must be signed in to change notification settings - Fork 476
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suppress command exit code error messages #1354
Suppress command exit code error messages #1354
Conversation
I didn't take a close look, but this looks good. Thanks for writing tests! Let's figure out if this flag should also suppress command echoing. |
Nice, let me know when this is ready to review! |
80f07eb
to
504c354
Compare
@casey, I think it is ready to review. We can update the docs when we agree on the implementation. I have a couple of concerns here. If we need to add multiple annotations, we are likely to support a syntax like |
Nice! I'm just heading out of town for the weekend, so I won't be able to look at this until next week when I get back. Apologies for the delay.
Good thinking. One note: The JSON dump format is unstable, i.e., requires the I actually think that recipes probably shouldn't have a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, thanks for all the tests!
A few high level thoughts:
-
I wasn't sure whether we should call these "attributes" or "annotations", so I did a google search for
programming "function attribute"
andprogramming "function annotation"
, and the search with "attribute" got 8x more hits, so I think we should go with that and call them "attributes" instead of annotations. -
Since the json now just includes a single
suppress_exit_error_messages
boolean, which will be backwards compatible with future additions, I think we should avoid parsing the comma-separate attribute list syntax, i.e.,[a,b,c]
, for now. We can easily add it in the future if we need it. -
Since an attribute is required to be directly in front of a recipe, instead of popping an attribute off the list of items, in the main parser loop, we can parse an attribute if we see a
[
, and then immediatly parse a recipe:} else if self.accepted(BracketL)? { items.push(Item::AnnotationContainer(self.parse_annotations()?)); self.expect_eol()?; self.parse_recipe()? }
This avoids the need to check for spurious newlines or make the
pop_doc_comment
function more complicated. -
I think the signature of
Parser::parse_atribute
should befn parse_attribute(&mut self) -> Result<Attribute>
, and attribute can be:enum Attribute { NoExitMessage }
This is nice because the parser returns a single, strongly-typed attribute, so downstream code doesn't need to worry about checking for invalid attributes.
Thanks for the review. I agree with all the thoughts. I will be back with the changes in a couple of days. |
96f4ba0
to
a54b8d7
Compare
815dc97
to
fd9ba23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice this is great! A few comments, but it's all small stuff.
@@ -98,6 +98,9 @@ pub(crate) enum CompileErrorKind<'src> { | |||
alias: &'src str, | |||
target: &'src str, | |||
}, | |||
UnknownAttribute { | |||
attribute: &'src str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attribute: &'src str, | |
attribute: Name<'src>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other CompileErrorKind
s like UnknownFunction
, UnknownSetting
all have &'src str
. I thought there was nothing special about the attribute. Considering your parse_attribute_name
suggestion, do you find anything wrong or ugly with the code below @casey?
...
UnknownAttribute {
attribute: &'src str,
},
/// Parse a recipe attribute name
fn parse_attribute_name(&mut self) -> CompileResult<'src, Attribute> {
let name = self.parse_name()?;
Attribute::from_name(name).ok_or_else(|| {
name.error(CompileErrorKind::UnknownAttribute {
attribute: name.lexeme(),
})
})
}
I think we should have &'src str
here. CompileError
returned by error()
method already has a token field. We should not have another Token
or Name
type field within the CompileErrorKind
.
pub(crate) struct CompileError<'src> {
pub(crate) token: Token<'src>,
pub(crate) kind: Box<CompileErrorKind<'src>>,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point, makes sense to me!
src/justfile.rs
Outdated
@@ -472,6 +472,7 @@ mod tests { | |||
recipe, | |||
line_number, | |||
code, | |||
.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more verbose, but I think I'd extract and check these with an assert below:
.. | |
suppress_error_message, |
src/parser.rs
Outdated
/// Parse a recipe attribute | ||
fn parse_attribute(&mut self) -> CompileResult<'src, Attribute> { | ||
let token = self.expect(Identifier)?; | ||
let lexeme = token.lexeme(); | ||
if let Some(attribute) = Attribute::from_lexeme(lexeme) { | ||
self.expect(BracketR)?; | ||
Ok(attribute) | ||
} else { | ||
Err(token.error(CompileErrorKind::UnknownAttribute { attribute: lexeme })) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not quite right, since you also need the token to produce the error message, but something like this:
/// Parse a recipe attribute | |
fn parse_attribute(&mut self) -> CompileResult<'src, Attribute> { | |
let token = self.expect(Identifier)?; | |
let lexeme = token.lexeme(); | |
if let Some(attribute) = Attribute::from_lexeme(lexeme) { | |
self.expect(BracketR)?; | |
Ok(attribute) | |
} else { | |
Err(token.error(CompileErrorKind::UnknownAttribute { attribute: lexeme })) | |
} | |
} | |
/// Parse a recipe attribute name | |
fn parse_attribute_name(&mut self) -> CompileResult<'src, Attribute> { | |
let name = self.parse_name()?; | |
Attribute::from_lexeme(name).ok_or_else(|| token.error(CompileErrorKind::UnknownAttribute { attribute: lexeme })) | |
} |
fd9ba23
to
cbb4a81
Compare
I am not sure about Is this OK? recipe : attribute? '@'? NAME parameter* variadic? ':' dependency* body?
attribute : '[' NAME ']' eol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor comment, otherwise looks great. Your suggestion for representing attributes in the grammar looks good to me.
src/parser.rs
Outdated
items.push(Item::Recipe(self.parse_recipe(doc, true)?)); | ||
items.push(Item::Recipe(self.parse_recipe(doc, true, false)?)); | ||
} else if self.accepted(BracketL)? { | ||
self.parse_attribute_name()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works, but it's a bit unclear what's going on. I'd do something like:
let Attribute::NoExitMessage = self.parse_atribute_name()?;
This makes it clear what's going on, and it will turn into a compile error when we add another variant.
When a recipe wraps cli tool and the tool exits with a non-zero code, just adds its own extra exit error message along with the messages from the tool. Introduce `no-exit-message` attribute to suppress this additional message.
19a4f1f
to
ef0278a
Compare
Very nice! Great work, especially for a non-trivial PR that touches the parser! |
When a recipe wraps cli tool and the tool exits with a non-zero code,
just adds its own extra exit error message along with the messages
from the tool. Introduce
no-exit-message
attribute to suppress thisadditional message.
Closes #1334