diff options
-rw-r--r-- | Cargo.lock | 39 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/Cargo.toml | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 11 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 13 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 19 | ||||
-rw-r--r-- | crates/rust-analyzer/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 29 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 158 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 1 | ||||
-rw-r--r-- | crates/syntax/Cargo.toml | 2 |
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]] |
170 | name = "chalk-derive" | 170 | name = "chalk-derive" |
171 | version = "0.43.0" | 171 | version = "0.45.0" |
172 | source = "registry+https://github.com/rust-lang/crates.io-index" | 172 | source = "registry+https://github.com/rust-lang/crates.io-index" |
173 | checksum = "e2d9e0c8adcced1ab0fea5cb8a38647922893d5b495e363e1814299fd380469b" | 173 | checksum = "ec7dacf94958d1a930b95d049d9443860859af59eadc77849392093eb577bcee" |
174 | dependencies = [ | 174 | dependencies = [ |
175 | "proc-macro2", | 175 | "proc-macro2", |
176 | "quote", | 176 | "quote", |
@@ -180,19 +180,20 @@ dependencies = [ | |||
180 | 180 | ||
181 | [[package]] | 181 | [[package]] |
182 | name = "chalk-ir" | 182 | name = "chalk-ir" |
183 | version = "0.43.0" | 183 | version = "0.45.0" |
184 | source = "registry+https://github.com/rust-lang/crates.io-index" | 184 | source = "registry+https://github.com/rust-lang/crates.io-index" |
185 | checksum = "c5218266a5709bc4943de997e64d3fab41c9e9f68efd54a898de53135e987bd3" | 185 | checksum = "a1a5b38ede247def17da87f4badb62396a5753db6048e2011d3089d8b3796c67" |
186 | dependencies = [ | 186 | dependencies = [ |
187 | "bitflags", | ||
187 | "chalk-derive", | 188 | "chalk-derive", |
188 | "lazy_static", | 189 | "lazy_static", |
189 | ] | 190 | ] |
190 | 191 | ||
191 | [[package]] | 192 | [[package]] |
192 | name = "chalk-recursive" | 193 | name = "chalk-recursive" |
193 | version = "0.43.0" | 194 | version = "0.45.0" |
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | 195 | source = "registry+https://github.com/rust-lang/crates.io-index" |
195 | checksum = "ed8f34f13fd4f30251f9f6f1dc56f80363201390ecbcac2fdfc8e33036cd9c4a" | 196 | checksum = "7a18db146d7a023edc20ad094e8c2284451f7888719645004979617d1f17c041" |
196 | dependencies = [ | 197 | dependencies = [ |
197 | "chalk-derive", | 198 | "chalk-derive", |
198 | "chalk-ir", | 199 | "chalk-ir", |
@@ -203,9 +204,9 @@ dependencies = [ | |||
203 | 204 | ||
204 | [[package]] | 205 | [[package]] |
205 | name = "chalk-solve" | 206 | name = "chalk-solve" |
206 | version = "0.43.0" | 207 | version = "0.45.0" |
207 | source = "registry+https://github.com/rust-lang/crates.io-index" | 208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
208 | checksum = "379c9f584488346044709d4c638c38d61a06fe593d4de2ac5f15fd2b0ba4cd9d" | 209 | checksum = "7f73e0de04a0f394e47ed8118e00541bcf681d7c3c2ef500fa743eb4cf3a4850" |
209 | dependencies = [ | 210 | dependencies = [ |
210 | "chalk-derive", | 211 | "chalk-derive", |
211 | "chalk-ir", | 212 | "chalk-ir", |
@@ -507,9 +508,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" | |||
507 | 508 | ||
508 | [[package]] | 509 | [[package]] |
509 | name = "heck" | 510 | name = "heck" |
510 | version = "0.3.1" | 511 | version = "0.3.2" |
511 | source = "registry+https://github.com/rust-lang/crates.io-index" | 512 | source = "registry+https://github.com/rust-lang/crates.io-index" |
512 | checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" | 513 | checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" |
513 | dependencies = [ | 514 | dependencies = [ |
514 | "unicode-segmentation", | 515 | "unicode-segmentation", |
515 | ] | 516 | ] |
@@ -1074,9 +1075,9 @@ dependencies = [ | |||
1074 | 1075 | ||
1075 | [[package]] | 1076 | [[package]] |
1076 | name = "parking_lot_core" | 1077 | name = "parking_lot_core" |
1077 | version = "0.8.1" | 1078 | version = "0.8.2" |
1078 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1079 | checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" | 1080 | checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" |
1080 | dependencies = [ | 1081 | dependencies = [ |
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]] |
1378 | name = "rustc-ap-rustc_lexer" | 1380 | name = "rustc-ap-rustc_lexer" |
1379 | version = "691.0.0" | 1381 | version = "695.0.0" |
1380 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1382 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1381 | checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec" | 1383 | checksum = "390bad134705b0bff02cd9541ac66df751a91c3cc734c3369cd6151ca269caed" |
1382 | dependencies = [ | 1384 | dependencies = [ |
1383 | "unicode-xid", | 1385 | "unicode-xid", |
1384 | ] | 1386 | ] |
@@ -1527,6 +1529,15 @@ dependencies = [ | |||
1527 | ] | 1529 | ] |
1528 | 1530 | ||
1529 | [[package]] | 1531 | [[package]] |
1532 | name = "serde_path_to_error" | ||
1533 | version = "0.1.4" | ||
1534 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1535 | checksum = "42f6109f0506e20f7e0f910e51a0079acf41da8e0694e6442527c4ddf5a2b158" | ||
1536 | dependencies = [ | ||
1537 | "serde", | ||
1538 | ] | ||
1539 | |||
1540 | [[package]] | ||
1530 | name = "serde_repr" | 1541 | name = "serde_repr" |
1531 | version = "0.1.6" | 1542 | version = "0.1.6" |
1532 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1543 | source = "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" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.43", default-features = false } | 20 | chalk-solve = { version = "0.45", default-features = false } |
21 | chalk-ir = "0.43" | 21 | chalk-ir = "0.45" |
22 | chalk-recursive = "0.43" | 22 | chalk-recursive = "0.45" |
23 | 23 | ||
24 | stdx = { path = "../stdx", version = "0.0.0" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
25 | hir_def = { path = "../hir_def", version = "0.0.0" } | 25 | hir_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 | ||
8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
9 | use ide_db::base_db::{AnchoredPathBuf, FileRange, SourceDatabaseExt}; | 9 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}; |
10 | use ide_db::{ | 10 | use 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 | ||
113 | pub(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 | |||
113 | fn find_module_at_offset( | 130 | fn 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" | |||
28 | rustc-hash = "1.1.0" | 28 | rustc-hash = "1.1.0" |
29 | serde = { version = "1.0.106", features = ["derive"] } | 29 | serde = { version = "1.0.106", features = ["derive"] } |
30 | serde_json = { version = "1.0.48", features = ["preserve_order"] } | 30 | serde_json = { version = "1.0.48", features = ["preserve_order"] } |
31 | serde_path_to_error = "0.1" | ||
31 | threadpool = "1.7.1" | 32 | threadpool = "1.7.1" |
32 | rayon = "1.5" | 33 | rayon = "1.5" |
33 | mimalloc = { version = "0.1.19", default-features = false, optional = true } | 34 | mimalloc = { 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; | |||
5 | use lsp_types::{ | 5 | use 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 | }; |
15 | use rustc_hash::FxHashSet; | 17 | use rustc_hash::FxHashSet; |
16 | use serde_json::json; | 18 | use 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 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | io::Write as _, | 6 | io::Write as _, |
7 | process::{self, Stdio}, | 7 | process::{self, Stdio}, |
8 | sync::Arc, | ||
8 | }; | 9 | }; |
9 | 10 | ||
10 | use ide::{ | 11 | use 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 | }; |
14 | use itertools::Itertools; | 16 | use itertools::Itertools; |
15 | use lsp_server::ErrorCode; | 17 | use lsp_server::ErrorCode; |
@@ -400,6 +402,45 @@ pub(crate) fn handle_workspace_symbol( | |||
400 | } | 402 | } |
401 | } | 403 | } |
402 | 404 | ||
405 | pub(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 | |||
403 | pub(crate) fn handle_goto_definition( | 444 | pub(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 | ||
868 | fn 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, ¶ms.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 ¶ms.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 | |||
918 | pub(crate) fn handle_code_action( | 909 | pub(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, ¶ms, &mut res)?; | 937 | let include_quick_fixes = match ¶ms.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 | ||
962 | fn 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 | |||
960 | pub(crate) fn handle_code_action_resolve( | 996 | pub(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>; | |||
46 | pub type Result<T, E = Error> = std::result::Result<T, E>; | 46 | pub type Result<T, E = Error> = std::result::Result<T, E>; |
47 | 47 | ||
48 | pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> { | 48 | pub 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] |
14 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
15 | rowan = "0.10.0" | 15 | rowan = "0.10.0" |
16 | rustc_lexer = { version = "691.0.0", package = "rustc-ap-rustc_lexer" } | 16 | rustc_lexer = { version = "695.0.0", package = "rustc-ap-rustc_lexer" } |
17 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
18 | arrayvec = "0.5.1" | 18 | arrayvec = "0.5.1" |
19 | once_cell = "1.3.1" | 19 | once_cell = "1.3.1" |