internal: Remove previous_token field from CompletionContext

This commit is contained in:
Lukas Wirth 2022-06-20 15:07:48 +02:00
parent 90483321ee
commit bcf10cde13
7 changed files with 50 additions and 37 deletions

View File

@ -541,8 +541,8 @@ pub(super) fn complete_name_ref(
NameRefKind::Keyword(item) => { NameRefKind::Keyword(item) => {
keyword::complete_for_and_where(acc, ctx, item); keyword::complete_for_and_where(acc, ctx, item);
} }
NameRefKind::RecordExpr(record_expr) => { NameRefKind::RecordExpr { dot_prefix, expr } => {
record::complete_record_expr_fields(acc, ctx, record_expr); record::complete_record_expr_fields(acc, ctx, expr, dot_prefix);
} }
NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx), NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
} }

View File

@ -33,6 +33,7 @@ pub(crate) use self::derive::complete_derive_path;
pub(crate) fn complete_known_attribute_input( pub(crate) fn complete_known_attribute_input(
acc: &mut Completions, acc: &mut Completions,
ctx: &CompletionContext, ctx: &CompletionContext,
&colon_prefix: &bool,
fake_attribute_under_caret: &ast::Attr, fake_attribute_under_caret: &ast::Attr,
) -> Option<()> { ) -> Option<()> {
let attribute = fake_attribute_under_caret; let attribute = fake_attribute_under_caret;
@ -47,7 +48,9 @@ pub(crate) fn complete_known_attribute_input(
match path.text().as_str() { match path.text().as_str() {
"repr" => repr::complete_repr(acc, ctx, tt), "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" => { "allow" | "warn" | "deny" | "forbid" => {
let existing_lints = parse_tt_as_comma_sep_paths(tt)?; let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
@ -60,7 +63,7 @@ pub(crate) fn complete_known_attribute_input(
.cloned() .cloned()
.collect(); .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), "cfg" => cfg::complete_cfg(acc, ctx),
_ => (), _ => (),

View File

@ -1,16 +1,16 @@
//! Completion for lints //! Completion for lints
use ide_db::{generated::lints::Lint, SymbolKind}; use ide_db::{generated::lints::Lint, SymbolKind};
use syntax::{ast, T}; use syntax::ast;
use crate::{context::CompletionContext, item::CompletionItem, Completions}; use crate::{context::CompletionContext, item::CompletionItem, Completions};
pub(super) fn complete_lint( pub(super) fn complete_lint(
acc: &mut Completions, acc: &mut Completions,
ctx: &CompletionContext, ctx: &CompletionContext,
is_qualified: bool,
existing_lints: &[ast::Path], existing_lints: &[ast::Path],
lints_completions: &[Lint], lints_completions: &[Lint],
) { ) {
let is_qualified = ctx.previous_token_is(T![:]);
for &Lint { label, description } in lints_completions { for &Lint { label, description } in lints_completions {
let (qual, name) = { let (qual, name) = {
// FIXME: change `Lint`'s label to not store a path in it but split the prefix off instead? // FIXME: change `Lint`'s label to not store a path in it but split the prefix off instead?

View File

@ -1,9 +1,6 @@
//! Complete fields in record literals and patterns. //! Complete fields in record literals and patterns.
use ide_db::SymbolKind; use ide_db::SymbolKind;
use syntax::{ use syntax::ast::{self, Expr};
ast::{self, Expr},
T,
};
use crate::{ use crate::{
context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified}, context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified},
@ -24,6 +21,7 @@ pub(crate) fn complete_record_expr_fields(
acc: &mut Completions, acc: &mut Completions,
ctx: &CompletionContext, ctx: &CompletionContext,
record_expr: &ast::RecordExpr, record_expr: &ast::RecordExpr,
&dot_prefix: &bool,
) { ) {
let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_expr.clone())); 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); let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
add_default_update(acc, ctx, ty, &missing_fields); add_default_update(acc, ctx, ty, &missing_fields);
if ctx.previous_token_is(T![.]) { if dot_prefix {
let mut item = let mut item =
CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), ".."); CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
item.insert_text("."); item.insert_text(".");

View File

@ -259,8 +259,11 @@ pub(super) enum NameRefKind {
DotAccess(DotAccess), DotAccess(DotAccess),
/// Position where we are only interested in keyword completions /// Position where we are only interested in keyword completions
Keyword(ast::Item), Keyword(ast::Item),
/// The record expression this nameref is a field of /// The record expression this nameref is a field of and whether a dot precedes the completion identifier.
RecordExpr(ast::RecordExpr), RecordExpr {
dot_prefix: bool,
expr: ast::RecordExpr,
},
Pattern(PatternContext), 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)` /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)`
UnexpandedAttrTT { UnexpandedAttrTT {
colon_prefix: bool,
fake_attribute_under_caret: Option<ast::Attr>, fake_attribute_under_caret: Option<ast::Attr>,
}, },
} }
@ -334,9 +338,6 @@ pub(crate) struct CompletionContext<'a> {
/// The expected type of what we are completing. /// The expected type of what we are completing.
pub(super) expected_type: Option<Type>, 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 // We might wanna split these out of CompletionContext
pub(super) ident_ctx: IdentContext, pub(super) ident_ctx: IdentContext,
pub(super) qualifier_ctx: QualifierCtx, 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 { pub(crate) fn famous_defs(&self) -> FamousDefs {
FamousDefs(&self.sema, self.krate) FamousDefs(&self.sema, self.krate)
} }
@ -507,9 +503,11 @@ impl<'a> CompletionContext<'a> {
module, module,
expected_name: None, expected_name: None,
expected_type: None, expected_type: None,
previous_token: None,
// dummy value, will be overwritten // 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(), qualifier_ctx: Default::default(),
locals, locals,
}; };

View File

@ -254,7 +254,9 @@ impl<'a> CompletionContext<'a> {
// match foo { $0 } // match foo { $0 }
// match foo { ..., pat => $0 } // match foo { ..., pat => $0 }
ast::MatchExpr(it) => { 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 } // match foo { ..., pat => $0 }
cov_mark::hit!(expected_type_match_arm_body_without_leading_char); cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
cov_mark::hit!(expected_type_match_arm_body_with_leading_char); cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
@ -327,9 +329,6 @@ impl<'a> CompletionContext<'a> {
return None; 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(); (self.expected_type, self.expected_name) = self.expected_type_and_name();
// Overwrite the path kind for derives // Overwrite the path kind for derives
@ -368,19 +367,19 @@ impl<'a> CompletionContext<'a> {
} else { } else {
// Fix up trailing whitespace problem // Fix up trailing whitespace problem
// #[attr(foo = $0 // #[attr(foo = $0
let token = if self.token.kind() == SyntaxKind::WHITESPACE { let token =
self.previous_token.as_ref()? syntax::algo::skip_trivia_token(self.token.clone(), Direction::Prev)?;
} else {
&self.token
};
let p = token.parent()?; let p = token.parent()?;
if p.kind() == SyntaxKind::TOKEN_TREE if p.kind() == SyntaxKind::TOKEN_TREE
&& p.ancestors().any(|it| it.kind() == SyntaxKind::META) && 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 { self.ident_ctx = IdentContext::UnexpandedAttrTT {
fake_attribute_under_caret: syntax_element fake_attribute_under_caret: syntax_element
.ancestors() .ancestors()
.find_map(ast::Attr::cast), .find_map(ast::Attr::cast),
colon_prefix,
}; };
} else { } else {
return None; return None;
@ -493,12 +492,15 @@ impl<'a> CompletionContext<'a> {
|kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default()); |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) { 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( return find_node_in_file_compensated(
sema, sema,
original_file, original_file,
&record_field.parent_record_lit(), &record_field.parent_record_lit(),
) )
.map(NameRefKind::RecordExpr) .map(|expr| NameRefKind::RecordExpr { expr, dot_prefix })
.map(make_res); .map(make_res);
} }
if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) { 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() .is_some()
} }
fn previous_non_trivia_token(token: SyntaxToken) -> Option<SyntaxToken> { fn previous_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
let mut token = token.prev_token(); let mut token = match e.into() {
SyntaxElement::Node(n) => n.first_token()?,
SyntaxElement::Token(t) => t,
}
.prev_token();
while let Some(inner) = token { while let Some(inner) = token {
if !inner.kind().is_trivia() { if !inner.kind().is_trivia() {
return Some(inner); return Some(inner);

View File

@ -181,8 +181,16 @@ pub fn completions(
completions::extern_abi::complete_extern_abi(acc, ctx, expanded); completions::extern_abi::complete_extern_abi(acc, ctx, expanded);
completions::format_string::format_string(acc, ctx, original, expanded); completions::format_string::format_string(acc, ctx, original, expanded);
} }
IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: Some(attr) } => { IdentContext::UnexpandedAttrTT {
completions::attribute::complete_known_attribute_input(acc, ctx, attr); colon_prefix,
fake_attribute_under_caret: Some(attr),
} => {
completions::attribute::complete_known_attribute_input(
acc,
ctx,
colon_prefix,
attr,
);
} }
IdentContext::UnexpandedAttrTT { .. } | IdentContext::String { .. } => (), IdentContext::UnexpandedAttrTT { .. } | IdentContext::String { .. } => (),
} }