From f5ba1624e01248b12d8d8cd5d9247ae174a8318f Mon Sep 17 00:00:00 2001 From: "Arend van Beelen jr." Date: Thu, 5 Dec 2024 10:18:43 +0100 Subject: [PATCH] refactor: add `Workspace` scanner (#4682) --- Cargo.lock | 6 +- Cargo.toml | 2 +- biome.json | 2 +- crates/biome_cli/src/commands/mod.rs | 13 +- crates/biome_cli/src/execute/migrate.rs | 6 +- crates/biome_cli/src/execute/mod.rs | 15 +- .../execute/process_file/workspace_file.rs | 4 +- crates/biome_cli/src/execute/std_in.rs | 8 +- crates/biome_cli/src/execute/traverse.rs | 20 +- crates/biome_cli/tests/snap_test.rs | 5 +- .../max_diagnostics_verbose.snap | 5 +- .../main_commands_check/print_verbose.snap | 4 + .../print_verbose_write.snap | 4 + .../unsupported_file_verbose.snap | 4 + .../main_commands_ci/print_verbose.snap | 4 + .../main_commands_lint/print_verbose.snap | 4 + .../unsupported_file_verbose.snap | 4 + crates/biome_fs/src/interner.rs | 3 +- .../biome_lsp/src/handlers/text_document.rs | 5 +- crates/biome_lsp/src/server.rs | 1 + crates/biome_service/Cargo.toml | 2 + crates/biome_service/src/diagnostics.rs | 57 +++++ crates/biome_service/src/file_handlers/mod.rs | 13 +- crates/biome_service/src/lib.rs | 22 +- crates/biome_service/src/scanner.rs | 214 ++++++++++++++++++ crates/biome_service/src/workspace.rs | 68 +++++- crates/biome_service/src/workspace/client.rs | 12 +- crates/biome_service/src/workspace/server.rs | 52 ++++- crates/biome_service/tests/workspace.rs | 42 ++-- .../@biomejs/backend-jsonrpc/src/workspace.ts | 5 +- .../backend-jsonrpc/tests/workspace.test.mjs | 2 +- packages/@biomejs/js-api/src/index.ts | 2 +- 32 files changed, 508 insertions(+), 102 deletions(-) create mode 100644 crates/biome_service/src/scanner.rs diff --git a/Cargo.lock b/Cargo.lock index 160f873dca6a..afb14f2fffee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1181,6 +1181,7 @@ dependencies = [ "biome_string_case", "biome_text_edit", "bpaf", + "crossbeam", "enumflags2", "getrandom 0.2.15", "ignore", @@ -1188,6 +1189,7 @@ dependencies = [ "insta", "oxc_resolver", "papaya", + "rayon", "regex", "rustc-hash 2.0.0", "schemars", @@ -2809,9 +2811,9 @@ dependencies = [ [[package]] name = "papaya" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71addb3836918693eecf8aa0f1c578798246b12c4d1171a079c53433fad72706" +checksum = "d5f8bc4fcfb351caef53d5b5d449a9e44ae910b78f58187d9a19ece1dbeaa045" dependencies = [ "seize", ] diff --git a/Cargo.toml b/Cargo.toml index 28b13301b47e..820c082a31e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -188,7 +188,7 @@ indexmap = { version = "2.6.0" } insta = "1.41.1" natord = "1.0.9" oxc_resolver = "1.12.0" -papaya = "0.1.5" +papaya = "0.1.6" proc-macro2 = "1.0.86" quickcheck = "1.0.3" quickcheck_macros = "1.0.0" diff --git a/biome.json b/biome.json index f2311cb3aca5..db4022722192 100644 --- a/biome.json +++ b/biome.json @@ -1,6 +1,6 @@ { "$schema": "./packages/@biomejs/biome/configuration_schema.json", - "assists": { + "assist": { "enabled": true, "ignore": [ "./packages/@biomejs/biome/configuration_schema.json" diff --git a/crates/biome_cli/src/commands/mod.rs b/crates/biome_cli/src/commands/mod.rs index e12680d837ad..d63b442ca45c 100644 --- a/crates/biome_cli/src/commands/mod.rs +++ b/crates/biome_cli/src/commands/mod.rs @@ -1,6 +1,6 @@ use crate::changed::{get_changed_files, get_staged_files}; use crate::cli_options::{cli_options, CliOptions, CliReporter, ColorsArg}; -use crate::execute::Stdin; +use crate::execute::{ReportMode, Stdin}; use crate::logging::LoggingKind; use crate::{ execute_mode, setup_cli_subscriber, CliDiagnostic, CliSession, Execution, LoggingLevel, VERSION, @@ -822,6 +822,17 @@ pub(crate) trait CommandRunner: Sized { })?; let execution = self.get_execution(cli_options, console, workspace)?; + + if execution.traversal_mode().should_scan_project() { + let result = workspace.scan_current_project_folder(())?; + if cli_options.verbose && matches!(execution.report_mode(), ReportMode::Terminal { .. }) + { + console.log(markup! { + "Scanned project folder in "{result.duration}"." + }); + } + } + Ok((execution, paths)) } diff --git a/crates/biome_cli/src/execute/migrate.rs b/crates/biome_cli/src/execute/migrate.rs index d3718c5594db..c6fb7ccb50e5 100644 --- a/crates/biome_cli/src/execute/migrate.rs +++ b/crates/biome_cli/src/execute/migrate.rs @@ -14,7 +14,9 @@ use biome_json_parser::{parse_json_with_cache, JsonParserOptions}; use biome_json_syntax::{JsonFileSource, JsonRoot}; use biome_migrate::{migrate_configuration, ControlFlow}; use biome_rowan::{AstNode, NodeCache}; -use biome_service::workspace::{ChangeFileParams, FixAction, FormatFileParams, OpenFileParams}; +use biome_service::workspace::{ + ChangeFileParams, FileContent, FixAction, FormatFileParams, OpenFileParams, +}; use std::borrow::Cow; use std::ffi::OsStr; use std::path::PathBuf; @@ -66,7 +68,7 @@ pub(crate) fn run(migrate_payload: MigratePayload) -> Result<(), CliDiagnostic> let biome_path = BiomePath::new(configuration_file_path.as_path()); workspace.open_file(OpenFileParams { path: biome_path.clone(), - content: biome_config_content.to_string(), + content: FileContent::FromClient(biome_config_content.to_string()), version: 0, document_file_source: Some(JsonFileSource::json().into()), })?; diff --git a/crates/biome_cli/src/execute/mod.rs b/crates/biome_cli/src/execute/mod.rs index 949277d25b9c..e1fef9360e7d 100644 --- a/crates/biome_cli/src/execute/mod.rs +++ b/crates/biome_cli/src/execute/mod.rs @@ -23,7 +23,8 @@ use biome_diagnostics::{category, Category}; use biome_fs::BiomePath; use biome_grit_patterns::GritTargetLanguage; use biome_service::workspace::{ - FeatureName, FeaturesBuilder, FixFileMode, FormatFileParams, OpenFileParams, PatternId, + FeatureName, FeaturesBuilder, FileContent, FixFileMode, FormatFileParams, OpenFileParams, + PatternId, }; use std::ffi::OsString; use std::fmt::{Display, Formatter}; @@ -228,6 +229,16 @@ impl Display for TraversalMode { } } +impl TraversalMode { + pub fn should_scan_project(&self) -> bool { + matches!(self, Self::CI { .. }) + || matches!( + self, + Self::Check { stdin,.. } | Self::Lint { stdin, .. } if stdin.is_none() + ) + } +} + /// Tells to the execution of the traversal how the information should be reported #[derive(Copy, Clone, Debug)] pub enum ReportMode { @@ -529,7 +540,7 @@ pub fn execute_mode( })?; let report_file = BiomePath::new("_report_output.json"); session.app.workspace.open_file(OpenFileParams { - content, + content: FileContent::FromClient(content), path: report_file.clone(), version: 0, document_file_source: None, diff --git a/crates/biome_cli/src/execute/process_file/workspace_file.rs b/crates/biome_cli/src/execute/process_file/workspace_file.rs index 8855bd84e06e..e7f1f4dac555 100644 --- a/crates/biome_cli/src/execute/process_file/workspace_file.rs +++ b/crates/biome_cli/src/execute/process_file/workspace_file.rs @@ -2,7 +2,7 @@ use crate::execute::diagnostics::{ResultExt, ResultIoExt}; use crate::execute::process_file::SharedTraversalOptions; use biome_diagnostics::{category, Error}; use biome_fs::{BiomePath, File, OpenOptions}; -use biome_service::workspace::{FileGuard, OpenFileParams}; +use biome_service::workspace::{FileContent, FileGuard, OpenFileParams}; use biome_service::{Workspace, WorkspaceError}; use std::ffi::OsStr; use std::path::{Path, PathBuf}; @@ -40,7 +40,7 @@ impl<'ctx, 'app> WorkspaceFile<'ctx, 'app> { document_file_source: None, path: biome_path, version: 0, - content: input.clone(), + content: FileContent::FromClient(input.clone()), }, ) .with_file_path_and_code(path.display().to_string(), category!("internalError/fs"))?; diff --git a/crates/biome_cli/src/execute/std_in.rs b/crates/biome_cli/src/execute/std_in.rs index ff718f42415d..54086c30171d 100644 --- a/crates/biome_cli/src/execute/std_in.rs +++ b/crates/biome_cli/src/execute/std_in.rs @@ -9,8 +9,8 @@ use biome_diagnostics::PrintDiagnostic; use biome_fs::BiomePath; use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler}; use biome_service::workspace::{ - ChangeFileParams, DropPatternParams, FeaturesBuilder, FixFileParams, FormatFileParams, - OpenFileParams, OrganizeImportsParams, SupportsFeatureParams, + ChangeFileParams, DropPatternParams, FeaturesBuilder, FileContent, FixFileParams, + FormatFileParams, OpenFileParams, OrganizeImportsParams, SupportsFeatureParams, }; use biome_service::WorkspaceError; use std::borrow::Cow; @@ -48,7 +48,7 @@ pub(crate) fn run<'a>( workspace.open_file(OpenFileParams { path: biome_path.clone(), version: 0, - content: content.into(), + content: FileContent::FromClient(content.into()), document_file_source: None, })?; let printed = workspace.format_file(FormatFileParams { @@ -80,7 +80,7 @@ pub(crate) fn run<'a>( workspace.open_file(OpenFileParams { path: biome_path.clone(), version: 0, - content: content.into(), + content: FileContent::FromClient(content.into()), document_file_source: None, })?; // apply fix file of the linter diff --git a/crates/biome_cli/src/execute/traverse.rs b/crates/biome_cli/src/execute/traverse.rs index 65612bbaee6f..78dcc3bcf796 100644 --- a/crates/biome_cli/src/execute/traverse.rs +++ b/crates/biome_cli/src/execute/traverse.rs @@ -25,10 +25,7 @@ use std::{ ffi::OsString, panic::catch_unwind, path::PathBuf, - sync::{ - atomic::{AtomicUsize, Ordering}, - Once, - }, + sync::atomic::{AtomicUsize, Ordering}, thread, time::{Duration, Instant}, }; @@ -45,8 +42,6 @@ pub(crate) fn traverse( cli_options: &CliOptions, mut inputs: Vec, ) -> Result { - init_thread_pool(); - if inputs.is_empty() { match &execution.traversal_mode { TraversalMode::Check { .. } @@ -155,19 +150,6 @@ pub(crate) fn traverse( }) } -/// This function will setup the global Rayon thread pool the first time it's called -/// -/// This is currently only used to assign friendly debug names to the threads of the pool -fn init_thread_pool() { - static INIT_ONCE: Once = Once::new(); - INIT_ONCE.call_once(|| { - rayon::ThreadPoolBuilder::new() - .thread_name(|index| format!("biome::worker_{index}")) - .build_global() - .expect("failed to initialize the global thread pool"); - }); -} - /// Initiate the filesystem traversal tasks with the provided input paths and /// run it to completion, returning the duration of the process and the evaluated paths fn traverse_inputs( diff --git a/crates/biome_cli/tests/snap_test.rs b/crates/biome_cli/tests/snap_test.rs index bde85c6e8bea..f925b04585ab 100644 --- a/crates/biome_cli/tests/snap_test.rs +++ b/crates/biome_cli/tests/snap_test.rs @@ -150,11 +150,10 @@ fn redact_snapshot(input: &str) -> Option> { let mut output = Cow::Borrowed(input); // There are some logs that print the timing, and we can't snapshot that message - // otherwise at each run we invalid the previous snapshot. + // otherwise at each run we invalidate the previous snapshot. // // This is a workaround, and it might not work for all cases. - let the_match = TIME_REGEX.find(output.as_ref()).map(|f| f.start()..f.end()); - if let Some(found) = the_match { + while let Some(found) = TIME_REGEX.find(&output).map(|f| f.start()..f.end()) { output.to_mut().replace_range(found, "