mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 15:15:24 +00:00
internal: Remove previous_token
field from CompletionContext
This commit is contained in:
parent
90483321ee
commit
bcf10cde13
7 changed files with 50 additions and 37 deletions
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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(".");
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 { .. } => (),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue