Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
31a3b8e
parser: bump edition to 2024
ada4a Sep 13, 2025
15c5aa1
unused/elidable lifetimes
ada4a Sep 14, 2025
208a962
redundant refs/derefs
ada4a Sep 14, 2025
7a752b8
clippy::uninlined_format_args
ada4a Sep 14, 2025
f1a3460
clippy::if_not_else
ada4a Sep 14, 2025
9d783f9
clippy::needless_return
ada4a Sep 14, 2025
e412dab
explicit iterator loops
ada4a Sep 14, 2025
d6dec99
clippy::useless_conversion
ada4a Sep 16, 2025
75b2de3
simplify thanks to the previous commit
ada4a Sep 16, 2025
edd0aa9
simplify `match`es
ada4a Sep 13, 2025
2d25c8c
use `std::iter::zip`
ada4a Sep 15, 2025
66ce392
clippy::inefficient_to_string
ada4a Sep 15, 2025
9c03903
clippy::ignored_unit_patterns
ada4a Sep 15, 2025
7654e22
derive `Default` for `IssueLinksCheckCommitsConfig`
ada4a Sep 15, 2025
d077123
use more idiomatic iterator/`Option` adaptors
ada4a Sep 15, 2025
bb4bbe0
clean-up consts
ada4a Sep 15, 2025
77dbd49
use `let-else`
ada4a Sep 15, 2025
e2625d7
clippy::cast_lossless
ada4a Sep 15, 2025
58313a5
documentation lints
ada4a Sep 15, 2025
69f68b0
reborrow instead of slicing
ada4a Sep 15, 2025
6ced8c8
add/remove semicolons
ada4a Sep 15, 2025
32a6ca0
clippy::write_with_newline
ada4a Sep 15, 2025
c4d2440
clippy::manual_string_new
ada4a Sep 15, 2025
8876c09
clippy::single_char_pattern
ada4a Sep 15, 2025
61e31a5
clippy::implicit_clone
ada4a Sep 15, 2025
3813996
get `command` without unwrapping
ada4a Sep 15, 2025
f4f9140
`write!` _inside_ `match`
ada4a Sep 15, 2025
03c89fb
clippy::unneded_struct_pattern
ada4a Sep 15, 2025
4b3d7ee
clippy::manual_strip
ada4a Sep 15, 2025
2d2f357
clippy::manual_assert
ada4a Sep 15, 2025
cb29213
needless `into_iter`
ada4a Sep 14, 2025
8b73667
clippy::legacy_numeric_constants
ada4a Sep 14, 2025
b1e183e
clippy::inconsistent_struct_constructor
ada4a Sep 14, 2025
46e82e2
clippy::redundant_closure_for_method_calls
ada4a Sep 14, 2025
20dcaec
clippy::manual_is_variant_and
ada4a Sep 14, 2025
c2305ee
clippy::needless_raw_string_hashes
ada4a Sep 14, 2025
6c9a953
clippy::question_mark
ada4a Sep 14, 2025
a2953f1
construct `HashMap` from array
ada4a Sep 14, 2025
8db437c
clippy::collapsible{,_else}_if
ada4a Sep 14, 2025
0cc6fb2
use `Result::ok_or` for trying out multiple things
ada4a Sep 14, 2025
d899dbe
use `as_deref` to avoid allocating a String
ada4a Sep 15, 2025
80c7d65
`RustcFormat::store_version`: take params by reference
ada4a Sep 14, 2025
7066f59
`config`: introduce `MaybeConfig` type alias
ada4a Sep 14, 2025
e07fdda
avoid eager/useless `format!`s
ada4a Sep 14, 2025
5a2c125
replace `std::iter::once(_)` with `[_]`
ada4a Sep 14, 2025
afbe76e
use `Itertools::format`
ada4a Sep 14, 2025
3a79e9c
replace `.ok_or_else(|| anyhow::anyhow!` with `.context(`
ada4a Sep 14, 2025
a2f4e71
don't destructure tuple for comparison
ada4a Sep 14, 2025
120f978
`expect` some lints
ada4a Sep 16, 2025
30ecf5d
clippy::field_reassign_with_default
ada4a Sep 16, 2025
bf61dd2
clippy::vec_init_then_push
ada4a Sep 16, 2025
2697421
avoid `clippy::partialeq_to_none`
ada4a Sep 16, 2025
9f16875
clippy::manual_find
ada4a Sep 16, 2025
f1482b4
clippy::ptr_arg
ada4a Sep 16, 2025
4d1b5bb
deref `Label` to `&str` directly
ada4a Sep 16, 2025
7d82ffd
clippy::redundant_pattern_matching
ada4a Sep 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions github-graphql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,17 +323,11 @@ pub mod project_items {

impl ProjectV2Item {
pub fn status(&self) -> Option<&str> {
let Some(ref status) = self.status else {
return None;
};
status.as_str()
self.status.as_ref()?.as_str()
}

pub fn date(&self) -> Option<Date> {
let Some(ref date) = self.date else {
return None;
};
date.as_date()
self.date.as_ref()?.as_date()
}
}

Expand Down
2 changes: 1 addition & 1 deletion parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "parser"
version = "0.1.0"
authors = ["Mark Rousskov <mark.simulacrum@gmail.com>"]
edition = "2021"
edition = "2024"

[dependencies]
pulldown-cmark = "0.12.0"
Expand Down
17 changes: 8 additions & 9 deletions parser/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl<'a> Input<'a> {
pub fn new(input: &'a str, bot: Vec<&'a str>) -> Input<'a> {
let bots: Vec<_> = bot.iter().map(|bot| format!(r"(?:@{bot}\b)")).collect();
let bot_re = Regex::new(&format!(
r#"(?i)(?P<review>\br\?)|{bots}"#,
r"(?i)(?P<review>\br\?)|{bots}",
bots = bots.join("|")
))
.unwrap();
Expand Down Expand Up @@ -140,13 +140,12 @@ impl<'a> Input<'a> {
&original_tokenizer,
));

if success.len() > 1 {
panic!(
"succeeded parsing {:?} to multiple commands: {:?}",
&self.all[self.parsed..],
success
);
}
assert!(
success.len() <= 1,
"succeeded parsing {:?} to multiple commands: {:?}",
&self.all[self.parsed..],
success
);

let (mut tok, c) = success.pop()?;
// if we errored out while parsing the command do not move the input forwards
Expand Down Expand Up @@ -201,7 +200,7 @@ impl<'a> Iterator for Input<'a> {
}
}

impl<'a> Command<'a> {
impl Command<'_> {
pub fn is_ok(&self) -> bool {
match self {
Command::Relabel(r) => r.is_ok(),
Expand Down
18 changes: 9 additions & 9 deletions parser/src/command/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ impl AssignCommand {
let mut toks = input.clone();
if let Some(Token::Word("claim")) = toks.peek_token()? {
toks.next_token()?;
if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(AssignCommand::Claim));
Ok(Some(AssignCommand::Claim))
} else {
return Err(toks.error(ParseError::ExpectedEnd));
Err(toks.error(ParseError::ExpectedEnd))
}
} else if let Some(Token::Word("assign")) = toks.peek_token()? {
toks.next_token()?;
Expand All @@ -63,22 +63,22 @@ impl AssignCommand {
username: user[1..].to_owned(),
}))
} else {
return Err(toks.error(ParseError::MentionUser));
Err(toks.error(ParseError::MentionUser))
}
} else {
return Err(toks.error(ParseError::NoUser));
Err(toks.error(ParseError::NoUser))
}
} else if let Some(Token::Word("release-assignment" | "unclaim")) = toks.peek_token()? {
toks.next_token()?;
if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(AssignCommand::ReleaseAssignment));
Ok(Some(AssignCommand::ReleaseAssignment))
} else {
return Err(toks.error(ParseError::ExpectedEnd));
Err(toks.error(ParseError::ExpectedEnd))
}
} else {
return Ok(None);
Ok(None)
}
}

Expand Down
10 changes: 5 additions & 5 deletions parser/src/command/concern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ impl ConcernCommand {
if let Some(Token::Word(mut action @ ("concern" | "resolve"))) = toks.peek_token()? {
toks.next_token()?;

if action == "concern" {
if let Some(Token::Word(sub_action @ "resolve")) = toks.peek_token()? {
toks.next_token()?;
action = sub_action;
}
if action == "concern"
&& let Some(Token::Word(sub_action @ "resolve")) = toks.peek_token()?
{
toks.next_token()?;
action = sub_action;
}

let title = toks.take_line()?.trim().to_string();
Expand Down
21 changes: 9 additions & 12 deletions parser/src/command/nominate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,23 @@ impl NominateCommand {
let style = match toks.peek_token()? {
Some(Token::Word("beta-nominate")) => Style::Beta,
Some(Token::Word("nominate")) => Style::Decision,
Some(Token::Word("beta-accept")) => Style::BetaApprove,
Some(Token::Word("beta-approve")) => Style::BetaApprove,
Some(Token::Word("beta-accept" | "beta-approve")) => Style::BetaApprove,
None | Some(_) => return Ok(None),
};
toks.next_token()?;
let team = if style != Style::BetaApprove {
if let Some(Token::Word(team)) = toks.next_token()? {
team.to_owned()
} else {
return Err(toks.error(ParseError::NoTeam));
}
} else {
let team = if style == Style::BetaApprove {
String::new()
} else if let Some(Token::Word(team)) = toks.next_token()? {
team.to_owned()
} else {
return Err(toks.error(ParseError::NoTeam));
};
if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(NominateCommand { team, style }));
Ok(Some(NominateCommand { team, style }))
} else {
return Err(toks.error(ParseError::ExpectedEnd));
Err(toks.error(ParseError::ExpectedEnd))
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions parser/src/command/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ impl PingCommand {
} else {
return Err(toks.error(ParseError::NoTeam));
};
if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
if let Some(Token::Dot | Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(PingCommand { team }));
Ok(Some(PingCommand { team }))
} else {
return Err(toks.error(ParseError::ExpectedEnd));
Err(toks.error(ParseError::ExpectedEnd))
}
} else {
return Ok(None);
Ok(None)
}
}
}
Expand Down
21 changes: 9 additions & 12 deletions parser/src/command/relabel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ impl Label {
}

impl std::ops::Deref for Label {
type Target = String;
fn deref(&self) -> &String {
&self.0
type Target = str;
fn deref(&self) -> &str {
self.0.as_str()
}
}

Expand All @@ -68,13 +68,13 @@ impl LabelDelta {
return Err(input.error(ParseError::ExpectedLabelDelta));
}
};
if delta.starts_with('+') {
if let Some(label) = delta.strip_prefix('+') {
Ok(LabelDelta::Add(
Label::parse(&delta[1..]).map_err(|e| input.error(e))?,
Label::parse(label).map_err(|e| input.error(e))?,
))
} else if delta.starts_with('-') {
} else if let Some(label) = delta.strip_prefix('-') {
Ok(LabelDelta::Remove(
Label::parse(&delta[1..]).map_err(|e| input.error(e))?,
Label::parse(label).map_err(|e| input.error(e))?,
))
} else {
Ok(LabelDelta::Add(
Expand All @@ -85,8 +85,7 @@ impl LabelDelta {

pub fn label(&self) -> &Label {
match self {
LabelDelta::Add(l) => l,
LabelDelta::Remove(l) => l,
LabelDelta::Add(l) | LabelDelta::Remove(l) => l,
}
}
}
Expand Down Expand Up @@ -129,9 +128,7 @@ impl RelabelCommand {
toks.eat_token(Token::Comma)?;
toks.eat_token(Token::Word("and"))?;

if let Some(Token::Semi) | Some(Token::Dot) | Some(Token::EndOfLine) =
toks.peek_token()?
{
if let Some(Token::Semi | Token::Dot | Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(RelabelCommand(deltas)));
Expand Down
20 changes: 10 additions & 10 deletions parser/src/command/shortcut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ impl fmt::Display for ParseError {

impl ShortcutCommand {
pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result<Option<Self>, Error<'a>> {
let mut shortcuts = HashMap::new();
shortcuts.insert("ready", ShortcutCommand::Ready);
shortcuts.insert("review", ShortcutCommand::Ready);
shortcuts.insert("reviewer", ShortcutCommand::Ready);
shortcuts.insert("author", ShortcutCommand::Author);
shortcuts.insert("blocked", ShortcutCommand::Blocked);
let shortcuts = HashMap::from([
("ready", ShortcutCommand::Ready),
("review", ShortcutCommand::Ready),
("reviewer", ShortcutCommand::Ready),
("author", ShortcutCommand::Author),
("blocked", ShortcutCommand::Blocked),
]);

let mut toks = input.clone();
if let Some(Token::Word(word)) = toks.peek_token()? {
if !shortcuts.contains_key(word) {
let Some(command) = shortcuts.get(word) else {
return Ok(None);
}
};
toks.next_token()?;
*input = toks;
let command = shortcuts.get(word).unwrap();
return Ok(Some(*command));
}
Ok(None)
Expand All @@ -57,7 +57,7 @@ impl ShortcutCommand {
#[cfg(test)]
fn parse(input: &str) -> Result<Option<ShortcutCommand>, Error<'_>> {
let mut toks = Tokenizer::new(input);
Ok(ShortcutCommand::parse(&mut toks)?)
ShortcutCommand::parse(&mut toks)
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions parser/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ pub struct Error<'a> {
pub source: Box<dyn error::Error + Send>,
}

impl<'a> PartialEq for Error<'a> {
impl PartialEq for Error<'_> {
fn eq(&self, other: &Self) -> bool {
self.input == other.input && self.position == other.position
}
}

impl<'a> error::Error for Error<'a> {
impl error::Error for Error<'_> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&*self.source)
}
}

impl<'a> Error<'a> {
impl Error<'_> {
pub fn position(&self) -> usize {
self.position
}
}

impl<'a> fmt::Display for Error<'a> {
impl fmt::Display for Error<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let space = 10;
let end = std::cmp::min(self.input.len(), self.position + space);
Expand Down
8 changes: 4 additions & 4 deletions parser/src/ignore_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl IgnoreBlocks {
macro_rules! ignore_till_end {
($p:pat) => {
let start = range.start;
while let Some((event, range)) = parser.next() {
for (event, range) in parser.by_ref() {
if let Event::End($p) = event {
ignore.push(start..range.end);
break;
Expand All @@ -28,15 +28,15 @@ impl IgnoreBlocks {
ignore_till_end!(TagEnd::CodeBlock);
}
Event::Start(Tag::Link { .. }) => {
ignore_till_end!(TagEnd::Link { .. });
ignore_till_end!(TagEnd::Link);
}
Event::Start(Tag::Image { .. }) => {
ignore_till_end!(TagEnd::Image { .. });
ignore_till_end!(TagEnd::Image);
}
Event::Start(Tag::BlockQuote(_)) => {
let start = range.start;
let mut count = 1;
while let Some((event, range)) = parser.next() {
for (event, range) in parser.by_ref() {
if let Event::Start(Tag::BlockQuote(_)) = event {
count += 1;
} else if let Event::End(TagEnd::BlockQuote(_)) = event {
Expand Down
16 changes: 7 additions & 9 deletions parser/src/mentions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ pub fn get_mentions(input: &str) -> Vec<&str> {

let mut mentions = Vec::new();
for (idx, _) in input.match_indices('@') {
if let Some(previous) = input[..idx].chars().next_back() {
// A github username must stand apart from other text.
//
// Oddly enough, english letters do not work, but letters outside
// ASCII do work as separators; for now just go with this limited
// list.
if let 'a'..='z' | 'A'..='Z' | '0'..='9' = previous {
continue;
}
// A github username must stand apart from other text.
//
// Oddly enough, english letters do not work, but letters outside
// ASCII do work as separators; for now just go with this limited
// list.
if let Some('a'..='z' | 'A'..='Z' | '0'..='9') = input[..idx].chars().next_back() {
continue;
}
let mut saw_slash = false;
let username_end = input
Expand Down
Loading