diff --git a/.rustfmt.toml b/.rustfmt.toml index 5159008..5eeeb01 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,2 +1,3 @@ imports_granularity = "item" group_imports = "StdExternalCrate" +max_width=80 diff --git a/crates/dtacheck/src/linter.rs b/crates/dtacheck/src/linter.rs index e0859e2..89196f9 100644 --- a/crates/dtacheck/src/linter.rs +++ b/crates/dtacheck/src/linter.rs @@ -13,7 +13,11 @@ pub trait Lint { fn to_codespan(&self, id: usize) -> Diagnostic; } -pub fn lint_file(ast: &[Node], tokens: &[Token], funcs: &Function) -> Vec> { +pub fn lint_file( + ast: &[Node], + tokens: &[Token], + funcs: &Function, +) -> Vec> { let mut lints = Vec::new(); lint_node(&mut lints, ast, funcs); lint_preprocs(&mut lints, tokens); @@ -23,13 +27,14 @@ pub fn lint_file(ast: &[Node], tokens: &[Token], funcs: &Function) -> Vec>, ast: &[Node], funcs: &Function) { for node in ast { match &node.kind { - NodeKind::Array(array) | NodeKind::Prop(array) | NodeKind::Define(_, array) => { - lint_node(lints, array, funcs) - } + NodeKind::Array(array) + | NodeKind::Prop(array) + | NodeKind::Define(_, array) => lint_node(lints, array, funcs), NodeKind::Stmt(array) => { lint_node(lints, array, funcs); - let has_preprocessor_directive = array.iter().any(|tok| tok.is_preproc()); + let has_preprocessor_directive = + array.iter().any(|tok| tok.is_preproc()); if !has_preprocessor_directive { lint_fn_args(lints, array, node.span.clone(), funcs); @@ -51,15 +56,17 @@ impl Lint for FunctionArgLint { fn to_codespan(&self, id: usize) -> Diagnostic { match self { Self::TooManyArgs(name, range) => Diagnostic::error() - .with_message(format!("calling `{name}` with too many arguments")) - .with_labels(vec![ - Label::primary(id, range.clone()).with_message("too many arguments") - ]), + .with_message(format!( + "calling `{name}` with too many arguments" + )) + .with_labels(vec![Label::primary(id, range.clone()) + .with_message("too many arguments")]), Self::NotEnoughArgs(name, range) => Diagnostic::error() - .with_message(format!("calling `{name}` with too few arguments")) - .with_labels(vec![ - Label::primary(id, range.clone()).with_message("not enough arguments") - ]), + .with_message(format!( + "calling `{name}` with too few arguments" + )) + .with_labels(vec![Label::primary(id, range.clone()) + .with_message("not enough arguments")]), } } } @@ -183,7 +190,9 @@ pub fn lint_preprocs(lints: &mut Vec>, tokens: &[Token]) { TokenKind::Else => { if let Some(entry) = directive_stack.pop() { if entry.1 { - lints.push(Box::new(PreProcLint::Extra(token.span.clone()))) + lints.push(Box::new(PreProcLint::Extra( + token.span.clone(), + ))) } directive_stack.push((token.span.clone(), true)); } else { @@ -199,10 +208,7 @@ pub fn lint_preprocs(lints: &mut Vec>, tokens: &[Token]) { } } - lints.append( - &mut directive_stack - .into_iter() - .map(|x| Box::new(PreProcLint::Unmatched(x.0)) as Box) - .collect::>(), - ); + for lint in directive_stack { + lints.push(Box::new(PreProcLint::Unmatched(lint.0))) + } } diff --git a/crates/dtacheck/src/parser.rs b/crates/dtacheck/src/parser.rs index f8dcdd7..5e9263b 100644 --- a/crates/dtacheck/src/parser.rs +++ b/crates/dtacheck/src/parser.rs @@ -29,14 +29,15 @@ impl Lint for ParseLint { Self::UnmatchedBrace(opening, closing) => Diagnostic::error() .with_message("unmatched delimiter") .with_labels(vec![ - Label::primary(id, closing.clone()).with_message("unexpected token"), - Label::primary(id, opening.clone()).with_message("unmatched delimiter"), + Label::primary(id, closing.clone()) + .with_message("unexpected token"), + Label::primary(id, opening.clone()) + .with_message("unmatched delimiter"), ]), Self::GenericError(span) => Diagnostic::error() .with_message("unexpected token") - .with_labels(vec![ - Label::primary(id, span.clone()).with_message("unexpected token") - ]), + .with_labels(vec![Label::primary(id, span.clone()) + .with_message("unexpected token")]), } } } @@ -74,7 +75,10 @@ impl<'a> Parser<'a> { } } - fn eat_open_brace(&mut self, f: fn(&TokenKind) -> bool) -> ParseResult { + fn eat_open_brace( + &mut self, + f: fn(&TokenKind) -> bool, + ) -> ParseResult { let token = self.lookahead(0); if f(&token.kind) { @@ -150,11 +154,14 @@ impl<'a> Parser<'a> { let upper_span = self.previous().span; Ok(Node::new_stmt(array, lower_span.start..upper_span.end)) } else if self.eat_if(TokenKind::is_define) { - let span = self.previous().span; + let lower_span = self.previous().span; let sym = self.eat(TokenKind::is_sym)?; self.eat_open_brace(TokenKind::is_l_paren)?; let array = self.parse_list(TokenKind::is_r_paren)?; - Ok(Node::new_define(span, sym, array)) + let upper_span = self.previous().span; + let lower = lower_span.start; + let upper = upper_span.end; + Ok(Node::new_define(lower..upper, sym, array)) } else if self.eat_if(TokenKind::is_include) { let span = self.previous().span; let sym = self.eat(TokenKind::is_sym)?; @@ -178,7 +185,37 @@ impl<'a> Parser<'a> { } } - fn parse_list(&mut self, stop: fn(&TokenKind) -> bool) -> ParseResult> { + fn recover_mismatched_braces(&mut self) -> bool { + if !self.brace_stack.is_empty() { + let token = self.lookahead(0); + let unmatched = self.brace_stack.last().unwrap().span.clone(); + let current = token.span.clone(); + let diag = ParseLint::UnmatchedBrace(unmatched, current); + + if token.kind.is_r_bracket() + || token.kind.is_r_paren() + || token.kind.is_r_brace() + { + self.diagnostics.push(diag); + self.bump(1); + self.brace_stack.pop().unwrap(); + return true; + } + + if token.kind.is_eof() { + self.diagnostics.push(diag); + self.brace_stack.pop().unwrap(); + return true; + } + } + + return false; + } + + fn parse_list( + &mut self, + stop: fn(&TokenKind) -> bool, + ) -> ParseResult> { let mut nodes = Vec::new(); loop { if self.eat_if(stop) { @@ -190,29 +227,9 @@ impl<'a> Parser<'a> { match self.parse_node() { Ok(x) => nodes.push(x), Err(e) => { - if !self.brace_stack.is_empty() { - let token = self.lookahead(0); - let unmatched = self.brace_stack.last().unwrap().span.clone(); - let current = token.span.clone(); - let diag = ParseLint::UnmatchedBrace(unmatched, current); - - if token.kind.is_r_bracket() - || token.kind.is_r_paren() - || token.kind.is_r_brace() - { - self.diagnostics.push(diag); - self.bump(1); - self.brace_stack.pop().unwrap(); - break; - } - - if token.kind.is_eof() { - self.diagnostics.push(diag); - self.brace_stack.pop().unwrap(); - break; - } + if self.recover_mismatched_braces() { + break; } - return Err(e); } } @@ -266,17 +283,6 @@ pub struct Node { pub span: Range, } -#[allow(clippy::reversed_empty_ranges)] -fn combine_node_spans(list: &[Node]) -> Range { - list.iter() - .map(|x| &x.span) - .fold(usize::MAX..0, |current, next| { - let start = current.start.min(next.start); - let end = current.end.max(next.end); - start..end - }) -} - impl Node { fn new_array(list: Vec, span: Range) -> Node { Node { @@ -300,8 +306,6 @@ impl Node { } fn new_define(span: Range, sym: Token, array: Vec) -> Node { - let vec_span = combine_node_spans(&array); - let span = span.start..vec_span.end.min(sym.span.end); Node { kind: NodeKind::Define(sym.kind.unwrap_sym(), array), span,