Skip to content

Commit 88c0674

Browse files
committed
clippy_dev: Rename RustSearcher to Cursor and move it to its own module.
1 parent 4f403f3 commit 88c0674

File tree

5 files changed

+277
-234
lines changed

5 files changed

+277
-234
lines changed

clippy_dev/src/new_lint.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::parse::{RustSearcher, Token};
1+
use crate::parse::cursor::{self, Cursor};
22
use crate::utils::Version;
33
use clap::ValueEnum;
44
use indoc::{formatdoc, writedoc};
@@ -517,21 +517,21 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
517517
// Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
518518
fn parse_mod_file(path: &Path, contents: &str) -> (&'static str, usize) {
519519
#[allow(clippy::enum_glob_use)]
520-
use Token::*;
520+
use cursor::Pat::*;
521521

522522
let mut context = None;
523523
let mut decl_end = None;
524-
let mut searcher = RustSearcher::new(contents);
525-
while let Some(name) = searcher.find_capture_token(CaptureIdent) {
524+
let mut cursor = Cursor::new(contents);
525+
while let Some(name) = cursor.find_capture_pat(CaptureIdent) {
526526
match name {
527527
"declare_clippy_lint" => {
528-
if searcher.match_tokens(&[Bang, OpenBrace], &mut []) && searcher.find_token(CloseBrace) {
529-
decl_end = Some(searcher.pos());
528+
if cursor.match_all(&[Bang, OpenBrace], &mut []) && cursor.find_pat(CloseBrace) {
529+
decl_end = Some(cursor.pos());
530530
}
531531
},
532532
"impl" => {
533533
let mut capture = "";
534-
if searcher.match_tokens(&[Lt, Lifetime, Gt, CaptureIdent], &mut [&mut capture]) {
534+
if cursor.match_all(&[Lt, Lifetime, Gt, CaptureIdent], &mut [&mut capture]) {
535535
match capture {
536536
"LateLintPass" => context = Some("LateContext"),
537537
"EarlyLintPass" => context = Some("EarlyContext"),

clippy_dev/src/parse.rs

Lines changed: 20 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -1,187 +1,12 @@
1+
pub mod cursor;
2+
3+
use self::cursor::Cursor;
14
use crate::utils::{ErrAction, File, expect_action};
25
use core::ops::Range;
3-
use core::slice;
4-
use rustc_lexer::{self as lexer, FrontmatterAllowed};
56
use std::fs;
67
use std::path::{Path, PathBuf};
78
use walkdir::{DirEntry, WalkDir};
89

9-
#[derive(Clone, Copy)]
10-
pub enum Token<'a> {
11-
/// Matches any number of comments / doc comments.
12-
AnyComment,
13-
Ident(&'a str),
14-
CaptureIdent,
15-
LitStr,
16-
CaptureLitStr,
17-
Bang,
18-
CloseBrace,
19-
CloseBracket,
20-
CloseParen,
21-
/// This will consume the first colon even if the second doesn't exist.
22-
DoubleColon,
23-
Comma,
24-
Eq,
25-
Lifetime,
26-
Lt,
27-
Gt,
28-
OpenBrace,
29-
OpenBracket,
30-
OpenParen,
31-
Pound,
32-
Semi,
33-
}
34-
35-
pub struct RustSearcher<'txt> {
36-
text: &'txt str,
37-
cursor: lexer::Cursor<'txt>,
38-
pos: u32,
39-
next_token: lexer::Token,
40-
}
41-
impl<'txt> RustSearcher<'txt> {
42-
#[must_use]
43-
#[expect(clippy::inconsistent_struct_constructor)]
44-
pub fn new(text: &'txt str) -> Self {
45-
let mut cursor = lexer::Cursor::new(text, FrontmatterAllowed::Yes);
46-
Self {
47-
text,
48-
pos: 0,
49-
next_token: cursor.advance_token(),
50-
cursor,
51-
}
52-
}
53-
54-
#[must_use]
55-
pub fn peek_text(&self) -> &'txt str {
56-
&self.text[self.pos as usize..(self.pos + self.next_token.len) as usize]
57-
}
58-
59-
#[must_use]
60-
pub fn peek_len(&self) -> u32 {
61-
self.next_token.len
62-
}
63-
64-
#[must_use]
65-
pub fn peek(&self) -> lexer::TokenKind {
66-
self.next_token.kind
67-
}
68-
69-
#[must_use]
70-
pub fn pos(&self) -> u32 {
71-
self.pos
72-
}
73-
74-
#[must_use]
75-
pub fn at_end(&self) -> bool {
76-
self.next_token.kind == lexer::TokenKind::Eof
77-
}
78-
79-
pub fn step(&mut self) {
80-
// `next_token.len` is zero for the eof marker.
81-
self.pos += self.next_token.len;
82-
self.next_token = self.cursor.advance_token();
83-
}
84-
85-
/// Consumes the next token if it matches the requested value and captures the value if
86-
/// requested. Returns true if a token was matched.
87-
fn read_token(&mut self, token: Token<'_>, captures: &mut slice::IterMut<'_, &mut &'txt str>) -> bool {
88-
loop {
89-
match (token, self.next_token.kind) {
90-
(_, lexer::TokenKind::Whitespace)
91-
| (
92-
Token::AnyComment,
93-
lexer::TokenKind::BlockComment { terminated: true, .. } | lexer::TokenKind::LineComment { .. },
94-
) => self.step(),
95-
(Token::AnyComment, _) => return true,
96-
(Token::Bang, lexer::TokenKind::Bang)
97-
| (Token::CloseBrace, lexer::TokenKind::CloseBrace)
98-
| (Token::CloseBracket, lexer::TokenKind::CloseBracket)
99-
| (Token::CloseParen, lexer::TokenKind::CloseParen)
100-
| (Token::Comma, lexer::TokenKind::Comma)
101-
| (Token::Eq, lexer::TokenKind::Eq)
102-
| (Token::Lifetime, lexer::TokenKind::Lifetime { .. })
103-
| (Token::Lt, lexer::TokenKind::Lt)
104-
| (Token::Gt, lexer::TokenKind::Gt)
105-
| (Token::OpenBrace, lexer::TokenKind::OpenBrace)
106-
| (Token::OpenBracket, lexer::TokenKind::OpenBracket)
107-
| (Token::OpenParen, lexer::TokenKind::OpenParen)
108-
| (Token::Pound, lexer::TokenKind::Pound)
109-
| (Token::Semi, lexer::TokenKind::Semi)
110-
| (
111-
Token::LitStr,
112-
lexer::TokenKind::Literal {
113-
kind: lexer::LiteralKind::Str { terminated: true } | lexer::LiteralKind::RawStr { .. },
114-
..
115-
},
116-
) => {
117-
self.step();
118-
return true;
119-
},
120-
(Token::Ident(x), lexer::TokenKind::Ident) if x == self.peek_text() => {
121-
self.step();
122-
return true;
123-
},
124-
(Token::DoubleColon, lexer::TokenKind::Colon) => {
125-
self.step();
126-
if !self.at_end() && matches!(self.next_token.kind, lexer::TokenKind::Colon) {
127-
self.step();
128-
return true;
129-
}
130-
return false;
131-
},
132-
#[rustfmt::skip]
133-
(
134-
Token::CaptureLitStr,
135-
lexer::TokenKind::Literal {
136-
kind:
137-
lexer::LiteralKind::Str { terminated: true }
138-
| lexer::LiteralKind::RawStr { n_hashes: Some(_) },
139-
..
140-
},
141-
)
142-
| (Token::CaptureIdent, lexer::TokenKind::Ident) => {
143-
**captures.next().unwrap() = self.peek_text();
144-
self.step();
145-
return true;
146-
},
147-
_ => return false,
148-
}
149-
}
150-
}
151-
152-
#[must_use]
153-
pub fn find_token(&mut self, token: Token<'_>) -> bool {
154-
let mut capture = [].iter_mut();
155-
while !self.read_token(token, &mut capture) {
156-
self.step();
157-
if self.at_end() {
158-
return false;
159-
}
160-
}
161-
true
162-
}
163-
164-
#[must_use]
165-
pub fn find_capture_token(&mut self, token: Token<'_>) -> Option<&'txt str> {
166-
let mut res = "";
167-
let mut capture = &mut res;
168-
let mut capture = slice::from_mut(&mut capture).iter_mut();
169-
while !self.read_token(token, &mut capture) {
170-
self.step();
171-
if self.at_end() {
172-
return None;
173-
}
174-
}
175-
Some(res)
176-
}
177-
178-
#[must_use]
179-
pub fn match_tokens(&mut self, tokens: &[Token<'_>], captures: &mut [&mut &'txt str]) -> bool {
180-
let mut captures = captures.iter_mut();
181-
tokens.iter().all(|&t| self.read_token(t, &mut captures))
182-
}
183-
}
184-
18510
pub struct Lint {
18611
pub name: String,
18712
pub group: String,
@@ -265,9 +90,9 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirE
26590
/// Parse a source file looking for `declare_clippy_lint` macro invocations.
26691
fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mut Vec<Lint>) {
26792
#[allow(clippy::enum_glob_use)]
268-
use Token::*;
93+
use cursor::Pat::*;
26994
#[rustfmt::skip]
270-
static DECL_TOKENS: &[Token<'_>] = &[
95+
static DECL_TOKENS: &[cursor::Pat<'_>] = &[
27196
// !{ /// docs
27297
Bang, OpenBrace, AnyComment,
27398
// #[clippy::version = "version"]
@@ -276,17 +101,17 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
276101
Ident("pub"), CaptureIdent, Comma, AnyComment, CaptureIdent, Comma,
277102
];
278103

279-
let mut searcher = RustSearcher::new(contents);
280-
while searcher.find_token(Ident("declare_clippy_lint")) {
281-
let start = searcher.pos() as usize - "declare_clippy_lint".len();
104+
let mut cursor = Cursor::new(contents);
105+
while cursor.find_pat(Ident("declare_clippy_lint")) {
106+
let start = cursor.pos() as usize - "declare_clippy_lint".len();
282107
let (mut name, mut group) = ("", "");
283-
if searcher.match_tokens(DECL_TOKENS, &mut [&mut name, &mut group]) && searcher.find_token(CloseBrace) {
108+
if cursor.match_all(DECL_TOKENS, &mut [&mut name, &mut group]) && cursor.find_pat(CloseBrace) {
284109
lints.push(Lint {
285110
name: name.to_lowercase(),
286111
group: group.into(),
287112
module: module.into(),
288113
path: path.into(),
289-
declaration_range: start..searcher.pos() as usize,
114+
declaration_range: start..cursor.pos() as usize,
290115
});
291116
}
292117
}
@@ -295,21 +120,21 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
295120
#[must_use]
296121
pub fn read_deprecated_lints() -> (Vec<DeprecatedLint>, Vec<RenamedLint>) {
297122
#[allow(clippy::enum_glob_use)]
298-
use Token::*;
123+
use cursor::Pat::*;
299124
#[rustfmt::skip]
300-
static DECL_TOKENS: &[Token<'_>] = &[
125+
static DECL_TOKENS: &[cursor::Pat<'_>] = &[
301126
// #[clippy::version = "version"]
302127
Pound, OpenBracket, Ident("clippy"), DoubleColon, Ident("version"), Eq, CaptureLitStr, CloseBracket,
303128
// ("first", "second"),
304129
OpenParen, CaptureLitStr, Comma, CaptureLitStr, CloseParen, Comma,
305130
];
306131
#[rustfmt::skip]
307-
static DEPRECATED_TOKENS: &[Token<'_>] = &[
132+
static DEPRECATED_TOKENS: &[cursor::Pat<'_>] = &[
308133
// !{ DEPRECATED(DEPRECATED_VERSION) = [
309134
Bang, OpenBrace, Ident("DEPRECATED"), OpenParen, Ident("DEPRECATED_VERSION"), CloseParen, Eq, OpenBracket,
310135
];
311136
#[rustfmt::skip]
312-
static RENAMED_TOKENS: &[Token<'_>] = &[
137+
static RENAMED_TOKENS: &[cursor::Pat<'_>] = &[
313138
// !{ RENAMED(RENAMED_VERSION) = [
314139
Bang, OpenBrace, Ident("RENAMED"), OpenParen, Ident("RENAMED_VERSION"), CloseParen, Eq, OpenBracket,
315140
];
@@ -320,19 +145,19 @@ pub fn read_deprecated_lints() -> (Vec<DeprecatedLint>, Vec<RenamedLint>) {
320145
let mut contents = String::new();
321146
File::open_read_to_cleared_string(path, &mut contents);
322147

323-
let mut searcher = RustSearcher::new(&contents);
148+
let mut cursor = Cursor::new(&contents);
324149

325150
// First instance is the macro definition.
326151
assert!(
327-
searcher.find_token(Ident("declare_with_version")),
152+
cursor.find_pat(Ident("declare_with_version")),
328153
"error reading deprecated lints"
329154
);
330155

331-
if searcher.find_token(Ident("declare_with_version")) && searcher.match_tokens(DEPRECATED_TOKENS, &mut []) {
156+
if cursor.find_pat(Ident("declare_with_version")) && cursor.match_all(DEPRECATED_TOKENS, &mut []) {
332157
let mut version = "";
333158
let mut name = "";
334159
let mut reason = "";
335-
while searcher.match_tokens(DECL_TOKENS, &mut [&mut version, &mut name, &mut reason]) {
160+
while cursor.match_all(DECL_TOKENS, &mut [&mut version, &mut name, &mut reason]) {
336161
deprecated.push(DeprecatedLint {
337162
name: parse_str_single_line(path.as_ref(), name),
338163
reason: parse_str_single_line(path.as_ref(), reason),
@@ -343,11 +168,11 @@ pub fn read_deprecated_lints() -> (Vec<DeprecatedLint>, Vec<RenamedLint>) {
343168
panic!("error reading deprecated lints");
344169
}
345170

346-
if searcher.find_token(Ident("declare_with_version")) && searcher.match_tokens(RENAMED_TOKENS, &mut []) {
171+
if cursor.find_pat(Ident("declare_with_version")) && cursor.match_all(RENAMED_TOKENS, &mut []) {
347172
let mut version = "";
348173
let mut old_name = "";
349174
let mut new_name = "";
350-
while searcher.match_tokens(DECL_TOKENS, &mut [&mut version, &mut old_name, &mut new_name]) {
175+
while cursor.match_all(DECL_TOKENS, &mut [&mut version, &mut old_name, &mut new_name]) {
351176
renamed.push(RenamedLint {
352177
old_name: parse_str_single_line(path.as_ref(), old_name),
353178
new_name: parse_str_single_line(path.as_ref(), new_name),

0 commit comments

Comments
 (0)