]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/context.rs
Add test for current incorrect behaviour
[rust.git] / crates / ide_completion / src / context.rs
index 4e3abff3b3f86223dd54278b9217c9286aedd9fa..ac01968126d152159bd639df7ba98b2fa719a707 100644 (file)
@@ -58,6 +58,7 @@ pub(crate) struct PathCompletionContext {
 pub(super) struct PatternContext {
     pub(super) refutability: PatternRefutability,
     pub(super) is_param: Option<ParamKind>,
+    pub(super) has_type_ascription: bool,
 }
 
 #[derive(Debug)]
@@ -134,7 +135,6 @@ pub(crate) fn source_range(&self) -> TextRange {
         // check kind of macro-expanded token, but use range of original token
         let kind = self.token.kind();
         if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() {
-            cov_mark::hit!(completes_if_prefix_is_keyword);
             self.original_token.text_range()
         } else if kind == CHAR {
             // assume we are completing a lifetime but the user has only typed the '
@@ -598,7 +598,8 @@ fn expected_type_and_name(&self) -> (Option<Type>, Option<NameOrNameRef>) {
                             .map(|c| (Some(c.return_type()), None))
                             .unwrap_or((None, None))
                     },
-                    ast::Stmt(_it) => (None, None),
+                    ast::ParamList(__) => (None, None),
+                    ast::Stmt(__) => (None, None),
                     ast::Item(__) => (None, None),
                     _ => {
                         match node.parent() {
@@ -709,15 +710,15 @@ fn classify_name(_sema: &Semantics<RootDatabase>, name: ast::Name) -> Option<Pat
             return None;
         }
         let mut is_param = None;
-        let refutability = bind_pat
+        let (refutability, has_type_ascription) = bind_pat
             .syntax()
             .ancestors()
             .skip_while(|it| ast::Pat::can_cast(it.kind()))
             .next()
-            .map_or(PatternRefutability::Irrefutable, |node| {
-                match_ast! {
+            .map_or((PatternRefutability::Irrefutable, false), |node| {
+                let refutability = match_ast! {
                     match node {
-                        ast::LetStmt(__) => PatternRefutability::Irrefutable,
+                        ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
                         ast::Param(param) => {
                             let is_closure_param = param
                                 .syntax()
@@ -730,16 +731,17 @@ fn classify_name(_sema: &Semantics<RootDatabase>, name: ast::Name) -> Option<Pat
                             } else {
                                 ParamKind::Function
                             });
-                            PatternRefutability::Irrefutable
+                            return (PatternRefutability::Irrefutable, param.ty().is_some())
                         },
                         ast::MatchArm(__) => PatternRefutability::Refutable,
                         ast::Condition(__) => PatternRefutability::Refutable,
                         ast::ForExpr(__) => PatternRefutability::Irrefutable,
                         _ => PatternRefutability::Irrefutable,
                     }
-                }
+                };
+                (refutability, false)
             });
-        Some(PatternContext { refutability, is_param })
+        Some(PatternContext { refutability, is_param, has_type_ascription })
     }
 
     fn classify_name_ref(
@@ -1173,4 +1175,23 @@ fn foo() {
             expect![[r#"ty: Foo, name: ?"#]],
         );
     }
+
+    #[test]
+    fn expected_type_param_pat() {
+        check_expected_type_and_name(
+            r#"
+struct Foo { field: u32 }
+fn foo(a$0: Foo) {}
+"#,
+            expect![[r#"ty: Foo, name: ?"#]],
+        );
+        check_expected_type_and_name(
+            r#"
+struct Foo { field: u32 }
+fn foo($0: Foo) {}
+"#,
+            // FIXME make this work, currently fails due to pattern recovery eating the `:`
+            expect![[r#"ty: ?, name: ?"#]],
+        );
+    }
 }