about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2020-07-17 11:20:28 +0200
committerAleksey Kladov <aleksey.kladov@gmail.com>2020-07-17 11:20:28 +0200
commit2729665235d941e83876a3799defe76326a5b807 (patch)
tree558a5016a73d424e7b4409a8804a4fea1cdd0fec
parent7e932f33391bd78a43a06d275a4d2f93fe3d7e8d (diff)
downloadrust-2729665235d941e83876a3799defe76326a5b807.tar.gz
rust-2729665235d941e83876a3799defe76326a5b807.zip
Continue non-doc comments with trailing space
-rw-r--r--crates/ra_ide/src/typing.rs1
-rw-r--r--crates/ra_ide/src/typing/on_enter.rs67
2 files changed, 59 insertions, 9 deletions
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 83776d2b6d3..d3ce744b44c 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -39,7 +39,6 @@ pub(crate) const TRIGGER_CHARS: &str = ".=>";
 // Some features trigger on typing certain characters:
 //
 // - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
-// - Enter inside comments automatically inserts `///`
 // - typing `.` in a chain method call auto-indents
 pub(crate) fn on_char_typed(
     db: &RootDatabase,
diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs
index 2faaa8ff071..143b1ae413e 100644
--- a/crates/ra_ide/src/typing/on_enter.rs
+++ b/crates/ra_ide/src/typing/on_enter.rs
@@ -7,10 +7,31 @@ use ra_syntax::{
     ast::{self, AstToken},
     AstNode, SmolStr, SourceFile,
     SyntaxKind::*,
-    SyntaxToken, TextSize, TokenAtOffset,
+    SyntaxToken, TextRange, TextSize, TokenAtOffset,
 };
 use ra_text_edit::TextEdit;
+use test_utils::mark;
 
+// Feature: On Enter
+//
+// rust-analyzer can override kbd:[Enter] key to make it smarter:
+//
+// - kbd:[Enter] inside triple-slash comments automatically inserts `///`
+// - kbd:[Enter] in the middle or after a trailing space in `//` inserts `//`
+//
+// This action needs to be assigned to shortcut explicitly.
+//
+// VS Code::
+//
+// Add the following to `keybindings.json`:
+// [source,json]
+// ----
+// {
+//   "key": "Enter",
+//   "command": "rust-analyzer.onEnter",
+//   "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
+// }
+// ----
 pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> {
     let parse = db.parse(position.file_id);
     let file = parse.tree();
@@ -30,15 +51,25 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Text
         return None;
     }
 
+    let mut remove_last_space = false;
     // Continuing single-line non-doc comments (like this one :) ) is annoying
-    if prefix == "//" && comment_range.end() == position.offset && !followed_by_comment(&comment) {
-        return None;
+    if prefix == "//" && comment_range.end() == position.offset {
+        if comment.text().ends_with(' ') {
+            mark::hit!(continues_end_of_line_comment_with_space);
+            remove_last_space = true;
+        } else if !followed_by_comment(&comment) {
+            return None;
+        }
     }
 
     let indent = node_indent(&file, comment.syntax())?;
     let inserted = format!("\n{}{} $0", indent, prefix);
-    let edit = TextEdit::insert(position.offset, inserted);
-
+    let delete = if remove_last_space {
+        TextRange::new(position.offset - TextSize::of(' '), position.offset)
+    } else {
+        TextRange::empty(position.offset)
+    };
+    let edit = TextEdit::replace(delete, inserted);
     Some(edit)
 }
 
@@ -75,10 +106,10 @@ fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
 
 #[cfg(test)]
 mod tests {
-    use test_utils::assert_eq_text;
+    use stdx::trim_indent;
+    use test_utils::{assert_eq_text, mark};
 
     use crate::mock_analysis::analysis_and_position;
-    use stdx::trim_indent;
 
     fn apply_on_enter(before: &str) -> Option<String> {
         let (analysis, position) = analysis_and_position(&before);
@@ -192,7 +223,7 @@ fn main() {
     }
 
     #[test]
-    fn does_not_continue_end_of_code_comment() {
+    fn does_not_continue_end_of_line_comment() {
         do_check_noop(
             r"
 fn main() {
@@ -202,4 +233,24 @@ fn main() {
 ",
         );
     }
+
+    #[test]
+    fn continues_end_of_line_comment_with_space() {
+        mark::check!(continues_end_of_line_comment_with_space);
+        do_check(
+            r#"
+fn main() {
+    // Fix me <|>
+    let x = 1 + 1;
+}
+"#,
+            r#"
+fn main() {
+    // Fix me
+    // $0
+    let x = 1 + 1;
+}
+"#,
+        );
+    }
 }