From 48e99d92ef4fcdaff3a65c41ebfee6ae93773a54 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 24 Apr 2024 15:57:25 +0100 Subject: [PATCH 1/6] refactor: foundations for LSP workspaces support --- Cargo.lock | 11 + Cargo.toml | 289 +++++++++--------- crates/biome_cli/src/commands/check.rs | 11 +- crates/biome_cli/src/commands/ci.rs | 12 +- crates/biome_cli/src/commands/format.rs | 12 +- crates/biome_cli/src/commands/lint.rs | 12 +- crates/biome_cli/src/commands/search.rs | 13 +- crates/biome_css_formatter/tests/language.rs | 4 +- crates/biome_formatter_test/src/lib.rs | 6 +- crates/biome_formatter_test/src/spec.rs | 4 +- crates/biome_fs/Cargo.toml | 36 +-- crates/biome_fs/src/path.rs | 2 +- crates/biome_js_formatter/tests/language.rs | 4 +- crates/biome_json_formatter/tests/language.rs | 4 +- crates/biome_lsp/src/server.rs | 18 +- crates/biome_lsp/src/session.rs | 19 +- crates/biome_service/Cargo.toml | 114 +++---- crates/biome_service/src/configuration.rs | 6 +- crates/biome_service/src/settings.rs | 216 ++++++++++--- crates/biome_service/src/workspace.rs | 52 +++- crates/biome_service/src/workspace/client.rs | 12 +- crates/biome_service/src/workspace/server.rs | 58 ++-- crates/biome_test_utils/src/lib.rs | 4 +- 23 files changed, 595 insertions(+), 324 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46ecb435c5fa..30e01dab321f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -931,6 +931,7 @@ dependencies = [ "schemars", "serde", "serde_json", + "slotmap", "tests_macros", "tracing", ] @@ -2902,6 +2903,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "serde", + "version_check", +] + [[package]] name = "smallvec" version = "1.10.0" diff --git a/Cargo.toml b/Cargo.toml index 43e8f003b226..dff7a0ddf851 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,190 +1,191 @@ [workspace] # Use the newer version of the cargo resolver # https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions -members = ["crates/*", "xtask/bench", "xtask/codegen", "xtask/coverage", "xtask/libs_bench", "xtask/contributors"] +members = ["crates/*", "xtask/bench", "xtask/codegen", "xtask/coverage", "xtask/libs_bench", "xtask/contributors"] resolver = "2" [workspace.lints.rust] absolute_paths_not_starting_with_crate = "warn" -dead_code = "warn" -trivial_numeric_casts = "warn" -unused_import_braces = "warn" -unused_lifetimes = "warn" -unused_macro_rules = "warn" +dead_code = "warn" +trivial_numeric_casts = "warn" +unused_import_braces = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" [workspace.lints.clippy] -cargo_common_metadata = "allow" +cargo_common_metadata = "allow" multiple_crate_versions = "allow" # pedantic -checked_conversions = "warn" -cloned_instead_of_copied = "warn" -copy_iterator = "warn" -dbg_macro = "warn" -doc_link_with_quotes = "warn" -empty_enum = "warn" -expl_impl_clone_on_copy = "warn" -explicit_into_iter_loop = "warn" -filter_map_next = "warn" -flat_map_option = "warn" -fn_params_excessive_bools = "warn" +checked_conversions = "warn" +cloned_instead_of_copied = "warn" +copy_iterator = "warn" +dbg_macro = "warn" +doc_link_with_quotes = "warn" +empty_enum = "warn" +expl_impl_clone_on_copy = "warn" +explicit_into_iter_loop = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +fn_params_excessive_bools = "warn" from_iter_instead_of_collect = "warn" -implicit_clone = "warn" -implicit_hasher = "warn" -index_refutable_slice = "warn" -inefficient_to_string = "warn" -invalid_upcast_comparisons = "warn" -iter_not_returning_iterator = "warn" -large_stack_arrays = "warn" -large_types_passed_by_value = "warn" -macro_use_imports = "warn" -manual_ok_or = "warn" -manual_string_new = "warn" -map_flatten = "warn" -map_unwrap_or = "warn" +implicit_clone = "warn" +implicit_hasher = "warn" +index_refutable_slice = "warn" +inefficient_to_string = "warn" +invalid_upcast_comparisons = "warn" +iter_not_returning_iterator = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +macro_use_imports = "warn" +manual_ok_or = "warn" +manual_string_new = "warn" +map_flatten = "warn" +map_unwrap_or = "warn" mismatching_type_param_order = "warn" -mut_mut = "warn" -naive_bytecount = "warn" -needless_bitwise_bool = "warn" -needless_continue = "warn" -needless_for_each = "warn" +mut_mut = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_continue = "warn" +needless_for_each = "warn" no_effect_underscore_binding = "warn" -ref_binding_to_reference = "warn" -ref_option_ref = "warn" -stable_sort_primitive = "warn" -unnecessary_box_returns = "warn" -unnecessary_join = "warn" -unnested_or_patterns = "warn" -unreadable_literal = "warn" -verbose_bit_mask = "warn" -zero_sized_map_values = "warn" +ref_binding_to_reference = "warn" +ref_option_ref = "warn" +stable_sort_primitive = "warn" +unnecessary_box_returns = "warn" +unnecessary_join = "warn" +unnested_or_patterns = "warn" +unreadable_literal = "warn" +verbose_bit_mask = "warn" +zero_sized_map_values = "warn" # restriction -empty_drop = "warn" -float_cmp_const = "warn" -get_unwrap = "warn" -infinite_loop = "warn" -lossy_float_literal = "warn" -mem_forget = "warn" -rc_buffer = "warn" -rc_mutex = "warn" +empty_drop = "warn" +float_cmp_const = "warn" +get_unwrap = "warn" +infinite_loop = "warn" +lossy_float_literal = "warn" +mem_forget = "warn" +rc_buffer = "warn" +rc_mutex = "warn" rest_pat_in_fully_bound_structs = "warn" -verbose_file_reads = "warn" +verbose_file_reads = "warn" [workspace.package] -authors = ["Biome Developers and Contributors"] +authors = ["Biome Developers and Contributors"] categories = ["development-tools", "web-programming"] -edition = "2021" -homepage = "https://biomejs.dev/" -keywords = ["parser", "linter", "formatter"] -license = "MIT OR Apache-2.0" +edition = "2021" +homepage = "https://biomejs.dev/" +keywords = ["parser", "linter", "formatter"] +license = "MIT OR Apache-2.0" repository = "https://github.com/biomejs/biome" [profile.release-with-debug] -debug = true +debug = true inherits = "release" [workspace.dependencies] # publish -biome_analyze = { version = "0.5.7", path = "./crates/biome_analyze" } -biome_aria = { version = "0.5.7", path = "./crates/biome_aria" } -biome_aria_metadata = { version = "0.5.7", path = "./crates/biome_aria_metadata" } -biome_console = { version = "0.5.7", path = "./crates/biome_console" } -biome_control_flow = { version = "0.5.7", path = "./crates/biome_control_flow" } -biome_css_analyze = { version = "0.5.7", path = "./crates/biome_css_analyze" } -biome_css_factory = { version = "0.5.7", path = "./crates/biome_css_factory" } -biome_css_formatter = { version = "0.5.7", path = "./crates/biome_css_formatter" } -biome_css_parser = { version = "0.5.7", path = "./crates/biome_css_parser" } -biome_css_syntax = { version = "0.5.7", path = "./crates/biome_css_syntax" } -biome_deserialize = { version = "0.5.7", path = "./crates/biome_deserialize" } -biome_deserialize_macros = { version = "0.5.7", path = "./crates/biome_deserialize_macros" } -biome_diagnostics = { version = "0.5.7", path = "./crates/biome_diagnostics" } +biome_analyze = { version = "0.5.7", path = "./crates/biome_analyze" } +biome_aria = { version = "0.5.7", path = "./crates/biome_aria" } +biome_aria_metadata = { version = "0.5.7", path = "./crates/biome_aria_metadata" } +biome_console = { version = "0.5.7", path = "./crates/biome_console" } +biome_control_flow = { version = "0.5.7", path = "./crates/biome_control_flow" } +biome_css_analyze = { version = "0.5.7", path = "./crates/biome_css_analyze" } +biome_css_factory = { version = "0.5.7", path = "./crates/biome_css_factory" } +biome_css_formatter = { version = "0.5.7", path = "./crates/biome_css_formatter" } +biome_css_parser = { version = "0.5.7", path = "./crates/biome_css_parser" } +biome_css_syntax = { version = "0.5.7", path = "./crates/biome_css_syntax" } +biome_deserialize = { version = "0.5.7", path = "./crates/biome_deserialize" } +biome_deserialize_macros = { version = "0.5.7", path = "./crates/biome_deserialize_macros" } +biome_diagnostics = { version = "0.5.7", path = "./crates/biome_diagnostics" } biome_diagnostics_categories = { version = "0.5.7", path = "./crates/biome_diagnostics_categories" } -biome_diagnostics_macros = { version = "0.5.7", path = "./crates/biome_diagnostics_macros" } -biome_formatter = { version = "0.5.7", path = "./crates/biome_formatter" } -biome_fs = { version = "0.5.7", path = "./crates/biome_fs" } -biome_graphql_factory = { version = "0.1.0", path = "./crates/biome_graphql_factory" } -biome_graphql_syntax = { version = "0.1.0", path = "./crates/biome_graphql_syntax" } -biome_grit_factory = { version = "0.5.7", path = "./crates/biome_grit_factory" } -biome_grit_parser = { version = "0.1.0", path = "./crates/biome_grit_parser" } -biome_grit_patterns = { version = "0.0.1", path = "./crates/biome_grit_patterns" } -biome_grit_syntax = { version = "0.5.7", path = "./crates/biome_grit_syntax" } -biome_html_factory = { version = "0.5.7", path = "./crates/biome_html_factory" } -biome_html_syntax = { version = "0.5.7", path = "./crates/biome_html_syntax" } -biome_js_analyze = { version = "0.5.7", path = "./crates/biome_js_analyze" } -biome_js_factory = { version = "0.5.7", path = "./crates/biome_js_factory" } -biome_js_formatter = { version = "0.5.7", path = "./crates/biome_js_formatter" } -biome_js_parser = { version = "0.5.7", path = "./crates/biome_js_parser" } -biome_js_semantic = { version = "0.5.7", path = "./crates/biome_js_semantic" } -biome_js_syntax = { version = "0.5.7", path = "./crates/biome_js_syntax" } -biome_json_analyze = { version = "0.5.7", path = "./crates/biome_json_analyze" } -biome_json_factory = { version = "0.5.7", path = "./crates/biome_json_factory" } -biome_json_formatter = { version = "0.5.7", path = "./crates/biome_json_formatter" } -biome_json_parser = { version = "0.5.7", path = "./crates/biome_json_parser" } -biome_json_syntax = { version = "0.5.7", path = "./crates/biome_json_syntax" } -biome_yaml_factory = { version = "0.0.1", path = "./crates/biome_yaml_factory" } -biome_yaml_parser = { version = "0.0.1", path = "./crates/biome_yaml_parser" } -biome_yaml_syntax = { version = "0.0.1", path = "./crates/biome_yaml_syntax" } +biome_diagnostics_macros = { version = "0.5.7", path = "./crates/biome_diagnostics_macros" } +biome_formatter = { version = "0.5.7", path = "./crates/biome_formatter" } +biome_fs = { version = "0.5.7", path = "./crates/biome_fs" } +biome_graphql_factory = { version = "0.1.0", path = "./crates/biome_graphql_factory" } +biome_graphql_syntax = { version = "0.1.0", path = "./crates/biome_graphql_syntax" } +biome_grit_factory = { version = "0.5.7", path = "./crates/biome_grit_factory" } +biome_grit_parser = { version = "0.1.0", path = "./crates/biome_grit_parser" } +biome_grit_patterns = { version = "0.0.1", path = "./crates/biome_grit_patterns" } +biome_grit_syntax = { version = "0.5.7", path = "./crates/biome_grit_syntax" } +biome_html_factory = { version = "0.5.7", path = "./crates/biome_html_factory" } +biome_html_syntax = { version = "0.5.7", path = "./crates/biome_html_syntax" } +biome_js_analyze = { version = "0.5.7", path = "./crates/biome_js_analyze" } +biome_js_factory = { version = "0.5.7", path = "./crates/biome_js_factory" } +biome_js_formatter = { version = "0.5.7", path = "./crates/biome_js_formatter" } +biome_js_parser = { version = "0.5.7", path = "./crates/biome_js_parser" } +biome_js_semantic = { version = "0.5.7", path = "./crates/biome_js_semantic" } +biome_js_syntax = { version = "0.5.7", path = "./crates/biome_js_syntax" } +biome_json_analyze = { version = "0.5.7", path = "./crates/biome_json_analyze" } +biome_json_factory = { version = "0.5.7", path = "./crates/biome_json_factory" } +biome_json_formatter = { version = "0.5.7", path = "./crates/biome_json_formatter" } +biome_json_parser = { version = "0.5.7", path = "./crates/biome_json_parser" } +biome_json_syntax = { version = "0.5.7", path = "./crates/biome_json_syntax" } +biome_yaml_factory = { version = "0.0.1", path = "./crates/biome_yaml_factory" } +biome_yaml_parser = { version = "0.0.1", path = "./crates/biome_yaml_parser" } +biome_yaml_syntax = { version = "0.0.1", path = "./crates/biome_yaml_syntax" } -biome_markup = { version = "0.5.7", path = "./crates/biome_markup" } -biome_parser = { version = "0.5.7", path = "./crates/biome_parser" } -biome_project = { version = "0.5.7", path = "./crates/biome_project" } -biome_rowan = { version = "0.5.7", path = "./crates/biome_rowan" } -biome_string_case = { version = "0.5.7", path = "./crates/biome_string_case" } -biome_suppression = { version = "0.5.7", path = "./crates/biome_suppression" } -biome_text_edit = { version = "0.5.7", path = "./crates/biome_text_edit" } -biome_text_size = { version = "0.5.7", path = "./crates/biome_text_size" } +biome_markup = { version = "0.5.7", path = "./crates/biome_markup" } +biome_parser = { version = "0.5.7", path = "./crates/biome_parser" } +biome_project = { version = "0.5.7", path = "./crates/biome_project" } +biome_rowan = { version = "0.5.7", path = "./crates/biome_rowan" } +biome_string_case = { version = "0.5.7", path = "./crates/biome_string_case" } +biome_suppression = { version = "0.5.7", path = "./crates/biome_suppression" } +biome_text_edit = { version = "0.5.7", path = "./crates/biome_text_edit" } +biome_text_size = { version = "0.5.7", path = "./crates/biome_text_size" } biome_unicode_table = { version = "0.5.7", path = "./crates/biome_unicode_table" } # not publish -biome_cli = { path = "./crates/biome_cli" } -biome_configuration = { path = "./crates/biome_configuration" } -biome_flags = { path = "./crates/biome_flags" } +biome_cli = { path = "./crates/biome_cli" } +biome_configuration = { path = "./crates/biome_configuration" } +biome_flags = { path = "./crates/biome_flags" } biome_formatter_test = { path = "./crates/biome_formatter_test" } -biome_lsp = { path = "./crates/biome_lsp" } -biome_migrate = { path = "./crates/biome_migrate" } -biome_service = { path = "./crates/biome_service" } -biome_test_utils = { path = "./crates/biome_test_utils" } -biome_ungrammar = { path = "./crates/biome_ungrammar" } -tests_macros = { path = "./crates/tests_macros" } +biome_lsp = { path = "./crates/biome_lsp" } +biome_migrate = { path = "./crates/biome_migrate" } +biome_service = { path = "./crates/biome_service" } +biome_test_utils = { path = "./crates/biome_test_utils" } +biome_ungrammar = { path = "./crates/biome_ungrammar" } +tests_macros = { path = "./crates/tests_macros" } # Crates needed in the workspace -bitflags = "2.5.0" -bpaf = { version = "0.9.9", features = ["derive"] } -countme = "3.0.1" -crossbeam = "0.8.4" -dashmap = "5.4.0" -ignore = "0.4.21" -indexmap = "1.9.3" -insta = "1.38.0" -lazy_static = "1.4.0" -oxc_resolver = "1.4.0" -proc-macro2 = "1.0.81" -quickcheck = "1.0.3" -quickcheck_macros = "1.0.0" -quote = "1.0.36" -rayon = "1.8.1" -regex = "1.10.4" -rustc-hash = "1.1.0" -schemars = { version = "0.8.12" } -serde = { version = "1.0.198", features = ["derive"] } -serde_json = "1.0.116" -similar = "2.5.0" -smallvec = { version = "1.10.0", features = ["union", "const_new"] } -syn = "1.0.109" -tokio = { version = "1.36.0" } -tracing = { version = "0.1.37", default-features = false, features = ["std"] } +bitflags = "2.5.0" +bpaf = { version = "0.9.9", features = ["derive"] } +countme = "3.0.1" +crossbeam = "0.8.4" +dashmap = "5.4.0" +ignore = "0.4.21" +indexmap = "1.9.3" +insta = "1.38.0" +lazy_static = "1.4.0" +oxc_resolver = "1.4.0" +proc-macro2 = "1.0.81" +quickcheck = "1.0.3" +quickcheck_macros = "1.0.0" +quote = "1.0.36" +rayon = "1.8.1" +regex = "1.10.4" +rustc-hash = "1.1.0" +schemars = { version = "0.8.12" } +serde = { version = "1.0.198", features = ["derive"] } +serde_json = "1.0.116" +similar = "2.5.0" +smallvec = { version = "1.10.0", features = ["union", "const_new"] } +syn = "1.0.109" +tokio = { version = "1.36.0" } +tracing = { version = "0.1.37", default-features = false, features = ["std"] } tracing-subscriber = "0.3.18" -unicode-bom = "2.0.3" +unicode-bom = "2.0.3" +slotmap = "1.0.7" [profile.dev.package.biome_wasm] -debug = true +debug = true opt-level = "s" [profile.test.package.biome_wasm] -debug = true +debug = true opt-level = "s" [profile.release.package.biome_wasm] -debug = false +debug = false opt-level = 3 diff --git a/crates/biome_cli/src/commands/check.rs b/crates/biome_cli/src/commands/check.rs index 4aaab8826a15..d590bc8acd81 100644 --- a/crates/biome_cli/src/commands/check.rs +++ b/crates/biome_cli/src/commands/check.rs @@ -11,6 +11,7 @@ use biome_configuration::{ }; use biome_deserialize::Merge; use biome_service::configuration::PartialConfigurationExt; +use biome_service::workspace::RegisterWorkspaceFoldersParams; use biome_service::{ configuration::{load_configuration, LoadedConfiguration}, workspace::{FixFileMode, UpdateSettingsParams}, @@ -129,11 +130,19 @@ pub(crate) fn check( paths = _paths; } + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; + session .app .workspace .update_settings(UpdateSettingsParams { - working_directory: session.app.fs.working_directory(), + workspace_directory: session.app.fs.working_directory(), configuration: fs_configuration, vcs_base_path, gitignore_matches, diff --git a/crates/biome_cli/src/commands/ci.rs b/crates/biome_cli/src/commands/ci.rs index cab1b0764ee9..820af8730e2e 100644 --- a/crates/biome_cli/src/commands/ci.rs +++ b/crates/biome_cli/src/commands/ci.rs @@ -8,7 +8,7 @@ use biome_deserialize::Merge; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::UpdateSettingsParams; +use biome_service::workspace::{RegisterWorkspaceFoldersParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct CiCommandPayload { @@ -106,12 +106,20 @@ pub(crate) fn ci(session: CliSession, payload: CiCommandPayload) -> Result<(), C paths = get_changed_files(&session.app.fs, &fs_configuration, since)?; } + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; + session .app .workspace .update_settings(UpdateSettingsParams { configuration: fs_configuration, - working_directory: session.app.fs.working_directory(), + workspace_directory: session.app.fs.working_directory(), vcs_base_path, gitignore_matches, })?; diff --git a/crates/biome_cli/src/commands/format.rs b/crates/biome_cli/src/commands/format.rs index 57fc758856cf..db3601d073b6 100644 --- a/crates/biome_cli/src/commands/format.rs +++ b/crates/biome_cli/src/commands/format.rs @@ -17,7 +17,7 @@ use biome_diagnostics::PrintDiagnostic; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::UpdateSettingsParams; +use biome_service::workspace::{RegisterWorkspaceFoldersParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct FormatCommandPayload { @@ -165,11 +165,19 @@ pub(crate) fn format( paths = _paths; } + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; + session .app .workspace .update_settings(UpdateSettingsParams { - working_directory: session.app.fs.working_directory(), + workspace_directory: session.app.fs.working_directory(), configuration, vcs_base_path, gitignore_matches, diff --git a/crates/biome_cli/src/commands/lint.rs b/crates/biome_cli/src/commands/lint.rs index 79eb84145968..caa71f53e653 100644 --- a/crates/biome_cli/src/commands/lint.rs +++ b/crates/biome_cli/src/commands/lint.rs @@ -13,7 +13,7 @@ use biome_deserialize::Merge; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::{FixFileMode, UpdateSettingsParams}; +use biome_service::workspace::{FixFileMode, RegisterWorkspaceFoldersParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct LintCommandPayload { @@ -106,11 +106,19 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<( let stdin = get_stdin(stdin_file_path, &mut *session.app.console, "lint")?; + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; + session .app .workspace .update_settings(UpdateSettingsParams { - working_directory: session.app.fs.working_directory(), + workspace_directory: session.app.fs.working_directory(), configuration: fs_configuration, vcs_base_path, gitignore_matches, diff --git a/crates/biome_cli/src/commands/search.rs b/crates/biome_cli/src/commands/search.rs index b829e003cfaa..61e8bc209982 100644 --- a/crates/biome_cli/src/commands/search.rs +++ b/crates/biome_cli/src/commands/search.rs @@ -8,7 +8,9 @@ use biome_deserialize::Merge; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::{ParsePatternParams, UpdateSettingsParams}; +use biome_service::workspace::{ + ParsePatternParams, RegisterWorkspaceFoldersParams, UpdateSettingsParams, +}; use std::ffi::OsString; pub(crate) struct SearchCommandPayload { @@ -59,8 +61,15 @@ pub(crate) fn search( configuration.retrieve_gitignore_matches(&session.app.fs, vcs_base_path.as_deref())?; let workspace = &session.app.workspace; + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; workspace.update_settings(UpdateSettingsParams { - working_directory: session.app.fs.working_directory(), + workspace_directory: session.app.fs.working_directory(), configuration, vcs_base_path, gitignore_matches, diff --git a/crates/biome_css_formatter/tests/language.rs b/crates/biome_css_formatter/tests/language.rs index 856421294a5f..4a03098df42f 100644 --- a/crates/biome_css_formatter/tests/language.rs +++ b/crates/biome_css_formatter/tests/language.rs @@ -6,7 +6,7 @@ use biome_formatter::{FormatResult, Formatted, Printed}; use biome_formatter_test::TestFormatLanguage; use biome_parser::AnyParse; use biome_rowan::{SyntaxNode, TextRange}; -use biome_service::settings::{ServiceLanguage, WorkspaceSettings}; +use biome_service::settings::{ServiceLanguage, Settings}; #[derive(Default)] pub struct CssTestFormatLanguage { @@ -26,7 +26,7 @@ impl TestFormatLanguage for CssTestFormatLanguage { fn to_language_settings<'a>( &self, - settings: &'a WorkspaceSettings, + settings: &'a Settings, ) -> &'a ::FormatterSettings { &settings.languages.css.formatter } diff --git a/crates/biome_formatter_test/src/lib.rs b/crates/biome_formatter_test/src/lib.rs index b79f54c9016d..ddd4e6e5cef3 100644 --- a/crates/biome_formatter_test/src/lib.rs +++ b/crates/biome_formatter_test/src/lib.rs @@ -4,7 +4,7 @@ use biome_parser::AnyParse; use biome_rowan::{SyntaxNode, TextRange}; use biome_service::file_handlers::DocumentFileSource; use biome_service::settings::ServiceLanguage; -use biome_service::settings::WorkspaceSettings; +use biome_service::settings::Settings; pub mod check_reformat; pub mod diff_report; @@ -25,7 +25,7 @@ pub trait TestFormatLanguage { fn to_language_settings<'a>( &self, - settings: &'a WorkspaceSettings, + settings: &'a Settings, ) -> &'a ::FormatterSettings; fn format_node( @@ -45,7 +45,7 @@ pub trait TestFormatLanguage { fn to_options( &self, - settings: &WorkspaceSettings, + settings: &Settings, file_source: &DocumentFileSource, ) -> ::FormatOptions { let language_settings = self.to_language_settings(settings); diff --git a/crates/biome_formatter_test/src/spec.rs b/crates/biome_formatter_test/src/spec.rs index 799287c55749..edf0c32c6676 100644 --- a/crates/biome_formatter_test/src/spec.rs +++ b/crates/biome_formatter_test/src/spec.rs @@ -10,7 +10,7 @@ use biome_formatter::{FormatOptions, Printed}; use biome_fs::BiomePath; use biome_parser::AnyParse; use biome_rowan::{TextRange, TextSize}; -use biome_service::settings::{ServiceLanguage, WorkspaceSettings}; +use biome_service::settings::{ServiceLanguage, Settings}; use biome_service::workspace::{DocumentFileSource, FeaturesBuilder, SupportsFeatureParams}; use biome_service::App; use std::ops::Range; @@ -222,7 +222,7 @@ where if options_path.exists() { let mut options_path = BiomePath::new(&options_path); - let mut settings = WorkspaceSettings::default(); + let mut settings = Settings::default(); // SAFETY: we checked its existence already, we assume we have rights to read it let (test_options, diagnostics) = deserialize_from_str::( options_path.get_buffer_from_file().as_str(), diff --git a/crates/biome_fs/Cargo.toml b/crates/biome_fs/Cargo.toml index 926008006f12..a72aab993427 100644 --- a/crates/biome_fs/Cargo.toml +++ b/crates/biome_fs/Cargo.toml @@ -1,29 +1,29 @@ [package] -authors.workspace = true +authors.workspace = true categories.workspace = true -description = "A small wrapper around std::path::PathBuf contains additional information and convenient methods" -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "biome_fs" +description = "A small wrapper around std::path::PathBuf contains additional information and convenient methods" +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "biome_fs" repository.workspace = true -version = "0.5.7" +version = "0.5.7" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] biome_diagnostics = { workspace = true } -crossbeam = { workspace = true } -directories = "5.0.1" -indexmap = { workspace = true } -oxc_resolver = { workspace = true } -parking_lot = { version = "0.12.0", features = ["arc_lock"] } -rayon = { workspace = true } -rustc-hash = { workspace = true } -schemars = { workspace = true, optional = true } -serde = { workspace = true } -tracing = { workspace = true } +crossbeam = { workspace = true } +directories = "5.0.1" +indexmap = { workspace = true } +oxc_resolver = { workspace = true } +parking_lot = { version = "0.12.0", features = ["arc_lock"] } +rayon = { workspace = true } +rustc-hash = { workspace = true } +schemars = { workspace = true, optional = true } +serde = { workspace = true } +tracing = { workspace = true } [features] serde = ["schemars", "biome_diagnostics/schema"] diff --git a/crates/biome_fs/src/path.rs b/crates/biome_fs/src/path.rs index 3b1c812de411..bf34107bfa45 100644 --- a/crates/biome_fs/src/path.rs +++ b/crates/biome_fs/src/path.rs @@ -6,7 +6,7 @@ use std::fs::{self, read_to_string}; use std::{fs::File, io, io::Write, ops::Deref, path::PathBuf}; -#[derive(Debug, Clone, Eq, Hash, PartialEq)] +#[derive(Debug, Clone, Eq, Hash, PartialEq, Default)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema) diff --git a/crates/biome_js_formatter/tests/language.rs b/crates/biome_js_formatter/tests/language.rs index 6add0c0d0548..4ad692e77939 100644 --- a/crates/biome_js_formatter/tests/language.rs +++ b/crates/biome_js_formatter/tests/language.rs @@ -6,7 +6,7 @@ use biome_js_parser::{parse, JsParserOptions}; use biome_js_syntax::{JsFileSource, JsLanguage}; use biome_parser::AnyParse; use biome_rowan::SyntaxNode; -use biome_service::settings::{ServiceLanguage, WorkspaceSettings}; +use biome_service::settings::{ServiceLanguage, Settings}; use biome_text_size::TextRange; pub struct JsTestFormatLanguage { @@ -36,7 +36,7 @@ impl TestFormatLanguage for JsTestFormatLanguage { fn to_language_settings<'a>( &self, - settings: &'a WorkspaceSettings, + settings: &'a Settings, ) -> &'a ::FormatterSettings { &settings.languages.javascript.formatter } diff --git a/crates/biome_json_formatter/tests/language.rs b/crates/biome_json_formatter/tests/language.rs index a6a7373984d9..b8878e3ab5b4 100644 --- a/crates/biome_json_formatter/tests/language.rs +++ b/crates/biome_json_formatter/tests/language.rs @@ -6,7 +6,7 @@ use biome_json_parser::{parse_json, JsonParserOptions}; use biome_json_syntax::{JsonFileSource, JsonLanguage}; use biome_parser::AnyParse; use biome_rowan::{SyntaxNode, TextRange}; -use biome_service::settings::{ServiceLanguage, WorkspaceSettings}; +use biome_service::settings::{ServiceLanguage, Settings}; use serde::{Deserialize, Serialize}; #[derive(Default)] @@ -27,7 +27,7 @@ impl TestFormatLanguage for JsonTestFormatLanguage { fn to_language_settings<'a>( &self, - settings: &'a WorkspaceSettings, + settings: &'a Settings, ) -> &'a ::FormatterSettings { &settings.languages.json.formatter } diff --git a/crates/biome_lsp/src/server.rs b/crates/biome_lsp/src/server.rs index ec99f3837a51..73b9c301064b 100644 --- a/crates/biome_lsp/src/server.rs +++ b/crates/biome_lsp/src/server.rs @@ -248,6 +248,14 @@ impl LanguageServer for LSPServer { self.is_initialized.store(true, Ordering::Relaxed); let server_capabilities = server_capabilities(¶ms.capabilities); + if params.root_path.is_some() { + warn!("The Biome Server was initialized with the deprecated `root_path` parameter: this is not supported, use `root_uri` instead"); + } + + if let Some(_folders) = ¶ms.workspace_folders { + warn!("The Biome Server was initialized with the `workspace_folders` parameter: this is unsupported at the moment, use `root_uri` instead"); + } + self.session.initialize( params.capabilities, params.client_info.map(|client_info| ClientInformation { @@ -255,16 +263,9 @@ impl LanguageServer for LSPServer { version: client_info.version, }), params.root_uri, + params.workspace_folders, ); - if params.root_path.is_some() { - warn!("The Biome Server was initialized with the deprecated `root_path` parameter: this is not supported, use `root_uri` instead"); - } - - if params.workspace_folders.is_some() { - warn!("The Biome Server was initialized with the `workspace_folders` parameter: this is unsupported at the moment, use `root_uri` instead"); - } - // let init = InitializeResult { capabilities: server_capabilities, @@ -574,6 +575,7 @@ impl ServerFactory { workspace_method!(builder, file_features); workspace_method!(builder, is_path_ignored); workspace_method!(builder, update_settings); + workspace_method!(builder, register_workspace_folder); workspace_method!(builder, open_file); workspace_method!(builder, open_project); workspace_method!(builder, update_current_project); diff --git a/crates/biome_lsp/src/session.rs b/crates/biome_lsp/src/session.rs index 129944c17b93..5282d65546fc 100644 --- a/crates/biome_lsp/src/session.rs +++ b/crates/biome_lsp/src/session.rs @@ -15,7 +15,7 @@ use biome_service::configuration::{ use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler}; use biome_service::workspace::{ FeaturesBuilder, GetFileContentParams, OpenProjectParams, PullDiagnosticsParams, - SupportsFeatureParams, UpdateProjectParams, + RegisterWorkspaceFoldersParams, SupportsFeatureParams, UpdateProjectParams, }; use biome_service::workspace::{RageEntry, RageParams, RageResult, UpdateSettingsParams}; use biome_service::Workspace; @@ -32,9 +32,9 @@ use std::sync::RwLock; use tokio::sync::Notify; use tokio::sync::OnceCell; use tower_lsp::lsp_types; -use tower_lsp::lsp_types::Unregistration; use tower_lsp::lsp_types::Url; use tower_lsp::lsp_types::{MessageType, Registration}; +use tower_lsp::lsp_types::{Unregistration, WorkspaceFolder}; use tracing::{debug, error, info}; pub(crate) struct ClientInformation { @@ -83,6 +83,8 @@ struct InitializeParams { client_capabilities: lsp_types::ClientCapabilities, client_information: Option, root_uri: Option, + #[allow(unused)] + workspace_folders: Option>, } #[repr(u8)] @@ -171,11 +173,13 @@ impl Session { client_capabilities: lsp_types::ClientCapabilities, client_information: Option, root_uri: Option, + workspace_folders: Option>, ) { let result = self.initialize_params.set(InitializeParams { client_capabilities, client_information, root_uri, + workspace_folders, }); if let Err(err) = result { @@ -236,7 +240,7 @@ impl Session { /// Get a [`Document`] matching the provided [`lsp_types::Url`] /// - /// If document does not exist, result is [SessionError::DocumentNotFound] + /// If document does not exist, result is [WorkspaceError::NotFound] pub(crate) fn document(&self, url: &lsp_types::Url) -> Result { self.documents .read() @@ -447,8 +451,15 @@ impl Session { match result { Ok((vcs_base_path, gitignore_matches)) => { + // We don't need the key for now, but will soon + let _ = self.workspace.register_workspace_folder( + RegisterWorkspaceFoldersParams { + path: fs.working_directory(), + set_as_current_workspace: true, + }, + ); let result = self.workspace.update_settings(UpdateSettingsParams { - working_directory: fs.working_directory(), + workspace_directory: fs.working_directory(), configuration, vcs_base_path, gitignore_matches, diff --git a/crates/biome_service/Cargo.toml b/crates/biome_service/Cargo.toml index e447a183d60e..9394d8541438 100644 --- a/crates/biome_service/Cargo.toml +++ b/crates/biome_service/Cargo.toml @@ -1,74 +1,74 @@ [package] -authors.workspace = true +authors.workspace = true categories.workspace = true -description = "Biome's core functionality" -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "biome_service" -publish = false +description = "Biome's core functionality" +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "biome_service" +publish = false repository.workspace = true -version = "0.0.0" +version = "0.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -biome_analyze = { workspace = true, features = ["serde"] } -biome_configuration = { workspace = true, features = ["schema"] } -biome_console = { workspace = true } -biome_css_analyze = { workspace = true } -biome_css_formatter = { workspace = true } -biome_css_parser = { workspace = true } -biome_css_syntax = { workspace = true } -biome_deserialize = { workspace = true } +biome_analyze = { workspace = true, features = ["serde"] } +biome_configuration = { workspace = true, features = ["schema"] } +biome_console = { workspace = true } +biome_css_analyze = { workspace = true } +biome_css_formatter = { workspace = true } +biome_css_parser = { workspace = true } +biome_css_syntax = { workspace = true } +biome_deserialize = { workspace = true } biome_deserialize_macros = { workspace = true } -biome_diagnostics = { workspace = true } -biome_flags = { workspace = true } -biome_formatter = { workspace = true, features = ["serde"] } -biome_fs = { workspace = true, features = ["serde"] } -biome_grit_patterns = { workspace = true } -biome_js_analyze = { workspace = true } -biome_js_factory = { workspace = true, optional = true } -biome_js_formatter = { workspace = true, features = ["serde"] } -biome_js_parser = { workspace = true } -biome_js_semantic = { workspace = true } -biome_js_syntax = { workspace = true, features = ["schema"] } -biome_json_analyze = { workspace = true } -biome_json_formatter = { workspace = true, features = ["serde"] } -biome_json_parser = { workspace = true } -biome_json_syntax = { workspace = true } -biome_parser = { workspace = true } -biome_project = { workspace = true } -biome_rowan = { workspace = true, features = ["serde"] } -biome_text_edit = { workspace = true } -bpaf = { workspace = true } -dashmap = { workspace = true } -ignore = { workspace = true } -indexmap = { workspace = true, features = ["serde"] } -lazy_static = { workspace = true } -oxc_resolver = { workspace = true } -regex = { workspace = true } -rustc-hash = { workspace = true } -schemars = { workspace = true, features = ["indexmap1"], optional = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true, features = ["raw_value"] } -tracing = { workspace = true, features = ["attributes", "log"] } - +biome_diagnostics = { workspace = true } +biome_flags = { workspace = true } +biome_formatter = { workspace = true, features = ["serde"] } +biome_fs = { workspace = true, features = ["serde"] } +biome_grit_patterns = { workspace = true } +biome_js_analyze = { workspace = true } +biome_js_factory = { workspace = true, optional = true } +biome_js_formatter = { workspace = true, features = ["serde"] } +biome_js_parser = { workspace = true } +biome_js_semantic = { workspace = true } +biome_js_syntax = { workspace = true, features = ["schema"] } +biome_json_analyze = { workspace = true } +biome_json_formatter = { workspace = true, features = ["serde"] } +biome_json_parser = { workspace = true } +biome_json_syntax = { workspace = true } +biome_parser = { workspace = true } +biome_project = { workspace = true } +biome_rowan = { workspace = true, features = ["serde"] } +biome_text_edit = { workspace = true } +bpaf = { workspace = true } +dashmap = { workspace = true } +ignore = { workspace = true } +indexmap = { workspace = true, features = ["serde"] } +lazy_static = { workspace = true } +oxc_resolver = { workspace = true } +regex = { workspace = true } +rustc-hash = { workspace = true } +schemars = { workspace = true, features = ["indexmap1"], optional = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["raw_value"] } +tracing = { workspace = true, features = ["attributes", "log"] } +slotmap = { workspace = true, features = ["serde"] } [features] format_css = ["biome_css_formatter/format_css"] schema = [ - "dep:schemars", - "biome_js_analyze/schema", - "biome_formatter/serde", - "biome_js_factory", - "biome_text_edit/schemars", - "biome_json_syntax/schema", - "biome_css_syntax/schema", + "dep:schemars", + "biome_js_analyze/schema", + "biome_formatter/serde", + "biome_js_factory", + "biome_text_edit/schemars", + "biome_json_syntax/schema", + "biome_css_syntax/schema", ] [dev-dependencies] -insta = { workspace = true } +insta = { workspace = true } tests_macros = { workspace = true } [lints] diff --git a/crates/biome_service/src/configuration.rs b/crates/biome_service/src/configuration.rs index 7efa5a13e37b..0ab4c8be1740 100644 --- a/crates/biome_service/src/configuration.rs +++ b/crates/biome_service/src/configuration.rs @@ -1,4 +1,4 @@ -use crate::settings::WorkspaceSettings; +use crate::settings::Settings; use crate::{DynRef, WorkspaceError, VERSION}; use biome_analyze::AnalyzerRules; use biome_configuration::diagnostics::CantLoadExtendFile; @@ -316,8 +316,8 @@ pub fn create_config( Ok(()) } -/// Returns the rules applied to a specific [Path], given the [WorkspaceSettings] -pub fn to_analyzer_rules(settings: &WorkspaceSettings, path: &Path) -> AnalyzerRules { +/// Returns the rules applied to a specific [Path], given the [Settings] +pub fn to_analyzer_rules(settings: &Settings, path: &Path) -> AnalyzerRules { let linter_settings = &settings.linter; let overrides = &settings.override_settings; let mut analyzer_rules = AnalyzerRules::default(); diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index 7fe6ca738915..b09972bfe28e 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -1,4 +1,4 @@ -use crate::workspace::DocumentFileSource; +use crate::workspace::{DocumentFileSource, WorkspaceData, WorkspaceKey}; use crate::{Matcher, WorkspaceError}; use biome_analyze::AnalyzerRules; use biome_configuration::diagnostics::InvalidIgnorePattern; @@ -30,62 +30,124 @@ use indexmap::IndexSet; use rustc_hash::FxHashMap; use std::borrow::Cow; use std::path::{Path, PathBuf}; +use std::sync::RwLockWriteGuard; use std::{ num::NonZeroU64, sync::{RwLock, RwLockReadGuard}, }; -/// Global settings for the entire workspace +#[derive(Debug)] +pub struct PathToSettings { + path: BiomePath, + settings: Settings, +} + +impl Default for PathToSettings { + fn default() -> Self { + Self { + path: BiomePath::default(), + settings: Settings::default(), + } + } +} + #[derive(Debug, Default)] pub struct WorkspaceSettings { - /// Formatter settings applied to all files in the workspaces - pub formatter: FormatSettings, - /// Linter settings applied to all files in the workspace - pub linter: LinterSettings, - /// Language specific settings - pub languages: LanguageListSettings, - /// Filesystem settings for the workspace - pub files: FilesSettings, - /// Analyzer settings - pub organize_imports: OrganizeImportsSettings, - /// overrides - pub override_settings: OverrideSettings, + data: WorkspaceData, + current_workspace: WorkspaceKey, } impl WorkspaceSettings { - /// Retrieves the settings of the formatter - pub fn formatter(&self) -> &FormatSettings { - &self.formatter + pub fn current_settings(&self) -> &Settings { + debug_assert!( + self.data.paths.len() > 0, + "You must have at least one workspace." + ); + let data = self.data.paths.get(self.current_workspace).unwrap(); + &data.settings } - /// Whether the formatter is disabled for JavaScript files - pub fn javascript_formatter_disabled(&self) -> bool { - let enabled = self.languages.javascript.formatter.enabled.as_ref(); - enabled == Some(&false) + pub fn register_current_workspace(&mut self, key: WorkspaceKey) { + self.current_workspace = key; } - /// Whether the formatter is disabled for JSON files - pub fn json_formatter_disabled(&self) -> bool { - let enabled = self.languages.json.formatter.enabled.as_ref(); - enabled == Some(&false) + pub fn current_settings_mut(&mut self) -> &mut Settings { + debug_assert!( + self.data.paths.len() > 0, + "You must have at least one workspace." + ); + &mut self.data.get_mut(self.current_workspace).unwrap().settings } - /// Whether the formatter is disabled for CSS files - pub fn css_formatter_disabled(&self) -> bool { - let enabled = self.languages.css.formatter.enabled.as_ref(); - enabled == Some(&false) + pub fn insert_workspace(&mut self, workspace_path: impl Into) -> WorkspaceKey { + self.data.paths.insert(PathToSettings { + path: BiomePath::new(workspace_path.into()), + settings: Settings::default(), + }) } - /// Retrieves the settings of the linter - pub fn linter(&self) -> &LinterSettings { - &self.linter + /// + pub fn current_workspace_path(&self, path: &BiomePath) -> (WorkspaceKey, &BiomePath) { + debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); + debug_assert!( + self.data.paths.len() > 0, + "You must have at least one workspace." + ); + for (key, path_to_settings) in &self.data.paths { + if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + return (key, &path_to_settings.path); + } + } + unreachable!("We should not reach here, the assertions should help.") } - /// Retrieves the settings of the organize imports - pub fn organize_imports(&self) -> &OrganizeImportsSettings { - &self.organize_imports + pub fn get_settings_by_path(&self, path: &BiomePath) -> &Settings { + debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); + debug_assert!( + self.data.paths.len() > 0, + "You must have at least one workspace." + ); + for (_, path_to_settings) in &self.data.paths { + if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + return &path_to_settings.settings; + } + } + unreachable!("We should not reach here, the assertions should help.") + } + + pub fn get_settings_by_path_mut(&mut self, path: &Path) -> &mut Settings { + debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); + debug_assert!( + self.data.paths.len() > 0, + "You must have at least one workspace." + ); + for (_, path_to_settings) in &mut self.data.paths { + if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + return &mut path_to_settings.settings; + } + } + unreachable!("We should not reach here, the assertions should help.") } +} +/// Global settings for the entire workspace +#[derive(Debug, Default)] +pub struct Settings { + /// Formatter settings applied to all files in the workspaces + pub formatter: FormatSettings, + /// Linter settings applied to all files in the workspace + pub linter: LinterSettings, + /// Language specific settings + pub languages: LanguageListSettings, + /// Filesystem settings for the workspace + pub files: FilesSettings, + /// Analyzer settings + pub organize_imports: OrganizeImportsSettings, + /// overrides + pub override_settings: OverrideSettings, +} + +impl Settings { /// The [PartialConfiguration] is merged into the workspace #[tracing::instrument(level = "trace", skip(self))] pub fn merge_with_configuration( @@ -148,6 +210,39 @@ impl WorkspaceSettings { Ok(()) } + /// Retrieves the settings of the formatter + pub fn formatter(&self) -> &FormatSettings { + &self.formatter + } + + /// Whether the formatter is disabled for JavaScript files + pub fn javascript_formatter_disabled(&self) -> bool { + let enabled = self.languages.javascript.formatter.enabled.as_ref(); + enabled == Some(&false) + } + + /// Whether the formatter is disabled for JSON files + pub fn json_formatter_disabled(&self) -> bool { + let enabled = self.languages.json.formatter.enabled.as_ref(); + enabled == Some(&false) + } + + /// Whether the formatter is disabled for CSS files + pub fn css_formatter_disabled(&self) -> bool { + let enabled = self.languages.css.formatter.enabled.as_ref(); + enabled == Some(&false) + } + + /// Retrieves the settings of the linter + pub fn linter(&self) -> &LinterSettings { + &self.linter + } + + /// Retrieves the settings of the organize imports + pub fn organize_imports(&self) -> &OrganizeImportsSettings { + &self.organize_imports + } + /// It retrieves the severity based on the `code` of the rule and the current configuration. /// /// The code of the has the following pattern: `{group}/{rule_name}`. @@ -504,9 +599,9 @@ impl<'a> SettingsHandle<'a> { } } -impl<'a> AsRef for SettingsHandle<'a> { - fn as_ref(&self) -> &WorkspaceSettings { - &self.inner +impl<'a> AsRef for SettingsHandle<'a> { + fn as_ref(&self) -> &Settings { + &self.inner.current_settings() } } @@ -521,15 +616,52 @@ impl<'a> SettingsHandle<'a> { L: ServiceLanguage, { L::resolve_format_options( - &self.inner.formatter, - &self.inner.override_settings, - &L::lookup_settings(&self.inner.languages).formatter, + &self.inner.current_settings().formatter, + &self.inner.current_settings().override_settings, + &L::lookup_settings(&self.inner.current_settings().languages).formatter, path, file_source, ) } } +#[derive(Debug)] +pub struct SettingsHandleMut<'a> { + inner: RwLockWriteGuard<'a, WorkspaceSettings>, +} + +impl<'a> SettingsHandleMut<'a> { + pub(crate) fn new(settings: &'a RwLock) -> Self { + Self { + inner: settings.write().unwrap(), + } + } +} + +impl<'a> AsMut for SettingsHandleMut<'a> { + fn as_mut(&mut self) -> &mut Settings { + self.inner.current_settings_mut() + } +} + +pub struct WorkspacesHandleMut<'a> { + inner: RwLockWriteGuard<'a, WorkspaceSettings>, +} + +impl<'a> WorkspacesHandleMut<'a> { + pub(crate) fn new(settings: &'a RwLock) -> Self { + Self { + inner: settings.write().unwrap(), + } + } +} + +impl<'a> AsMut for WorkspacesHandleMut<'a> { + fn as_mut(&mut self) -> &mut WorkspaceSettings { + &mut self.inner + } +} + #[derive(Debug, Default)] pub struct OverrideSettings { pub patterns: Vec, @@ -1042,7 +1174,7 @@ impl TryFrom for OrganizeImportsSettings { pub fn to_override_settings( working_directory: Option, overrides: Overrides, - current_settings: &WorkspaceSettings, + current_settings: &Settings, ) -> Result { let mut override_settings = OverrideSettings::default(); for mut pattern in overrides.0 { diff --git a/crates/biome_service/src/workspace.rs b/crates/biome_service/src/workspace.rs index c381fe9aa21e..216f853fc8b2 100644 --- a/crates/biome_service/src/workspace.rs +++ b/crates/biome_service/src/workspace.rs @@ -63,6 +63,7 @@ use biome_formatter::Printed; use biome_fs::BiomePath; use biome_js_syntax::{TextRange, TextSize}; use biome_text_edit::TextEdit; +use slotmap::{new_key_type, DenseSlotMap}; use std::collections::HashMap; use std::ffi::OsStr; use std::path::{Path, PathBuf}; @@ -71,7 +72,7 @@ use tracing::debug; pub use self::client::{TransportRequest, WorkspaceClient, WorkspaceTransport}; pub use crate::file_handlers::DocumentFileSource; -use crate::settings::WorkspaceSettings; +use crate::settings::Settings; mod client; mod server; @@ -149,7 +150,7 @@ impl FileFeaturesResult { pub(crate) fn with_settings_and_language( mut self, - settings: &WorkspaceSettings, + settings: &Settings, file_source: &DocumentFileSource, path: &Path, ) -> Self { @@ -405,7 +406,7 @@ pub struct UpdateSettingsParams { pub vcs_base_path: Option, // @ematipico TODO: have a better data structure for this pub gitignore_matches: Vec, - pub working_directory: Option, + pub workspace_directory: Option, } #[derive(Debug, serde::Serialize, serde::Deserialize)] @@ -731,6 +732,13 @@ pub struct IsPathIgnoredParams { pub features: Vec, } +#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +pub struct RegisterWorkspaceFoldersParams { + pub path: Option, + pub set_as_current_workspace: bool, +} + pub trait Workspace: Send + Sync + RefUnwindSafe { /// Checks whether a certain feature is supported. There are different conditions: /// - Biome doesn't recognize a file, so it can't provide the feature; @@ -758,6 +766,12 @@ pub trait Workspace: Send + Sync + RefUnwindSafe { /// Add a new project to the workspace fn open_project(&self, params: OpenProjectParams) -> Result<(), WorkspaceError>; + /// Register a possible workspace folders. Returns the key of said workspace. Use this key when you want to switch to different workspaces. + fn register_workspace_folder( + &self, + params: RegisterWorkspaceFoldersParams, + ) -> Result; + /// Sets the current project path fn update_current_project(&self, params: UpdateProjectParams) -> Result<(), WorkspaceError>; @@ -984,3 +998,35 @@ fn test_order() { assert!(items[0] < items[1], "{} < {}", items[0], items[1]); } } + +new_key_type! { + pub struct WorkspaceKey; +} + +#[derive(Debug, Default)] +pub struct WorkspaceData { + /// [DenseSlotMap] is the slowest type in insertion/removal, but the fastest in iteration + /// + /// Users wouldn't change workspace folders very often, + pub paths: DenseSlotMap, +} + +impl WorkspaceData { + /// Inserts an item + pub fn insert(&mut self, item: impl Into) { + self.paths.insert(Into::into(item)); + } + + /// Removes an item + pub fn remove(&mut self, key: WorkspaceKey) { + self.paths.remove(key); + } + + pub fn get_value_by_key(&self, key: WorkspaceKey) -> Option<&T> { + self.paths.get(key) + } + + pub fn get_mut(&mut self, key: WorkspaceKey) -> Option<&mut T> { + self.paths.get_mut(key) + } +} diff --git a/crates/biome_service/src/workspace/client.rs b/crates/biome_service/src/workspace/client.rs index d9207d7ad7cc..50cace62b03e 100644 --- a/crates/biome_service/src/workspace/client.rs +++ b/crates/biome_service/src/workspace/client.rs @@ -1,7 +1,7 @@ use crate::workspace::{ FileFeaturesResult, GetFileContentParams, IsPathIgnoredParams, OpenProjectParams, - OrganizeImportsParams, OrganizeImportsResult, RageParams, RageResult, ServerInfo, - UpdateProjectParams, + OrganizeImportsParams, OrganizeImportsResult, RageParams, RageResult, + RegisterWorkspaceFoldersParams, ServerInfo, UpdateProjectParams, WorkspaceKey, }; use crate::{TransportError, Workspace, WorkspaceError}; use biome_formatter::Printed; @@ -110,7 +110,6 @@ where fn is_path_ignored(&self, params: IsPathIgnoredParams) -> Result { self.request("biome/is_path_ignored", params) } - fn update_settings(&self, params: UpdateSettingsParams) -> Result<(), WorkspaceError> { self.request("biome/update_settings", params) } @@ -123,6 +122,13 @@ where self.request("biome/open_project", params) } + fn register_workspace_folder( + &self, + params: RegisterWorkspaceFoldersParams, + ) -> Result { + self.request("biome/register_workspace_folder", params) + } + fn update_current_project(&self, params: UpdateProjectParams) -> Result<(), WorkspaceError> { self.request("biome/update_current_project", params) } diff --git a/crates/biome_service/src/workspace/server.rs b/crates/biome_service/src/workspace/server.rs index 1183f46e95ad..8740be6e8899 100644 --- a/crates/biome_service/src/workspace/server.rs +++ b/crates/biome_service/src/workspace/server.rs @@ -3,21 +3,19 @@ use super::{ FormatOnTypeParams, FormatRangeParams, GetControlFlowGraphParams, GetFormatterIRParams, GetSyntaxTreeParams, GetSyntaxTreeResult, OpenFileParams, OpenProjectParams, ParsePatternParams, ParsePatternResult, PatternId, PullActionsParams, PullActionsResult, - PullDiagnosticsParams, PullDiagnosticsResult, RenameResult, SearchPatternParams, SearchResults, - SupportsFeatureParams, UpdateProjectParams, UpdateSettingsParams, + PullDiagnosticsParams, PullDiagnosticsResult, RegisterWorkspaceFoldersParams, RenameResult, + SearchPatternParams, SearchResults, SupportsFeatureParams, UpdateProjectParams, + UpdateSettingsParams, WorkspaceKey, }; use crate::file_handlers::{ Capabilities, CodeActionsParams, DocumentFileSource, FixAllParams, LintParams, ParseResult, }; +use crate::settings::{SettingsHandleMut, WorkspaceSettings, WorkspacesHandleMut}; use crate::workspace::{ FileFeaturesResult, GetFileContentParams, IsPathIgnoredParams, OrganizeImportsParams, OrganizeImportsResult, RageEntry, RageParams, RageResult, ServerInfo, }; -use crate::{ - file_handlers::Features, - settings::{SettingsHandle, WorkspaceSettings}, - Workspace, WorkspaceError, -}; +use crate::{file_handlers::Features, settings::SettingsHandle, Workspace, WorkspaceError}; use biome_analyze::AnalysisFilter; use biome_diagnostics::{ serde::Diagnostic as SerdeDiagnostic, Diagnostic, DiagnosticExt, Severity, @@ -98,10 +96,20 @@ impl WorkspaceServer { } } + /// Provides a reference to the current settings fn settings(&self) -> SettingsHandle { SettingsHandle::new(&self.settings) } + /// Provides a mutable reference to the current settings + fn settings_mut(&self) -> SettingsHandleMut { + SettingsHandleMut::new(&self.settings) + } + + fn workspaces_mut(&self) -> WorkspacesHandleMut { + WorkspacesHandleMut::new(&self.settings) + } + /// Get the supported capabilities for a given file path fn get_file_capabilities(&self, path: &BiomePath) -> Capabilities { let language = self.get_file_source(path); @@ -338,14 +346,14 @@ impl Workspace for WorkspaceServer { let capabilities = self.get_file_capabilities(¶ms.path); let language = DocumentFileSource::from_path(¶ms.path); let path = params.path.as_path(); - let settings = self.settings.read().unwrap(); + let settings = self.settings(); let mut file_features = FileFeaturesResult::new(); let file_name = path.file_name().and_then(|s| s.to_str()); file_features = file_features .with_capabilities(&capabilities) - .with_settings_and_language(&settings, &language, path); + .with_settings_and_language(settings.as_ref(), &language, path); - if settings.files.ignore_unknown + if settings.as_ref().files.ignore_unknown && language == DocumentFileSource::Unknown && self.get_file_source(¶ms.path) == DocumentFileSource::Unknown { @@ -386,11 +394,11 @@ impl Workspace for WorkspaceServer { /// by another thread having previously panicked while holding the lock #[tracing::instrument(level = "trace", skip(self))] fn update_settings(&self, params: UpdateSettingsParams) -> Result<(), WorkspaceError> { - let mut settings = self.settings.write().unwrap(); + let mut settings = self.settings_mut(); - settings.merge_with_configuration( + settings.as_mut().merge_with_configuration( params.configuration, - params.working_directory, + params.workspace_directory, params.vcs_base_path, params.gitignore_matches.as_slice(), )?; @@ -399,7 +407,6 @@ impl Workspace for WorkspaceServer { self.file_features.clear(); Ok(()) } - /// Add a new file to the workspace fn open_file(&self, params: OpenFileParams) -> Result<(), WorkspaceError> { let index = self.set_source( @@ -419,7 +426,6 @@ impl Workspace for WorkspaceServer { ); Ok(()) } - fn open_project(&self, params: OpenProjectParams) -> Result<(), WorkspaceError> { let index = self.set_source(JsonFileSource::json().into()); self.syntax.remove(¶ms.path); @@ -435,6 +441,20 @@ impl Workspace for WorkspaceServer { Ok(()) } + fn register_workspace_folder( + &self, + params: RegisterWorkspaceFoldersParams, + ) -> Result { + let mut workspace = self.workspaces_mut(); + let key = workspace + .as_mut() + .insert_workspace(params.path.unwrap_or_default()); + if params.set_as_current_workspace { + workspace.as_mut().register_current_workspace(key); + } + Ok(key) + } + fn update_current_project(&self, params: UpdateProjectParams) -> Result<(), WorkspaceError> { let mut current_project_path = self.current_project_path.write().unwrap(); let _ = current_project_path.insert(params.path); @@ -586,8 +606,8 @@ impl Workspace for WorkspaceServer { .ok_or_else(self.build_capability_error(¶ms.path))?; let parse = self.get_parse(params.path.clone())?; - let settings = self.settings.read().unwrap(); - let rules = settings.linter().rules.as_ref(); + let settings = self.settings(); + let rules = settings.as_ref().linter().rules.as_ref(); let manifest = self.get_current_project()?.map(|pr| pr.manifest); let language = self.get_file_source(¶ms.path); Ok(code_actions(CodeActionsParams { @@ -671,10 +691,10 @@ impl Workspace for WorkspaceServer { .analyzer .fix_all .ok_or_else(self.build_capability_error(¶ms.path))?; - let settings = self.settings.read().unwrap(); + let settings = self.settings(); let parse = self.get_parse(params.path.clone())?; // Compute final rules (taking `overrides` into account) - let rules = settings.as_rules(params.path.as_path()); + let rules = settings.as_ref().as_rules(params.path.as_path()); let rule_filter_list = rules .as_ref() .map(|rules| rules.as_enabled_rules()) diff --git a/crates/biome_test_utils/src/lib.rs b/crates/biome_test_utils/src/lib.rs index 3ccc4b523026..30159e4695b2 100644 --- a/crates/biome_test_utils/src/lib.rs +++ b/crates/biome_test_utils/src/lib.rs @@ -9,7 +9,7 @@ use biome_json_parser::{JsonParserOptions, ParseDiagnostic}; use biome_project::PackageJson; use biome_rowan::{SyntaxKind, SyntaxNode, SyntaxSlot}; use biome_service::configuration::to_analyzer_rules; -use biome_service::settings::{ServiceLanguage, WorkspaceSettings}; +use biome_service::settings::{ServiceLanguage, Settings}; use json_comments::StripComments; use similar::TextDiff; use std::ffi::{c_int, OsStr}; @@ -67,7 +67,7 @@ pub fn create_analyzer_options( ); } else { let configuration = deserialized.into_deserialized().unwrap_or_default(); - let mut settings = WorkspaceSettings::default(); + let mut settings = Settings::default(); analyzer_configuration.preferred_quote = configuration .javascript .as_ref() From b886e809e30d8703ed7c9b221a4234fa5b045fdd Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 24 Apr 2024 16:00:42 +0100 Subject: [PATCH 2/6] refactor: foundations for LSP workspaces support --- Cargo.toml | 290 +++++++++++++-------------- crates/biome_fs/Cargo.toml | 36 ++-- crates/biome_service/Cargo.toml | 114 +++++------ crates/biome_service/src/settings.rs | 29 +-- 4 files changed, 230 insertions(+), 239 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dff7a0ddf851..69d9021c36d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,191 +1,191 @@ [workspace] # Use the newer version of the cargo resolver # https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions -members = ["crates/*", "xtask/bench", "xtask/codegen", "xtask/coverage", "xtask/libs_bench", "xtask/contributors"] +members = ["crates/*", "xtask/bench", "xtask/codegen", "xtask/coverage", "xtask/libs_bench", "xtask/contributors"] resolver = "2" [workspace.lints.rust] absolute_paths_not_starting_with_crate = "warn" -dead_code = "warn" -trivial_numeric_casts = "warn" -unused_import_braces = "warn" -unused_lifetimes = "warn" -unused_macro_rules = "warn" +dead_code = "warn" +trivial_numeric_casts = "warn" +unused_import_braces = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" [workspace.lints.clippy] -cargo_common_metadata = "allow" +cargo_common_metadata = "allow" multiple_crate_versions = "allow" # pedantic -checked_conversions = "warn" -cloned_instead_of_copied = "warn" -copy_iterator = "warn" -dbg_macro = "warn" -doc_link_with_quotes = "warn" -empty_enum = "warn" -expl_impl_clone_on_copy = "warn" -explicit_into_iter_loop = "warn" -filter_map_next = "warn" -flat_map_option = "warn" -fn_params_excessive_bools = "warn" +checked_conversions = "warn" +cloned_instead_of_copied = "warn" +copy_iterator = "warn" +dbg_macro = "warn" +doc_link_with_quotes = "warn" +empty_enum = "warn" +expl_impl_clone_on_copy = "warn" +explicit_into_iter_loop = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +fn_params_excessive_bools = "warn" from_iter_instead_of_collect = "warn" -implicit_clone = "warn" -implicit_hasher = "warn" -index_refutable_slice = "warn" -inefficient_to_string = "warn" -invalid_upcast_comparisons = "warn" -iter_not_returning_iterator = "warn" -large_stack_arrays = "warn" -large_types_passed_by_value = "warn" -macro_use_imports = "warn" -manual_ok_or = "warn" -manual_string_new = "warn" -map_flatten = "warn" -map_unwrap_or = "warn" +implicit_clone = "warn" +implicit_hasher = "warn" +index_refutable_slice = "warn" +inefficient_to_string = "warn" +invalid_upcast_comparisons = "warn" +iter_not_returning_iterator = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +macro_use_imports = "warn" +manual_ok_or = "warn" +manual_string_new = "warn" +map_flatten = "warn" +map_unwrap_or = "warn" mismatching_type_param_order = "warn" -mut_mut = "warn" -naive_bytecount = "warn" -needless_bitwise_bool = "warn" -needless_continue = "warn" -needless_for_each = "warn" +mut_mut = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_continue = "warn" +needless_for_each = "warn" no_effect_underscore_binding = "warn" -ref_binding_to_reference = "warn" -ref_option_ref = "warn" -stable_sort_primitive = "warn" -unnecessary_box_returns = "warn" -unnecessary_join = "warn" -unnested_or_patterns = "warn" -unreadable_literal = "warn" -verbose_bit_mask = "warn" -zero_sized_map_values = "warn" +ref_binding_to_reference = "warn" +ref_option_ref = "warn" +stable_sort_primitive = "warn" +unnecessary_box_returns = "warn" +unnecessary_join = "warn" +unnested_or_patterns = "warn" +unreadable_literal = "warn" +verbose_bit_mask = "warn" +zero_sized_map_values = "warn" # restriction -empty_drop = "warn" -float_cmp_const = "warn" -get_unwrap = "warn" -infinite_loop = "warn" -lossy_float_literal = "warn" -mem_forget = "warn" -rc_buffer = "warn" -rc_mutex = "warn" +empty_drop = "warn" +float_cmp_const = "warn" +get_unwrap = "warn" +infinite_loop = "warn" +lossy_float_literal = "warn" +mem_forget = "warn" +rc_buffer = "warn" +rc_mutex = "warn" rest_pat_in_fully_bound_structs = "warn" -verbose_file_reads = "warn" +verbose_file_reads = "warn" [workspace.package] -authors = ["Biome Developers and Contributors"] +authors = ["Biome Developers and Contributors"] categories = ["development-tools", "web-programming"] -edition = "2021" -homepage = "https://biomejs.dev/" -keywords = ["parser", "linter", "formatter"] -license = "MIT OR Apache-2.0" +edition = "2021" +homepage = "https://biomejs.dev/" +keywords = ["parser", "linter", "formatter"] +license = "MIT OR Apache-2.0" repository = "https://github.com/biomejs/biome" [profile.release-with-debug] -debug = true +debug = true inherits = "release" [workspace.dependencies] # publish -biome_analyze = { version = "0.5.7", path = "./crates/biome_analyze" } -biome_aria = { version = "0.5.7", path = "./crates/biome_aria" } -biome_aria_metadata = { version = "0.5.7", path = "./crates/biome_aria_metadata" } -biome_console = { version = "0.5.7", path = "./crates/biome_console" } -biome_control_flow = { version = "0.5.7", path = "./crates/biome_control_flow" } -biome_css_analyze = { version = "0.5.7", path = "./crates/biome_css_analyze" } -biome_css_factory = { version = "0.5.7", path = "./crates/biome_css_factory" } -biome_css_formatter = { version = "0.5.7", path = "./crates/biome_css_formatter" } -biome_css_parser = { version = "0.5.7", path = "./crates/biome_css_parser" } -biome_css_syntax = { version = "0.5.7", path = "./crates/biome_css_syntax" } -biome_deserialize = { version = "0.5.7", path = "./crates/biome_deserialize" } -biome_deserialize_macros = { version = "0.5.7", path = "./crates/biome_deserialize_macros" } -biome_diagnostics = { version = "0.5.7", path = "./crates/biome_diagnostics" } +biome_analyze = { version = "0.5.7", path = "./crates/biome_analyze" } +biome_aria = { version = "0.5.7", path = "./crates/biome_aria" } +biome_aria_metadata = { version = "0.5.7", path = "./crates/biome_aria_metadata" } +biome_console = { version = "0.5.7", path = "./crates/biome_console" } +biome_control_flow = { version = "0.5.7", path = "./crates/biome_control_flow" } +biome_css_analyze = { version = "0.5.7", path = "./crates/biome_css_analyze" } +biome_css_factory = { version = "0.5.7", path = "./crates/biome_css_factory" } +biome_css_formatter = { version = "0.5.7", path = "./crates/biome_css_formatter" } +biome_css_parser = { version = "0.5.7", path = "./crates/biome_css_parser" } +biome_css_syntax = { version = "0.5.7", path = "./crates/biome_css_syntax" } +biome_deserialize = { version = "0.5.7", path = "./crates/biome_deserialize" } +biome_deserialize_macros = { version = "0.5.7", path = "./crates/biome_deserialize_macros" } +biome_diagnostics = { version = "0.5.7", path = "./crates/biome_diagnostics" } biome_diagnostics_categories = { version = "0.5.7", path = "./crates/biome_diagnostics_categories" } -biome_diagnostics_macros = { version = "0.5.7", path = "./crates/biome_diagnostics_macros" } -biome_formatter = { version = "0.5.7", path = "./crates/biome_formatter" } -biome_fs = { version = "0.5.7", path = "./crates/biome_fs" } -biome_graphql_factory = { version = "0.1.0", path = "./crates/biome_graphql_factory" } -biome_graphql_syntax = { version = "0.1.0", path = "./crates/biome_graphql_syntax" } -biome_grit_factory = { version = "0.5.7", path = "./crates/biome_grit_factory" } -biome_grit_parser = { version = "0.1.0", path = "./crates/biome_grit_parser" } -biome_grit_patterns = { version = "0.0.1", path = "./crates/biome_grit_patterns" } -biome_grit_syntax = { version = "0.5.7", path = "./crates/biome_grit_syntax" } -biome_html_factory = { version = "0.5.7", path = "./crates/biome_html_factory" } -biome_html_syntax = { version = "0.5.7", path = "./crates/biome_html_syntax" } -biome_js_analyze = { version = "0.5.7", path = "./crates/biome_js_analyze" } -biome_js_factory = { version = "0.5.7", path = "./crates/biome_js_factory" } -biome_js_formatter = { version = "0.5.7", path = "./crates/biome_js_formatter" } -biome_js_parser = { version = "0.5.7", path = "./crates/biome_js_parser" } -biome_js_semantic = { version = "0.5.7", path = "./crates/biome_js_semantic" } -biome_js_syntax = { version = "0.5.7", path = "./crates/biome_js_syntax" } -biome_json_analyze = { version = "0.5.7", path = "./crates/biome_json_analyze" } -biome_json_factory = { version = "0.5.7", path = "./crates/biome_json_factory" } -biome_json_formatter = { version = "0.5.7", path = "./crates/biome_json_formatter" } -biome_json_parser = { version = "0.5.7", path = "./crates/biome_json_parser" } -biome_json_syntax = { version = "0.5.7", path = "./crates/biome_json_syntax" } -biome_yaml_factory = { version = "0.0.1", path = "./crates/biome_yaml_factory" } -biome_yaml_parser = { version = "0.0.1", path = "./crates/biome_yaml_parser" } -biome_yaml_syntax = { version = "0.0.1", path = "./crates/biome_yaml_syntax" } +biome_diagnostics_macros = { version = "0.5.7", path = "./crates/biome_diagnostics_macros" } +biome_formatter = { version = "0.5.7", path = "./crates/biome_formatter" } +biome_fs = { version = "0.5.7", path = "./crates/biome_fs" } +biome_graphql_factory = { version = "0.1.0", path = "./crates/biome_graphql_factory" } +biome_graphql_syntax = { version = "0.1.0", path = "./crates/biome_graphql_syntax" } +biome_grit_factory = { version = "0.5.7", path = "./crates/biome_grit_factory" } +biome_grit_parser = { version = "0.1.0", path = "./crates/biome_grit_parser" } +biome_grit_patterns = { version = "0.0.1", path = "./crates/biome_grit_patterns" } +biome_grit_syntax = { version = "0.5.7", path = "./crates/biome_grit_syntax" } +biome_html_factory = { version = "0.5.7", path = "./crates/biome_html_factory" } +biome_html_syntax = { version = "0.5.7", path = "./crates/biome_html_syntax" } +biome_js_analyze = { version = "0.5.7", path = "./crates/biome_js_analyze" } +biome_js_factory = { version = "0.5.7", path = "./crates/biome_js_factory" } +biome_js_formatter = { version = "0.5.7", path = "./crates/biome_js_formatter" } +biome_js_parser = { version = "0.5.7", path = "./crates/biome_js_parser" } +biome_js_semantic = { version = "0.5.7", path = "./crates/biome_js_semantic" } +biome_js_syntax = { version = "0.5.7", path = "./crates/biome_js_syntax" } +biome_json_analyze = { version = "0.5.7", path = "./crates/biome_json_analyze" } +biome_json_factory = { version = "0.5.7", path = "./crates/biome_json_factory" } +biome_json_formatter = { version = "0.5.7", path = "./crates/biome_json_formatter" } +biome_json_parser = { version = "0.5.7", path = "./crates/biome_json_parser" } +biome_json_syntax = { version = "0.5.7", path = "./crates/biome_json_syntax" } +biome_yaml_factory = { version = "0.0.1", path = "./crates/biome_yaml_factory" } +biome_yaml_parser = { version = "0.0.1", path = "./crates/biome_yaml_parser" } +biome_yaml_syntax = { version = "0.0.1", path = "./crates/biome_yaml_syntax" } -biome_markup = { version = "0.5.7", path = "./crates/biome_markup" } -biome_parser = { version = "0.5.7", path = "./crates/biome_parser" } -biome_project = { version = "0.5.7", path = "./crates/biome_project" } -biome_rowan = { version = "0.5.7", path = "./crates/biome_rowan" } -biome_string_case = { version = "0.5.7", path = "./crates/biome_string_case" } -biome_suppression = { version = "0.5.7", path = "./crates/biome_suppression" } -biome_text_edit = { version = "0.5.7", path = "./crates/biome_text_edit" } -biome_text_size = { version = "0.5.7", path = "./crates/biome_text_size" } +biome_markup = { version = "0.5.7", path = "./crates/biome_markup" } +biome_parser = { version = "0.5.7", path = "./crates/biome_parser" } +biome_project = { version = "0.5.7", path = "./crates/biome_project" } +biome_rowan = { version = "0.5.7", path = "./crates/biome_rowan" } +biome_string_case = { version = "0.5.7", path = "./crates/biome_string_case" } +biome_suppression = { version = "0.5.7", path = "./crates/biome_suppression" } +biome_text_edit = { version = "0.5.7", path = "./crates/biome_text_edit" } +biome_text_size = { version = "0.5.7", path = "./crates/biome_text_size" } biome_unicode_table = { version = "0.5.7", path = "./crates/biome_unicode_table" } # not publish -biome_cli = { path = "./crates/biome_cli" } -biome_configuration = { path = "./crates/biome_configuration" } -biome_flags = { path = "./crates/biome_flags" } +biome_cli = { path = "./crates/biome_cli" } +biome_configuration = { path = "./crates/biome_configuration" } +biome_flags = { path = "./crates/biome_flags" } biome_formatter_test = { path = "./crates/biome_formatter_test" } -biome_lsp = { path = "./crates/biome_lsp" } -biome_migrate = { path = "./crates/biome_migrate" } -biome_service = { path = "./crates/biome_service" } -biome_test_utils = { path = "./crates/biome_test_utils" } -biome_ungrammar = { path = "./crates/biome_ungrammar" } -tests_macros = { path = "./crates/tests_macros" } +biome_lsp = { path = "./crates/biome_lsp" } +biome_migrate = { path = "./crates/biome_migrate" } +biome_service = { path = "./crates/biome_service" } +biome_test_utils = { path = "./crates/biome_test_utils" } +biome_ungrammar = { path = "./crates/biome_ungrammar" } +tests_macros = { path = "./crates/tests_macros" } # Crates needed in the workspace -bitflags = "2.5.0" -bpaf = { version = "0.9.9", features = ["derive"] } -countme = "3.0.1" -crossbeam = "0.8.4" -dashmap = "5.4.0" -ignore = "0.4.21" -indexmap = "1.9.3" -insta = "1.38.0" -lazy_static = "1.4.0" -oxc_resolver = "1.4.0" -proc-macro2 = "1.0.81" -quickcheck = "1.0.3" -quickcheck_macros = "1.0.0" -quote = "1.0.36" -rayon = "1.8.1" -regex = "1.10.4" -rustc-hash = "1.1.0" -schemars = { version = "0.8.12" } -serde = { version = "1.0.198", features = ["derive"] } -serde_json = "1.0.116" -similar = "2.5.0" -smallvec = { version = "1.10.0", features = ["union", "const_new"] } -syn = "1.0.109" -tokio = { version = "1.36.0" } -tracing = { version = "0.1.37", default-features = false, features = ["std"] } +bitflags = "2.5.0" +bpaf = { version = "0.9.9", features = ["derive"] } +countme = "3.0.1" +crossbeam = "0.8.4" +dashmap = "5.4.0" +ignore = "0.4.21" +indexmap = "1.9.3" +insta = "1.38.0" +lazy_static = "1.4.0" +oxc_resolver = "1.4.0" +proc-macro2 = "1.0.81" +quickcheck = "1.0.3" +quickcheck_macros = "1.0.0" +quote = "1.0.36" +rayon = "1.8.1" +regex = "1.10.4" +rustc-hash = "1.1.0" +schemars = { version = "0.8.12" } +serde = { version = "1.0.198", features = ["derive"] } +serde_json = "1.0.116" +similar = "2.5.0" +slotmap = "1.0.7" +smallvec = { version = "1.10.0", features = ["union", "const_new"] } +syn = "1.0.109" +tokio = { version = "1.36.0" } +tracing = { version = "0.1.37", default-features = false, features = ["std"] } tracing-subscriber = "0.3.18" -unicode-bom = "2.0.3" -slotmap = "1.0.7" +unicode-bom = "2.0.3" [profile.dev.package.biome_wasm] -debug = true +debug = true opt-level = "s" [profile.test.package.biome_wasm] -debug = true +debug = true opt-level = "s" [profile.release.package.biome_wasm] -debug = false +debug = false opt-level = 3 diff --git a/crates/biome_fs/Cargo.toml b/crates/biome_fs/Cargo.toml index a72aab993427..926008006f12 100644 --- a/crates/biome_fs/Cargo.toml +++ b/crates/biome_fs/Cargo.toml @@ -1,29 +1,29 @@ [package] -authors.workspace = true +authors.workspace = true categories.workspace = true -description = "A small wrapper around std::path::PathBuf contains additional information and convenient methods" -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "biome_fs" +description = "A small wrapper around std::path::PathBuf contains additional information and convenient methods" +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "biome_fs" repository.workspace = true -version = "0.5.7" +version = "0.5.7" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] biome_diagnostics = { workspace = true } -crossbeam = { workspace = true } -directories = "5.0.1" -indexmap = { workspace = true } -oxc_resolver = { workspace = true } -parking_lot = { version = "0.12.0", features = ["arc_lock"] } -rayon = { workspace = true } -rustc-hash = { workspace = true } -schemars = { workspace = true, optional = true } -serde = { workspace = true } -tracing = { workspace = true } +crossbeam = { workspace = true } +directories = "5.0.1" +indexmap = { workspace = true } +oxc_resolver = { workspace = true } +parking_lot = { version = "0.12.0", features = ["arc_lock"] } +rayon = { workspace = true } +rustc-hash = { workspace = true } +schemars = { workspace = true, optional = true } +serde = { workspace = true } +tracing = { workspace = true } [features] serde = ["schemars", "biome_diagnostics/schema"] diff --git a/crates/biome_service/Cargo.toml b/crates/biome_service/Cargo.toml index 9394d8541438..5d63bf97af46 100644 --- a/crates/biome_service/Cargo.toml +++ b/crates/biome_service/Cargo.toml @@ -1,74 +1,74 @@ [package] -authors.workspace = true +authors.workspace = true categories.workspace = true -description = "Biome's core functionality" -edition.workspace = true -homepage.workspace = true -keywords.workspace = true -license.workspace = true -name = "biome_service" -publish = false +description = "Biome's core functionality" +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "biome_service" +publish = false repository.workspace = true -version = "0.0.0" +version = "0.0.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -biome_analyze = { workspace = true, features = ["serde"] } -biome_configuration = { workspace = true, features = ["schema"] } -biome_console = { workspace = true } -biome_css_analyze = { workspace = true } -biome_css_formatter = { workspace = true } -biome_css_parser = { workspace = true } -biome_css_syntax = { workspace = true } -biome_deserialize = { workspace = true } +biome_analyze = { workspace = true, features = ["serde"] } +biome_configuration = { workspace = true, features = ["schema"] } +biome_console = { workspace = true } +biome_css_analyze = { workspace = true } +biome_css_formatter = { workspace = true } +biome_css_parser = { workspace = true } +biome_css_syntax = { workspace = true } +biome_deserialize = { workspace = true } biome_deserialize_macros = { workspace = true } -biome_diagnostics = { workspace = true } -biome_flags = { workspace = true } -biome_formatter = { workspace = true, features = ["serde"] } -biome_fs = { workspace = true, features = ["serde"] } -biome_grit_patterns = { workspace = true } -biome_js_analyze = { workspace = true } -biome_js_factory = { workspace = true, optional = true } -biome_js_formatter = { workspace = true, features = ["serde"] } -biome_js_parser = { workspace = true } -biome_js_semantic = { workspace = true } -biome_js_syntax = { workspace = true, features = ["schema"] } -biome_json_analyze = { workspace = true } -biome_json_formatter = { workspace = true, features = ["serde"] } -biome_json_parser = { workspace = true } -biome_json_syntax = { workspace = true } -biome_parser = { workspace = true } -biome_project = { workspace = true } -biome_rowan = { workspace = true, features = ["serde"] } -biome_text_edit = { workspace = true } -bpaf = { workspace = true } -dashmap = { workspace = true } -ignore = { workspace = true } -indexmap = { workspace = true, features = ["serde"] } -lazy_static = { workspace = true } -oxc_resolver = { workspace = true } -regex = { workspace = true } -rustc-hash = { workspace = true } -schemars = { workspace = true, features = ["indexmap1"], optional = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true, features = ["raw_value"] } -tracing = { workspace = true, features = ["attributes", "log"] } -slotmap = { workspace = true, features = ["serde"] } +biome_diagnostics = { workspace = true } +biome_flags = { workspace = true } +biome_formatter = { workspace = true, features = ["serde"] } +biome_fs = { workspace = true, features = ["serde"] } +biome_grit_patterns = { workspace = true } +biome_js_analyze = { workspace = true } +biome_js_factory = { workspace = true, optional = true } +biome_js_formatter = { workspace = true, features = ["serde"] } +biome_js_parser = { workspace = true } +biome_js_semantic = { workspace = true } +biome_js_syntax = { workspace = true, features = ["schema"] } +biome_json_analyze = { workspace = true } +biome_json_formatter = { workspace = true, features = ["serde"] } +biome_json_parser = { workspace = true } +biome_json_syntax = { workspace = true } +biome_parser = { workspace = true } +biome_project = { workspace = true } +biome_rowan = { workspace = true, features = ["serde"] } +biome_text_edit = { workspace = true } +bpaf = { workspace = true } +dashmap = { workspace = true } +ignore = { workspace = true } +indexmap = { workspace = true, features = ["serde"] } +lazy_static = { workspace = true } +oxc_resolver = { workspace = true } +regex = { workspace = true } +rustc-hash = { workspace = true } +schemars = { workspace = true, features = ["indexmap1"], optional = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true, features = ["raw_value"] } +slotmap = { workspace = true, features = ["serde"] } +tracing = { workspace = true, features = ["attributes", "log"] } [features] format_css = ["biome_css_formatter/format_css"] schema = [ - "dep:schemars", - "biome_js_analyze/schema", - "biome_formatter/serde", - "biome_js_factory", - "biome_text_edit/schemars", - "biome_json_syntax/schema", - "biome_css_syntax/schema", + "dep:schemars", + "biome_js_analyze/schema", + "biome_formatter/serde", + "biome_js_factory", + "biome_text_edit/schemars", + "biome_json_syntax/schema", + "biome_css_syntax/schema", ] [dev-dependencies] -insta = { workspace = true } +insta = { workspace = true } tests_macros = { workspace = true } [lints] diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index b09972bfe28e..9ccb06913baf 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -36,21 +36,12 @@ use std::{ sync::{RwLock, RwLockReadGuard}, }; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct PathToSettings { path: BiomePath, settings: Settings, } -impl Default for PathToSettings { - fn default() -> Self { - Self { - path: BiomePath::default(), - settings: Settings::default(), - } - } -} - #[derive(Debug, Default)] pub struct WorkspaceSettings { data: WorkspaceData, @@ -60,7 +51,7 @@ pub struct WorkspaceSettings { impl WorkspaceSettings { pub fn current_settings(&self) -> &Settings { debug_assert!( - self.data.paths.len() > 0, + !self.data.paths.is_empty(), "You must have at least one workspace." ); let data = self.data.paths.get(self.current_workspace).unwrap(); @@ -73,7 +64,7 @@ impl WorkspaceSettings { pub fn current_settings_mut(&mut self) -> &mut Settings { debug_assert!( - self.data.paths.len() > 0, + !self.data.paths.is_empty(), "You must have at least one workspace." ); &mut self.data.get_mut(self.current_workspace).unwrap().settings @@ -90,11 +81,11 @@ impl WorkspaceSettings { pub fn current_workspace_path(&self, path: &BiomePath) -> (WorkspaceKey, &BiomePath) { debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); debug_assert!( - self.data.paths.len() > 0, + !self.data.paths.is_empty(), "You must have at least one workspace." ); for (key, path_to_settings) in &self.data.paths { - if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { return (key, &path_to_settings.path); } } @@ -104,11 +95,11 @@ impl WorkspaceSettings { pub fn get_settings_by_path(&self, path: &BiomePath) -> &Settings { debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); debug_assert!( - self.data.paths.len() > 0, + !self.data.paths.is_empty(), "You must have at least one workspace." ); for (_, path_to_settings) in &self.data.paths { - if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { return &path_to_settings.settings; } } @@ -118,11 +109,11 @@ impl WorkspaceSettings { pub fn get_settings_by_path_mut(&mut self, path: &Path) -> &mut Settings { debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); debug_assert!( - self.data.paths.len() > 0, + !self.data.paths.is_empty(), "You must have at least one workspace." ); for (_, path_to_settings) in &mut self.data.paths { - if let Ok(_) = path.strip_prefix(path_to_settings.path.as_path()) { + if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { return &mut path_to_settings.settings; } } @@ -601,7 +592,7 @@ impl<'a> SettingsHandle<'a> { impl<'a> AsRef for SettingsHandle<'a> { fn as_ref(&self) -> &Settings { - &self.inner.current_settings() + self.inner.current_settings() } } From be217befa508050ccc9c72c0daa996c546cd238e Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 25 Apr 2024 08:57:28 +0100 Subject: [PATCH 3/6] chore: fix regressions --- crates/biome_cli/src/commands/migrate.rs | 9 +++++ crates/biome_service/src/workspace.rs | 14 ++++++++ crates/biome_service/src/workspace_types.rs | 3 +- crates/biome_wasm/src/lib.rs | 19 +++++++++- .../@biomejs/backend-jsonrpc/src/workspace.ts | 13 ++++++- packages/@biomejs/js-api/src/index.ts | 36 ++++++++++--------- 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/crates/biome_cli/src/commands/migrate.rs b/crates/biome_cli/src/commands/migrate.rs index 11cbb2dafa61..dd91c0ed4b2f 100644 --- a/crates/biome_cli/src/commands/migrate.rs +++ b/crates/biome_cli/src/commands/migrate.rs @@ -4,6 +4,7 @@ use crate::execute::{execute_mode, Execution, TraversalMode}; use crate::{setup_cli_subscriber, CliDiagnostic, CliSession}; use biome_console::{markup, ConsoleExt}; use biome_service::configuration::{load_configuration, LoadedConfiguration}; +use biome_service::workspace::RegisterWorkspaceFoldersParams; use super::MigrateSubCommand; @@ -23,6 +24,14 @@ pub(crate) fn migrate( } = load_configuration(&session.app.fs, base_path)?; setup_cli_subscriber(cli_options.log_level, cli_options.log_kind); + session + .app + .workspace + .register_workspace_folder(RegisterWorkspaceFoldersParams { + path: session.app.fs.working_directory(), + set_as_current_workspace: true, + })?; + if let (Some(path), Some(directory_path)) = (file_path, directory_path) { execute_mode( Execution::new(TraversalMode::Migrate { diff --git a/crates/biome_service/src/workspace.rs b/crates/biome_service/src/workspace.rs index 216f853fc8b2..4ca6af7cb014 100644 --- a/crates/biome_service/src/workspace.rs +++ b/crates/biome_service/src/workspace.rs @@ -63,6 +63,8 @@ use biome_formatter::Printed; use biome_fs::BiomePath; use biome_js_syntax::{TextRange, TextSize}; use biome_text_edit::TextEdit; +#[cfg(feature = "schema")] +use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema}; use slotmap::{new_key_type, DenseSlotMap}; use std::collections::HashMap; use std::ffi::OsStr; @@ -734,6 +736,7 @@ pub struct IsPathIgnoredParams { #[derive(Debug, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase")] pub struct RegisterWorkspaceFoldersParams { pub path: Option, pub set_as_current_workspace: bool, @@ -1003,6 +1006,17 @@ new_key_type! { pub struct WorkspaceKey; } +#[cfg(feature = "schema")] +impl JsonSchema for WorkspaceKey { + fn schema_name() -> String { + "WorkspaceKey".to_string() + } + + fn json_schema(gen: &mut SchemaGenerator) -> Schema { + ::json_schema(gen) + } +} + #[derive(Debug, Default)] pub struct WorkspaceData { /// [DenseSlotMap] is the slowest type in insertion/removal, but the fastest in iteration diff --git a/crates/biome_service/src/workspace_types.rs b/crates/biome_service/src/workspace_types.rs index 7e447f4377f7..5ab741d08949 100644 --- a/crates/biome_service/src/workspace_types.rs +++ b/crates/biome_service/src/workspace_types.rs @@ -451,10 +451,11 @@ macro_rules! workspace_method { } /// Returns a list of signature for all the methods in the [Workspace] trait -pub fn methods() -> [WorkspaceMethod; 19] { +pub fn methods() -> [WorkspaceMethod; 20] { [ WorkspaceMethod::of::("file_features"), workspace_method!(update_settings), + workspace_method!(register_workspace_folder), workspace_method!(update_current_project), workspace_method!(open_project), workspace_method!(open_file), diff --git a/crates/biome_wasm/src/lib.rs b/crates/biome_wasm/src/lib.rs index 8ff379832869..391263c20549 100644 --- a/crates/biome_wasm/src/lib.rs +++ b/crates/biome_wasm/src/lib.rs @@ -5,7 +5,7 @@ use biome_service::workspace::{ self, ChangeFileParams, CloseFileParams, FixFileParams, FormatFileParams, FormatOnTypeParams, FormatRangeParams, GetControlFlowGraphParams, GetFileContentParams, GetFormatterIRParams, GetSyntaxTreeParams, OrganizeImportsParams, PullActionsParams, PullDiagnosticsParams, - RenameParams, UpdateSettingsParams, + RegisterWorkspaceFoldersParams, RenameParams, UpdateSettingsParams, WorkspaceKey, }; use biome_service::workspace::{OpenFileParams, SupportsFeatureParams}; @@ -56,6 +56,23 @@ impl Workspace { self.inner.update_settings(params).map_err(into_error) } + #[wasm_bindgen(js_name = registerWorkspaceFolder)] + pub fn register_workspace_folder( + &self, + params: IRegisterWorkspaceFoldersParams, + ) -> Result { + let params: RegisterWorkspaceFoldersParams = + serde_wasm_bindgen::from_value(params.into()).map_err(into_error)?; + let result = self + .inner + .register_workspace_folder(params) + .map_err(into_error)?; + + to_value(&result) + .map(IWorkspaceKey::from) + .map_err(into_error) + } + #[wasm_bindgen(js_name = openFile)] pub fn open_file(&self, params: IOpenFileParams) -> Result<(), Error> { let params: OpenFileParams = diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 64e80b479d75..0ee1365d355a 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -21,7 +21,7 @@ export interface UpdateSettingsParams { configuration: PartialConfiguration; gitignore_matches: string[]; vcs_base_path?: string; - working_directory?: string; + workspace_directory?: string; } /** * The configuration that is contained inside the file `biome.json` @@ -1729,6 +1729,11 @@ export type FilenameCase = | "kebab-case" | "PascalCase" | "snake_case"; +export interface RegisterWorkspaceFoldersParams { + path?: string; + setAsCurrentWorkspace: boolean; +} +export type WorkspaceKey = string; export interface UpdateProjectParams { path: BiomePath; } @@ -2337,6 +2342,9 @@ export type Configuration = PartialConfiguration; export interface Workspace { fileFeatures(params: SupportsFeatureParams): Promise; updateSettings(params: UpdateSettingsParams): Promise; + registerWorkspaceFolder( + params: RegisterWorkspaceFoldersParams, + ): Promise; updateCurrentProject(params: UpdateProjectParams): Promise; openProject(params: OpenProjectParams): Promise; openFile(params: OpenFileParams): Promise; @@ -2368,6 +2376,9 @@ export function createWorkspace(transport: Transport): Workspace { updateSettings(params) { return transport.request("biome/update_settings", params); }, + registerWorkspaceFolder(params) { + return transport.request("biome/register_workspace_folder", params); + }, updateCurrentProject(params) { return transport.request("biome/update_current_project", params); }, diff --git a/packages/@biomejs/js-api/src/index.ts b/packages/@biomejs/js-api/src/index.ts index 1e6e8b2d768b..58f33663842c 100644 --- a/packages/@biomejs/js-api/src/index.ts +++ b/packages/@biomejs/js-api/src/index.ts @@ -6,12 +6,12 @@ import type { PullDiagnosticsResult, Workspace, } from "@biomejs/wasm-nodejs"; -import { Distribution, type WasmModule, loadModule, wrapError } from "./wasm"; +import {Distribution, type WasmModule, loadModule, wrapError} from "./wasm"; // Re-export of some useful types for users export type Configuration = PartialConfiguration; -export type { Diagnostic }; -export { Distribution }; +export type {Diagnostic}; +export {Distribution}; export interface FormatContentDebugOptions extends FormatContentOptions { /** @@ -93,7 +93,8 @@ export class Biome { private constructor( private readonly module: WasmModule, private readonly workspace: Workspace, - ) {} + ) { + } /** * It creates a new instance of the class {Biome}. @@ -123,6 +124,9 @@ export class Biome { */ public applyConfiguration(configuration: Configuration): void { try { + this.workspace.registerWorkspaceFolder({ + setAsCurrentWorkspace: true + }) this.workspace.updateSettings({ configuration, gitignore_matches: [], @@ -185,7 +189,7 @@ export class Biome { return this.withFile(options.filePath, content, (path) => { let code = content; - const { diagnostics } = this.workspace.pullDiagnostics({ + const {diagnostics} = this.workspace.pullDiagnostics({ path, categories: ["Syntax"], max_diagnostics: Number.MAX_SAFE_INTEGER, @@ -236,26 +240,26 @@ export class Biome { */ lintContent( content: string, - { filePath, fixFileMode }: LintContentOptions, + {filePath, fixFileMode}: LintContentOptions, ): LintResult { const maybeFixedContent = fixFileMode ? this.withFile(filePath, content, (path) => { - let code = content; + let code = content; - const result = this.workspace.fixFile({ - path, - fix_file_mode: fixFileMode, - should_format: false, - }); + const result = this.workspace.fixFile({ + path, + fix_file_mode: fixFileMode, + should_format: false, + }); - code = result.code; + code = result.code; - return code; - }) + return code; + }) : content; return this.withFile(filePath, maybeFixedContent, (path) => { - const { diagnostics } = this.workspace.pullDiagnostics({ + const {diagnostics} = this.workspace.pullDiagnostics({ path, categories: ["Syntax", "Lint"], max_diagnostics: Number.MAX_SAFE_INTEGER, From 270be05fb5d96eddc1aa21040a9805c8c1b76c42 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 25 Apr 2024 09:13:00 +0100 Subject: [PATCH 4/6] chore: rename to sue the "project" concept --- crates/biome_cli/src/commands/check.rs | 4 +- crates/biome_cli/src/commands/ci.rs | 4 +- crates/biome_cli/src/commands/format.rs | 4 +- crates/biome_cli/src/commands/lint.rs | 4 +- crates/biome_cli/src/commands/migrate.rs | 4 +- crates/biome_cli/src/commands/search.rs | 4 +- crates/biome_lsp/src/server.rs | 2 +- crates/biome_lsp/src/session.rs | 6 +- crates/biome_service/src/settings.rs | 67 +++++++------------- crates/biome_service/src/workspace.rs | 20 +++--- crates/biome_service/src/workspace/client.rs | 12 ++-- crates/biome_service/src/workspace/server.rs | 18 +++--- crates/biome_service/src/workspace_types.rs | 2 +- crates/biome_wasm/src/lib.rs | 10 +-- packages/@biomejs/js-api/src/index.ts | 6 +- 15 files changed, 72 insertions(+), 95 deletions(-) diff --git a/crates/biome_cli/src/commands/check.rs b/crates/biome_cli/src/commands/check.rs index d590bc8acd81..25899e9e6076 100644 --- a/crates/biome_cli/src/commands/check.rs +++ b/crates/biome_cli/src/commands/check.rs @@ -11,7 +11,7 @@ use biome_configuration::{ }; use biome_deserialize::Merge; use biome_service::configuration::PartialConfigurationExt; -use biome_service::workspace::RegisterWorkspaceFoldersParams; +use biome_service::workspace::RegisterProjectFolderParams; use biome_service::{ configuration::{load_configuration, LoadedConfiguration}, workspace::{FixFileMode, UpdateSettingsParams}, @@ -133,7 +133,7 @@ pub(crate) fn check( session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_cli/src/commands/ci.rs b/crates/biome_cli/src/commands/ci.rs index 820af8730e2e..fd7540748447 100644 --- a/crates/biome_cli/src/commands/ci.rs +++ b/crates/biome_cli/src/commands/ci.rs @@ -8,7 +8,7 @@ use biome_deserialize::Merge; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::{RegisterWorkspaceFoldersParams, UpdateSettingsParams}; +use biome_service::workspace::{RegisterProjectFolderParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct CiCommandPayload { @@ -109,7 +109,7 @@ pub(crate) fn ci(session: CliSession, payload: CiCommandPayload) -> Result<(), C session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_cli/src/commands/format.rs b/crates/biome_cli/src/commands/format.rs index db3601d073b6..7efae9ddaf6d 100644 --- a/crates/biome_cli/src/commands/format.rs +++ b/crates/biome_cli/src/commands/format.rs @@ -17,7 +17,7 @@ use biome_diagnostics::PrintDiagnostic; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::{RegisterWorkspaceFoldersParams, UpdateSettingsParams}; +use biome_service::workspace::{RegisterProjectFolderParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct FormatCommandPayload { @@ -168,7 +168,7 @@ pub(crate) fn format( session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_cli/src/commands/lint.rs b/crates/biome_cli/src/commands/lint.rs index caa71f53e653..e010f2962ced 100644 --- a/crates/biome_cli/src/commands/lint.rs +++ b/crates/biome_cli/src/commands/lint.rs @@ -13,7 +13,7 @@ use biome_deserialize::Merge; use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; -use biome_service::workspace::{FixFileMode, RegisterWorkspaceFoldersParams, UpdateSettingsParams}; +use biome_service::workspace::{FixFileMode, RegisterProjectFolderParams, UpdateSettingsParams}; use std::ffi::OsString; pub(crate) struct LintCommandPayload { @@ -109,7 +109,7 @@ pub(crate) fn lint(session: CliSession, payload: LintCommandPayload) -> Result<( session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_cli/src/commands/migrate.rs b/crates/biome_cli/src/commands/migrate.rs index dd91c0ed4b2f..3a58f3e17e0c 100644 --- a/crates/biome_cli/src/commands/migrate.rs +++ b/crates/biome_cli/src/commands/migrate.rs @@ -4,7 +4,7 @@ use crate::execute::{execute_mode, Execution, TraversalMode}; use crate::{setup_cli_subscriber, CliDiagnostic, CliSession}; use biome_console::{markup, ConsoleExt}; use biome_service::configuration::{load_configuration, LoadedConfiguration}; -use biome_service::workspace::RegisterWorkspaceFoldersParams; +use biome_service::workspace::RegisterProjectFolderParams; use super::MigrateSubCommand; @@ -27,7 +27,7 @@ pub(crate) fn migrate( session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_cli/src/commands/search.rs b/crates/biome_cli/src/commands/search.rs index 61e8bc209982..c599962cd2d1 100644 --- a/crates/biome_cli/src/commands/search.rs +++ b/crates/biome_cli/src/commands/search.rs @@ -9,7 +9,7 @@ use biome_service::configuration::{ load_configuration, LoadedConfiguration, PartialConfigurationExt, }; use biome_service::workspace::{ - ParsePatternParams, RegisterWorkspaceFoldersParams, UpdateSettingsParams, + ParsePatternParams, RegisterProjectFolderParams, UpdateSettingsParams, }; use std::ffi::OsString; @@ -64,7 +64,7 @@ pub(crate) fn search( session .app .workspace - .register_workspace_folder(RegisterWorkspaceFoldersParams { + .register_project_folder(RegisterProjectFolderParams { path: session.app.fs.working_directory(), set_as_current_workspace: true, })?; diff --git a/crates/biome_lsp/src/server.rs b/crates/biome_lsp/src/server.rs index 73b9c301064b..c8197e277aa2 100644 --- a/crates/biome_lsp/src/server.rs +++ b/crates/biome_lsp/src/server.rs @@ -575,7 +575,7 @@ impl ServerFactory { workspace_method!(builder, file_features); workspace_method!(builder, is_path_ignored); workspace_method!(builder, update_settings); - workspace_method!(builder, register_workspace_folder); + workspace_method!(builder, register_project_folder); workspace_method!(builder, open_file); workspace_method!(builder, open_project); workspace_method!(builder, update_current_project); diff --git a/crates/biome_lsp/src/session.rs b/crates/biome_lsp/src/session.rs index 5282d65546fc..872f24c16f4e 100644 --- a/crates/biome_lsp/src/session.rs +++ b/crates/biome_lsp/src/session.rs @@ -15,7 +15,7 @@ use biome_service::configuration::{ use biome_service::file_handlers::{AstroFileHandler, SvelteFileHandler, VueFileHandler}; use biome_service::workspace::{ FeaturesBuilder, GetFileContentParams, OpenProjectParams, PullDiagnosticsParams, - RegisterWorkspaceFoldersParams, SupportsFeatureParams, UpdateProjectParams, + RegisterProjectFolderParams, SupportsFeatureParams, UpdateProjectParams, }; use biome_service::workspace::{RageEntry, RageParams, RageResult, UpdateSettingsParams}; use biome_service::Workspace; @@ -452,8 +452,8 @@ impl Session { match result { Ok((vcs_base_path, gitignore_matches)) => { // We don't need the key for now, but will soon - let _ = self.workspace.register_workspace_folder( - RegisterWorkspaceFoldersParams { + let _ = self.workspace.register_project_folder( + RegisterProjectFolderParams { path: fs.working_directory(), set_as_current_workspace: true, }, diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index 9ccb06913baf..0946a196d190 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -1,4 +1,4 @@ -use crate::workspace::{DocumentFileSource, WorkspaceData, WorkspaceKey}; +use crate::workspace::{DocumentFileSource, ProjectKey, WorkspaceData}; use crate::{Matcher, WorkspaceError}; use biome_analyze::AnalyzerRules; use biome_configuration::diagnostics::InvalidIgnorePattern; @@ -45,53 +45,44 @@ pub struct PathToSettings { #[derive(Debug, Default)] pub struct WorkspaceSettings { data: WorkspaceData, - current_workspace: WorkspaceKey, + current_workspace: ProjectKey, } impl WorkspaceSettings { + /// Retrieves the settings of the current workspace folder pub fn current_settings(&self) -> &Settings { - debug_assert!( - !self.data.paths.is_empty(), - "You must have at least one workspace." - ); - let data = self.data.paths.get(self.current_workspace).unwrap(); + let data = self + .data + .paths + .get(self.current_workspace) + .expect("You must have at least one workspace."); &data.settings } - pub fn register_current_workspace(&mut self, key: WorkspaceKey) { + /// Register a new + pub fn register_current_project(&mut self, key: ProjectKey) { self.current_workspace = key; } - pub fn current_settings_mut(&mut self) -> &mut Settings { - debug_assert!( - !self.data.paths.is_empty(), - "You must have at least one workspace." - ); - &mut self.data.get_mut(self.current_workspace).unwrap().settings + /// Retrieves a mutable reference of the settings of the current project + pub fn get_current_settings_mut(&mut self) -> &mut Settings { + &mut self + .data + .get_mut(self.current_workspace) + .expect("You must have at least one workspace.") + .settings } - pub fn insert_workspace(&mut self, workspace_path: impl Into) -> WorkspaceKey { + /// Register a new project using its folder. Use [WorkspaceSettings::get_current_settings_mut] to retrieve + /// its settings and change them. + pub fn insert_project(&mut self, workspace_path: impl Into) -> ProjectKey { self.data.paths.insert(PathToSettings { path: BiomePath::new(workspace_path.into()), settings: Settings::default(), }) } - /// - pub fn current_workspace_path(&self, path: &BiomePath) -> (WorkspaceKey, &BiomePath) { - debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); - debug_assert!( - !self.data.paths.is_empty(), - "You must have at least one workspace." - ); - for (key, path_to_settings) in &self.data.paths { - if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { - return (key, &path_to_settings.path); - } - } - unreachable!("We should not reach here, the assertions should help.") - } - + /// Retrieves the settings by path. pub fn get_settings_by_path(&self, path: &BiomePath) -> &Settings { debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); debug_assert!( @@ -105,20 +96,6 @@ impl WorkspaceSettings { } unreachable!("We should not reach here, the assertions should help.") } - - pub fn get_settings_by_path_mut(&mut self, path: &Path) -> &mut Settings { - debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); - debug_assert!( - !self.data.paths.is_empty(), - "You must have at least one workspace." - ); - for (_, path_to_settings) in &mut self.data.paths { - if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { - return &mut path_to_settings.settings; - } - } - unreachable!("We should not reach here, the assertions should help.") - } } /// Global settings for the entire workspace @@ -631,7 +608,7 @@ impl<'a> SettingsHandleMut<'a> { impl<'a> AsMut for SettingsHandleMut<'a> { fn as_mut(&mut self) -> &mut Settings { - self.inner.current_settings_mut() + self.inner.get_current_settings_mut() } } diff --git a/crates/biome_service/src/workspace.rs b/crates/biome_service/src/workspace.rs index 4ca6af7cb014..749f6637e80a 100644 --- a/crates/biome_service/src/workspace.rs +++ b/crates/biome_service/src/workspace.rs @@ -737,7 +737,7 @@ pub struct IsPathIgnoredParams { #[derive(Debug, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[serde(rename_all = "camelCase")] -pub struct RegisterWorkspaceFoldersParams { +pub struct RegisterProjectFolderParams { pub path: Option, pub set_as_current_workspace: bool, } @@ -770,10 +770,10 @@ pub trait Workspace: Send + Sync + RefUnwindSafe { fn open_project(&self, params: OpenProjectParams) -> Result<(), WorkspaceError>; /// Register a possible workspace folders. Returns the key of said workspace. Use this key when you want to switch to different workspaces. - fn register_workspace_folder( + fn register_project_folder( &self, - params: RegisterWorkspaceFoldersParams, - ) -> Result; + params: RegisterProjectFolderParams, + ) -> Result; /// Sets the current project path fn update_current_project(&self, params: UpdateProjectParams) -> Result<(), WorkspaceError>; @@ -1003,11 +1003,11 @@ fn test_order() { } new_key_type! { - pub struct WorkspaceKey; + pub struct ProjectKey; } #[cfg(feature = "schema")] -impl JsonSchema for WorkspaceKey { +impl JsonSchema for ProjectKey { fn schema_name() -> String { "WorkspaceKey".to_string() } @@ -1022,7 +1022,7 @@ pub struct WorkspaceData { /// [DenseSlotMap] is the slowest type in insertion/removal, but the fastest in iteration /// /// Users wouldn't change workspace folders very often, - pub paths: DenseSlotMap, + pub paths: DenseSlotMap, } impl WorkspaceData { @@ -1032,15 +1032,15 @@ impl WorkspaceData { } /// Removes an item - pub fn remove(&mut self, key: WorkspaceKey) { + pub fn remove(&mut self, key: ProjectKey) { self.paths.remove(key); } - pub fn get_value_by_key(&self, key: WorkspaceKey) -> Option<&T> { + pub fn get_value_by_key(&self, key: ProjectKey) -> Option<&T> { self.paths.get(key) } - pub fn get_mut(&mut self, key: WorkspaceKey) -> Option<&mut T> { + pub fn get_mut(&mut self, key: ProjectKey) -> Option<&mut T> { self.paths.get_mut(key) } } diff --git a/crates/biome_service/src/workspace/client.rs b/crates/biome_service/src/workspace/client.rs index 50cace62b03e..e45d7a6fbf92 100644 --- a/crates/biome_service/src/workspace/client.rs +++ b/crates/biome_service/src/workspace/client.rs @@ -1,7 +1,7 @@ use crate::workspace::{ FileFeaturesResult, GetFileContentParams, IsPathIgnoredParams, OpenProjectParams, - OrganizeImportsParams, OrganizeImportsResult, RageParams, RageResult, - RegisterWorkspaceFoldersParams, ServerInfo, UpdateProjectParams, WorkspaceKey, + OrganizeImportsParams, OrganizeImportsResult, ProjectKey, RageParams, RageResult, + RegisterProjectFolderParams, ServerInfo, UpdateProjectParams, }; use crate::{TransportError, Workspace, WorkspaceError}; use biome_formatter::Printed; @@ -122,11 +122,11 @@ where self.request("biome/open_project", params) } - fn register_workspace_folder( + fn register_project_folder( &self, - params: RegisterWorkspaceFoldersParams, - ) -> Result { - self.request("biome/register_workspace_folder", params) + params: RegisterProjectFolderParams, + ) -> Result { + self.request("biome/register_project_folder", params) } fn update_current_project(&self, params: UpdateProjectParams) -> Result<(), WorkspaceError> { diff --git a/crates/biome_service/src/workspace/server.rs b/crates/biome_service/src/workspace/server.rs index 8740be6e8899..f6d7c03b2b0f 100644 --- a/crates/biome_service/src/workspace/server.rs +++ b/crates/biome_service/src/workspace/server.rs @@ -2,10 +2,10 @@ use super::{ ChangeFileParams, CloseFileParams, FeatureName, FixFileResult, FormatFileParams, FormatOnTypeParams, FormatRangeParams, GetControlFlowGraphParams, GetFormatterIRParams, GetSyntaxTreeParams, GetSyntaxTreeResult, OpenFileParams, OpenProjectParams, - ParsePatternParams, ParsePatternResult, PatternId, PullActionsParams, PullActionsResult, - PullDiagnosticsParams, PullDiagnosticsResult, RegisterWorkspaceFoldersParams, RenameResult, - SearchPatternParams, SearchResults, SupportsFeatureParams, UpdateProjectParams, - UpdateSettingsParams, WorkspaceKey, + ParsePatternParams, ParsePatternResult, PatternId, ProjectKey, PullActionsParams, + PullActionsResult, PullDiagnosticsParams, PullDiagnosticsResult, RegisterProjectFolderParams, + RenameResult, SearchPatternParams, SearchResults, SupportsFeatureParams, UpdateProjectParams, + UpdateSettingsParams, }; use crate::file_handlers::{ Capabilities, CodeActionsParams, DocumentFileSource, FixAllParams, LintParams, ParseResult, @@ -441,16 +441,16 @@ impl Workspace for WorkspaceServer { Ok(()) } - fn register_workspace_folder( + fn register_project_folder( &self, - params: RegisterWorkspaceFoldersParams, - ) -> Result { + params: RegisterProjectFolderParams, + ) -> Result { let mut workspace = self.workspaces_mut(); let key = workspace .as_mut() - .insert_workspace(params.path.unwrap_or_default()); + .insert_project(params.path.unwrap_or_default()); if params.set_as_current_workspace { - workspace.as_mut().register_current_workspace(key); + workspace.as_mut().register_current_project(key); } Ok(key) } diff --git a/crates/biome_service/src/workspace_types.rs b/crates/biome_service/src/workspace_types.rs index 5ab741d08949..36df09a7d986 100644 --- a/crates/biome_service/src/workspace_types.rs +++ b/crates/biome_service/src/workspace_types.rs @@ -455,7 +455,7 @@ pub fn methods() -> [WorkspaceMethod; 20] { [ WorkspaceMethod::of::("file_features"), workspace_method!(update_settings), - workspace_method!(register_workspace_folder), + workspace_method!(register_project_folder), workspace_method!(update_current_project), workspace_method!(open_project), workspace_method!(open_file), diff --git a/crates/biome_wasm/src/lib.rs b/crates/biome_wasm/src/lib.rs index 391263c20549..0e97b5527cde 100644 --- a/crates/biome_wasm/src/lib.rs +++ b/crates/biome_wasm/src/lib.rs @@ -5,7 +5,7 @@ use biome_service::workspace::{ self, ChangeFileParams, CloseFileParams, FixFileParams, FormatFileParams, FormatOnTypeParams, FormatRangeParams, GetControlFlowGraphParams, GetFileContentParams, GetFormatterIRParams, GetSyntaxTreeParams, OrganizeImportsParams, PullActionsParams, PullDiagnosticsParams, - RegisterWorkspaceFoldersParams, RenameParams, UpdateSettingsParams, WorkspaceKey, + RegisterProjectFolderParams, RenameParams, UpdateSettingsParams, }; use biome_service::workspace::{OpenFileParams, SupportsFeatureParams}; @@ -56,16 +56,16 @@ impl Workspace { self.inner.update_settings(params).map_err(into_error) } - #[wasm_bindgen(js_name = registerWorkspaceFolder)] + #[wasm_bindgen(js_name = registerProjectFolder)] pub fn register_workspace_folder( &self, - params: IRegisterWorkspaceFoldersParams, + params: IRegisterProjectFolderParams, ) -> Result { - let params: RegisterWorkspaceFoldersParams = + let params: RegisterProjectFolderParams = serde_wasm_bindgen::from_value(params.into()).map_err(into_error)?; let result = self .inner - .register_workspace_folder(params) + .register_project_folder(params) .map_err(into_error)?; to_value(&result) diff --git a/packages/@biomejs/js-api/src/index.ts b/packages/@biomejs/js-api/src/index.ts index 58f33663842c..6063f926859d 100644 --- a/packages/@biomejs/js-api/src/index.ts +++ b/packages/@biomejs/js-api/src/index.ts @@ -124,9 +124,9 @@ export class Biome { */ public applyConfiguration(configuration: Configuration): void { try { - this.workspace.registerWorkspaceFolder({ - setAsCurrentWorkspace: true - }) + this.workspace.registerProjectFolder({ + setAsCurrentWorkspace: true, + }); this.workspace.updateSettings({ configuration, gitignore_matches: [], From 830f8d880585839b0283b27c1693ebadca128871 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 25 Apr 2024 09:33:37 +0100 Subject: [PATCH 5/6] apply feedback --- crates/biome_service/src/settings.rs | 10 +++--- crates/biome_service/src/workspace.rs | 36 ++++++++++++++++--- crates/biome_wasm/src/lib.rs | 6 ++-- .../@biomejs/backend-jsonrpc/src/workspace.ts | 14 ++++---- packages/@biomejs/js-api/src/index.ts | 33 +++++++++-------- 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index 0946a196d190..bdf077715a65 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -53,8 +53,7 @@ impl WorkspaceSettings { pub fn current_settings(&self) -> &Settings { let data = self .data - .paths - .get(self.current_workspace) + .get_value_by_key(self.current_workspace) .expect("You must have at least one workspace."); &data.settings } @@ -76,7 +75,7 @@ impl WorkspaceSettings { /// Register a new project using its folder. Use [WorkspaceSettings::get_current_settings_mut] to retrieve /// its settings and change them. pub fn insert_project(&mut self, workspace_path: impl Into) -> ProjectKey { - self.data.paths.insert(PathToSettings { + self.data.insert(PathToSettings { path: BiomePath::new(workspace_path.into()), settings: Settings::default(), }) @@ -86,10 +85,11 @@ impl WorkspaceSettings { pub fn get_settings_by_path(&self, path: &BiomePath) -> &Settings { debug_assert!(path.is_absolute(), "Workspaces paths must be absolutes."); debug_assert!( - !self.data.paths.is_empty(), + !self.data.is_empty(), "You must have at least one workspace." ); - for (_, path_to_settings) in &self.data.paths { + let iter = self.data.iter(); + for (_, path_to_settings) in iter { if path.strip_prefix(path_to_settings.path.as_path()).is_ok() { return &path_to_settings.settings; } diff --git a/crates/biome_service/src/workspace.rs b/crates/biome_service/src/workspace.rs index 749f6637e80a..512c082b55ce 100644 --- a/crates/biome_service/src/workspace.rs +++ b/crates/biome_service/src/workspace.rs @@ -1009,7 +1009,7 @@ new_key_type! { #[cfg(feature = "schema")] impl JsonSchema for ProjectKey { fn schema_name() -> String { - "WorkspaceKey".to_string() + "ProjectKey".to_string() } fn json_schema(gen: &mut SchemaGenerator) -> Schema { @@ -1022,13 +1022,13 @@ pub struct WorkspaceData { /// [DenseSlotMap] is the slowest type in insertion/removal, but the fastest in iteration /// /// Users wouldn't change workspace folders very often, - pub paths: DenseSlotMap, + paths: DenseSlotMap, } impl WorkspaceData { /// Inserts an item - pub fn insert(&mut self, item: impl Into) { - self.paths.insert(Into::into(item)); + pub fn insert(&mut self, item: T) -> ProjectKey { + self.paths.insert(item) } /// Removes an item @@ -1043,4 +1043,32 @@ impl WorkspaceData { pub fn get_mut(&mut self, key: ProjectKey) -> Option<&mut T> { self.paths.get_mut(key) } + + pub fn is_empty(&self) -> bool { + self.paths.is_empty() + } + + pub fn iter(&self) -> WorkspaceDataIterator<'_, T> { + WorkspaceDataIterator::new(self) + } +} + +pub struct WorkspaceDataIterator<'a, V> { + iterator: slotmap::dense::Iter<'a, ProjectKey, V>, +} + +impl<'a, V> WorkspaceDataIterator<'a, V> { + fn new(data: &'a WorkspaceData) -> Self { + Self { + iterator: data.paths.iter(), + } + } +} + +impl<'a, V> Iterator for WorkspaceDataIterator<'a, V> { + type Item = (ProjectKey, &'a V); + + fn next(&mut self) -> Option { + self.iterator.next() + } } diff --git a/crates/biome_wasm/src/lib.rs b/crates/biome_wasm/src/lib.rs index 0e97b5527cde..fa96cb405a42 100644 --- a/crates/biome_wasm/src/lib.rs +++ b/crates/biome_wasm/src/lib.rs @@ -60,7 +60,7 @@ impl Workspace { pub fn register_workspace_folder( &self, params: IRegisterProjectFolderParams, - ) -> Result { + ) -> Result { let params: RegisterProjectFolderParams = serde_wasm_bindgen::from_value(params.into()).map_err(into_error)?; let result = self @@ -68,9 +68,7 @@ impl Workspace { .register_project_folder(params) .map_err(into_error)?; - to_value(&result) - .map(IWorkspaceKey::from) - .map_err(into_error) + to_value(&result).map(IProjectKey::from).map_err(into_error) } #[wasm_bindgen(js_name = openFile)] diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 0ee1365d355a..6683262c4c26 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1729,11 +1729,11 @@ export type FilenameCase = | "kebab-case" | "PascalCase" | "snake_case"; -export interface RegisterWorkspaceFoldersParams { +export interface RegisterProjectFolderParams { path?: string; setAsCurrentWorkspace: boolean; } -export type WorkspaceKey = string; +export type ProjectKey = string; export interface UpdateProjectParams { path: BiomePath; } @@ -2342,9 +2342,9 @@ export type Configuration = PartialConfiguration; export interface Workspace { fileFeatures(params: SupportsFeatureParams): Promise; updateSettings(params: UpdateSettingsParams): Promise; - registerWorkspaceFolder( - params: RegisterWorkspaceFoldersParams, - ): Promise; + registerProjectFolder( + params: RegisterProjectFolderParams, + ): Promise; updateCurrentProject(params: UpdateProjectParams): Promise; openProject(params: OpenProjectParams): Promise; openFile(params: OpenFileParams): Promise; @@ -2376,8 +2376,8 @@ export function createWorkspace(transport: Transport): Workspace { updateSettings(params) { return transport.request("biome/update_settings", params); }, - registerWorkspaceFolder(params) { - return transport.request("biome/register_workspace_folder", params); + registerProjectFolder(params) { + return transport.request("biome/register_project_folder", params); }, updateCurrentProject(params) { return transport.request("biome/update_current_project", params); diff --git a/packages/@biomejs/js-api/src/index.ts b/packages/@biomejs/js-api/src/index.ts index 6063f926859d..fe1e26780621 100644 --- a/packages/@biomejs/js-api/src/index.ts +++ b/packages/@biomejs/js-api/src/index.ts @@ -6,12 +6,12 @@ import type { PullDiagnosticsResult, Workspace, } from "@biomejs/wasm-nodejs"; -import {Distribution, type WasmModule, loadModule, wrapError} from "./wasm"; +import { Distribution, type WasmModule, loadModule, wrapError } from "./wasm"; // Re-export of some useful types for users export type Configuration = PartialConfiguration; -export type {Diagnostic}; -export {Distribution}; +export type { Diagnostic }; +export { Distribution }; export interface FormatContentDebugOptions extends FormatContentOptions { /** @@ -93,8 +93,7 @@ export class Biome { private constructor( private readonly module: WasmModule, private readonly workspace: Workspace, - ) { - } + ) {} /** * It creates a new instance of the class {Biome}. @@ -189,7 +188,7 @@ export class Biome { return this.withFile(options.filePath, content, (path) => { let code = content; - const {diagnostics} = this.workspace.pullDiagnostics({ + const { diagnostics } = this.workspace.pullDiagnostics({ path, categories: ["Syntax"], max_diagnostics: Number.MAX_SAFE_INTEGER, @@ -240,26 +239,26 @@ export class Biome { */ lintContent( content: string, - {filePath, fixFileMode}: LintContentOptions, + { filePath, fixFileMode }: LintContentOptions, ): LintResult { const maybeFixedContent = fixFileMode ? this.withFile(filePath, content, (path) => { - let code = content; + let code = content; - const result = this.workspace.fixFile({ - path, - fix_file_mode: fixFileMode, - should_format: false, - }); + const result = this.workspace.fixFile({ + path, + fix_file_mode: fixFileMode, + should_format: false, + }); - code = result.code; + code = result.code; - return code; - }) + return code; + }) : content; return this.withFile(filePath, maybeFixedContent, (path) => { - const {diagnostics} = this.workspace.pullDiagnostics({ + const { diagnostics } = this.workspace.pullDiagnostics({ path, categories: ["Syntax", "Lint"], max_diagnostics: Number.MAX_SAFE_INTEGER, From dccb98826a7a307d7c50660d8ce941d55ad0aff7 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 25 Apr 2024 10:34:12 +0100 Subject: [PATCH 6/6] fix regression --- packages/@biomejs/js-api/src/index.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/@biomejs/js-api/src/index.ts b/packages/@biomejs/js-api/src/index.ts index fe1e26780621..430b70af9b16 100644 --- a/packages/@biomejs/js-api/src/index.ts +++ b/packages/@biomejs/js-api/src/index.ts @@ -101,7 +101,9 @@ export class Biome { public static async create(options: BiomeCreate): Promise { const module = await loadModule(options.distribution); const workspace = new module.Workspace(); - return new Biome(module, workspace); + const biome = new Biome(module, workspace); + biome.registerProjectFolder(); + return biome; } /** @@ -123,18 +125,24 @@ export class Biome { */ public applyConfiguration(configuration: Configuration): void { try { - this.workspace.registerProjectFolder({ - setAsCurrentWorkspace: true, - }); this.workspace.updateSettings({ configuration, gitignore_matches: [], + workspace_directory: "./", }); } catch (e) { throw wrapError(e); } } + public registerProjectFolder(): void; + public registerProjectFolder(path?: string): void { + this.workspace.registerProjectFolder({ + path, + setAsCurrentWorkspace: true, + }); + } + private tryCatchWrapper(func: () => T): T { try { return func();