aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock39
-rw-r--r--crates/hir/src/code_model.rs6
-rw-r--r--crates/hir_ty/Cargo.toml6
-rw-r--r--crates/hir_ty/src/traits/chalk.rs11
-rw-r--r--crates/ide/src/diagnostics.rs13
-rw-r--r--crates/ide/src/lib.rs8
-rw-r--r--crates/ide/src/references/rename.rs19
-rw-r--r--crates/rust-analyzer/Cargo.toml1
-rw-r--r--crates/rust-analyzer/src/caps.rs29
-rw-r--r--crates/rust-analyzer/src/handlers.rs158
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/syntax/Cargo.toml2
13 files changed, 205 insertions, 90 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 891cff55e..fd04ec3c5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -168,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
168 168
169[[package]] 169[[package]]
170name = "chalk-derive" 170name = "chalk-derive"
171version = "0.43.0" 171version = "0.45.0"
172source = "registry+https://github.com/rust-lang/crates.io-index" 172source = "registry+https://github.com/rust-lang/crates.io-index"
173checksum = "e2d9e0c8adcced1ab0fea5cb8a38647922893d5b495e363e1814299fd380469b" 173checksum = "ec7dacf94958d1a930b95d049d9443860859af59eadc77849392093eb577bcee"
174dependencies = [ 174dependencies = [
175 "proc-macro2", 175 "proc-macro2",
176 "quote", 176 "quote",
@@ -180,19 +180,20 @@ dependencies = [
180 180
181[[package]] 181[[package]]
182name = "chalk-ir" 182name = "chalk-ir"
183version = "0.43.0" 183version = "0.45.0"
184source = "registry+https://github.com/rust-lang/crates.io-index" 184source = "registry+https://github.com/rust-lang/crates.io-index"
185checksum = "c5218266a5709bc4943de997e64d3fab41c9e9f68efd54a898de53135e987bd3" 185checksum = "a1a5b38ede247def17da87f4badb62396a5753db6048e2011d3089d8b3796c67"
186dependencies = [ 186dependencies = [
187 "bitflags",
187 "chalk-derive", 188 "chalk-derive",
188 "lazy_static", 189 "lazy_static",
189] 190]
190 191
191[[package]] 192[[package]]
192name = "chalk-recursive" 193name = "chalk-recursive"
193version = "0.43.0" 194version = "0.45.0"
194source = "registry+https://github.com/rust-lang/crates.io-index" 195source = "registry+https://github.com/rust-lang/crates.io-index"
195checksum = "ed8f34f13fd4f30251f9f6f1dc56f80363201390ecbcac2fdfc8e33036cd9c4a" 196checksum = "7a18db146d7a023edc20ad094e8c2284451f7888719645004979617d1f17c041"
196dependencies = [ 197dependencies = [
197 "chalk-derive", 198 "chalk-derive",
198 "chalk-ir", 199 "chalk-ir",
@@ -203,9 +204,9 @@ dependencies = [
203 204
204[[package]] 205[[package]]
205name = "chalk-solve" 206name = "chalk-solve"
206version = "0.43.0" 207version = "0.45.0"
207source = "registry+https://github.com/rust-lang/crates.io-index" 208source = "registry+https://github.com/rust-lang/crates.io-index"
208checksum = "379c9f584488346044709d4c638c38d61a06fe593d4de2ac5f15fd2b0ba4cd9d" 209checksum = "7f73e0de04a0f394e47ed8118e00541bcf681d7c3c2ef500fa743eb4cf3a4850"
209dependencies = [ 210dependencies = [
210 "chalk-derive", 211 "chalk-derive",
211 "chalk-ir", 212 "chalk-ir",
@@ -507,9 +508,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
507 508
508[[package]] 509[[package]]
509name = "heck" 510name = "heck"
510version = "0.3.1" 511version = "0.3.2"
511source = "registry+https://github.com/rust-lang/crates.io-index" 512source = "registry+https://github.com/rust-lang/crates.io-index"
512checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 513checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
513dependencies = [ 514dependencies = [
514 "unicode-segmentation", 515 "unicode-segmentation",
515] 516]
@@ -1074,9 +1075,9 @@ dependencies = [
1074 1075
1075[[package]] 1076[[package]]
1076name = "parking_lot_core" 1077name = "parking_lot_core"
1077version = "0.8.1" 1078version = "0.8.2"
1078source = "registry+https://github.com/rust-lang/crates.io-index" 1079source = "registry+https://github.com/rust-lang/crates.io-index"
1079checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" 1080checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
1080dependencies = [ 1081dependencies = [
1081 "cfg-if 1.0.0", 1082 "cfg-if 1.0.0",
1082 "instant", 1083 "instant",
@@ -1358,6 +1359,7 @@ dependencies = [
1358 "rustc-hash", 1359 "rustc-hash",
1359 "serde", 1360 "serde",
1360 "serde_json", 1361 "serde_json",
1362 "serde_path_to_error",
1361 "ssr", 1363 "ssr",
1362 "stdx", 1364 "stdx",
1363 "syntax", 1365 "syntax",
@@ -1376,9 +1378,9 @@ dependencies = [
1376 1378
1377[[package]] 1379[[package]]
1378name = "rustc-ap-rustc_lexer" 1380name = "rustc-ap-rustc_lexer"
1379version = "691.0.0" 1381version = "695.0.0"
1380source = "registry+https://github.com/rust-lang/crates.io-index" 1382source = "registry+https://github.com/rust-lang/crates.io-index"
1381checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec" 1383checksum = "390bad134705b0bff02cd9541ac66df751a91c3cc734c3369cd6151ca269caed"
1382dependencies = [ 1384dependencies = [
1383 "unicode-xid", 1385 "unicode-xid",
1384] 1386]
@@ -1527,6 +1529,15 @@ dependencies = [
1527] 1529]
1528 1530
1529[[package]] 1531[[package]]
1532name = "serde_path_to_error"
1533version = "0.1.4"
1534source = "registry+https://github.com/rust-lang/crates.io-index"
1535checksum = "42f6109f0506e20f7e0f910e51a0079acf41da8e0694e6442527c4ddf5a2b158"
1536dependencies = [
1537 "serde",
1538]
1539
1540[[package]]
1530name = "serde_repr" 1541name = "serde_repr"
1531version = "0.1.6" 1542version = "0.1.6"
1532source = "registry+https://github.com/rust-lang/crates.io-index" 1543source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 1d7e5ddd7..6d17d546a 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -374,8 +374,6 @@ impl Module {
374 let crate_def_map = db.crate_def_map(self.id.krate); 374 let crate_def_map = db.crate_def_map(self.id.krate);
375 crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink); 375 crate_def_map.add_diagnostics(db.upcast(), self.id.local_id, sink);
376 for decl in self.declarations(db) { 376 for decl in self.declarations(db) {
377 decl.diagnostics(db, sink);
378
379 match decl { 377 match decl {
380 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 378 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
381 crate::ModuleDef::Module(m) => { 379 crate::ModuleDef::Module(m) => {
@@ -384,7 +382,9 @@ impl Module {
384 m.diagnostics(db, sink) 382 m.diagnostics(db, sink)
385 } 383 }
386 } 384 }
387 _ => (), 385 _ => {
386 decl.diagnostics(db, sink);
387 }
388 } 388 }
389 } 389 }
390 390
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 289e812fe..965c1780a 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -17,9 +17,9 @@ ena = "0.14.0"
17log = "0.4.8" 17log = "0.4.8"
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19scoped-tls = "1" 19scoped-tls = "1"
20chalk-solve = { version = "0.43", default-features = false } 20chalk-solve = { version = "0.45", default-features = false }
21chalk-ir = "0.43" 21chalk-ir = "0.45"
22chalk-recursive = "0.43" 22chalk-recursive = "0.45"
23 23
24stdx = { path = "../stdx", version = "0.0.0" } 24stdx = { path = "../stdx", version = "0.0.0" }
25hir_def = { path = "../hir_def", version = "0.0.0" } 25hir_def = { path = "../hir_def", version = "0.0.0" }
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 69eae6f79..2196af677 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -56,8 +56,13 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
56 fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> { 56 fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> {
57 self.db.struct_datum(self.krate, struct_id) 57 self.db.struct_datum(self.krate, struct_id)
58 } 58 }
59 fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr { 59 fn adt_repr(&self, _struct_id: AdtId) -> Arc<rust_ir::AdtRepr<Interner>> {
60 rust_ir::AdtRepr { repr_c: false, repr_packed: false } 60 // FIXME: keep track of these
61 Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None })
62 }
63 fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> {
64 // FIXME: keep track of this
65 chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner)
61 } 66 }
62 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { 67 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
63 self.db.impl_datum(self.krate, impl_id) 68 self.db.impl_datum(self.krate, impl_id)
@@ -457,6 +462,7 @@ fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> {
457 "fn" => WellKnownTrait::Fn, 462 "fn" => WellKnownTrait::Fn,
458 "unsize" => WellKnownTrait::Unsize, 463 "unsize" => WellKnownTrait::Unsize,
459 "coerce_unsized" => WellKnownTrait::CoerceUnsized, 464 "coerce_unsized" => WellKnownTrait::CoerceUnsized,
465 "discriminant_kind" => WellKnownTrait::DiscriminantKind,
460 _ => return None, 466 _ => return None,
461 }) 467 })
462} 468}
@@ -473,6 +479,7 @@ fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str {
473 WellKnownTrait::Unsize => "unsize", 479 WellKnownTrait::Unsize => "unsize",
474 WellKnownTrait::Unpin => "unpin", 480 WellKnownTrait::Unpin => "unpin",
475 WellKnownTrait::CoerceUnsized => "coerce_unsized", 481 WellKnownTrait::CoerceUnsized => "coerce_unsized",
482 WellKnownTrait::DiscriminantKind => "discriminant_kind",
476 } 483 }
477} 484}
478 485
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 3ad30f0c9..b2714cb69 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -895,4 +895,17 @@ impl TestStruct {
895"#, 895"#,
896 ); 896 );
897 } 897 }
898
899 #[test]
900 fn test_single_incorrect_case_diagnostic_in_function_name_issue_6970() {
901 let input = r#"fn FOO<|>() {}"#;
902 let expected = r#"fn foo() {}"#;
903
904 let (analysis, file_position) = fixture::position(input);
905 let diagnostics =
906 analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap();
907 assert_eq!(diagnostics.len(), 1);
908
909 check_fixes(input, expected);
910 }
898} 911}
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index dbad9a84f..52c7f9775 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -535,6 +535,14 @@ impl Analysis {
535 self.with_db(|db| references::rename::prepare_rename(db, position)) 535 self.with_db(|db| references::rename::prepare_rename(db, position))
536 } 536 }
537 537
538 pub fn will_rename_file(
539 &self,
540 file_id: FileId,
541 new_name_stem: &str,
542 ) -> Cancelable<Option<SourceChange>> {
543 self.with_db(|db| references::rename::will_rename_file(db, file_id, new_name_stem))
544 }
545
538 pub fn structural_search_replace( 546 pub fn structural_search_replace(
539 &self, 547 &self,
540 query: &str, 548 query: &str,
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index cd721b7eb..15c95f239 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -6,7 +6,7 @@ use std::{
6}; 6};
7 7
8use hir::{Module, ModuleDef, ModuleSource, Semantics}; 8use hir::{Module, ModuleDef, ModuleSource, Semantics};
9use ide_db::base_db::{AnchoredPathBuf, FileRange, SourceDatabaseExt}; 9use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt};
10use ide_db::{ 10use ide_db::{
11 defs::{Definition, NameClass, NameRefClass}, 11 defs::{Definition, NameClass, NameRefClass},
12 RootDatabase, 12 RootDatabase,
@@ -110,6 +110,23 @@ pub(crate) fn rename_with_semantics(
110 } 110 }
111} 111}
112 112
113pub(crate) fn will_rename_file(
114 db: &RootDatabase,
115 file_id: FileId,
116 new_name_stem: &str,
117) -> Option<SourceChange> {
118 let sema = Semantics::new(db);
119 let module = sema.to_module_def(file_id)?;
120
121 let decl = module.declaration_source(db)?;
122 let range = decl.value.name()?.syntax().text_range();
123
124 let position = FilePosition { file_id: decl.file_id.original_file(db), offset: range.start() };
125 let mut change = rename_mod(&sema, position, module, new_name_stem).ok()?.info;
126 change.file_system_edits.clear();
127 Some(change)
128}
129
113fn find_module_at_offset( 130fn find_module_at_offset(
114 sema: &Semantics<RootDatabase>, 131 sema: &Semantics<RootDatabase>,
115 position: FilePosition, 132 position: FilePosition,
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 0b4d3f4eb..53e70eaf7 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -28,6 +28,7 @@ oorandom = "11.1.2"
28rustc-hash = "1.1.0" 28rustc-hash = "1.1.0"
29serde = { version = "1.0.106", features = ["derive"] } 29serde = { version = "1.0.106", features = ["derive"] }
30serde_json = { version = "1.0.48", features = ["preserve_order"] } 30serde_json = { version = "1.0.48", features = ["preserve_order"] }
31serde_path_to_error = "0.1"
31threadpool = "1.7.1" 32threadpool = "1.7.1"
32rayon = "1.5" 33rayon = "1.5"
33mimalloc = { version = "0.1.19", default-features = false, optional = true } 34mimalloc = { version = "0.1.19", default-features = false, optional = true }
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index de5eb93b5..80e46bf7f 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -5,12 +5,14 @@ use ide::CompletionResolveCapability;
5use lsp_types::{ 5use lsp_types::{
6 CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions, 6 CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions,
7 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, 7 CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
8 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, HoverProviderCapability, 8 DocumentOnTypeFormattingOptions, FileOperationFilter, FileOperationPattern,
9 ImplementationProviderCapability, OneOf, RenameOptions, SaveOptions, 9 FileOperationPatternKind, FileOperationRegistrationOptions, FoldingRangeProviderCapability,
10 HoverProviderCapability, ImplementationProviderCapability, OneOf, RenameOptions, SaveOptions,
10 SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend, 11 SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend,
11 SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, 12 SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability,
12 TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, 13 TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability,
13 WorkDoneProgressOptions, 14 WorkDoneProgressOptions, WorkspaceFileOperationsServerCapabilities,
15 WorkspaceServerCapabilities,
14}; 16};
15use rustc_hash::FxHashSet; 17use rustc_hash::FxHashSet;
16use serde_json::json; 18use serde_json::json;
@@ -68,7 +70,26 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
68 document_link_provider: None, 70 document_link_provider: None,
69 color_provider: None, 71 color_provider: None,
70 execute_command_provider: None, 72 execute_command_provider: None,
71 workspace: None, 73 workspace: Some(WorkspaceServerCapabilities {
74 workspace_folders: None,
75 file_operations: Some(WorkspaceFileOperationsServerCapabilities {
76 did_create: None,
77 will_create: None,
78 did_rename: None,
79 will_rename: Some(FileOperationRegistrationOptions {
80 filters: vec![FileOperationFilter {
81 scheme: Some(String::from("file")),
82 pattern: FileOperationPattern {
83 glob: String::from("**/*.rs"),
84 matches: Some(FileOperationPatternKind::File),
85 options: None,
86 },
87 }],
88 }),
89 did_delete: None,
90 will_delete: None,
91 }),
92 }),
72 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), 93 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
73 semantic_tokens_provider: Some( 94 semantic_tokens_provider: Some(
74 SemanticTokensOptions { 95 SemanticTokensOptions {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 66f8bee99..25692793b 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -5,11 +5,13 @@
5use std::{ 5use std::{
6 io::Write as _, 6 io::Write as _,
7 process::{self, Stdio}, 7 process::{self, Stdio},
8 sync::Arc,
8}; 9};
9 10
10use ide::{ 11use ide::{
11 CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, 12 AssistConfig, CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction,
12 NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit, 13 HoverGotoTypeData, LineIndex, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind,
14 SearchScope, SourceChange, SymbolKind, TextEdit,
13}; 15};
14use itertools::Itertools; 16use itertools::Itertools;
15use lsp_server::ErrorCode; 17use lsp_server::ErrorCode;
@@ -400,6 +402,45 @@ pub(crate) fn handle_workspace_symbol(
400 } 402 }
401} 403}
402 404
405pub(crate) fn handle_will_rename_files(
406 snap: GlobalStateSnapshot,
407 params: lsp_types::RenameFilesParams,
408) -> Result<Option<lsp_types::WorkspaceEdit>> {
409 let _p = profile::span("handle_will_rename_files");
410
411 let source_changes: Vec<SourceChange> = params
412 .files
413 .into_iter()
414 .filter_map(|file_rename| {
415 let from = Url::parse(&file_rename.old_uri).ok()?;
416 let to = Url::parse(&file_rename.new_uri).ok()?;
417
418 let from_path = from.to_file_path().ok()?;
419 let to_path = to.to_file_path().ok()?;
420
421 // Limit to single-level moves for now.
422 match (from_path.parent(), to_path.parent()) {
423 (Some(p1), Some(p2)) if p1 == p2 => {
424 let new_name = to_path.file_stem()?;
425 let new_name = new_name.to_str()?;
426 Some((snap.url_to_file_id(&from).ok()?, new_name.to_string()))
427 }
428 _ => None,
429 }
430 })
431 .filter_map(|(file_id, new_name)| {
432 snap.analysis.will_rename_file(file_id, &new_name).ok()?
433 })
434 .collect();
435
436 // Drop file system edits since we're just renaming things on the same level
437 let edits = source_changes.into_iter().map(|it| it.source_file_edits).flatten().collect();
438 let source_change = SourceChange::from_edits(edits, Vec::new());
439
440 let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
441 Ok(Some(workspace_edit))
442}
443
403pub(crate) fn handle_goto_definition( 444pub(crate) fn handle_goto_definition(
404 snap: GlobalStateSnapshot, 445 snap: GlobalStateSnapshot,
405 params: lsp_types::GotoDefinitionParams, 446 params: lsp_types::GotoDefinitionParams,
@@ -865,58 +906,8 @@ pub(crate) fn handle_formatting(
865 } 906 }
866} 907}
867 908
868fn handle_fixes(
869 snap: &GlobalStateSnapshot,
870 params: &lsp_types::CodeActionParams,
871 res: &mut Vec<lsp_ext::CodeAction>,
872) -> Result<()> {
873 let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
874 let line_index = snap.analysis.file_line_index(file_id)?;
875 let range = from_proto::text_range(&line_index, params.range);
876
877 match &params.context.only {
878 Some(v) => {
879 if !v.iter().any(|it| {
880 it == &lsp_types::CodeActionKind::EMPTY
881 || it == &lsp_types::CodeActionKind::QUICKFIX
882 }) {
883 return Ok(());
884 }
885 }
886 None => {}
887 };
888
889 let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, file_id)?;
890
891 for fix in diagnostics
892 .into_iter()
893 .filter_map(|d| d.fix)
894 .filter(|fix| fix.fix_trigger_range.intersect(range).is_some())
895 {
896 let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
897 let action = lsp_ext::CodeAction {
898 title: fix.label.to_string(),
899 group: None,
900 kind: Some(CodeActionKind::QUICKFIX),
901 edit: Some(edit),
902 is_preferred: Some(false),
903 data: None,
904 };
905 res.push(action);
906 }
907
908 for fix in snap.check_fixes.get(&file_id).into_iter().flatten() {
909 let fix_range = from_proto::text_range(&line_index, fix.range);
910 if fix_range.intersect(range).is_none() {
911 continue;
912 }
913 res.push(fix.action.clone());
914 }
915 Ok(())
916}
917
918pub(crate) fn handle_code_action( 909pub(crate) fn handle_code_action(
919 mut snap: GlobalStateSnapshot, 910 snap: GlobalStateSnapshot,
920 params: lsp_types::CodeActionParams, 911 params: lsp_types::CodeActionParams,
921) -> Result<Option<Vec<lsp_ext::CodeAction>>> { 912) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
922 let _p = profile::span("handle_code_action"); 913 let _p = profile::span("handle_code_action");
@@ -932,24 +923,35 @@ pub(crate) fn handle_code_action(
932 let range = from_proto::text_range(&line_index, params.range); 923 let range = from_proto::text_range(&line_index, params.range);
933 let frange = FileRange { file_id, range }; 924 let frange = FileRange { file_id, range };
934 925
935 snap.config.assist.allowed = params 926 let assists_config = AssistConfig {
936 .clone() 927 allowed: params
937 .context 928 .clone()
938 .only 929 .context
939 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); 930 .only
931 .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()),
932 ..snap.config.assist
933 };
940 934
941 let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); 935 let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
942 936
943 handle_fixes(&snap, &params, &mut res)?; 937 let include_quick_fixes = match &params.context.only {
938 Some(v) => v.iter().any(|it| {
939 it == &lsp_types::CodeActionKind::EMPTY || it == &lsp_types::CodeActionKind::QUICKFIX
940 }),
941 None => true,
942 };
943 if include_quick_fixes {
944 add_quick_fixes(&snap, frange, &line_index, &mut res)?;
945 }
944 946
945 if snap.config.client_caps.code_action_resolve { 947 if snap.config.client_caps.code_action_resolve {
946 for (index, assist) in 948 for (index, assist) in
947 snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() 949 snap.analysis.unresolved_assists(&assists_config, frange)?.into_iter().enumerate()
948 { 950 {
949 res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?); 951 res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?);
950 } 952 }
951 } else { 953 } else {
952 for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() { 954 for assist in snap.analysis.resolved_assists(&assists_config, frange)?.into_iter() {
953 res.push(to_proto::resolved_code_action(&snap, assist)?); 955 res.push(to_proto::resolved_code_action(&snap, assist)?);
954 } 956 }
955 } 957 }
@@ -957,6 +959,40 @@ pub(crate) fn handle_code_action(
957 Ok(Some(res)) 959 Ok(Some(res))
958} 960}
959 961
962fn add_quick_fixes(
963 snap: &GlobalStateSnapshot,
964 frange: FileRange,
965 line_index: &Arc<LineIndex>,
966 acc: &mut Vec<lsp_ext::CodeAction>,
967) -> Result<()> {
968 let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, frange.file_id)?;
969
970 for fix in diagnostics
971 .into_iter()
972 .filter_map(|d| d.fix)
973 .filter(|fix| fix.fix_trigger_range.intersect(frange.range).is_some())
974 {
975 let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
976 let action = lsp_ext::CodeAction {
977 title: fix.label.to_string(),
978 group: None,
979 kind: Some(CodeActionKind::QUICKFIX),
980 edit: Some(edit),
981 is_preferred: Some(false),
982 data: None,
983 };
984 acc.push(action);
985 }
986
987 for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() {
988 let fix_range = from_proto::text_range(&line_index, fix.range);
989 if fix_range.intersect(frange.range).is_some() {
990 acc.push(fix.action.clone());
991 }
992 }
993 Ok(())
994}
995
960pub(crate) fn handle_code_action_resolve( 996pub(crate) fn handle_code_action_resolve(
961 mut snap: GlobalStateSnapshot, 997 mut snap: GlobalStateSnapshot,
962 mut code_action: lsp_ext::CodeAction, 998 mut code_action: lsp_ext::CodeAction,
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 79fe30e53..d538ad69a 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -46,7 +46,7 @@ pub type Error = Box<dyn std::error::Error + Send + Sync>;
46pub type Result<T, E = Error> = std::result::Result<T, E>; 46pub type Result<T, E = Error> = std::result::Result<T, E>;
47 47
48pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { 48pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> {
49 let res = T::deserialize(&json) 49 let res = serde_path_to_error::deserialize(&json)
50 .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?; 50 .map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?;
51 Ok(res) 51 Ok(res)
52} 52}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index ec3d5e060..5d55dc96e 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -485,6 +485,7 @@ impl GlobalState {
485 .on::<lsp_types::request::SemanticTokensRangeRequest>( 485 .on::<lsp_types::request::SemanticTokensRangeRequest>(
486 handlers::handle_semantic_tokens_range, 486 handlers::handle_semantic_tokens_range,
487 ) 487 )
488 .on::<lsp_types::request::WillRenameFiles>(handlers::handle_will_rename_files)
488 .on::<lsp_ext::Ssr>(handlers::handle_ssr) 489 .on::<lsp_ext::Ssr>(handlers::handle_ssr)
489 .finish(); 490 .finish();
490 Ok(()) 491 Ok(())
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index c6a6f11e1..21015591c 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13[dependencies] 13[dependencies]
14itertools = "0.9.0" 14itertools = "0.9.0"
15rowan = "0.10.0" 15rowan = "0.10.0"
16rustc_lexer = { version = "691.0.0", package = "rustc-ap-rustc_lexer" } 16rustc_lexer = { version = "695.0.0", package = "rustc-ap-rustc_lexer" }
17rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
18arrayvec = "0.5.1" 18arrayvec = "0.5.1"
19once_cell = "1.3.1" 19once_cell = "1.3.1"