diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/ra_ide/src/lib.rs | 9 | ||||
| -rw-r--r-- | crates/ra_text_edit/src/lib.rs | 33 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/caps.rs | 9 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 6 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 30 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 7 |
6 files changed, 60 insertions, 34 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index d0aeb3ba7..97ff67ee8 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
| @@ -89,6 +89,7 @@ pub use ra_ide_db::{ | |||
| 89 | symbol_index::Query, | 89 | symbol_index::Query, |
| 90 | RootDatabase, | 90 | RootDatabase, |
| 91 | }; | 91 | }; |
| 92 | pub use ra_text_edit::{Indel, TextEdit}; | ||
| 92 | 93 | ||
| 93 | pub type Cancelable<T> = Result<T, Canceled>; | 94 | pub type Cancelable<T> = Result<T, Canceled>; |
| 94 | 95 | ||
| @@ -285,14 +286,10 @@ impl Analysis { | |||
| 285 | 286 | ||
| 286 | /// Returns an edit to remove all newlines in the range, cleaning up minor | 287 | /// Returns an edit to remove all newlines in the range, cleaning up minor |
| 287 | /// stuff like trailing commas. | 288 | /// stuff like trailing commas. |
| 288 | pub fn join_lines(&self, frange: FileRange) -> Cancelable<SourceChange> { | 289 | pub fn join_lines(&self, frange: FileRange) -> Cancelable<TextEdit> { |
| 289 | self.with_db(|db| { | 290 | self.with_db(|db| { |
| 290 | let parse = db.parse(frange.file_id); | 291 | let parse = db.parse(frange.file_id); |
| 291 | let file_edit = SourceFileEdit { | 292 | join_lines::join_lines(&parse.tree(), frange.range) |
| 292 | file_id: frange.file_id, | ||
| 293 | edit: join_lines::join_lines(&parse.tree(), frange.range), | ||
| 294 | }; | ||
| 295 | SourceChange::source_file_edit("Join lines", file_edit) | ||
| 296 | }) | 293 | }) |
| 297 | } | 294 | } |
| 298 | 295 | ||
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs index 199fd1096..25554f583 100644 --- a/crates/ra_text_edit/src/lib.rs +++ b/crates/ra_text_edit/src/lib.rs | |||
| @@ -17,7 +17,7 @@ pub struct Indel { | |||
| 17 | pub delete: TextRange, | 17 | pub delete: TextRange, |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | #[derive(Debug, Clone)] | 20 | #[derive(Default, Debug, Clone)] |
| 21 | pub struct TextEdit { | 21 | pub struct TextEdit { |
| 22 | indels: Vec<Indel>, | 22 | indels: Vec<Indel>, |
| 23 | } | 23 | } |
| @@ -64,14 +64,6 @@ impl TextEdit { | |||
| 64 | builder.finish() | 64 | builder.finish() |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | pub(crate) fn from_indels(mut indels: Vec<Indel>) -> TextEdit { | ||
| 68 | indels.sort_by_key(|a| (a.delete.start(), a.delete.end())); | ||
| 69 | for (a1, a2) in indels.iter().zip(indels.iter().skip(1)) { | ||
| 70 | assert!(a1.delete.end() <= a2.delete.start()) | ||
| 71 | } | ||
| 72 | TextEdit { indels } | ||
| 73 | } | ||
| 74 | |||
| 75 | pub fn len(&self) -> usize { | 67 | pub fn len(&self) -> usize { |
| 76 | self.indels.len() | 68 | self.indels.len() |
| 77 | } | 69 | } |
| @@ -122,6 +114,17 @@ impl TextEdit { | |||
| 122 | *text = buf | 114 | *text = buf |
| 123 | } | 115 | } |
| 124 | 116 | ||
| 117 | pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> { | ||
| 118 | // FIXME: can be done without allocating intermediate vector | ||
| 119 | let mut all = self.iter().chain(other.iter()).collect::<Vec<_>>(); | ||
| 120 | if !check_disjoint(&mut all) { | ||
| 121 | return Err(other); | ||
| 122 | } | ||
| 123 | self.indels.extend(other.indels); | ||
| 124 | assert!(check_disjoint(&mut self.indels)); | ||
| 125 | Ok(()) | ||
| 126 | } | ||
| 127 | |||
| 125 | pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> { | 128 | pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> { |
| 126 | let mut res = offset; | 129 | let mut res = offset; |
| 127 | for indel in self.indels.iter() { | 130 | for indel in self.indels.iter() { |
| @@ -149,9 +152,19 @@ impl TextEditBuilder { | |||
| 149 | self.indels.push(Indel::insert(offset, text)) | 152 | self.indels.push(Indel::insert(offset, text)) |
| 150 | } | 153 | } |
| 151 | pub fn finish(self) -> TextEdit { | 154 | pub fn finish(self) -> TextEdit { |
| 152 | TextEdit::from_indels(self.indels) | 155 | let mut indels = self.indels; |
| 156 | assert!(check_disjoint(&mut indels)); | ||
| 157 | TextEdit { indels } | ||
| 153 | } | 158 | } |
| 154 | pub fn invalidates_offset(&self, offset: TextSize) -> bool { | 159 | pub fn invalidates_offset(&self, offset: TextSize) -> bool { |
| 155 | self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) | 160 | self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) |
| 156 | } | 161 | } |
| 157 | } | 162 | } |
| 163 | |||
| 164 | fn check_disjoint(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bool { | ||
| 165 | indels.sort_by_key(|indel| (indel.borrow().delete.start(), indel.borrow().delete.end())); | ||
| 166 | indels | ||
| 167 | .iter() | ||
| 168 | .zip(indels.iter().skip(1)) | ||
| 169 | .all(|(l, r)| l.borrow().delete.end() <= r.borrow().delete.start()) | ||
| 170 | } | ||
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 110c9a442..4c417c270 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | //! Advertizes the capabilities of the LSP Server. | 1 | //! Advertizes the capabilities of the LSP Server. |
| 2 | use std::env; | 2 | use std::env; |
| 3 | 3 | ||
| 4 | use crate::semantic_tokens; | ||
| 5 | |||
| 6 | use lsp_types::{ | 4 | use lsp_types::{ |
| 7 | CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability, | 5 | CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability, |
| 8 | CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions, | 6 | CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions, |
| @@ -12,6 +10,9 @@ use lsp_types::{ | |||
| 12 | ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, | 10 | ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, |
| 13 | TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, | 11 | TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, |
| 14 | }; | 12 | }; |
| 13 | use serde_json::json; | ||
| 14 | |||
| 15 | use crate::semantic_tokens; | ||
| 15 | 16 | ||
| 16 | pub fn server_capabilities() -> ServerCapabilities { | 17 | pub fn server_capabilities() -> ServerCapabilities { |
| 17 | ServerCapabilities { | 18 | ServerCapabilities { |
| @@ -91,6 +92,8 @@ pub fn server_capabilities() -> ServerCapabilities { | |||
| 91 | } | 92 | } |
| 92 | .into(), | 93 | .into(), |
| 93 | ), | 94 | ), |
| 94 | experimental: Default::default(), | 95 | experimental: Some(json!({ |
| 96 | "joinLines": true, | ||
| 97 | })), | ||
| 95 | } | 98 | } |
| 96 | } | 99 | } |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 3c7bd609d..1bb1b02ab 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
| @@ -87,15 +87,15 @@ pub enum JoinLines {} | |||
| 87 | 87 | ||
| 88 | impl Request for JoinLines { | 88 | impl Request for JoinLines { |
| 89 | type Params = JoinLinesParams; | 89 | type Params = JoinLinesParams; |
| 90 | type Result = SourceChange; | 90 | type Result = Vec<lsp_types::TextEdit>; |
| 91 | const METHOD: &'static str = "rust-analyzer/joinLines"; | 91 | const METHOD: &'static str = "experimental/joinLines"; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | #[derive(Deserialize, Serialize, Debug)] | 94 | #[derive(Deserialize, Serialize, Debug)] |
| 95 | #[serde(rename_all = "camelCase")] | 95 | #[serde(rename_all = "camelCase")] |
| 96 | pub struct JoinLinesParams { | 96 | pub struct JoinLinesParams { |
| 97 | pub text_document: TextDocumentIdentifier, | 97 | pub text_document: TextDocumentIdentifier, |
| 98 | pub range: Range, | 98 | pub ranges: Vec<Range>, |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | pub enum OnEnter {} | 101 | pub enum OnEnter {} |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index fcf08cd79..121964718 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
| @@ -15,10 +15,11 @@ use lsp_types::{ | |||
| 15 | DocumentSymbol, FoldingRange, FoldingRangeParams, Hover, HoverContents, Location, | 15 | DocumentSymbol, FoldingRange, FoldingRangeParams, Hover, HoverContents, Location, |
| 16 | MarkupContent, MarkupKind, Position, PrepareRenameResponse, Range, RenameParams, | 16 | MarkupContent, MarkupKind, Position, PrepareRenameResponse, Range, RenameParams, |
| 17 | SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult, | 17 | SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult, |
| 18 | SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, TextEdit, Url, WorkspaceEdit, | 18 | SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, Url, WorkspaceEdit, |
| 19 | }; | 19 | }; |
| 20 | use ra_ide::{ | 20 | use ra_ide::{ |
| 21 | Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope, | 21 | Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope, |
| 22 | TextEdit, | ||
| 22 | }; | 23 | }; |
| 23 | use ra_prof::profile; | 24 | use ra_prof::profile; |
| 24 | use ra_project_model::TargetKind; | 25 | use ra_project_model::TargetKind; |
| @@ -149,11 +150,24 @@ pub fn handle_find_matching_brace( | |||
| 149 | pub fn handle_join_lines( | 150 | pub fn handle_join_lines( |
| 150 | world: WorldSnapshot, | 151 | world: WorldSnapshot, |
| 151 | params: lsp_ext::JoinLinesParams, | 152 | params: lsp_ext::JoinLinesParams, |
| 152 | ) -> Result<lsp_ext::SourceChange> { | 153 | ) -> Result<Vec<lsp_types::TextEdit>> { |
| 153 | let _p = profile("handle_join_lines"); | 154 | let _p = profile("handle_join_lines"); |
| 154 | let frange = from_proto::file_range(&world, params.text_document, params.range)?; | 155 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; |
| 155 | let source_change = world.analysis().join_lines(frange)?; | 156 | let line_index = world.analysis().file_line_index(file_id)?; |
| 156 | to_proto::source_change(&world, source_change) | 157 | let line_endings = world.file_line_endings(file_id); |
| 158 | let mut res = TextEdit::default(); | ||
| 159 | for range in params.ranges { | ||
| 160 | let range = from_proto::text_range(&line_index, range); | ||
| 161 | let edit = world.analysis().join_lines(FileRange { file_id, range })?; | ||
| 162 | match res.union(edit) { | ||
| 163 | Ok(()) => (), | ||
| 164 | Err(_edit) => { | ||
| 165 | // just ignore overlapping edits | ||
| 166 | } | ||
| 167 | } | ||
| 168 | } | ||
| 169 | let res = to_proto::text_edit_vec(&line_index, line_endings, res); | ||
| 170 | Ok(res) | ||
| 157 | } | 171 | } |
| 158 | 172 | ||
| 159 | pub fn handle_on_enter( | 173 | pub fn handle_on_enter( |
| @@ -172,7 +186,7 @@ pub fn handle_on_enter( | |||
| 172 | pub fn handle_on_type_formatting( | 186 | pub fn handle_on_type_formatting( |
| 173 | world: WorldSnapshot, | 187 | world: WorldSnapshot, |
| 174 | params: lsp_types::DocumentOnTypeFormattingParams, | 188 | params: lsp_types::DocumentOnTypeFormattingParams, |
| 175 | ) -> Result<Option<Vec<TextEdit>>> { | 189 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { |
| 176 | let _p = profile("handle_on_type_formatting"); | 190 | let _p = profile("handle_on_type_formatting"); |
| 177 | let mut position = from_proto::file_position(&world, params.text_document_position)?; | 191 | let mut position = from_proto::file_position(&world, params.text_document_position)?; |
| 178 | let line_index = world.analysis().file_line_index(position.file_id)?; | 192 | let line_index = world.analysis().file_line_index(position.file_id)?; |
| @@ -618,7 +632,7 @@ pub fn handle_references( | |||
| 618 | pub fn handle_formatting( | 632 | pub fn handle_formatting( |
| 619 | world: WorldSnapshot, | 633 | world: WorldSnapshot, |
| 620 | params: DocumentFormattingParams, | 634 | params: DocumentFormattingParams, |
| 621 | ) -> Result<Option<Vec<TextEdit>>> { | 635 | ) -> Result<Option<Vec<lsp_types::TextEdit>>> { |
| 622 | let _p = profile("handle_formatting"); | 636 | let _p = profile("handle_formatting"); |
| 623 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; | 637 | let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?; |
| 624 | let file = world.analysis().file_text(file_id)?; | 638 | let file = world.analysis().file_text(file_id)?; |
| @@ -685,7 +699,7 @@ pub fn handle_formatting( | |||
| 685 | } | 699 | } |
| 686 | } | 700 | } |
| 687 | 701 | ||
| 688 | Ok(Some(vec![TextEdit { | 702 | Ok(Some(vec![lsp_types::TextEdit { |
| 689 | range: Range::new(Position::new(0, 0), end_position), | 703 | range: Range::new(Position::new(0, 0), end_position), |
| 690 | new_text: captured_stdout, | 704 | new_text: captured_stdout, |
| 691 | }])) | 705 | }])) |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 617197963..f6f4bb134 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
| @@ -2,12 +2,11 @@ | |||
| 2 | use ra_db::{FileId, FileRange}; | 2 | use ra_db::{FileId, FileRange}; |
| 3 | use ra_ide::{ | 3 | use ra_ide::{ |
| 4 | Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind, | 4 | Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind, |
| 5 | FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, InlayHint, | 5 | FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, Indel, |
| 6 | InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, Severity, | 6 | InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, Severity, |
| 7 | SourceChange, SourceFileEdit, | 7 | SourceChange, SourceFileEdit, TextEdit, |
| 8 | }; | 8 | }; |
| 9 | use ra_syntax::{SyntaxKind, TextRange, TextSize}; | 9 | use ra_syntax::{SyntaxKind, TextRange, TextSize}; |
| 10 | use ra_text_edit::{Indel, TextEdit}; | ||
| 11 | use ra_vfs::LineEndings; | 10 | use ra_vfs::LineEndings; |
| 12 | 11 | ||
| 13 | use crate::{lsp_ext, semantic_tokens, world::WorldSnapshot, Result}; | 12 | use crate::{lsp_ext, semantic_tokens, world::WorldSnapshot, Result}; |
