diff --git a/Cargo.lock b/Cargo.lock index 49bd6b4d5f59..49af57f4174d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,7 +249,6 @@ name = "buramu" version = "0.1.0" dependencies = [ "chrono", - "lazy_static", "rayon", "regex", ] @@ -492,7 +491,6 @@ dependencies = [ "encoding", "flate2", "globset", - "lazy_static", "num_cpus", "rand", "rayon", @@ -532,7 +530,6 @@ dependencies = [ "clap", "codeql-extractor", "encoding", - "lazy_static", "rayon", "regex", "serde_json", @@ -550,7 +547,6 @@ dependencies = [ "clap", "codeql-extractor", "encoding", - "lazy_static", "rayon", "regex", "serde", diff --git a/Cargo.toml b/Cargo.toml index b4edfedb9138..8e17f02f3503 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,5 +32,24 @@ exclude = [ [workspace.lints.clippy] all = { level = "warn", priority = -1 } -explicit_iter_loop = "warn" -manual_let_else = "warn" +pedantic = { level = "warn", priority = -1 } + +# Allowlist of pedantic rules that we've observed to be of questionable value +missing_errors_doc = "allow" +missing_panics_doc = "allow" +must_use_candidate = "allow" +implicit_hasher = "allow" +if_not_else = "allow" +# This lint has a lot of results in generated code. +unnecessary_wraps = "allow" +# Spelling out the full method name can often be tedious. +# E.g., `|v| v.as_slice()` vs `vec::Vec::as_slice` +redundant_closure_for_method_calls = "allow" +# The next three are only false positives and questionable results +cast_possible_truncation = "allow" +cast_possible_wrap = "allow" +cast_sign_loss = "allow" +# False positives +struct_excessive_bools = "allow" +# False positives for things like "matches" and "matched" +similar_names = "allow" diff --git a/MODULE.bazel b/MODULE.bazel index 04f9f865718e..409af33fd8f1 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -142,7 +142,6 @@ use_repo( "vendor_rs__globset-0.4.18", "vendor_rs__itertools-0.14.0", "vendor_rs__itertools-0.15.0", - "vendor_rs__lazy_static-1.5.1", "vendor_rs__mustache-0.9.0", "vendor_rs__num-traits-0.2.19", "vendor_rs__num_cpus-1.17.0", diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000000..e901773fa799 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,2 @@ +# Names that do not need to be backtick quoted within documentation comments. +doc-valid-idents = ["CodeQL", ".."] diff --git a/cpp/extractor/bmn/src/compiler.rs b/cpp/extractor/bmn/src/compiler.rs index 8da60fdb66af..a61f4f6497f3 100644 --- a/cpp/extractor/bmn/src/compiler.rs +++ b/cpp/extractor/bmn/src/compiler.rs @@ -519,7 +519,9 @@ fn get_compiler_override( &clang_cpp_compiler, ) .ok_or(anyhow!( - "Could not find clang compilers: {clang_c_compiler:?}, {clang_cpp_compiler:?}" + "Could not find clang compilers: {}, {}", + clang_c_compiler.display(), + clang_cpp_compiler.display() )) } else if override_instruction == "gnu" { // These can be just a command name, e.g. "gcc-18", or a full path, e.g. @@ -529,17 +531,23 @@ fn get_compiler_override( let gnu_cpp_compiler = environment::get_required_os(environment::CODEQL_EXTRACTOR_CPP_BMN_COMPILER_GNU_CPP)?; find_posix(telemetry, Compiler::Gnu, &gnu_c_compiler, &gnu_cpp_compiler).ok_or(anyhow!( - "Could not find gnu compilers: {gnu_c_compiler:?}, {gnu_cpp_compiler:?}" + "Could not find gnu compilers: {}, {}", + gnu_c_compiler.display(), + gnu_cpp_compiler.display() )) } else if override_instruction == "msvc" { // These can be just a command name, e.g. "cl", or a full path, e.g. // "c:\msvc\cl.exe" let msvc_compiler = environment::get_required_os(environment::CODEQL_EXTRACTOR_CPP_BMN_COMPILER_MSVC)?; - use_cl(&msvc_compiler).ok_or(anyhow!("Could not find msvc compiler: {msvc_compiler:?}")) + use_cl(&msvc_compiler).ok_or(anyhow!( + "Could not find msvc compiler: {}", + msvc_compiler.display() + )) } else { Err(anyhow!( - "Unsupported compiler override instruction: {override_instruction:?}" + "Unsupported compiler override instruction: {}", + override_instruction.display() )) } } diff --git a/cpp/extractor/bmn/src/dependency_installation.rs b/cpp/extractor/bmn/src/dependency_installation.rs index f65c80146231..b707af025545 100644 --- a/cpp/extractor/bmn/src/dependency_installation.rs +++ b/cpp/extractor/bmn/src/dependency_installation.rs @@ -45,7 +45,7 @@ fn run_command(command: &mut Command) -> anyhow::Result<()> { } else { OsString::from("Failed to read output") }; - Err(anyhow!("\"{command_name}\" failed: {error:?}")) + Err(anyhow!("\"{command_name}\" failed: {}", error.display())) } Err(e) => Err(anyhow!("Error waiting for process \"{command_name}\": {e}")), } diff --git a/cpp/extractor/bmn/src/file_filter.rs b/cpp/extractor/bmn/src/file_filter.rs index 8b952b659568..b6c311260e3f 100644 --- a/cpp/extractor/bmn/src/file_filter.rs +++ b/cpp/extractor/bmn/src/file_filter.rs @@ -97,7 +97,8 @@ fn relativize_path(path: PathBuf) -> Result { Ok(PathBuf::from_iter(sliced)) } _ => Err(anyhow!( - "Path cannot start with .. or the drive prefix: {path:?}" + "Path cannot start with .. or the drive prefix: {}", + path.display() )), } } diff --git a/cpp/extractor/bmn/src/gnu_compiler_default_include_finder.rs b/cpp/extractor/bmn/src/gnu_compiler_default_include_finder.rs index 9b208da27bf3..a0f1e60fe932 100644 --- a/cpp/extractor/bmn/src/gnu_compiler_default_include_finder.rs +++ b/cpp/extractor/bmn/src/gnu_compiler_default_include_finder.rs @@ -95,7 +95,8 @@ fn execute_command_with_args_get_stderr(cmd: &OsStr, args: &[&str]) -> Result Ok(output.stderr), _ => Err(anyhow!( - "Error invoking the compiler {cmd:?} to get the default include folders." + "Error invoking the compiler {} to get the default include folders.", + cmd.display() )), } } @@ -597,7 +598,7 @@ End of search list."#; assert_true!(output.is_err()); assert_eq!( output.unwrap_err().to_string(), - format!("Error invoking the compiler {cmd:?} to get the default include folders.") + "Error invoking the compiler command-not-existing to get the default include folders." ); } @@ -608,7 +609,7 @@ End of search list."#; assert_true!(result.is_err()); assert_eq!( result.unwrap_err().to_string(), - format!("Error invoking the compiler {cmd:?} to get the default include folders.") + "Error invoking the compiler command-not-existing to get the default include folders." ); } } diff --git a/cpp/extractor/bmn/src/main.rs b/cpp/extractor/bmn/src/main.rs index 54e57d02d6bb..c6e860d7a99a 100644 --- a/cpp/extractor/bmn/src/main.rs +++ b/cpp/extractor/bmn/src/main.rs @@ -52,8 +52,8 @@ fn get_extractor_executable() -> Result { let extractor = PathBuf::from_iter([&root_dir, "tools", &platform, &binary_name]); if !extractor.exists() { Err(anyhow::anyhow!( - "Extractor executable not found at: {:?}", - extractor + "Extractor executable not found at: {}", + extractor.display() )) } else { Ok(extractor) diff --git a/cpp/extractor/bmn/src/package_database.rs b/cpp/extractor/bmn/src/package_database.rs index fd70b5bcd314..1a1556260292 100644 --- a/cpp/extractor/bmn/src/package_database.rs +++ b/cpp/extractor/bmn/src/package_database.rs @@ -150,19 +150,27 @@ pub fn get_package_database() -> anyhow::Result { { if !path.exists() { return Err(anyhow!( - "Local deptrace database path specified but file does not exist: {path:?}.", + "Local deptrace database path specified but file does not exist: {}.", + path.display() )); } debug!( "Using local deptrace database from {}: {path:?}", environment::CODEQL_EXTRACTOR_CPP_LOCAL_DEPTRACE_DB, ); - fs::read_to_string(&path) - .map_err(|e| anyhow!("Failed to read local deptrace database from {path:?}: {e}"))? + fs::read_to_string(&path).map_err(|e| { + anyhow!( + "Failed to read local deptrace database from {}: {e}", + path.display() + ) + })? } else { let archive_file_path = get_deptrace_db_zip_path()?; extract_content_from_zip(&archive_file_path).map_err(|e| { - anyhow!("Failed to extract package database from {archive_file_path:?}: {e}") + anyhow!( + "Failed to extract package database from {}: {e}", + archive_file_path.display() + ) })? }; PackageDatabase::from_deptrace_content(&content) @@ -213,17 +221,31 @@ fn infer_os_version_name() -> Option { /// as a string. fn extract_content_from_zip(archive_zip_name: &Path) -> anyhow::Result { let inner_file_name = "deptrace-db.txt"; - let file = File::open(archive_zip_name) - .map_err(|e| anyhow!("Could not open archive zip name {archive_zip_name:?}: {e}"))?; - let mut archive = ZipArchive::new(file) - .map_err(|e| anyhow!("Could not read zip archive {archive_zip_name:?}: {e}"))?; + let file = File::open(archive_zip_name).map_err(|e| { + anyhow!( + "Could not open archive zip name {}: {e}", + archive_zip_name.display() + ) + })?; + let mut archive = ZipArchive::new(file).map_err(|e| { + anyhow!( + "Could not read zip archive {}: {e}", + archive_zip_name.display() + ) + })?; let mut zipped_file = archive.by_name(inner_file_name).map_err(|e| { - anyhow!("Could not find {inner_file_name} in archive {archive_zip_name:?}: {e}") + anyhow!( + "Could not find {inner_file_name} in archive {}: {e}", + archive_zip_name.display() + ) })?; let mut buffer = String::new(); zipped_file.read_to_string(&mut buffer).map_err(|e| { - anyhow!("Could not read {inner_file_name} from archive {archive_zip_name:?}: {e}") + anyhow!( + "Could not read {inner_file_name} from archive {}: {e}", + archive_zip_name.display() + ) })?; Ok(buffer) diff --git a/misc/bazel/3rdparty/rust_workspace_deps/BUILD.bazel b/misc/bazel/3rdparty/rust_workspace_deps/BUILD.bazel index 01cf30c6bdf3..20e67a6711c0 100644 --- a/misc/bazel/3rdparty/rust_workspace_deps/BUILD.bazel +++ b/misc/bazel/3rdparty/rust_workspace_deps/BUILD.bazel @@ -211,18 +211,6 @@ alias( tags = ["manual"], ) -alias( - name = "lazy_static-1.5.1", - actual = "@vendor_rs__lazy_static-1.5.1//:lazy_static", - tags = ["manual"], -) - -alias( - name = "lazy_static", - actual = "@vendor_rs__lazy_static-1.5.1//:lazy_static", - tags = ["manual"], -) - alias( name = "mustache-0.9.0", actual = "@vendor_rs__mustache-0.9.0//:mustache", diff --git a/misc/bazel/3rdparty/rust_workspace_deps/crates.bzl b/misc/bazel/3rdparty/rust_workspace_deps/crates.bzl index f8a1af628fb8..b5e41d6139f7 100644 --- a/misc/bazel/3rdparty/rust_workspace_deps/crates.bzl +++ b/misc/bazel/3rdparty/rust_workspace_deps/crates.bzl @@ -356,7 +356,6 @@ _NORMAL_DEPENDENCIES = { "ql/buramu": { _COMMON_CONDITION: { "chrono": Label("@vendor_rs//chrono-0.4.45"), - "lazy_static": Label("@vendor_rs//lazy_static-1.5.1"), "rayon": Label("@vendor_rs//rayon-1.12.0"), "regex": Label("@vendor_rs//regex-1.13.1"), }, @@ -384,7 +383,6 @@ _NORMAL_DEPENDENCIES = { _COMMON_CONDITION: { "clap": Label("@vendor_rs//clap-4.6.7"), "encoding": Label("@vendor_rs//encoding-0.2.33"), - "lazy_static": Label("@vendor_rs//lazy_static-1.5.1"), "rayon": Label("@vendor_rs//rayon-1.12.0"), "regex": Label("@vendor_rs//regex-1.13.1"), "serde_json": Label("@vendor_rs//serde_json-1.0.154"), @@ -461,7 +459,6 @@ _NORMAL_DEPENDENCIES = { "encoding": Label("@vendor_rs//encoding-0.2.33"), "flate2": Label("@vendor_rs//flate2-1.1.9"), "globset": Label("@vendor_rs//globset-0.4.18"), - "lazy_static": Label("@vendor_rs//lazy_static-1.5.1"), "num_cpus": Label("@vendor_rs//num_cpus-1.17.0"), "rayon": Label("@vendor_rs//rayon-1.12.0"), "regex": Label("@vendor_rs//regex-1.13.1"), @@ -502,7 +499,6 @@ _NORMAL_DEPENDENCIES = { _COMMON_CONDITION: { "clap": Label("@vendor_rs//clap-4.6.7"), "encoding": Label("@vendor_rs//encoding-0.2.33"), - "lazy_static": Label("@vendor_rs//lazy_static-1.5.1"), "rayon": Label("@vendor_rs//rayon-1.12.0"), "regex": Label("@vendor_rs//regex-1.13.1"), "serde": Label("@vendor_rs//serde-1.0.229"), @@ -4816,7 +4812,6 @@ def crate_repositories(): struct(repo = "vendor_rs__globset-0.4.18", is_dev_dep = False), struct(repo = "vendor_rs__itertools-0.14.0", is_dev_dep = False), struct(repo = "vendor_rs__itertools-0.15.0", is_dev_dep = False), - struct(repo = "vendor_rs__lazy_static-1.5.1", is_dev_dep = False), struct(repo = "vendor_rs__mustache-0.9.0", is_dev_dep = False), struct(repo = "vendor_rs__num-traits-0.2.19", is_dev_dep = False), struct(repo = "vendor_rs__num_cpus-1.17.0", is_dev_dep = False), diff --git a/misc/bazel/3rdparty/rust_workspace_deps/lazy_static-1.5.1/BUILD.bazel b/misc/bazel/3rdparty/rust_workspace_deps/lazy_static-1.5.1/BUILD.bazel deleted file mode 100644 index 3140ccb8ad63..000000000000 --- a/misc/bazel/3rdparty/rust_workspace_deps/lazy_static-1.5.1/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @@//misc/bazel/3rdparty:vendor_rust_workspace_deps -############################################################################### - -package(default_visibility = ["//visibility:public"]) - -alias( - name = "lazy_static-1.5.1", - actual = "@vendor_rs__lazy_static-1.5.1//:lazy_static", - tags = ["manual"], -) diff --git a/misc/bazel/3rdparty/rust_workspace_deps/lazy_static/BUILD.bazel b/misc/bazel/3rdparty/rust_workspace_deps/lazy_static/BUILD.bazel deleted file mode 100644 index 04eca0f691a9..000000000000 --- a/misc/bazel/3rdparty/rust_workspace_deps/lazy_static/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################### -# @generated -# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To -# regenerate this file, run the following: -# -# bazel run @@//misc/bazel/3rdparty:vendor_rust_workspace_deps -############################################################################### - -package(default_visibility = ["//visibility:public"]) - -alias( - name = "lazy_static", - actual = "@vendor_rs__lazy_static-1.5.1//:lazy_static", - tags = ["manual"], -) diff --git a/ql/buramu/Cargo.toml b/ql/buramu/Cargo.toml index ab5b5fde76f1..f004f3e973a2 100644 --- a/ql/buramu/Cargo.toml +++ b/ql/buramu/Cargo.toml @@ -9,7 +9,6 @@ edition = "2021" workspace = true [dependencies] -lazy_static = "1.4.0" chrono = "0.4.37" rayon = "1.9.0" regex = "1.10.4" diff --git a/ql/buramu/src/main.rs b/ql/buramu/src/main.rs index 11305c34bf57..9efe9e4c7e9d 100644 --- a/ql/buramu/src/main.rs +++ b/ql/buramu/src/main.rs @@ -1,7 +1,7 @@ -use lazy_static::lazy_static; use rayon::prelude::*; use regex::Regex; use std::collections::HashMap; +use std::sync::LazyLock; use std::{io::BufRead, process::Command}; // A map from filenames to lists of line numbers (for just the lines with deprecations) @@ -53,7 +53,7 @@ fn get_blame_dates_for_filedeprecation(file: &str, linenos: &[String]) -> LastMo let mut command = Command::new("git"); command.arg("blame"); for lineno in linenos { - command.arg("-L").arg(format!("{},{}", lineno, lineno)); + command.arg("-L").arg(format!("{lineno},{lineno}")); } command.arg(file); let output = command.output().expect("failed to execute process"); @@ -69,10 +69,8 @@ fn get_blame_dates_for_filedeprecation(file: &str, linenos: &[String]) -> LastMo blame_dates } -lazy_static! { - static ref BLAME_RE: Regex = - Regex::new("(\\d{4}-\\d{2}-\\d{2}).*[+-]\\d{4}\\s+(\\d+)\\)").unwrap(); -} +static BLAME_RE: LazyLock = + LazyLock::new(|| Regex::new("(\\d{4}-\\d{2}-\\d{2}).*[+-]\\d{4}\\s+(\\d+)\\)").unwrap()); fn get_last_modified(line: &str) -> LastModifiedLine { let caps = BLAME_RE.captures(line).unwrap(); @@ -97,7 +95,7 @@ fn main() { .par_iter() .map(|(file, linenos)| (file, get_blame_dates_for_filedeprecation(file, linenos))); deprecations.for_each(|(file, linenos_and_dates)| { - println!("file: {}", file); + println!("file: {file}"); for (date, linenos) in &linenos_and_dates { println!(" last_modified: {} {}", date, linenos.join(" ")); } diff --git a/ruby/extractor/Cargo.toml b/ruby/extractor/Cargo.toml index 27640687f866..4ca43af279ce 100644 --- a/ruby/extractor/Cargo.toml +++ b/ruby/extractor/Cargo.toml @@ -19,7 +19,6 @@ tracing-subscriber = { version = "0.3.23", features = ["env-filter"] } rayon = "1.12.0" regex = "1.13.1" encoding = "0.2" -lazy_static = "1.5.1" serde_json = "1.0.154" codeql-extractor = { path = "../../shared/tree-sitter-extractor" } diff --git a/ruby/extractor/src/extractor.rs b/ruby/extractor/src/extractor.rs index 91852a5b0057..8e30454e7a2f 100644 --- a/ruby/extractor/src/extractor.rs +++ b/ruby/extractor/src/extractor.rs @@ -1,12 +1,12 @@ use clap::Args; use codeql_extractor::file_paths::PathTransformer; -use lazy_static::lazy_static; use rayon::prelude::*; use std::borrow::Cow; use std::collections::HashSet; use std::fs; use std::io::BufRead; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use tree_sitter::{Language, Parser, Range}; use codeql_extractor::{diagnostics, extractor, file_paths, node_types, trap}; @@ -26,7 +26,8 @@ pub struct Options { file_list: String, } -pub fn run(options: Options) -> std::io::Result<()> { +#[allow(clippy::too_many_lines)] +pub fn run(options: &Options) -> std::io::Result<()> { extractor::set_tracing_level("ruby"); tracing::info!("Extraction started"); let diagnostics = diagnostics::DiagnosticLoggers::new("ruby"); @@ -159,7 +160,7 @@ pub fn run(options: Options) -> std::io::Result<()> { match encoding .decode(&source, encoding::types::DecoderTrap::Replace) { - Ok(str) => source = str.as_bytes().to_owned(), + Ok(str) => str.as_bytes().clone_into(&mut source), Err(msg) => { needs_conversion = false; diagnostics_writer.write( @@ -222,7 +223,7 @@ pub fn run(options: Options) -> std::io::Result<()> { } else { std::fs::copy(&path, &src_archive_file)?; } - write_trap(&trap_dir, path, &trap_writer, trap_compression, path_transformer.as_ref()) + write_trap(&trap_dir, &path, &trap_writer, trap_compression, path_transformer.as_ref()) }) .expect("failed to extract files"); @@ -231,7 +232,7 @@ pub fn run(options: Options) -> std::io::Result<()> { extractor::populate_empty_location(&mut trap_writer); let res = write_trap( &trap_dir, - path, + &path, &trap_writer, trap_compression, path_transformer.as_ref(), @@ -246,9 +247,8 @@ pub fn run(options: Options) -> std::io::Result<()> { res } -lazy_static! { - static ref CP_NUMBER: regex::Regex = regex::Regex::new("cp([0-9]+)").unwrap(); -} +static CP_NUMBER: LazyLock = + LazyLock::new(|| regex::Regex::new("cp([0-9]+)").unwrap()); /// Returns the `encoding::Encoding` corresponding to the given encoding name, if one exists. fn encoding_from_name(encoding_name: &str) -> Option<&(dyn encoding::Encoding + Send + Sync)> { @@ -264,14 +264,14 @@ fn encoding_from_name(encoding_name: &str) -> Option<&(dyn encoding::Encoding + fn write_trap( trap_dir: &Path, - path: PathBuf, + path: &Path, trap_writer: &trap::Writer, trap_compression: trap::Compression, path_transformer: Option<&PathTransformer>, ) -> std::io::Result<()> { let trap_file = file_paths::path_for( trap_dir, - &path, + path, trap_compression.extension(), path_transformer, ); @@ -372,6 +372,8 @@ fn get_overlay_changed_files() -> Option> { } fn scan_coding_comment(content: &[u8]) -> std::option::Option> { + const CODING: [char; 12] = ['C', 'c', 'O', 'o', 'D', 'd', 'I', 'i', 'N', 'n', 'G', 'g']; + let mut index = 0; // skip UTF-8 BOM marker if there is one if content.len() >= 3 && content[0] == 0xef && content[1] == 0xbb && content[2] == 0xbf { @@ -384,9 +386,9 @@ fn scan_coding_comment(content: &[u8]) -> std::option::Option> { { index += 2; while index < content.len() && content[index] as char != '\n' { - index += 1 + index += 1; } - index += 1 + index += 1; } index = skip_space(content, index); @@ -395,13 +397,12 @@ fn scan_coding_comment(content: &[u8]) -> std::option::Option> { } index += 1; - const CODING: [char; 12] = ['C', 'c', 'O', 'o', 'D', 'd', 'I', 'i', 'N', 'n', 'G', 'g']; let mut word_index = 0; while index < content.len() && word_index < CODING.len() && content[index] as char != '\n' { if content[index] as char == CODING[word_index] || content[index] as char == CODING[word_index + 1] { - word_index += 2 + word_index += 2; } else { word_index = 0; } diff --git a/ruby/extractor/src/main.rs b/ruby/extractor/src/main.rs index e6721d4e2243..7768a535bc30 100644 --- a/ruby/extractor/src/main.rs +++ b/ruby/extractor/src/main.rs @@ -16,7 +16,7 @@ fn main() -> std::io::Result<()> { let cli = Cli::parse(); match cli { - Cli::Extract(options) => extractor::run(options), + Cli::Extract(options) => extractor::run(&options), Cli::Generate(options) => generator::run(options), Cli::Autobuild(options) => autobuilder::run(options), } diff --git a/rust/ast-generator/patches/rust-analyzer.patch b/rust/ast-generator/patches/rust-analyzer.patch index ffe12683b4aa..cac63dc2b3d8 100644 --- a/rust/ast-generator/patches/rust-analyzer.patch +++ b/rust/ast-generator/patches/rust-analyzer.patch @@ -22,7 +22,64 @@ index 0aad1e2..68f679f 100644 use self::ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc}; pub(crate) fn generate(check: bool) { -@@ -775,7 +779,7 @@ fn pluralize(s: &str) -> String { +@@ -317,7 +321,7 @@ fn generate_nodes(grammar: &AstSrc) -> String { + let trait_name = format_ident!("{}", trait_name); + let kinds: Vec<_> = nodes + .iter() +- .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string()))) ++ .map(|name| format_ident!("{}", to_upper_snake_case(&name.name))) + .collect(); + let nodes = nodes.iter().map(|node| format_ident!("{}", node.name)); + ( +@@ -521,9 +525,12 @@ + contextual_keywords.iter().map(fmt_kw_as_variant).collect::>(); + let contextual_keywords_tokens = contextual_keywords.iter().map(|it| format_ident!("{it}")); + let contextual_keywords_str_match_arm = grammar.contextual_keywords.iter().map(|kw| { +- match grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw) { +- Some((_, ed)) => quote! { #kw if edition < #ed }, +- None => quote! { #kw }, ++ if let Some((_, ed)) = ++ grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw) ++ { ++ quote! { #kw if edition < #ed } ++ } else { ++ quote! { #kw } + } + }); + let contextual_keywords_variants_match_arm = grammar +@@ -531,9 +538,12 @@ + .iter() + .map(|kw_s| { + let kw = fmt_kw_as_variant(kw_s); +- match grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw_s) { +- Some((_, ed)) => quote! { #kw if edition < #ed }, +- None => quote! { #kw }, ++ if let Some((_, ed)) = ++ grammar.edition_dependent_keywords.iter().find(|(ed_kw, _)| ed_kw == kw_s) ++ { ++ quote! { #kw if edition < #ed } ++ } else { ++ quote! { #kw } + } + }) + .collect::>(); +@@ -731,6 +741,6 @@ fn to_upper_snake_case(s: &str) -> String { + let mut prev = false; + for c in s.chars() { + if c.is_ascii_uppercase() && prev { +- buf.push('_') ++ buf.push('_'); + } + prev = true; +@@ -745,6 +755,6 @@ fn to_lower_snake_case(s: &str) -> String { + let mut prev = false; + for c in s.chars() { + if c.is_ascii_uppercase() && prev { +- buf.push('_') ++ buf.push('_'); + } + prev = true; +@@ -775,7 +785,7 @@ fn pluralize(s: &str) -> String { } impl Field { @@ -31,8 +88,9 @@ index 0aad1e2..68f679f 100644 matches!(self, Field::Node { cardinality: Cardinality::Many, .. }) } fn token_kind(&self) -> Option { -@@ -787,7 +791,7 @@ impl Field { - _ => None, +@@ -787,7 +797,7 @@ impl Field { +- _ => None, ++ Field::Node { .. } => None, } } - fn method_name(&self) -> String { @@ -40,7 +98,7 @@ index 0aad1e2..68f679f 100644 match self { Field::Token { name, token, .. } => { if let Some(name) = name { -@@ -836,7 +840,7 @@ impl Field { +@@ -836,7 +846,7 @@ impl Field { } } } @@ -49,7 +107,7 @@ index 0aad1e2..68f679f 100644 match self { Field::Token { .. } => format_ident!("SyntaxToken"), Field::Node { ty, .. } => format_ident!("{}", ty), -@@ -849,7 +853,7 @@ fn clean_token_name(name: &str) -> String { +@@ -849,7 +859,7 @@ fn clean_token_name(name: &str) -> String { if cleaned.is_empty() { name.to_owned() } else { cleaned.to_owned() } } @@ -58,6 +116,38 @@ index 0aad1e2..68f679f 100644 let mut res = AstSrc { tokens: "Whitespace Comment String ByteString CString IntNumber FloatNumber Char Byte Ident" +@@ -865,15 +875,12 @@ + let name = grammar[node].name.clone(); + let rule = &grammar[node].rule; + let _g = panic_context::enter(name.clone()); +- match lower_enum(grammar, rule) { +- Some(variants) => { +- let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants }; +- res.enums.push(enum_src); +- } +- None => { +- let mut fields = Vec::new(); +- lower_rule(&mut fields, grammar, None, rule); +- res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields }); +- } ++ if let Some(variants) = lower_enum(grammar, rule) { ++ let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants }; ++ res.enums.push(enum_src); ++ } else { ++ let mut fields = Vec::new(); ++ lower_rule(&mut fields, grammar, None, rule); ++ res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields }); + } + } +@@ -979,7 +986,7 @@ fn lower_rule( + } + Rule::Seq(rules) | Rule::Alt(rules) => { + for rule in rules { +- lower_rule(acc, grammar, label, rule) ++ lower_rule(acc, grammar, label, rule); + } + } + Rule::Opt(rule) => lower_rule(acc, grammar, label, rule), diff --git a/xtask/src/codegen/grammar/ast_src.rs b/xtask/src/codegen/grammar/ast_src.rs index 1ae139f..d4d791e 100644 --- a/xtask/src/codegen/grammar/ast_src.rs diff --git a/rust/ast-generator/src/main.rs b/rust/ast-generator/src/main.rs index f136fd57fc41..4b2d98138aab 100644 --- a/rust/ast-generator/src/main.rs +++ b/rust/ast-generator/src/main.rs @@ -31,8 +31,7 @@ fn class_name(type_name: &str) -> String { fn property_name(type_name: &str, field_name: &str) -> String { let name = match (type_name, field_name) { ("CallExpr", "expr") => "function", - ("LetExpr", "expr") => "scrutinee", - ("MatchExpr", "expr") => "scrutinee", + ("LetExpr" | "MatchExpr", "expr") => "scrutinee", ("Variant", "expr") => "discriminant", ("FieldExpr", "expr") => "container", (_, "name_ref") => "identifier", @@ -128,8 +127,7 @@ fn get_additional_fields(node_name: &str) -> Vec { FieldInfo::optional("self_ty", "Type"), ], "ForExpr" => vec![FieldInfo::optional("iterable", "Expr")], - "WhileExpr" => vec![FieldInfo::optional("condition", "Expr")], - "MatchGuard" => vec![FieldInfo::optional("condition", "Expr")], + "WhileExpr" | "MatchGuard" => vec![FieldInfo::optional("condition", "Expr")], "MacroDef" => vec![ FieldInfo::body("args", "TokenTree"), FieldInfo::body("body", "TokenTree"), @@ -139,8 +137,7 @@ fn get_additional_fields(node_name: &str) -> Vec { "FormatArgsExpr" => vec![FieldInfo::list("args", "FormatArgsArg")], "ArgList" => vec![FieldInfo::list("args", "Expr")], "Fn" => vec![FieldInfo::body("body", "BlockExpr")], - "Const" => vec![FieldInfo::body("body", "Expr")], - "Static" => vec![FieldInfo::body("body", "Expr")], + "Const" | "Static" => vec![FieldInfo::body("body", "Expr")], "Param" => vec![FieldInfo::body("pat", "Pat")], "ClosureExpr" => vec![FieldInfo::optional("body", "Expr")], "ArrayExpr" => vec![FieldInfo::predicate("is_semicolon")], @@ -191,7 +188,7 @@ fn should_predicate_be_extracted(name: &str) -> bool { } fn project_root() -> PathBuf { - let dir = env::var("CARGO_MANIFEST_DIR").unwrap().to_owned(); + let dir = env::var("CARGO_MANIFEST_DIR").unwrap(); PathBuf::from(dir).parent().unwrap().to_owned() } @@ -200,7 +197,7 @@ fn to_lower_snake_case(s: &str) -> String { let mut prev = false; for c in s.chars() { if c.is_ascii_uppercase() && prev { - buf.push('_') + buf.push('_'); } prev = true; @@ -229,10 +226,10 @@ struct Schema { } fn get_bases(name: &str, super_types: &BTreeMap>) -> Vec { - super_types - .get(name) - .map(|tys| tys.iter().map(|t| class_name(t)).collect()) - .unwrap_or_else(|| vec!["AstNode".to_string()]) + super_types.get(name).map_or_else( + || vec!["AstNode".to_string()], + |tys| tys.iter().map(|t| class_name(t)).collect(), + ) } fn enum_src_to_schema_class( @@ -279,7 +276,7 @@ fn node_src_to_schema_class( fn fix_blank_lines(s: &str) -> String { // mustache is not very good at avoiding blank lines // adopting the workaround from https://github.com/groue/GRMustache/issues/46#issuecomment-19498046 - s.split("\n") + s.split('\n') .filter(|line| !line.trim().is_empty()) .map(|line| if line == "¶" { "" } else { line }) .join("\n") @@ -288,7 +285,7 @@ fn fix_blank_lines(s: &str) -> String { fn write_schema( grammar: &AstSrc, - super_types: BTreeMap>, + super_types: &BTreeMap>, mustache_ctx: &mustache::Context, ) -> mustache::Result { let mut schema = Schema::default(); @@ -296,13 +293,13 @@ fn write_schema( grammar .enums .iter() - .map(|node| enum_src_to_schema_class(node, &super_types)), + .map(|node| enum_src_to_schema_class(node, super_types)), ); schema.classes.extend( grammar .nodes .iter() - .map(|node| node_src_to_schema_class(node, &super_types)), + .map(|node| node_src_to_schema_class(node, super_types)), ); let template = mustache_ctx.compile_path("schema")?; let res = template.render_to_string(&schema)?; @@ -413,7 +410,7 @@ fn enum_to_extractor_info(node: &AstEnumSrc) -> ExtractorEnumInfo { EnumVariantInfo { name, snake_case_name, - variant_ast_name: v.to_string(), + variant_ast_name: v.clone(), emission, } }) @@ -519,7 +516,7 @@ fn main() -> anyhow::Result<()> { for node in &grammar.enums { for variant in &node.variants { let set = super_types.entry(variant.to_owned()).or_default(); - set.insert(node.name.to_owned()); + set.insert(node.name.clone()); } } // sort things while ensuring super clases are defined before they are used @@ -533,7 +530,7 @@ fn main() -> anyhow::Result<()> { template_path: root.join("ast-generator").join("templates"), template_extension: "mustache".to_string(), }; - let schema = write_schema(&grammar, super_types, &mustache_ctx)?; + let schema = write_schema(&grammar, &super_types, &mustache_ctx)?; let schema_path = root.join("schema/ast.py"); codegen::ensure_file_contents( crate::flags::CodegenType::Grammar, diff --git a/rust/extractor/src/config.rs b/rust/extractor/src/config.rs index 88f7ada715c6..f3893409c490 100644 --- a/rust/extractor/src/config.rs +++ b/rust/extractor/src/config.rs @@ -246,7 +246,7 @@ impl Config { } fn to_cfg_override(spec: &str) -> CfgAtom { - if let Some((key, value)) = spec.split_once("=") { + if let Some((key, value)) = spec.split_once('=') { CfgAtom::KeyValue { key: Symbol::intern(key), value: Symbol::intern(value), diff --git a/rust/extractor/src/config/deserialize.rs b/rust/extractor/src/config/deserialize.rs index 6e1b9b398b63..17985ff177b5 100644 --- a/rust/extractor/src/config/deserialize.rs +++ b/rust/extractor/src/config/deserialize.rs @@ -62,7 +62,7 @@ impl<'de, S: BuildHasher + Default> Visitor<'de> for MapVisitor { while let Some(el) = seq.next_element::()? { match el.split_once('=') { None => { - ret.insert(el.to_owned(), None); + ret.insert(el, None); } Some((key, value)) => { ret.insert(key.to_owned(), Some(value.to_owned())); diff --git a/rust/extractor/src/configuration.rs b/rust/extractor/src/configuration.rs index cbf94ee068d3..bee817689ff1 100644 --- a/rust/extractor/src/configuration.rs +++ b/rust/extractor/src/configuration.rs @@ -97,8 +97,12 @@ impl Ord for DependencySource<'_> { fn cmp(&self, other: &Self) -> Ordering { // Compare by cfg options first, then by manifest parent directory // (arbitrary but deterministic). - cmp_option_by(&self.cfg_options, &other.cfg_options, compare_cfg_options) - .then_with(|| manifest_parent(self.manifest).cmp(manifest_parent(other.manifest))) + cmp_option_by( + self.cfg_options.as_ref(), + other.cfg_options.as_ref(), + compare_cfg_options, + ) + .then_with(|| manifest_parent(self.manifest).cmp(manifest_parent(other.manifest))) } } @@ -211,7 +215,7 @@ impl<'a> DependencyFiles<'a> { mod tests { use super::*; use ra_ap_base_db::{ - CrateGraphBuilder, CrateOrigin, CrateWorkspaceData, FileChange, FileSet, SourceRoot, + CrateGraphBuilder, CrateOrigin, CrateWorkspaceData, Env, FileChange, FileSet, SourceRoot, }; use ra_ap_intern::Symbol; use ra_ap_span::Edition; @@ -247,7 +251,7 @@ mod tests { None, cfg(features), None, - Default::default(), + Env::default(), CrateOrigin::Library { repo: None, name: Symbol::intern(name), diff --git a/rust/extractor/src/crate_graph.rs b/rust/extractor/src/crate_graph.rs index 072bffdc1bf1..49c86f0f81ab 100644 --- a/rust/extractor/src/crate_graph.rs +++ b/rust/extractor/src/crate_graph.rs @@ -33,13 +33,13 @@ pub fn extract_crate_graph(trap_provider: &trap::TrapFileProvider, db: &RootData krate_id .cfg_options(db) .into_iter() - .sorted_by(cmp_flag) + .sorted_by(|&a, &b| cmp_flag(a, b)) .for_each(|x| format!("{x}").hash(&mut hasher)); krate .dependencies .iter() - .flat_map(|d| crate_id_map.get(&d.crate_id)) + .filter_map(|d| crate_id_map.get(&d.crate_id)) .sorted() .for_each(|x| x.hash(&mut hasher)); let hash = hasher.finish(); @@ -61,7 +61,7 @@ pub fn extract_crate_graph(trap_provider: &trap::TrapFileProvider, db: &RootData let crate_dependencies: Vec = krate .dependencies .iter() - .flat_map(|x| crate_id_map.get(&x.crate_id).map(|y| (&x.name, y))) + .filter_map(|x| crate_id_map.get(&x.crate_id).map(|y| (&x.name, y))) .map(|(name, (module, hash))| generated::NamedCrate { id: trap::TrapId::Star, name: name.to_string(), @@ -76,7 +76,7 @@ pub fn extract_crate_graph(trap_provider: &trap::TrapFileProvider, db: &RootData .display_name .as_ref() .map(|x| x.canonical_name().to_string()), - version: krate_extra.version.to_owned(), + version: krate_extra.version.clone(), cfg_options: krate_id .cfg_options(db) .into_iter() @@ -96,13 +96,13 @@ pub fn extract_crate_graph(trap_provider: &trap::TrapFileProvider, db: &RootData "Failed to write trap file for crate: {}: {}", root_module_file.display(), err.to_string() - ) + ); }); } } } -fn cmp_flag(a: &&CfgAtom, b: &&CfgAtom) -> Ordering { +fn cmp_flag(a: &CfgAtom, b: &CfgAtom) -> Ordering { match (a, b) { (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()), (CfgAtom::Flag(a), CfgAtom::KeyValue { key: b, value: _ }) => { diff --git a/rust/extractor/src/diagnostics.rs b/rust/extractor/src/diagnostics.rs index ab88192c5d3e..8b84f6074351 100644 --- a/rust/extractor/src/diagnostics.rs +++ b/rust/extractor/src/diagnostics.rs @@ -40,7 +40,7 @@ enum Message { impl Default for Message { fn default() -> Self { - Message::TextMessage("".to_string()) + Message::TextMessage(String::new()) } } diff --git a/rust/extractor/src/main.rs b/rust/extractor/src/main.rs index 4ede43224d35..63bf04088b02 100644 --- a/rust/extractor/src/main.rs +++ b/rust/extractor/src/main.rs @@ -101,7 +101,7 @@ impl<'a> Extractor<'a> { "Failed to write trap file for: {}: {}", file.display(), err.to_string() - ) + ); }); self.steps .push(ExtractionStep::extract(before_extract, source_kind, file)); @@ -165,7 +165,7 @@ impl<'a> Extractor<'a> { )); } _ => {} - }; + } self.steps.push(ExtractionStep::load_source(before, file)); Ok(()) } @@ -239,6 +239,7 @@ fn cwd() -> anyhow::Result { Ok(abs_path) } +#[allow(clippy::too_many_lines)] fn main() -> anyhow::Result<()> { let start = Instant::now(); let config = config::Config::extract().context("failed to load configuration")?; @@ -258,8 +259,7 @@ fn main() -> anyhow::Result<()> { let (flame_layer, _flush_guard) = if let Some(path) = &config.logging_flamegraph { tracing_flame::FlameLayer::with_file(path) .ok() - .map(|(a, b)| (Some(a), Some(b))) - .unwrap_or((None, None)) + .map_or((None, None), |(a, b)| (Some(a), Some(b))) } else { (None, None) }; @@ -282,7 +282,7 @@ fn main() -> anyhow::Result<()> { let files = inputs .iter() .map(|file| { - let file = std::path::absolute(file).unwrap_or(file.to_path_buf()); + let file = std::path::absolute(file).unwrap_or(file.clone()); // On Windows, rust analyzer expects non-`//?/` prefixed paths (see [1]), which is what // `std::fs::canonicalize` returns. So we use `dunce::canonicalize` instead. // [1]: https://github.com/rust-lang/rust-analyzer/issues/18894#issuecomment-2580014730 @@ -326,7 +326,7 @@ fn main() -> anyhow::Result<()> { match extractor.load_source(file, &semantics, &vfs) { Ok(()) => extractor.extract_with_semantics(file, &semantics, &vfs, source_mode), Err(e) => extractor.extract_without_semantics(file, source_mode, e), - }; + } } // Fast path when there is no ambiguity in dependency extraction. if dependency_extraction_ambiguity { @@ -396,7 +396,11 @@ fn main() -> anyhow::Result<()> { let entry = entry.context("failed to read builtins directory")?; let path = entry.path(); if path.extension().is_some_and(|ext| ext == "rs") { - extractor.extract_without_semantics(&path, SourceKind::Library, Default::default()); + extractor.extract_without_semantics( + &path, + SourceKind::Library, + RustAnalyzerNoSemantics::default(), + ); } } diff --git a/rust/extractor/src/rust_analyzer.rs b/rust/extractor/src/rust_analyzer.rs index d3129af12796..2abf505188bc 100644 --- a/rust/extractor/src/rust_analyzer.rs +++ b/rust/extractor/src/rust_analyzer.rs @@ -273,6 +273,8 @@ fn find_workspace(reader: &mut TomlReader, manifest: &ProjectManifest) -> Option pub fn find_project_manifests( files: &[PathBuf], ) -> anyhow::Result> { + const LOG_LIMIT: usize = 10; + let current = std::env::current_dir()?; let abs_files: Vec<_> = files .iter() @@ -286,7 +288,6 @@ pub fn find_project_manifests( ret.insert(workspace); } let iter = || ret.iter().map(|m| format!(" {m}")); - const LOG_LIMIT: usize = 10; if ret.len() <= LOG_LIMIT { info!("found manifests:\n{}", iter().join("\n")); } else { @@ -304,6 +305,8 @@ pub fn find_project_manifests( } fn from_utf8_lossy(v: &[u8]) -> (Cow<'_, str>, Option) { + const REPLACEMENT: &str = "\u{FFFD}"; + let mut iter = v.utf8_chunks(); let (first_valid, first_invalid) = if let Some(chunk) = iter.next() { let valid = chunk.valid(); @@ -317,7 +320,6 @@ fn from_utf8_lossy(v: &[u8]) -> (Cow<'_, str>, Option) { return (Cow::Borrowed(""), None); }; - const REPLACEMENT: &str = "\u{FFFD}"; let error_start = first_valid.len() as u32; let error_end = error_start + first_invalid.len() as u32; let error_range = TextRange::new(TextSize::new(error_start), TextSize::new(error_end)); diff --git a/rust/extractor/src/translate/base.rs b/rust/extractor/src/translate/base.rs index 981a600102c4..d24a65af293c 100644 --- a/rust/extractor/src/translate/base.rs +++ b/rust/extractor/src/translate/base.rs @@ -227,7 +227,7 @@ impl<'db> Translator<'db> { UNKNOWN_LOCATION, ), Some((start, end)) => self.trap.emit_location(self.label, label, start, end), - }; + } } pub fn emit_location_token( &mut self, @@ -242,7 +242,7 @@ impl<'db> Translator<'db> { { let token_range = clipped_range + parent_range2.start() - parent_range.start(); if let Some((start, end)) = self.location(token_range) { - self.trap.emit_location(self.label, label, start, end) + self.trap.emit_location(self.label, label, start, end); } } } @@ -390,7 +390,7 @@ impl<'db> Translator<'db> { .text_range() .start(); self.emit_parse_error(node, &SyntaxError::new(error.message, location)); - }; + } } for err in value.value.iter() { self.emit_parse_error(node, err); @@ -596,14 +596,14 @@ impl<'db> Translator<'db> { .and_then(ast::Type::cast) .and_then(|t| self.emit_type(&t)) { - generated::PathSegment::emit_type_repr(label, t, &mut self.trap.writer) + generated::PathSegment::emit_type_repr(label, t, &mut self.trap.writer); } if let Some(t) = type_refs .next() .and_then(ast::PathType::cast) .and_then(|t| self.emit_path_type(&t)) { - generated::PathSegment::emit_trait_type_repr(label, t, &mut self.trap.writer) + generated::PathSegment::emit_trait_type_repr(label, t, &mut self.trap.writer); } // moreover as we're skipping emission of TypeAnchor, we need to attach its comments to // this path segment diff --git a/rust/extractor/src/util.rs b/rust/extractor/src/util.rs index a12ca6de74a1..5bfa5e3fc8b3 100644 --- a/rust/extractor/src/util.rs +++ b/rust/extractor/src/util.rs @@ -2,8 +2,8 @@ use std::cmp::Ordering; /// Compares options using a custom comparator, with `None` ordered before `Some`. pub(crate) fn cmp_option_by( - left: &Option, - right: &Option, + left: Option<&T>, + right: Option<&T>, compare: impl FnOnce(&T, &T) -> Ordering, ) -> Ordering { match (left, right) { diff --git a/shared/tree-sitter-extractor/Cargo.toml b/shared/tree-sitter-extractor/Cargo.toml index f9702d0ff1de..11ecf7a0e9e9 100644 --- a/shared/tree-sitter-extractor/Cargo.toml +++ b/shared/tree-sitter-extractor/Cargo.toml @@ -17,7 +17,6 @@ tracing-subscriber = { version = "0.3.23", features = ["env-filter"] } rayon = "1.12.0" regex = "1.13.1" encoding = "0.2" -lazy_static = "1.5.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = { version = "0.4.45", features = ["serde"] } diff --git a/shared/tree-sitter-extractor/src/diagnostics.rs b/shared/tree-sitter-extractor/src/diagnostics.rs index 412647ee07a5..325b199d9388 100644 --- a/shared/tree-sitter-extractor/src/diagnostics.rs +++ b/shared/tree-sitter-extractor/src/diagnostics.rs @@ -95,7 +95,7 @@ impl LogWriter { source: Source { id: format!("{}/{}", self.extractor, id), name: name.to_owned(), - extractor_name: Some(self.extractor.to_owned()), + extractor_name: Some(self.extractor.clone()), }, markdown_message: String::new(), plaintext_message: String::new(), @@ -134,7 +134,7 @@ impl LogWriter { e ); self.path = None; - self.inner = None + self.inner = None; } Ok(file) => self.inner = Some(std::io::BufWriter::new(file)), } @@ -189,7 +189,7 @@ impl DiagnosticLoggers { }; } THREAD_NUM.with(|n| LogWriter { - extractor: self.extractor.to_owned(), + extractor: self.extractor.clone(), inner: None, path: self .root @@ -235,12 +235,12 @@ impl DiagnosticMessage { start_line: Some(line), .. }) => format!("{}:{}: {}", path, line, self.plaintext_message), - _ => self.plaintext_message.to_owned(), + _ => self.plaintext_message.clone(), } } fn text(&mut self, text: &str) -> &mut Self { - self.plaintext_message = text.to_owned(); + text.clone_into(&mut self.plaintext_message); self } @@ -285,7 +285,7 @@ impl DiagnosticMessage { } pub fn markdown(&mut self, text: &str) -> &mut Self { - self.markdown_message = text.to_owned(); + text.clone_into(&mut self.markdown_message); self } pub fn severity(&mut self, severity: Severity) -> &mut Self { @@ -317,7 +317,7 @@ impl DiagnosticMessage { self } pub fn file(&mut self, path: &str) -> &mut Self { - let loc = self.location.get_or_insert(Default::default()); + let loc = self.location.get_or_insert(Location::default()); loc.file = Some(path.to_owned()); self } @@ -329,7 +329,7 @@ impl DiagnosticMessage { end_line: usize, end_column: usize, ) -> &mut Self { - let loc = self.location.get_or_insert(Default::default()); + let loc = self.location.get_or_insert(Location::default()); loc.file = Some(path.to_owned()); loc.start_line = Some(start_line); loc.start_column = Some(start_column); diff --git a/shared/tree-sitter-extractor/src/extractor/driver.rs b/shared/tree-sitter-extractor/src/extractor/driver.rs index 6e6172b7425b..8a6ee33accc9 100644 --- a/shared/tree-sitter-extractor/src/extractor/driver.rs +++ b/shared/tree-sitter-extractor/src/extractor/driver.rs @@ -45,6 +45,7 @@ pub(crate) trait LanguageExtractor: Sync { /// Sets up the thread pool, builds a combined glob set, and for each input file /// dispatches to the matching language's [`LanguageExtractor::extract_file`], /// writing the resulting TRAP and a source-archive copy. +#[allow(clippy::too_many_lines)] pub(crate) fn run_extractor( prefix: &str, languages: &[L], @@ -103,7 +104,7 @@ pub(crate) fn run_extractor( .iter() .map(|file_list| { File::open(file_list) - .unwrap_or_else(|_| panic!("Unable to open file list at {file_list:?}")) + .unwrap_or_else(|_| panic!("Unable to open file list at {}", file_list.display())) }) .collect(); diff --git a/shared/tree-sitter-extractor/src/extractor/mod.rs b/shared/tree-sitter-extractor/src/extractor/mod.rs index 1bd8677b7414..83c06e8b572b 100644 --- a/shared/tree-sitter-extractor/src/extractor/mod.rs +++ b/shared/tree-sitter-extractor/src/extractor/mod.rs @@ -39,7 +39,7 @@ trait AstNode { } } -impl<'a> AstNode for Node<'a> { +impl AstNode for Node<'_> { fn kind(&self) -> &str { Node::kind(self) } @@ -135,17 +135,17 @@ pub fn default_subscriber_with_level( .with_filter( tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else( |_| -> tracing_subscriber::EnvFilter { - let verbosity = verbosity - .as_ref() - .map(|v| match v.to_lowercase().as_str() { - "off" | "errors" => "error", - "warnings" => "warn", - "info" | "progress" => "info", - "debug" | "progress+" => "debug", - "trace" | "progress++" | "progress+++" => "trace", - _ => "warn", - }) - .unwrap_or_else(|| "warn"); + let verbosity = + verbosity + .as_ref() + .map_or("warn", |v| match v.to_lowercase().as_str() { + "off" | "errors" => "error", + "info" | "progress" => "info", + "debug" | "progress+" => "debug", + "trace" | "progress++" | "progress+++" => "trace", + // "warnings" or any other string + _ => "warn", + }); tracing_subscriber::EnvFilter::new(format!( "{language}_extractor={verbosity},codeql_extractor={verbosity}" )) @@ -184,7 +184,7 @@ fn populate_empty_file(writer: &mut trap::Writer) -> trap::Label { "files", vec![ trap::Arg::Label(file_label), - trap::Arg::String("".to_string()), + trap::Arg::String(String::new()), ], ); } @@ -478,7 +478,7 @@ struct ExtraNode { } impl AstNode for ExtraNode { - fn kind(&self) -> &str { + fn kind(&self) -> &'static str { "extra" } fn is_named(&self) -> bool { @@ -528,9 +528,9 @@ struct Visitor<'a> { file_label: trap::Label, /// The source code as a UTF-8 byte array source: &'a [u8], - /// A diagnostics::LogWriter to write diagnostic messages + /// A `diagnostics::LogWriter` to write diagnostic messages diagnostics_writer: &'a mut diagnostics::LogWriter, - /// A trap::Writer to accumulate trap entries + /// A `trap::Writer` to accumulate trap entries trap_writer: &'a mut trap::Writer, /// Language-specific name of the AST location table ast_node_location_table_name: String, @@ -547,7 +547,7 @@ struct Visitor<'a> { /// All children append their data to the list. When the visitor leaves a /// node the list containing the child data is popped from the stack and /// matched against the dbscheme for the node. If the expectations are met - /// the corresponding row definitions are added to the trap_output. + /// the corresponding row definitions are added to the `trap_output`. stack: Vec<(trap::Label, usize, Vec)>, } @@ -623,7 +623,7 @@ impl<'a> Visitor<'a> { trap::Arg::Label(id), trap::Arg::Int(severity_code), trap::Arg::String("parse_error".to_string()), - trap::Arg::String(mesg.plaintext_message.to_owned()), + trap::Arg::String(mesg.plaintext_message.clone()), trap::Arg::String(full_error_message), trap::Arg::Label(loc), ], @@ -676,7 +676,7 @@ impl<'a> Visitor<'a> { true, ); return false; - }; + } let id = self.trap_writer.fresh_id(); @@ -684,6 +684,7 @@ impl<'a> Visitor<'a> { true } + #[allow(clippy::too_many_lines)] fn leave_node(&mut self, field_name: Option<&'static str>, node: &N) { if node.is_error() || node.is_missing() { return; @@ -722,7 +723,7 @@ impl<'a> Visitor<'a> { trap::Arg::Int(parent_index), ], ); - }; + } self.trap_writer.add_tuple( &self.tokeninfo_table_name, vec![ @@ -750,13 +751,13 @@ impl<'a> Visitor<'a> { trap::Arg::Int(parent_index), ], ); - }; + } let mut all_args = vec![trap::Arg::Label(id)]; all_args.extend(args); self.trap_writer.add_tuple(table_name, all_args); } } - _ => { + EntryKind::Union { .. } => { self.record_parse_error( loc_label, self.diagnostics_writer @@ -793,7 +794,7 @@ impl<'a> Visitor<'a> { named: node.is_named(), }, }); - }; + } } } @@ -891,7 +892,7 @@ impl<'a> Visitor<'a> { } let mut args = vec![trap::Arg::Label(parent_id)]; if *has_index { - args.push(trap::Arg::Int(index)) + args.push(trap::Arg::Int(index)); } args.push(child_value.clone()); self.trap_writer.add_tuple(table_name, args); diff --git a/shared/tree-sitter-extractor/src/file_paths.rs b/shared/tree-sitter-extractor/src/file_paths.rs index 821a4b2309dd..c87a7f4ffba8 100644 --- a/shared/tree-sitter-extractor/src/file_paths.rs +++ b/shared/tree-sitter-extractor/src/file_paths.rs @@ -11,8 +11,7 @@ pub fn relativize_for_diagnostic(path: &Path, source_root: Option<&Path>) -> Str source_root .and_then(|root| path.strip_prefix(root).ok()) .and_then(|rel| rel.to_str()) - .map(|s| s.replace('\\', "/")) - .unwrap_or_else(|| path.display().to_string()) + .map_or_else(|| path.display().to_string(), |s| s.replace('\\', "/")) } /// This represents the minimum supported path transformation that is needed to support extracting @@ -115,11 +114,10 @@ fn normalize_path(path: &Path) -> String { if path_components.peek().is_none() { // The path points at a root directory, so we need to add a // trailing slash, e.g. `C:/` instead of `C:`. - components.push("".to_string()); + components.push(String::new()); } } - std::path::Component::CurDir => {} - std::path::Component::ParentDir => {} + std::path::Component::CurDir | std::path::Component::ParentDir => {} } } components.join("/") @@ -135,8 +133,8 @@ pub fn path_from_string(path: &str) -> PathBuf { let mut path = PathBuf::from(path); // make path absolute if path.is_relative() { - path = std::env::current_dir().unwrap().join(path) - }; + path = std::env::current_dir().unwrap().join(path); + } let mut components = path.components(); // make Windows paths verbatim (with `\\?\` prefixes) which allow for extended-length paths. @@ -167,7 +165,7 @@ pub fn path_from_string(path: &str) -> PathBuf { // remove `.` and `..` components for component in components { match component { - std::path::Component::CurDir => continue, + std::path::Component::CurDir => {} std::path::Component::ParentDir => { result.pop(); } @@ -194,7 +192,7 @@ pub fn path_for( match component { std::path::Component::Prefix(prefix) => match prefix.kind() { std::path::Prefix::Disk(letter) | std::path::Prefix::VerbatimDisk(letter) => { - result.push(format!("{}_", letter as char)) + result.push(format!("{}_", letter as char)); } std::path::Prefix::Verbatim(x) | std::path::Prefix::DeviceNS(x) => { result.push(x); @@ -206,15 +204,12 @@ pub fn path_for( result.push(share); } }, - std::path::Component::RootDir => { + std::path::Component::RootDir | std::path::Component::CurDir => { // skip } std::path::Component::Normal(_) => { result.push(component); } - std::path::Component::CurDir => { - // skip - } std::path::Component::ParentDir => { result.pop(); } diff --git a/shared/tree-sitter-extractor/src/generator/mod.rs b/shared/tree-sitter-extractor/src/generator/mod.rs index 81bf0955cd6e..732f12ca6ee6 100644 --- a/shared/tree-sitter-extractor/src/generator/mod.rs +++ b/shared/tree-sitter-extractor/src/generator/mod.rs @@ -14,6 +14,7 @@ pub mod ql; pub mod ql_gen; /// Generate a dbscheme and QL library for the given languages. +#[allow(clippy::too_many_lines)] pub fn generate( languages: Vec, dbscheme_path: PathBuf, @@ -65,14 +66,14 @@ pub fn generate( for language in languages { let prefix = node_types::to_snake_case(&language.name); - let ast_node_name = format!("{}_ast_node", prefix); - let node_location_table_name = format!("{}_ast_node_location", prefix); - let node_parent_table_name = format!("{}_ast_node_parent", prefix); - let token_name = format!("{}_token", prefix); - let tokeninfo_name = format!("{}_tokeninfo", prefix); - let trivia_token_name = format!("{}_trivia_token", prefix); - let trivia_tokeninfo_name = format!("{}_trivia_tokeninfo", prefix); - let reserved_word_name = format!("{}_reserved_word", prefix); + let ast_node_name = format!("{prefix}_ast_node"); + let node_location_table_name = format!("{prefix}_ast_node_location"); + let node_parent_table_name = format!("{prefix}_ast_node_parent"); + let token_name = format!("{prefix}_token"); + let tokeninfo_name = format!("{prefix}_tokeninfo"); + let trivia_token_name = format!("{prefix}_trivia_token"); + let trivia_tokeninfo_name = format!("{prefix}_trivia_tokeninfo"); + let reserved_word_name = format!("{prefix}_reserved_word"); // When a desugaring is configured, comments and other `extra` nodes are // preserved from the original parse tree as `TriviaToken`s. let has_trivia_tokens = language.desugar.is_some(); @@ -97,7 +98,7 @@ pub fn generate( } writeln!(&mut dbscheme_writer, "/*- {} dbscheme -*/", language.name)?; dbscheme::write(&mut dbscheme_writer, &dbscheme_entries)?; - let token_case = create_token_case(&token_name, token_kinds); + let token_case = create_token_case(&token_name, &token_kinds); let mut dbscheme_tail = vec![ dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)), dbscheme::Entry::Case(token_case), @@ -295,8 +296,8 @@ fn make_field_type<'a>( let case = dbscheme::Entry::Case(dbscheme::Case { name: parent_name, column: match &field.storage { - node_types::Storage::Column { name } => name, - node_types::Storage::Table { name, .. } => name, + node_types::Storage::Column { name } + | node_types::Storage::Table { name, .. } => name, }, branches, }); @@ -592,7 +593,7 @@ fn create_tokeninfo<'a>(name: &'a str, type_name: &'a str) -> dbscheme::Table<'a } } -fn create_token_case<'a>(name: &'a str, token_kinds: Map<&'a str, usize>) -> dbscheme::Case<'a> { +fn create_token_case<'a>(name: &'a str, token_kinds: &Map<&'a str, usize>) -> dbscheme::Case<'a> { let branches: Vec<(usize, &str)> = token_kinds .iter() .map(|(&name, kind_id)| (*kind_id, name)) diff --git a/shared/tree-sitter-extractor/src/generator/ql.rs b/shared/tree-sitter-extractor/src/generator/ql.rs index c780aec681cd..5c6e12a13a6c 100644 --- a/shared/tree-sitter-extractor/src/generator/ql.rs +++ b/shared/tree-sitter-extractor/src/generator/ql.rs @@ -365,7 +365,7 @@ impl fmt::Display for FormalParameter<'_> { /// Generates a QL library by writing the given `elements` to the `file`. pub fn write(file: &mut dyn std::io::Write, elements: &[TopLevel]) -> std::io::Result<()> { for element in elements { - write!(file, "{}\n\n", element)?; + write!(file, "{element}\n\n")?; } Ok(()) } diff --git a/shared/tree-sitter-extractor/src/generator/ql_gen.rs b/shared/tree-sitter-extractor/src/generator/ql_gen.rs index bd05de8316d8..ecf390c8d571 100644 --- a/shared/tree-sitter-extractor/src/generator/ql_gen.rs +++ b/shared/tree-sitter-extractor/src/generator/ql_gen.rs @@ -4,6 +4,7 @@ use crate::{generator::ql, node_types}; /// Creates the hard-coded `AstNode` class that acts as a supertype of all /// classes we generate. +#[allow(clippy::too_many_lines)] pub fn create_ast_node_class<'a>( ast_node: &'a str, node_location_table: &'a str, @@ -622,6 +623,7 @@ fn create_get_field_expr_for_table_storage<'a>( /// `parent_name` - the name of the parent node /// `field` - the field whose getters we are creating /// `field_type` - the db name of the field's type (possibly being a union we created) +#[allow(clippy::too_many_lines)] fn create_field_getters<'a>( main_table_name: &'a str, main_table_arity: usize, @@ -636,8 +638,9 @@ fn create_field_getters<'a>( // be bound to? let get_value_result_var_name = match &field.type_info { node_types::FieldTypeInfo::ReservedWordInt(_) => "value", - node_types::FieldTypeInfo::Single(_) => "result", - node_types::FieldTypeInfo::Multiple { .. } => "result", + node_types::FieldTypeInfo::Single(_) | node_types::FieldTypeInfo::Multiple { .. } => { + "result" + } }; // Two expressions for getting the value. One that's suitable use in the @@ -966,6 +969,7 @@ fn is_predicate_inherited( } /// Converts the given node types into CodeQL classes wrapping the dbscheme. +#[allow(clippy::too_many_lines)] pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec> { let mut classes = Vec::new(); let mut token_kinds = BTreeSet::new(); @@ -1037,9 +1041,11 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec> { name: main_table_name, fields, } => { - if fields.is_empty() { - panic!("Encountered node '{}' with no fields", type_name.kind); - } + assert!( + !fields.is_empty(), + "Encountered node '{}' with no fields", + type_name.kind + ); // Count how many columns there will be in the main table. There // will be one for the id, plus one for each field that's stored @@ -1091,7 +1097,7 @@ pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec> { } main_class.predicates.extend(get_preds); if let Some(get_child_expr) = get_child_expr { - get_child_exprs.push(get_child_expr) + get_child_exprs.push(get_child_expr); } } @@ -1217,7 +1223,7 @@ mod tests { #[test] fn indexes_predicate_signatures_exposed_by_classes() { - let yaml = r#" + let yaml = r" supertypes: callable: subtypes: [function_like] @@ -1236,7 +1242,7 @@ named: parameter: block: identifier: -"#; +"; let json = yeast::node_types_yaml::convert(yaml).unwrap(); let nodes = node_types::read_node_types_str("test", &json).unwrap(); let signatures = compute_exposed_predicate_signatures(&nodes); @@ -1267,7 +1273,7 @@ named: #[test] fn generates_supertype_getters_and_concrete_overrides() { - let yaml = r#" + let yaml = r" supertypes: callable: subtypes: [function] @@ -1280,7 +1286,7 @@ named: body?: block parameter: block: -"#; +"; let json = yeast::node_types_yaml::convert(yaml).unwrap(); let nodes = node_types::read_node_types_str("test", &json).unwrap(); let generated = convert_nodes(&nodes) diff --git a/shared/tree-sitter-extractor/src/node_types.rs b/shared/tree-sitter-extractor/src/node_types.rs index 43fc3e11683d..5486555ed169 100644 --- a/shared/tree-sitter-extractor/src/node_types.rs +++ b/shared/tree-sitter-extractor/src/node_types.rs @@ -5,7 +5,7 @@ use std::path::Path; use std::collections::BTreeSet as Set; use std::fs; -/// A lookup table from TypeName to Entry. +/// A lookup table from `TypeName` to `Entry`. pub type NodeTypeMap = BTreeMap; #[derive(Debug)] @@ -60,7 +60,7 @@ pub struct Field { pub parent: TypeName, pub type_info: FieldTypeInfo, /// The name of the field or None for the anonymous 'children' - /// entry from node_types.json + /// entry from `node_types.json` pub name: Option, /// The name of the predicate to get this field. pub getter_name: String, @@ -70,7 +70,7 @@ pub struct Field { pub storage: Storage, } -fn name_for_field_or_child(name: &Option) -> String { +fn name_for_field_or_child(name: Option<&String>) -> String { match name { Some(name) => name.clone(), None => "child".to_owned(), @@ -110,7 +110,7 @@ pub fn read_node_types_str(prefix: &str, node_types_json: &str) -> std::io::Resu fn convert_type(node_type: &NodeType) -> TypeName { TypeName { - kind: node_type.kind.to_string(), + kind: node_type.kind.clone(), named: node_type.named, } } @@ -119,6 +119,7 @@ fn convert_types(node_types: &[NodeType]) -> Set { node_types.iter().map(convert_type).collect() } +#[allow(clippy::too_many_lines)] pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { let mut entries = NodeTypeMap::new(); let mut token_kinds = Set::new(); @@ -138,7 +139,7 @@ pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { let flattened_name = &node_type_name(&node.kind, node.named); let dbscheme_name = escape_name(flattened_name); let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name); - let dbscheme_name = format!("{}_{}", prefix, dbscheme_name); + let dbscheme_name = format!("{prefix}_{dbscheme_name}"); let subtypes = &node.subtypes; if !subtypes.is_empty() { // It's a tree-sitter supertype node, for which we create a union @@ -152,7 +153,7 @@ pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { add_field( prefix, &type_name, - Some(field_name.to_string()), + Some(field_name.clone()), field_info, &mut fields, &token_kinds, @@ -187,8 +188,8 @@ pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { kind: node.kind.clone(), named: node.named, }; - let table_name = escape_name(&(format!("{}_def", flattened_name))); - let table_name = format!("{}_{}", prefix, table_name); + let table_name = escape_name(&(format!("{flattened_name}_def"))); + let table_name = format!("{prefix}_{table_name}"); let mut fields = Vec::new(); @@ -198,7 +199,7 @@ pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { add_field( prefix, &type_name, - Some(field_name.to_string()), + Some(field_name.clone()), field_info, &mut fields, &token_kinds, @@ -234,13 +235,13 @@ pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { counter += 1; let unprefixed_name = node_type_name(&type_name.kind, true); Entry { - dbscheme_name: escape_name(&format!("{}_token_{}", prefix, unprefixed_name)), + dbscheme_name: escape_name(&format!("{prefix}_token_{unprefixed_name}")), ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)), kind: EntryKind::Token { kind_id: counter }, } } else { Entry { - dbscheme_name: format!("{}_reserved_word", prefix), + dbscheme_name: format!("{prefix}_reserved_word"), ql_class_name: "ReservedWord".to_owned(), kind: EntryKind::Token { kind_id: 0 }, } @@ -259,7 +260,7 @@ fn add_field( token_kinds: &Set, ) { let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named); - let column_name = escape_name(&name_for_field_or_child(&field_name)); + let column_name = escape_name(&name_for_field_or_child(field_name.as_ref())); let storage = if !field_info.multiple && field_info.required { // This field must appear exactly once, so we add it as // a column to the main table for the node type. @@ -271,7 +272,7 @@ fn add_field( "{}_{}_{}", prefix, parent_flattened_name, - name_for_field_or_child(&field_name) + name_for_field_or_child(field_name.as_ref()) )); Storage::Table { has_index, @@ -293,7 +294,7 @@ fn add_field( for (counter, t) in converted_types.into_iter().enumerate() { let dbscheme_variant_name = escape_name(&format!("{}_{}_{}", prefix, parent_flattened_name, t.kind)); - field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name)); + field_token_ints.insert(t.kind, (counter, dbscheme_variant_name)); } FieldTypeInfo::ReservedWordInt(field_token_ints) } else if field_info.types.len() == 1 { @@ -306,14 +307,14 @@ fn add_field( "{}_{}_{}_type", prefix, parent_flattened_name, - name_for_field_or_child(&field_name) + name_for_field_or_child(field_name.as_ref()) ), ql_class: "AstNode".to_owned(), } }; let getter_name = format!( "get{}", - dbscheme_name_to_class_name(&escape_name(&name_for_field_or_child(&field_name))) + dbscheme_name_to_class_name(&escape_name(&name_for_field_or_child(field_name.as_ref()))) ); let getter_suffix = getter_name.strip_prefix("get").unwrap_or(&getter_name); let article = match getter_suffix.chars().next().map(|c| c.to_ascii_lowercase()) { @@ -327,7 +328,7 @@ fn add_field( }; fields.push(Field { parent: TypeName { - kind: parent_type_name.kind.to_string(), + kind: parent_type_name.kind.clone(), named: parent_type_name.named, }, type_info, @@ -424,7 +425,7 @@ fn escape_name(name: &str) -> String { '@' => result.push_str("at"), _ if c.is_uppercase() => { result.push('_'); - result.push_str(&c.to_lowercase().to_string()) + result.push_str(&c.to_lowercase().to_string()); } _ => result.push(c), } @@ -446,7 +447,7 @@ pub fn to_snake_case(word: &str) -> String { for c in word.chars() { if c.is_uppercase() { if !prev_upper { - result.push('_') + result.push('_'); } prev_upper = true; result.push(c.to_ascii_lowercase()); @@ -457,8 +458,8 @@ pub fn to_snake_case(word: &str) -> String { } result } -/// Given a valid dbscheme name (i.e. in snake case), produces the equivalent QL -/// name (i.e. in CamelCase). For example, "foo_bar_baz" becomes "FooBarBaz". +/// Given a valid dbscheme name (i.e. in `snake case`), produces the equivalent QL +/// name (i.e. in `CamelCase`). For example, `foo_bar_baz` becomes `FooBarBaz`. fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String { fn to_title_case(word: &str) -> String { let mut first = true; @@ -476,8 +477,7 @@ fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String { dbscheme_name .split('_') .map(to_title_case) - .collect::>() - .join("") + .collect::() } #[test] @@ -495,7 +495,7 @@ fn to_snake_case_test() { #[test] fn supertype_fields_are_preserved() { - let yaml = r#" + let yaml = r" supertypes: callable: subtypes: [function] @@ -506,7 +506,7 @@ named: function: parameter: block: -"#; +"; let json = yeast::node_types_yaml::convert(yaml).unwrap(); let nodes = read_node_types_str("test", &json).unwrap(); let callable = nodes diff --git a/shared/tree-sitter-extractor/src/options.rs b/shared/tree-sitter-extractor/src/options.rs index 4be253104f19..52555bb2eac1 100644 --- a/shared/tree-sitter-extractor/src/options.rs +++ b/shared/tree-sitter-extractor/src/options.rs @@ -1,12 +1,12 @@ use num_cpus; /// Gets the number of threads the extractor should use. -/// This is controlled by the CODEQL_THREADS environment variable. +/// This is controlled by the `CODEQL_THREADS` environment variable. pub fn num_threads() -> Result { let threads_str = std::env::var("CODEQL_THREADS").unwrap_or_else(|_| "-1".into()); let num_cpus = num_cpus::get(); parse_codeql_threads(&threads_str, num_cpus) - .ok_or_else(|| format!("Unable to parse CODEQL_THREADS value '{}'", threads_str)) + .ok_or_else(|| format!("Unable to parse CODEQL_THREADS value '{threads_str}'")) } /// Parses the given string to determine the number of threads the extractor diff --git a/shared/tree-sitter-extractor/src/trap.rs b/shared/tree-sitter-extractor/src/trap.rs index 492349c6d4ab..80ace03fbc7c 100644 --- a/shared/tree-sitter-extractor/src/trap.rs +++ b/shared/tree-sitter-extractor/src/trap.rs @@ -55,7 +55,7 @@ impl Writer { /// Note: You probably want to make sure that the key strings that you use are disjoint /// for disjoint column types; the standard way of doing this is to prefix (or append) /// the column type name to the ID. Thus, you might identify methods in Java by the - /// full ID "methods_com.method.package.DeclaringClass.method(argumentList)". + /// full ID `methods_com.method.package.DeclaringClass.method(argumentList)`. pub fn global_id(&mut self, key: &str) -> (Label, bool) { if let Some(label) = self.global_keys.get(key) { return (*label, false); @@ -81,7 +81,7 @@ impl Writer { pub fn add_tuple(&mut self, table_name: &str, args: Vec) { self.trap_output - .push(Entry::GenericTuple(table_name.to_owned(), args)) + .push(Entry::GenericTuple(table_name.to_owned(), args)); } pub fn comment(&mut self, text: String) { @@ -123,7 +123,7 @@ pub enum Entry { FreshId(Label), /// Maps the label to a key, e.g. `#7=@"foo"`. MapLabelToKey(Label, String), - /// foo_bar(arg*) + /// `foo_bar(arg*)` GenericTuple(String, Vec), Comment(String), } @@ -174,7 +174,7 @@ pub enum Arg { String(String), } -const MAX_STRLEN: usize = 1048576; +const MAX_STRLEN: usize = 1_048_576; impl fmt::Display for Arg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -218,11 +218,10 @@ pub struct Program(Vec); impl fmt::Display for Program { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut text = String::new(); for trap_entry in &self.0 { - text.push_str(&format!("{trap_entry}\n")); + writeln!(f, "{trap_entry}")?; } - write!(f, "{text}") + Ok(()) } } @@ -277,7 +276,7 @@ fn limit_string(string: &str, max_size: usize) -> &str { // encoded data any byte that matches the bit pattern 10XXXXXX is not a start byte. // Therefore we decrement the index as long as there are bytes matching this pattern. // This ensures we cut the string at the border between one character and another. - while index > 0 && (p[index] & 0b11000000) == 0b10000000 { + while index > 0 && (p[index] & 0b1100_0000) == 0b1000_0000 { index -= 1; } &string[0..index] @@ -298,7 +297,7 @@ impl Compression { match std::env::var(var_name) { Ok(method) => match Compression::from_string(&method) { Some(c) => Ok(c), - None => Err(format!("Unknown compression method '{}'", method)), + None => Err(format!("Unknown compression method '{method}'")), }, // Default compression method if the env var isn't set: Err(_) => Ok(Compression::Gzip), diff --git a/shared/tree-sitter-extractor/tests/common/mod.rs b/shared/tree-sitter-extractor/tests/common/mod.rs index 9871ae401c05..f5ffc099ce1e 100644 --- a/shared/tree-sitter-extractor/tests/common/mod.rs +++ b/shared/tree-sitter-extractor/tests/common/mod.rs @@ -9,7 +9,7 @@ use flate2::read::GzDecoder; pub struct SourceArchive { pub root_dir: PathBuf, pub file_list: PathBuf, - pub source_archive_dir: PathBuf, + pub archive_dir: PathBuf, pub trap_dir: PathBuf, } @@ -21,11 +21,11 @@ pub fn create_source_dir(files: Vec<(&'static str, &'static str)>) -> SourceArch .expect("failed to canonicalize root directory"); let trap_dir = create_dir(&root_dir, "trap"); - let source_archive_dir = create_dir(&root_dir, "src"); + let archive_dir = create_dir(&root_dir, "src"); let mut file_paths = vec![]; for (filename, contents) in files { - let path = source_archive_dir.join(filename); + let path = archive_dir.join(filename); let mut file = File::create(&path).unwrap(); file.write_all(contents.as_bytes()).unwrap(); file_paths.push(path); @@ -45,7 +45,7 @@ pub fn create_source_dir(files: Vec<(&'static str, &'static str)>) -> SourceArch SourceArchive { root_dir, file_list, - source_archive_dir, + archive_dir, trap_dir, } } diff --git a/shared/tree-sitter-extractor/tests/integration_test.rs b/shared/tree-sitter-extractor/tests/integration_test.rs index 2b243ff7945b..474923d4732b 100644 --- a/shared/tree-sitter-extractor/tests/integration_test.rs +++ b/shared/tree-sitter-extractor/tests/integration_test.rs @@ -19,7 +19,7 @@ fn simple_extractor() { let SourceArchive { root_dir, file_list, - source_archive_dir, + archive_dir, trap_dir, } = create_source_dir(vec![("foo.qll", "predicate p(int a) { a = 1 }")]); @@ -27,7 +27,7 @@ fn simple_extractor() { prefix: "ql".to_string(), languages: vec![language], trap_dir, - source_archive_dir, + source_archive_dir: archive_dir, file_lists: vec![file_list], trap_compression: Ok(trap::Compression::Gzip), }; diff --git a/shared/tree-sitter-extractor/tests/multiple_languages.rs b/shared/tree-sitter-extractor/tests/multiple_languages.rs index 2e45e56754a3..7c285a987d28 100644 --- a/shared/tree-sitter-extractor/tests/multiple_languages.rs +++ b/shared/tree-sitter-extractor/tests/multiple_languages.rs @@ -25,7 +25,7 @@ fn multiple_language_extractor() { let SourceArchive { root_dir, file_list, - source_archive_dir, + archive_dir, trap_dir, } = create_source_dir(vec![ ("foo.qll", "predicate p(int a) { a = 1 }"), @@ -37,7 +37,7 @@ fn multiple_language_extractor() { prefix: "ql".to_string(), languages: vec![lang_ql, lang_json], trap_dir, - source_archive_dir, + source_archive_dir: archive_dir, file_lists: vec![file_list], trap_compression: Ok(trap::Compression::Gzip), }; diff --git a/shared/yeast-macros/src/ast.rs b/shared/yeast-macros/src/ast.rs index f534fe4d83a7..0f341fcef29d 100644 --- a/shared/yeast-macros/src/ast.rs +++ b/shared/yeast-macros/src/ast.rs @@ -209,12 +209,12 @@ mod tests { fn output_leaf_kinds() -> BTreeSet { yeast_schema::node_types_yaml::leaf_kinds_from_yaml( - r#" + r" named: assignment: left: identifier identifier: -"#, +", ) .unwrap() } diff --git a/shared/yeast-macros/src/lower.rs b/shared/yeast-macros/src/lower.rs index 6cf8767e2f1b..e971e09ff68e 100644 --- a/shared/yeast-macros/src/lower.rs +++ b/shared/yeast-macros/src/lower.rs @@ -58,15 +58,15 @@ impl Rule { let captures_ident = Ident::new("__captures", Span::call_site()); let translated_captures_ident = Ident::new("__translated_captures", Span::call_site()); let guard_bindings = - capture_bindings(captures.iter(), quote! { yeast::Id }, &captures_ident); + capture_bindings(captures.iter(), "e! { yeast::Id }, &captures_ident); let raw_bindings = capture_bindings( raw_captures.into_iter(), - quote! { yeast::Id }, + "e! { yeast::Id }, &captures_ident, ); let translated_bindings = capture_bindings( translated_captures.into_iter(), - quote! { yeast::OutputId }, + "e! { yeast::OutputId }, &translated_captures_ident, ); let replacement = self.replacement.lower(); @@ -278,7 +278,7 @@ fn combine_cardinality(parent: Cardinality, child: Cardinality) -> Cardinality { fn capture_bindings<'a>( captures: impl Iterator, - id_type: TokenStream, + id_type: &TokenStream, captures_ident: &Ident, ) -> Vec { captures @@ -367,14 +367,14 @@ impl Template { fn lower_choice(alternatives: &[Alternative]) -> TokenStream { let pick = alternatives.iter().rev().fold( quote! { ::std::option::Option::None }, - |fallback, alternative| alternative.lower_candidate(fallback), + |fallback, alternative| alternative.lower_candidate(&fallback), ); quote! {{ #pick }} } } impl Alternative { - fn lower_candidate(&self, fallback: TokenStream) -> TokenStream { + fn lower_candidate(&self, fallback: &TokenStream) -> TokenStream { let interpolations = RefCell::new(Vec::new()); let context = LoweringContext { choice_alternative_scope: Some(ChoiceAlternativeScope { @@ -445,6 +445,7 @@ impl Alternative { } impl Node { + #[allow(clippy::too_many_lines)] fn lower(&self, context: LoweringContext<'_>) -> TokenStream { let ctx = Ident::new("ctx", Span::call_site()); let kind_str = self.kind.to_string(); diff --git a/shared/yeast-macros/src/template_parse.rs b/shared/yeast-macros/src/template_parse.rs index cce42fd0ab19..4b6b2aa8bd7d 100644 --- a/shared/yeast-macros/src/template_parse.rs +++ b/shared/yeast-macros/src/template_parse.rs @@ -38,11 +38,11 @@ fn parse_one(tokens: &mut Tokens) -> Result