about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelicián Németh <felician.nemeth@gmail.com>2022-04-05 18:35:03 +0200
committerFelicián Németh <felician.nemeth@gmail.com>2022-05-22 10:40:53 +0200
commitf7c963c0f238a6ebb07bbb290d31f772b448c7aa (patch)
tree3f416c863307a1a13f719b0ba9760e4e4cc2ccdf
parent3bb02f2329623f1bb83512135746ce77ecb72b0b (diff)
downloadrust-f7c963c0f238a6ebb07bbb290d31f772b448c7aa.tar.gz
rust-f7c963c0f238a6ebb07bbb290d31f772b448c7aa.zip
onTypeFormatting: don't insert > if another > is there
-rw-r--r--crates/ide/src/typing.rs106
1 files changed, 101 insertions, 5 deletions
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index be1a6da7ea8..6af62d0ab23 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -83,19 +83,20 @@ fn on_char_typed_inner(
     offset: TextSize,
     char_typed: char,
 ) -> Option<ExtendedTextEdit> {
-    fn conv(text_edit: Option<TextEdit>) -> Option<ExtendedTextEdit> {
-        Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
-    }
     if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
         return None;
     }
-    match char_typed {
+    return match char_typed {
         '.' => conv(on_dot_typed(&file.tree(), offset)),
         '=' => conv(on_eq_typed(&file.tree(), offset)),
         '<' => on_left_angle_typed(&file.tree(), offset),
         '>' => conv(on_right_angle_typed(&file.tree(), offset)),
         '{' => conv(on_opening_brace_typed(file, offset)),
         _ => unreachable!(),
+    };
+
+    fn conv(text_edit: Option<TextEdit>) -> Option<ExtendedTextEdit> {
+        Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
     }
 }
 
@@ -319,8 +320,17 @@ fn on_left_angle_typed(file: &SourceFile, offset: TextSize) -> Option<ExtendedTe
     if !stdx::always!(file_text.char_at(offset) == Some('<')) {
         return None;
     }
-    let range = TextRange::at(offset, TextSize::of('<'));
 
+    // Find the next non-whitespace char in the line.
+    let mut next_offset = offset + TextSize::of('<');
+    while file_text.char_at(next_offset) == Some(' ') {
+        next_offset += TextSize::of(' ')
+    }
+    if file_text.char_at(next_offset) == Some('>') {
+        return None;
+    }
+
+    let range = TextRange::at(offset, TextSize::of('<'));
     if let Some(t) = file.syntax().token_at_offset(offset).left_biased() {
         if T![impl] == t.kind() {
             return Some(ExtendedTextEdit {
@@ -1082,6 +1092,92 @@ fn main() {
     }
 
     #[test]
+    fn dont_add_closing_angle_bracket_if_it_is_already_there() {
+        type_char_noop(
+            '<',
+            r#"
+fn foo() {
+    bar::$0>
+}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+fn foo(bar: &[u64]) {
+    bar.iter().collect::$0   >();
+}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+fn foo$0>() {}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+fn foo$0>
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+struct Foo$0> {}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+struct Foo$0>();
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+struct Foo$0>
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+enum Foo$0>
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+trait Foo$0>
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+type Foo$0> = Bar;
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+impl$0> Foo {}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+impl<T> Foo$0> {}
+            "#,
+        );
+        type_char_noop(
+            '<',
+            r#"
+impl Foo$0> {}
+            "#,
+        );
+    }
+
+    #[test]
     fn regression_629() {
         type_char_noop(
             '.',