diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs | 1099 |
1 files changed, 1099 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs new file mode 100644 index 000000000..4cc46af1b --- /dev/null +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -0,0 +1,1099 @@ +//! The most high-level integrated tests for rust-analyzer. +//! +//! This tests run a full LSP event loop, spawn cargo and process stdlib from +//! sysroot. For this reason, the tests here are very slow, and should be +//! avoided unless absolutely necessary. +//! +//! In particular, it's fine *not* to test that client & server agree on +//! specific JSON shapes here -- there's little value in such tests, as we can't +//! be sure without a real client anyway. + +#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] + +#[cfg(not(feature = "in-rust-tree"))] +mod sourcegen; +mod support; +mod testdir; +mod tidy; + +use std::{collections::HashMap, path::PathBuf, time::Instant}; + +use expect_test::expect; +use lsp_types::{ + notification::DidOpenTextDocument, + request::{ + CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest, + WillRenameFiles, WorkspaceSymbol, + }, + CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams, + DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams, + PartialResultParams, Position, Range, RenameFilesParams, TextDocumentItem, + TextDocumentPositionParams, WorkDoneProgressParams, +}; +use rust_analyzer::lsp_ext::{OnEnter, Runnables, RunnablesParams}; +use serde_json::json; +use test_utils::skip_slow_tests; + +use crate::{ + support::{project, Project}, + testdir::TestDir, +}; + +const PROFILE: &str = ""; +// const PROFILE: &'static str = "*@3>100"; + +#[test] +fn completes_items_from_standard_library() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +use std::collections::Spam; +"#, + ) + .with_config(serde_json::json!({ + "cargo": { "noSysroot": false } + })) + .server() + .wait_until_workspace_is_loaded(); + + let res = server.send_request::<Completion>(CompletionParams { + text_document_position: TextDocumentPositionParams::new( + server.doc_id("src/lib.rs"), + Position::new(0, 23), + ), + context: None, + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + }); + assert!(res.to_string().contains("HashMap")); +} + +#[test] +fn test_runnables_project() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r#" +//- /foo/Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /foo/src/lib.rs +pub fn foo() {} + +//- /foo/tests/spam.rs +#[test] +fn test_eggs() {} + +//- /bar/Cargo.toml +[package] +name = "bar" +version = "0.0.0" + +//- /bar/src/main.rs +fn main() {} +"#, + ) + .root("foo") + .root("bar") + .server() + .wait_until_workspace_is_loaded(); + + server.request::<Runnables>( + RunnablesParams { text_document: server.doc_id("foo/tests/spam.rs"), position: None }, + json!([ + { + "args": { + "cargoArgs": ["test", "--package", "foo", "--test", "spam"], + "executableArgs": ["test_eggs", "--exact", "--nocapture"], + "cargoExtraArgs": [], + "overrideCargo": null, + "workspaceRoot": server.path().join("foo") + }, + "kind": "cargo", + "label": "test test_eggs", + "location": { + "targetRange": { + "end": { "character": 17, "line": 1 }, + "start": { "character": 0, "line": 0 } + }, + "targetSelectionRange": { + "end": { "character": 12, "line": 1 }, + "start": { "character": 3, "line": 1 } + }, + "targetUri": "file:///[..]/tests/spam.rs" + } + }, + { + "args": { + "overrideCargo": null, + "workspaceRoot": server.path().join("foo"), + "cargoArgs": [ + "test", + "--package", + "foo", + "--test", + "spam" + ], + "cargoExtraArgs": [], + "executableArgs": [ + "", + "--nocapture" + ] + }, + "kind": "cargo", + "label": "test-mod ", + "location": { + "targetUri": "file:///[..]/tests/spam.rs", + "targetRange": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 3, + "character": 0 + } + }, + "targetSelectionRange": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 3, + "character": 0 + } + } + }, + }, + { + "args": { + "cargoArgs": ["check", "--package", "foo", "--all-targets"], + "executableArgs": [], + "cargoExtraArgs": [], + "overrideCargo": null, + "workspaceRoot": server.path().join("foo") + }, + "kind": "cargo", + "label": "cargo check -p foo --all-targets" + }, + { + "args": { + "cargoArgs": ["test", "--package", "foo", "--all-targets"], + "executableArgs": [], + "cargoExtraArgs": [], + "overrideCargo": null, + "workspaceRoot": server.path().join("foo") + }, + "kind": "cargo", + "label": "cargo test -p foo --all-targets" + } + ]), + ); +} + +// Each package in these workspaces should be run from its own root +#[test] +fn test_path_dependency_runnables() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r#" +//- /consumer/Cargo.toml +[package] +name = "consumer" +version = "0.1.0" +[dependencies] +dependency = { path = "../dependency" } + +//- /consumer/src/lib.rs +#[cfg(test)] +mod tests { + #[test] + fn consumer() {} +} + +//- /dependency/Cargo.toml +[package] +name = "dependency" +version = "0.1.0" +[dev-dependencies] +devdependency = { path = "../devdependency" } + +//- /dependency/src/lib.rs +#[cfg(test)] +mod tests { + #[test] + fn dependency() {} +} + +//- /devdependency/Cargo.toml +[package] +name = "devdependency" +version = "0.1.0" + +//- /devdependency/src/lib.rs +#[cfg(test)] +mod tests { + #[test] + fn devdependency() {} +} + "#, + ) + .root("consumer") + .root("dependency") + .root("devdependency") + .server() + .wait_until_workspace_is_loaded(); + + for runnable in ["consumer", "dependency", "devdependency"] { + server.request::<Runnables>( + RunnablesParams { + text_document: server.doc_id(&format!("{}/src/lib.rs", runnable)), + position: None, + }, + json!([ + "{...}", + { + "label": "cargo test -p [..] --all-targets", + "kind": "cargo", + "args": { + "overrideCargo": null, + "workspaceRoot": server.path().join(runnable), + "cargoArgs": [ + "test", + "--package", + runnable, + "--all-targets" + ], + "cargoExtraArgs": [], + "executableArgs": [] + }, + }, + "{...}", + "{...}" + ]), + ); + } +} + +#[test] +fn test_format_document() { + if skip_slow_tests() { + return; + } + + let server = project( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +mod bar; + +fn main() { +} + +pub use std::collections::HashMap; +"#, + ) + .wait_until_workspace_is_loaded(); + + server.request::<Formatting>( + DocumentFormattingParams { + text_document: server.doc_id("src/lib.rs"), + options: FormattingOptions { + tab_size: 4, + insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, + properties: HashMap::new(), + }, + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([ + { + "newText": "", + "range": { + "end": { "character": 0, "line": 3 }, + "start": { "character": 11, "line": 2 } + } + } + ]), + ); +} + +#[test] +fn test_format_document_2018() { + if skip_slow_tests() { + return; + } + + let server = project( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" +edition = "2018" + +//- /src/lib.rs +mod bar; + +async fn test() { +} + +fn main() { +} + +pub use std::collections::HashMap; +"#, + ) + .wait_until_workspace_is_loaded(); + + server.request::<Formatting>( + DocumentFormattingParams { + text_document: server.doc_id("src/lib.rs"), + options: FormattingOptions { + tab_size: 4, + insert_spaces: false, + properties: HashMap::new(), + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([ + { + "newText": "", + "range": { + "end": { "character": 0, "line": 3 }, + "start": { "character": 17, "line": 2 } + } + }, + { + "newText": "", + "range": { + "end": { "character": 0, "line": 6 }, + "start": { "character": 11, "line": 5 } + } + } + ]), + ); +} + +#[test] +fn test_format_document_unchanged() { + if skip_slow_tests() { + return; + } + + let server = project( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +fn main() {} +"#, + ) + .wait_until_workspace_is_loaded(); + + server.request::<Formatting>( + DocumentFormattingParams { + text_document: server.doc_id("src/lib.rs"), + options: FormattingOptions { + tab_size: 4, + insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, + properties: HashMap::new(), + }, + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!(null), + ); +} + +#[test] +fn test_missing_module_code_action() { + if skip_slow_tests() { + return; + } + + let server = project( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +mod bar; + +fn main() {} +"#, + ) + .wait_until_workspace_is_loaded(); + + server.request::<CodeActionRequest>( + CodeActionParams { + text_document: server.doc_id("src/lib.rs"), + range: Range::new(Position::new(0, 4), Position::new(0, 7)), + context: CodeActionContext::default(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([ + { + "title": "Create module at `bar.rs`", + "kind": "quickfix", + "edit": { + "documentChanges": [ + { + "kind": "create", + "uri": "file://[..]/src/bar.rs" + } + ] + } + }, + { + "title": "Create module at `bar/mod.rs`", + "kind": "quickfix", + "edit": { + "documentChanges": [ + { + "kind": "create", + "uri": "file://[..]src/bar/mod.rs" + } + ] + } + } + ]), + ); + + server.request::<CodeActionRequest>( + CodeActionParams { + text_document: server.doc_id("src/lib.rs"), + range: Range::new(Position::new(2, 8), Position::new(2, 8)), + context: CodeActionContext::default(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([]), + ); +} + +#[test] +fn test_missing_module_code_action_in_json_project() { + if skip_slow_tests() { + // return; + } + + let tmp_dir = TestDir::new(); + + let path = tmp_dir.path(); + + let project = json!({ + "roots": [path], + "crates": [ { + "root_module": path.join("src/lib.rs"), + "deps": [], + "edition": "2015", + "cfg": [ "cfg_atom_1", "feature=\"cfg_1\""], + } ] + }); + + let code = format!( + r#" +//- /rust-project.json +{PROJECT} + +//- /src/lib.rs +mod bar; + +fn main() {{}} +"#, + PROJECT = project, + ); + + let server = + Project::with_fixture(&code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded(); + + server.request::<CodeActionRequest>( + CodeActionParams { + text_document: server.doc_id("src/lib.rs"), + range: Range::new(Position::new(0, 4), Position::new(0, 7)), + context: CodeActionContext::default(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([ + { + "title": "Create module at `bar.rs`", + "kind": "quickfix", + "edit": { + "documentChanges": [ + { + "kind": "create", + "uri": "file://[..]/src/bar.rs" + } + ] + } + }, + { + "title": "Create module at `bar/mod.rs`", + "kind": "quickfix", + "edit": { + "documentChanges": [ + { + "kind": "create", + "uri": "file://[..]src/bar/mod.rs" + } + ] + } + } + ]), + ); + + server.request::<CodeActionRequest>( + CodeActionParams { + text_document: server.doc_id("src/lib.rs"), + range: Range::new(Position::new(2, 8), Position::new(2, 8)), + context: CodeActionContext::default(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), + }, + json!([]), + ); +} + +#[test] +fn diagnostics_dont_block_typing() { + if skip_slow_tests() { + return; + } + + let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect(); + let libs: String = (0..10).map(|i| format!("//- /src/m{}.rs\nfn foo() {{}}\n\n", i)).collect(); + let server = Project::with_fixture(&format!( + r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +{} + +{} + +fn main() {{}} +"#, + librs, libs + )) + .with_config(serde_json::json!({ + "cargo": { "noSysroot": false } + })) + .server() + .wait_until_workspace_is_loaded(); + + for i in 0..10 { + server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: server.doc_id(&format!("src/m{}.rs", i)).uri, + language_id: "rust".to_string(), + version: 0, + text: "/// Docs\nfn foo() {}".to_string(), + }, + }); + } + let start = Instant::now(); + server.request::<OnEnter>( + TextDocumentPositionParams { + text_document: server.doc_id("src/m0.rs"), + position: Position { line: 0, character: 5 }, + }, + json!([{ + "insertTextFormat": 2, + "newText": "\n/// $0", + "range": { + "end": { "character": 5, "line": 0 }, + "start": { "character": 5, "line": 0 } + } + }]), + ); + let elapsed = start.elapsed(); + assert!(elapsed.as_millis() < 2000, "typing enter took {:?}", elapsed); +} + +#[test] +fn preserves_dos_line_endings() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + " +//- /Cargo.toml +[package] +name = \"foo\" +version = \"0.0.0\" + +//- /src/main.rs +/// Some Docs\r\nfn main() {} +", + ) + .server() + .wait_until_workspace_is_loaded(); + + server.request::<OnEnter>( + TextDocumentPositionParams { + text_document: server.doc_id("src/main.rs"), + position: Position { line: 0, character: 8 }, + }, + json!([{ + "insertTextFormat": 2, + "newText": "\r\n/// $0", + "range": { + "end": { "line": 0, "character": 8 }, + "start": { "line": 0, "character": 8 } + } + }]), + ); +} + +#[test] +fn out_dirs_check() { + if skip_slow_tests() { + // return; + } + + let server = Project::with_fixture( + r###" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /build.rs +use std::{env, fs, path::Path}; + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("hello.rs"); + fs::write( + &dest_path, + r#"pub fn message() -> &'static str { "Hello, World!" }"#, + ) + .unwrap(); + println!("cargo:rustc-cfg=atom_cfg"); + println!("cargo:rustc-cfg=featlike=\"set\""); + println!("cargo:rerun-if-changed=build.rs"); +} +//- /src/main.rs +#[rustc_builtin_macro] macro_rules! include {} +#[rustc_builtin_macro] macro_rules! include_str {} +#[rustc_builtin_macro] macro_rules! concat {} +#[rustc_builtin_macro] macro_rules! env {} + +include!(concat!(env!("OUT_DIR"), "/hello.rs")); + +#[cfg(atom_cfg)] +struct A; +#[cfg(bad_atom_cfg)] +struct A; +#[cfg(featlike = "set")] +struct B; +#[cfg(featlike = "not_set")] +struct B; + +fn main() { + let va = A; + let vb = B; + let should_be_str = message(); + let another_str = include_str!("main.rs"); +} +"###, + ) + .with_config(serde_json::json!({ + "cargo": { + "buildScripts": { + "enable": true + }, + "noSysroot": true, + } + })) + .server() + .wait_until_workspace_is_loaded(); + + let res = server.send_request::<HoverRequest>(HoverParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(19, 10), + ), + work_done_progress_params: Default::default(), + }); + assert!(res.to_string().contains("&str")); + + let res = server.send_request::<HoverRequest>(HoverParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(20, 10), + ), + work_done_progress_params: Default::default(), + }); + assert!(res.to_string().contains("&str")); + + server.request::<GotoTypeDefinition>( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(17, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { "character": 10, "line": 17 }, + "start": { "character": 8, "line": 17 } + }, + "targetRange": { + "end": { "character": 9, "line": 8 }, + "start": { "character": 0, "line": 7 } + }, + "targetSelectionRange": { + "end": { "character": 8, "line": 8 }, + "start": { "character": 7, "line": 8 } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); + + server.request::<GotoTypeDefinition>( + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("src/main.rs"), + Position::new(18, 9), + ), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + json!([{ + "originSelectionRange": { + "end": { "character": 10, "line": 18 }, + "start": { "character": 8, "line": 18 } + }, + "targetRange": { + "end": { "character": 9, "line": 12 }, + "start": { "character": 0, "line":11 } + }, + "targetSelectionRange": { + "end": { "character": 8, "line": 12 }, + "start": { "character": 7, "line": 12 } + }, + "targetUri": "file:///[..]src/main.rs" + }]), + ); +} + +#[test] +fn resolve_proc_macro() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r###" +//- /foo/Cargo.toml +[package] +name = "foo" +version = "0.0.0" +edition = "2021" +[dependencies] +bar = {path = "../bar"} + +//- /foo/src/main.rs +use bar::Bar; + +#[rustc_builtin_macro] +macro derive($item:item) {} +trait Bar { + fn bar(); +} +#[derive(Bar)] +struct Foo {} +fn main() { + Foo::bar(); +} + +//- /bar/Cargo.toml +[package] +name = "bar" +version = "0.0.0" +edition = "2021" + +[lib] +proc-macro = true + +//- /bar/src/lib.rs +extern crate proc_macro; +use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; +macro_rules! t { + ($n:literal) => { + TokenTree::from(Ident::new($n, Span::call_site())) + }; + ({}) => { + TokenTree::from(Group::new(Delimiter::Brace, TokenStream::new())) + }; + (()) => { + TokenTree::from(Group::new(Delimiter::Parenthesis, TokenStream::new())) + }; +} +#[proc_macro_derive(Bar)] +pub fn foo(_input: TokenStream) -> TokenStream { + // We hard code the output here for preventing to use any deps + let mut res = TokenStream::new(); + + // ill behaved proc-macro will use the stdout + // we should ignore it + println!("I am bad guy"); + + // impl Bar for Foo { fn bar() {} } + let mut tokens = vec![t!("impl"), t!("Bar"), t!("for"), t!("Foo")]; + let mut fn_stream = TokenStream::new(); + fn_stream.extend(vec![t!("fn"), t!("bar"), t!(()), t!({})]); + tokens.push(Group::new(Delimiter::Brace, fn_stream).into()); + res.extend(tokens); + res +} + +"###, + ) + .with_config(serde_json::json!({ + "cargo": { + "buildScripts": { + "enable": true + }, + "noSysroot": true, + }, + "procMacro": { + "enable": true, + "server": PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")), + } + })) + .root("foo") + .root("bar") + .server() + .wait_until_workspace_is_loaded(); + + let res = server.send_request::<HoverRequest>(HoverParams { + text_document_position_params: TextDocumentPositionParams::new( + server.doc_id("foo/src/main.rs"), + Position::new(10, 9), + ), + work_done_progress_params: Default::default(), + }); + let value = res.get("contents").unwrap().get("value").unwrap().as_str().unwrap(); + + expect![[r#" + + ```rust + foo::Foo + ``` + + ```rust + fn bar() + ```"#]] + .assert_eq(value); +} + +#[test] +fn test_will_rename_files_same_level() { + if skip_slow_tests() { + return; + } + + let tmp_dir = TestDir::new(); + let tmp_dir_path = tmp_dir.path().to_owned(); + let tmp_dir_str = tmp_dir_path.to_str().unwrap(); + let base_path = PathBuf::from(format!("file://{}", tmp_dir_str)); + + let code = r#" +//- /Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /src/lib.rs +mod old_file; +mod from_mod; +mod to_mod; +mod old_folder; +fn main() {} + +//- /src/old_file.rs + +//- /src/old_folder/mod.rs + +//- /src/from_mod/mod.rs + +//- /src/to_mod/foo.rs + +"#; + let server = + Project::with_fixture(code).tmp_dir(tmp_dir).server().wait_until_workspace_is_loaded(); + + //rename same level file + server.request::<WillRenameFiles>( + RenameFilesParams { + files: vec![FileRename { + old_uri: base_path.join("src/old_file.rs").to_str().unwrap().to_string(), + new_uri: base_path.join("src/new_file.rs").to_str().unwrap().to_string(), + }], + }, + json!({ + "documentChanges": [ + { + "textDocument": { + "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace('\\', "/")), + "version": null + }, + "edits": [ + { + "range": { + "start": { + "line": 0, + "character": 4 + }, + "end": { + "line": 0, + "character": 12 + } + }, + "newText": "new_file" + } + ] + } + ] + }), + ); + + //rename file from mod.rs to foo.rs + server.request::<WillRenameFiles>( + RenameFilesParams { + files: vec![FileRename { + old_uri: base_path.join("src/from_mod/mod.rs").to_str().unwrap().to_string(), + new_uri: base_path.join("src/from_mod/foo.rs").to_str().unwrap().to_string(), + }], + }, + json!(null), + ); + + //rename file from foo.rs to mod.rs + server.request::<WillRenameFiles>( + RenameFilesParams { + files: vec![FileRename { + old_uri: base_path.join("src/to_mod/foo.rs").to_str().unwrap().to_string(), + new_uri: base_path.join("src/to_mod/mod.rs").to_str().unwrap().to_string(), + }], + }, + json!(null), + ); + + //rename same level file + server.request::<WillRenameFiles>( + RenameFilesParams { + files: vec![FileRename { + old_uri: base_path.join("src/old_folder").to_str().unwrap().to_string(), + new_uri: base_path.join("src/new_folder").to_str().unwrap().to_string(), + }], + }, + json!({ + "documentChanges": [ + { + "textDocument": { + "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace('\\', "/")), + "version": null + }, + "edits": [ + { + "range": { + "start": { + "line": 3, + "character": 4 + }, + "end": { + "line": 3, + "character": 14 + } + }, + "newText": "new_folder" + } + ] + } + ] + }), + ); +} + +#[test] +fn test_exclude_config_works() { + if skip_slow_tests() { + return; + } + + let server = Project::with_fixture( + r#" +//- /foo/Cargo.toml +[package] +name = "foo" +version = "0.0.0" + +//- /foo/src/lib.rs +pub fn foo() {} + +//- /bar/Cargo.toml +[package] +name = "bar" +version = "0.0.0" + +//- /bar/src/lib.rs +pub fn bar() {} +"#, + ) + .root("foo") + .root("bar") + .with_config(json!({ + "files": { + "excludeDirs": ["foo", "bar"] + } + })) + .server() + .wait_until_workspace_is_loaded(); + + server.request::<WorkspaceSymbol>(Default::default(), json!([])); +} |