refactor: bump rust to 1.88, use the new niceties (#161)
Some checks are pending
CI / Lint (push) Waiting to run
CI / Format (push) Waiting to run
CI / Test (push) Waiting to run
CI / Corpus test (push) Waiting to run
CI / Generate schema (push) Waiting to run

This commit is contained in:
Riley Bruins 2025-07-03 02:25:00 +02:00 committed by GitHub
parent ac8c28c06f
commit 1d59e4bbd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 198 additions and 208 deletions

View file

@ -15,7 +15,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.86.0
- uses: dtolnay/rust-toolchain@1.88.0
id: toolchain
with:
components: clippy
@ -35,7 +35,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.86.0
- uses: dtolnay/rust-toolchain@1.88.0
id: toolchain
with:
components: rustfmt
@ -47,7 +47,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.86.0
- uses: dtolnay/rust-toolchain@1.88.0
id: toolchain
- uses: actions/cache@v3
with:
@ -68,7 +68,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: tree-sitter/setup-action/cli@v1
- uses: dtolnay/rust-toolchain@1.86.0
- uses: dtolnay/rust-toolchain@1.88.0
id: toolchain
- uses: actions/cache@v3
with:
@ -121,7 +121,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.86.0
- uses: dtolnay/rust-toolchain@1.88.0
id: toolchain
- uses: actions/cache@v3
with:

View file

@ -50,38 +50,36 @@ pub async fn check_directories(
.map(|lang| Arc::new(init_language_data(lang, name)))
})
});
if let Some(lang) = language_data {
if let Ok(source) = fs::read_to_string(&path) {
return Some(tokio::spawn(async move {
if let Some(new_source) = lint_file(
&path,
&uri,
&source,
options_arc.clone(),
fix,
Some(lang),
&exit_code,
)
.await
{
if fs::write(&path, new_source).is_err() {
eprintln!("Failed to write {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
}
};
}));
} else {
eprintln!("Failed to read {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
}
} else {
let Some(lang) = language_data else {
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
eprintln!(
"Could not retrieve language for {:?}",
path.canonicalize().unwrap()
)
);
return None;
};
None
let Ok(source) = fs::read_to_string(&path) else {
eprintln!("Failed to read {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
return None;
};
Some(tokio::spawn(async move {
if let Some(new_source) = lint_file(
&path,
&uri,
&source,
options_arc.clone(),
fix,
Some(lang),
&exit_code,
)
.await
&& fs::write(&path, new_source).is_err()
{
eprintln!("Failed to write {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
};
}))
});
join_all(tasks).await;
if format && format_directories(directories, true).await != 0 {

View file

@ -21,31 +21,32 @@ pub async fn format_directories(directories: &[PathBuf], check: bool) -> i32 {
let tasks = scm_files.into_iter().map(|path| {
let exit_code = exit_code.clone();
tokio::spawn(async move {
if let Ok(contents) = fs::read_to_string(&path) {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&QUERY_LANGUAGE)
.expect("Error loading Query grammar");
let tree = parser.parse(contents.as_str(), None).unwrap();
let rope = Rope::from(contents.as_str());
if let Some(formatted) = formatting::format_document(&rope, &tree.root_node()) {
if check {
let edits = formatting::diff(&contents, &formatted, &rope);
if !edits.is_empty() {
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
eprintln!(
"Improper formatting detected for {:?}",
path.canonicalize().unwrap()
);
}
} else if fs::write(&path, formatted).is_err() {
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
eprint!("Failed to write to {:?}", path.canonicalize().unwrap())
}
}
} else {
let Ok(contents) = fs::read_to_string(&path) else {
eprintln!("Failed to read {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
return;
};
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&QUERY_LANGUAGE)
.expect("Error loading Query grammar");
let tree = parser.parse(contents.as_str(), None).unwrap();
let rope = Rope::from(contents.as_str());
let Some(formatted) = formatting::format_document(&rope, &tree.root_node()) else {
return;
};
if check {
let edits = formatting::diff(&contents, &formatted, &rope);
if !edits.is_empty() {
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
eprintln!(
"Improper formatting detected for {:?}",
path.canonicalize().unwrap()
);
}
} else if fs::write(&path, formatted).is_err() {
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
eprint!("Failed to write to {:?}", path.canonicalize().unwrap())
}
})
});

View file

@ -128,11 +128,10 @@ pub async fn lint_directories(directories: &[PathBuf], config: String, fix: bool
Some(tokio::spawn(async move {
if let Some(new_source) =
lint_file(&path, &uri, &source, options, fix, None, &exit_code).await
&& fs::write(&path, new_source).is_err()
{
if fs::write(&path, new_source).is_err() {
eprintln!("Failed to write {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
}
eprintln!("Failed to write {:?}", path.canonicalize().unwrap());
exit_code.store(1, std::sync::atomic::Ordering::Relaxed);
};
}))
} else {

View file

@ -43,57 +43,53 @@ pub async fn profile_directories(directories: &[PathBuf], config: String, per_fi
.map(|lang| Arc::new(init_language_data(lang, name)))
})
});
if let Some(lang_data) = language_data {
let lang = lang_data.language.clone().unwrap();
if let Ok(source) = fs::read_to_string(&path) {
Some(tokio::spawn(async move {
let mut results = Vec::new();
if per_file {
let now = Instant::now();
let _ = Query::new(&lang, &source);
results.push((path_str.clone(), 1, now.elapsed().as_micros()));
} else {
let mut parser = Parser::new();
parser.set_language(&QUERY_LANGUAGE).unwrap();
let tree = parser.parse(&source, None).expect("Tree should exist");
let mut cursor = QueryCursor::new();
let source_bytes = source.as_bytes();
let mut matches = cursor.matches(
&PATTERN_DEFINITION_QUERY,
tree.root_node(),
source_bytes,
);
while let Some(match_) = matches.next() {
for capture in match_.captures {
let now = Instant::now();
let _ = Query::new(
&lang,
capture
.node
.utf8_text(source_bytes)
.expect("Source should be UTF-8"),
);
results.push((
path_str.clone(),
capture.node.start_position().row + 1,
now.elapsed().as_micros(),
));
}
}
}
results
}))
} else {
eprintln!("Failed to read {:?}", path.canonicalize().unwrap());
None
}
} else {
let Some(lang_data) = language_data else {
eprintln!(
"Could not retrieve language for {:?}",
path.canonicalize().unwrap()
);
None
}
return None;
};
let lang = lang_data.language.clone().unwrap();
let Ok(source) = fs::read_to_string(&path) else {
eprintln!("Failed to read {:?}", path.canonicalize().unwrap());
return None;
};
Some(tokio::spawn(async move {
if per_file {
let now = Instant::now();
let _ = Query::new(&lang, &source);
return vec![(path_str.clone(), 1, now.elapsed().as_micros())];
}
let mut results = Vec::new();
let mut parser = Parser::new();
parser.set_language(&QUERY_LANGUAGE).unwrap();
let tree = parser.parse(&source, None).expect("Tree should exist");
let mut cursor = QueryCursor::new();
let source_bytes = source.as_bytes();
let mut matches =
cursor.matches(&PATTERN_DEFINITION_QUERY, tree.root_node(), source_bytes);
while let Some(match_) = matches.next() {
for capture in match_.captures {
let now = Instant::now();
let _ = Query::new(
&lang,
capture
.node
.utf8_text(source_bytes)
.expect("Source should be UTF-8"),
);
results.push((
path_str.clone(),
capture.node.start_position().row + 1,
now.elapsed().as_micros(),
));
}
}
results
}))
});
let results = join_all(tasks).await;
let mut results = results

View file

@ -159,64 +159,65 @@ pub async fn completion(
let in_capture = cursor_after_at_sign || node_is_or_has_ancestor(root, current_node, "capture");
let in_predicate = node_is_or_has_ancestor(root, current_node, "predicate");
let in_missing = node_is_or_has_ancestor(root, current_node, "missing_node");
if !in_capture && !in_predicate {
if let Some(language_data) = language_data {
let symbols = &language_data.symbols_vec;
let supertypes = &language_data.supertype_map;
let fields = &language_data.fields_vec;
let in_anon = node_is_or_has_ancestor(root, current_node, "string") && !in_predicate;
let top_level = current_node.kind() == "program";
let in_negated_field = current_node.kind() == "negated_field"
|| cursor_after_exclamation_point
|| (current_node.kind() == "identifier"
&& current_node
.parent()
.is_some_and(|p| p.kind() == "negated_field"));
if !in_capture
&& !in_predicate
&& let Some(language_data) = language_data
{
let symbols = &language_data.symbols_vec;
let supertypes = &language_data.supertype_map;
let fields = &language_data.fields_vec;
let in_anon = node_is_or_has_ancestor(root, current_node, "string") && !in_predicate;
let top_level = current_node.kind() == "program";
let in_negated_field = current_node.kind() == "negated_field"
|| cursor_after_exclamation_point
|| (current_node.kind() == "identifier"
&& current_node
.parent()
.is_some_and(|p| p.kind() == "negated_field"));
if in_negated_field {
for field in fields.clone() {
completion_items.push(CompletionItem {
label: field,
kind: Some(CompletionItemKind::FIELD),
..Default::default()
});
}
return Ok(Some(CompletionResponse::Array(completion_items)));
if in_negated_field {
for field in fields.clone() {
completion_items.push(CompletionItem {
label: field,
kind: Some(CompletionItemKind::FIELD),
..Default::default()
});
}
if !top_level {
for symbol in symbols.iter() {
if (in_anon && !symbol.named) || (!in_anon && symbol.named) {
completion_items.push(CompletionItem {
label: symbol.label.clone(),
kind: if symbol.named {
if !supertypes.contains_key(symbol) {
Some(CompletionItemKind::CLASS)
} else {
Some(CompletionItemKind::INTERFACE)
}
return Ok(Some(CompletionResponse::Array(completion_items)));
}
if !top_level {
for symbol in symbols.iter() {
if (in_anon && !symbol.named) || (!in_anon && symbol.named) {
completion_items.push(CompletionItem {
label: symbol.label.clone(),
kind: if symbol.named {
if !supertypes.contains_key(symbol) {
Some(CompletionItemKind::CLASS)
} else {
Some(CompletionItemKind::CONSTANT)
},
..Default::default()
});
}
Some(CompletionItemKind::INTERFACE)
}
} else {
Some(CompletionItemKind::CONSTANT)
},
..Default::default()
});
}
}
if !in_missing && !in_anon {
if !top_level {
completion_items.push(CompletionItem {
label: String::from("MISSING"),
kind: Some(CompletionItemKind::KEYWORD),
..Default::default()
});
}
for field in fields {
completion_items.push(CompletionItem {
label: format!("{field}: "),
kind: Some(CompletionItemKind::FIELD),
..Default::default()
});
}
}
if !in_missing && !in_anon {
if !top_level {
completion_items.push(CompletionItem {
label: String::from("MISSING"),
kind: Some(CompletionItemKind::KEYWORD),
..Default::default()
});
}
for field in fields {
completion_items.push(CompletionItem {
label: format!("{field}: "),
kind: Some(CompletionItemKind::FIELD),
..Default::default()
});
}
}
}

View file

@ -130,30 +130,30 @@ pub async fn populate_import_documents(
imported_uris: &Vec<(u32, u32, Option<Url>)>,
) {
for (_, _, uri) in imported_uris {
if let Some(uri) = uri {
if !backend.document_map.contains_key(uri) {
let path = uri.to_file_path().unwrap();
if let Ok(contents) = fs::read_to_string(path) {
let rope = Rope::from_str(&contents);
let mut parser = Parser::new();
parser
.set_language(&QUERY_LANGUAGE)
.expect("Error loading Query grammar");
let tree = parser.parse(&contents, None).unwrap();
let nested_imported_uris = get_imported_uris(backend, uri, &rope, &tree).await;
backend.document_map.insert(
uri.clone(),
DocumentData {
rope,
tree,
language_name: None,
version: -1,
imported_uris: nested_imported_uris.clone(),
},
);
Box::pin(populate_import_documents(backend, &nested_imported_uris)).await
}
}
if let Some(uri) = uri
&& !backend.document_map.contains_key(uri)
&& let Ok(contents) = uri
.to_file_path()
.and_then(|path| fs::read_to_string(path).map_err(|_| ()))
{
let rope = Rope::from_str(&contents);
let mut parser = Parser::new();
parser
.set_language(&QUERY_LANGUAGE)
.expect("Error loading Query grammar");
let tree = parser.parse(&contents, None).unwrap();
let nested_imported_uris = get_imported_uris(backend, uri, &rope, &tree).await;
backend.document_map.insert(
uri.clone(),
DocumentData {
rope,
tree,
language_name: None,
version: -1,
imported_uris: nested_imported_uris.clone(),
},
);
Box::pin(populate_import_documents(backend, &nested_imported_uris)).await
}
}
}

View file

@ -33,7 +33,6 @@ pub async fn document_symbol(
let capture_node = capture.node;
let node_text = capture_node.text(rope);
let parent = capture_node.parent().unwrap();
#[allow(deprecated)]
document_symbols.push(DocumentSymbol {
name: node_text,
kind: SymbolKind::VARIABLE,
@ -43,6 +42,7 @@ pub async fn document_symbol(
// TODO: Structure this hierarchically
children: None,
tags: None,
#[allow(deprecated)]
deprecated: None,
});
}
@ -172,7 +172,6 @@ mod test {
// Assert
let actual = Some(DocumentSymbolResponse::Nested(
#[allow(deprecated)]
symbols
.iter()
.map(|s| DocumentSymbol {
@ -183,6 +182,7 @@ mod test {
detail: None,
children: None,
tags: None,
#[allow(deprecated)]
deprecated: None,
})
.collect(),

View file

@ -230,8 +230,7 @@ fn format_iter<'a>(
}
}
if map.comment_fix.contains(id) {
let text = child.text(rope);
if let Some(mat) = COMMENT_PAT.captures(text.as_str()) {
if let Some(mat) = COMMENT_PAT.captures(&child.text(rope)) {
lines
.last_mut()
.unwrap()
@ -310,10 +309,10 @@ fn handle_predicate(
Some(node) => node.kind(),
};
for arg in &args[1..] {
if let QueryPredicateArg::String(kind) = arg {
if node_type == kind.deref() {
return false;
}
if let QueryPredicateArg::String(kind) = arg
&& node_type == kind.deref()
{
return false;
}
}
}

View file

@ -285,13 +285,12 @@ fn get_first_valid_file_config(workspace_uris: Vec<Url>) -> Option<Options> {
if let Ok(mut path) = folder_url.to_file_path() {
let mut config_path = path.join(".tsqueryrc.json");
loop {
if config_path.is_file() {
let data = fs::read_to_string(&config_path)
if config_path.is_file()
&& let Some(options) = fs::read_to_string(&config_path)
.ok()
.and_then(|data| serde_json::from_str(&data).ok());
if let Some(options) = data {
return options;
}
.and_then(|data| serde_json::from_str(&data).ok())
{
return options;
}
path = match path.parent() {
Some(parent) => parent.into(),
@ -386,23 +385,20 @@ pub async fn get_file_uris(backend: &Backend, language_name: &str, query_type: &
.iter()
.filter_map(|uri| uri.to_file_path().ok())
.collect::<Vec<_>>();
let scm_files = get_scm_files(&dirs);
let language_retrieval_regexes = &backend.options.read().await.language_retrieval_patterns;
let mut urls = Vec::new();
for scm_file in scm_files {
for scm_file in get_scm_files(&dirs) {
for re in language_retrieval_regexes {
if let Some(lang_name) = re
.captures(&scm_file.canonicalize().unwrap().to_string_lossy())
.and_then(|caps| caps.get(1))
if scm_file.file_stem().is_some_and(|stem| stem == query_type)
&& let Some(lang_name) = re
.captures(&scm_file.canonicalize().unwrap().to_string_lossy())
.and_then(|caps| caps.get(1))
&& lang_name.as_str() == language_name
{
if lang_name.as_str() == language_name
&& scm_file.file_stem().is_some_and(|stem| stem == query_type)
{
urls.push(Url::from_file_path(&scm_file).unwrap());
break;
}
urls.push(Url::from_file_path(&scm_file).unwrap());
break;
}
}
}