about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2022-06-20 15:07:48 +0200
committerLukas Wirth <lukastw97@gmail.com>2022-06-20 15:07:48 +0200
commitbcf10cde137bb0b0c4e2be8564c31c2e0e392406 (patch)
tree2bd2c6efa006e3bdb12eeddb011fb6c6521985c8
parent90483321ee0b47d48a5019bd9bbb11b45a24ac84 (diff)
downloadrust-bcf10cde137bb0b0c4e2be8564c31c2e0e392406.tar.gz
rust-bcf10cde137bb0b0c4e2be8564c31c2e0e392406.zip
internal: Remove `previous_token` field from `CompletionContext`
-rw-r--r--crates/ide-completion/src/completions.rs4
-rw-r--r--crates/ide-completion/src/completions/attribute.rs7
-rw-r--r--crates/ide-completion/src/completions/attribute/lint.rs4
-rw-r--r--crates/ide-completion/src/completions/record.rs8
-rw-r--r--crates/ide-completion/src/context.rs22
-rw-r--r--crates/ide-completion/src/context/analysis.rs30
-rw-r--r--crates/ide-completion/src/lib.rs12
7 files changed, 50 insertions, 37 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index c1081dbde32..3f9314bbb31 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -541,8 +541,8 @@ pub(super) fn complete_name_ref(
         NameRefKind::Keyword(item) => {
             keyword::complete_for_and_where(acc, ctx, item);
         }
-        NameRefKind::RecordExpr(record_expr) => {
-            record::complete_record_expr_fields(acc, ctx, record_expr);
+        NameRefKind::RecordExpr { dot_prefix, expr } => {
+            record::complete_record_expr_fields(acc, ctx, expr, dot_prefix);
         }
         NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
     }
diff --git a/crates/ide-completion/src/completions/attribute.rs b/crates/ide-completion/src/completions/attribute.rs
index 37e042a1609..3115971c857 100644
--- a/crates/ide-completion/src/completions/attribute.rs
+++ b/crates/ide-completion/src/completions/attribute.rs
@@ -33,6 +33,7 @@ pub(crate) use self::derive::complete_derive_path;
 pub(crate) fn complete_known_attribute_input(
     acc: &mut Completions,
     ctx: &CompletionContext,
+    &colon_prefix: &bool,
     fake_attribute_under_caret: &ast::Attr,
 ) -> Option<()> {
     let attribute = fake_attribute_under_caret;
@@ -47,7 +48,9 @@ pub(crate) fn complete_known_attribute_input(
 
     match path.text().as_str() {
         "repr" => repr::complete_repr(acc, ctx, tt),
-        "feature" => lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?, FEATURES),
+        "feature" => {
+            lint::complete_lint(acc, ctx, colon_prefix, &parse_tt_as_comma_sep_paths(tt)?, FEATURES)
+        }
         "allow" | "warn" | "deny" | "forbid" => {
             let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
 
@@ -60,7 +63,7 @@ pub(crate) fn complete_known_attribute_input(
                 .cloned()
                 .collect();
 
-            lint::complete_lint(acc, ctx, &existing_lints, &lints);
+            lint::complete_lint(acc, ctx, colon_prefix, &existing_lints, &lints);
         }
         "cfg" => cfg::complete_cfg(acc, ctx),
         _ => (),
diff --git a/crates/ide-completion/src/completions/attribute/lint.rs b/crates/ide-completion/src/completions/attribute/lint.rs
index 8991d657e85..5c048103187 100644
--- a/crates/ide-completion/src/completions/attribute/lint.rs
+++ b/crates/ide-completion/src/completions/attribute/lint.rs
@@ -1,16 +1,16 @@
 //! Completion for lints
 use ide_db::{generated::lints::Lint, SymbolKind};
-use syntax::{ast, T};
+use syntax::ast;
 
 use crate::{context::CompletionContext, item::CompletionItem, Completions};
 
 pub(super) fn complete_lint(
     acc: &mut Completions,
     ctx: &CompletionContext,
+    is_qualified: bool,
     existing_lints: &[ast::Path],
     lints_completions: &[Lint],
 ) {
-    let is_qualified = ctx.previous_token_is(T![:]);
     for &Lint { label, description } in lints_completions {
         let (qual, name) = {
             // FIXME: change `Lint`'s label to not store a path in it but split the prefix off instead?
diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs
index 12c449bf352..9f834e1ca15 100644
--- a/crates/ide-completion/src/completions/record.rs
+++ b/crates/ide-completion/src/completions/record.rs
@@ -1,9 +1,6 @@
 //! Complete fields in record literals and patterns.
 use ide_db::SymbolKind;
-use syntax::{
-    ast::{self, Expr},
-    T,
-};
+use syntax::ast::{self, Expr};
 
 use crate::{
     context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified},
@@ -24,6 +21,7 @@ pub(crate) fn complete_record_expr_fields(
     acc: &mut Completions,
     ctx: &CompletionContext,
     record_expr: &ast::RecordExpr,
+    &dot_prefix: &bool,
 ) {
     let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone()));
 
@@ -45,7 +43,7 @@ pub(crate) fn complete_record_expr_fields(
             let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
 
             add_default_update(acc, ctx, ty, &missing_fields);
-            if ctx.previous_token_is(T![.]) {
+            if dot_prefix {
                 let mut item =
                     CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
                 item.insert_text(".");
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 8c73709f4ce..9aee1e8b49e 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -259,8 +259,11 @@ pub(super) enum NameRefKind {
     DotAccess(DotAccess),
     /// Position where we are only interested in keyword completions
     Keyword(ast::Item),
-    /// The record expression this nameref is a field of
-    RecordExpr(ast::RecordExpr),
+    /// The record expression this nameref is a field of and whether a dot precedes the completion identifier.
+    RecordExpr {
+        dot_prefix: bool,
+        expr: ast::RecordExpr,
+    },
     Pattern(PatternContext),
 }
 
@@ -279,6 +282,7 @@ pub(super) enum IdentContext {
     },
     /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)`
     UnexpandedAttrTT {
+        colon_prefix: bool,
         fake_attribute_under_caret: Option<ast::Attr>,
     },
 }
@@ -334,9 +338,6 @@ pub(crate) struct CompletionContext<'a> {
     /// The expected type of what we are completing.
     pub(super) expected_type: Option<Type>,
 
-    // FIXME: This shouldn't exist
-    pub(super) previous_token: Option<SyntaxToken>,
-
     // We might wanna split these out of CompletionContext
     pub(super) ident_ctx: IdentContext,
     pub(super) qualifier_ctx: QualifierCtx,
@@ -361,11 +362,6 @@ impl<'a> CompletionContext<'a> {
         }
     }
 
-    // FIXME: This shouldn't exist
-    pub(crate) fn previous_token_is(&self, kind: SyntaxKind) -> bool {
-        self.previous_token.as_ref().map_or(false, |tok| tok.kind() == kind)
-    }
-
     pub(crate) fn famous_defs(&self) -> FamousDefs {
         FamousDefs(&self.sema, self.krate)
     }
@@ -507,9 +503,11 @@ impl<'a> CompletionContext<'a> {
             module,
             expected_name: None,
             expected_type: None,
-            previous_token: None,
             // dummy value, will be overwritten
-            ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None },
+            ident_ctx: IdentContext::UnexpandedAttrTT {
+                fake_attribute_under_caret: None,
+                colon_prefix: false,
+            },
             qualifier_ctx: Default::default(),
             locals,
         };
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 551fa7fb865..1f691f3baf6 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -254,7 +254,9 @@ impl<'a> CompletionContext<'a> {
                     // match foo { $0 }
                     // match foo { ..., pat => $0 }
                     ast::MatchExpr(it) => {
-                        let ty = if self.previous_token_is(T![=>]) {
+                        let on_arrow = previous_non_trivia_token(self.token.clone()).map_or(false, |it| T![=>] == it.kind());
+
+                        let ty = if on_arrow {
                             // match foo { ..., pat => $0 }
                             cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
                             cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
@@ -327,9 +329,6 @@ impl<'a> CompletionContext<'a> {
             return None;
         }
 
-        self.previous_token =
-            syntax_element.clone().into_token().and_then(previous_non_trivia_token);
-
         (self.expected_type, self.expected_name) = self.expected_type_and_name();
 
         // Overwrite the path kind for derives
@@ -368,19 +367,19 @@ impl<'a> CompletionContext<'a> {
                 } else {
                     // Fix up trailing whitespace problem
                     // #[attr(foo = $0
-                    let token = if self.token.kind() == SyntaxKind::WHITESPACE {
-                        self.previous_token.as_ref()?
-                    } else {
-                        &self.token
-                    };
+                    let token =
+                        syntax::algo::skip_trivia_token(self.token.clone(), Direction::Prev)?;
                     let p = token.parent()?;
                     if p.kind() == SyntaxKind::TOKEN_TREE
                         && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
                     {
+                        let colon_prefix = previous_non_trivia_token(self.token.clone())
+                            .map_or(false, |it| T![:] == it.kind());
                         self.ident_ctx = IdentContext::UnexpandedAttrTT {
                             fake_attribute_under_caret: syntax_element
                                 .ancestors()
                                 .find_map(ast::Attr::cast),
+                            colon_prefix,
                         };
                     } else {
                         return None;
@@ -493,12 +492,15 @@ impl<'a> CompletionContext<'a> {
             |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
 
         if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
+            let dot_prefix = previous_non_trivia_token(name_ref.syntax().clone())
+                .map_or(false, |it| T![.] == it.kind());
+
             return find_node_in_file_compensated(
                 sema,
                 original_file,
                 &record_field.parent_record_lit(),
             )
-            .map(NameRefKind::RecordExpr)
+            .map(|expr| NameRefKind::RecordExpr { expr, dot_prefix })
             .map(make_res);
         }
         if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
@@ -1180,8 +1182,12 @@ pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
         .is_some()
 }
 
-fn previous_non_trivia_token(token: SyntaxToken) -> Option<SyntaxToken> {
-    let mut token = token.prev_token();
+fn previous_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
+    let mut token = match e.into() {
+        SyntaxElement::Node(n) => n.first_token()?,
+        SyntaxElement::Token(t) => t,
+    }
+    .prev_token();
     while let Some(inner) = token {
         if !inner.kind().is_trivia() {
             return Some(inner);
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 90e2628439f..bf75dcf26bc 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -181,8 +181,16 @@ pub fn completions(
                 completions::extern_abi::complete_extern_abi(acc, ctx, expanded);
                 completions::format_string::format_string(acc, ctx, original, expanded);
             }
-            IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: Some(attr) } => {
-                completions::attribute::complete_known_attribute_input(acc, ctx, attr);
+            IdentContext::UnexpandedAttrTT {
+                colon_prefix,
+                fake_attribute_under_caret: Some(attr),
+            } => {
+                completions::attribute::complete_known_attribute_input(
+                    acc,
+                    ctx,
+                    colon_prefix,
+                    attr,
+                );
             }
             IdentContext::UnexpandedAttrTT { .. } | IdentContext::String { .. } => (),
         }