mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
avoid speculation when completing macros
This commit is contained in:
parent
5c11b363df
commit
726da9884b
5 changed files with 41 additions and 17 deletions
|
@ -10,7 +10,7 @@ use hir_def::{
|
||||||
resolver::{self, HasResolver, Resolver, TypeNs},
|
resolver::{self, HasResolver, Resolver, TypeNs},
|
||||||
AsMacroCall, FunctionId, TraitId, VariantId,
|
AsMacroCall, FunctionId, TraitId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{name::AsName, ExpansionInfo};
|
use hir_expand::{name::AsName, ExpansionInfo, MacroCallLoc};
|
||||||
use hir_ty::{associated_type_shorthand_candidates, Interner};
|
use hir_ty::{associated_type_shorthand_candidates, Interner};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
@ -160,6 +160,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
self.imp.expand_attr_macro(item)
|
self.imp.expand_attr_macro(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<MacroDef>> {
|
||||||
|
self.imp.resolve_derive_macro(derive)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expand_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<SyntaxNode>> {
|
pub fn expand_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<SyntaxNode>> {
|
||||||
self.imp.expand_derive_macro(derive)
|
self.imp.expand_derive_macro(derive)
|
||||||
}
|
}
|
||||||
|
@ -443,6 +447,25 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
Some(node)
|
Some(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<MacroDef>> {
|
||||||
|
let item = attr.syntax().parent().and_then(ast::Item::cast)?;
|
||||||
|
let file_id = self.find_file(item.syntax()).file_id;
|
||||||
|
let item = InFile::new(file_id, &item);
|
||||||
|
let src = InFile::new(file_id, attr.clone());
|
||||||
|
self.with_ctx(|ctx| {
|
||||||
|
let macro_call_ids = ctx.attr_to_derive_macro_call(item, src)?;
|
||||||
|
|
||||||
|
let res = macro_call_ids
|
||||||
|
.iter()
|
||||||
|
.map(|&call| {
|
||||||
|
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call);
|
||||||
|
MacroDef { id: loc.def }
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Some(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
|
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
|
||||||
let item = attr.syntax().parent().and_then(ast::Item::cast)?;
|
let item = attr.syntax().parent().and_then(ast::Item::cast)?;
|
||||||
let file_id = self.find_file(item.syntax()).file_id;
|
let file_id = self.find_file(item.syntax()).file_id;
|
||||||
|
|
|
@ -26,7 +26,7 @@ mod lint;
|
||||||
mod repr;
|
mod repr;
|
||||||
|
|
||||||
pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||||
let attribute = ctx.attribute_under_caret.as_ref()?;
|
let attribute = ctx.fake_attribute_under_caret.as_ref()?;
|
||||||
let name_ref = match attribute.path() {
|
let name_ref = match attribute.path() {
|
||||||
Some(p) => Some(p.as_single_name_ref()?),
|
Some(p) => Some(p.as_single_name_ref()?),
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -34,7 +34,7 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
|
||||||
match (name_ref, attribute.token_tree()) {
|
match (name_ref, attribute.token_tree()) {
|
||||||
(Some(path), Some(tt)) if tt.l_paren_token().is_some() => match path.text().as_str() {
|
(Some(path), Some(tt)) if tt.l_paren_token().is_some() => match path.text().as_str() {
|
||||||
"repr" => repr::complete_repr(acc, ctx, tt),
|
"repr" => repr::complete_repr(acc, ctx, tt),
|
||||||
"derive" => derive::complete_derive(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?),
|
"derive" => derive::complete_derive(acc, ctx, ctx.attr.as_ref()?),
|
||||||
"feature" => lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?, FEATURES),
|
"feature" => lint::complete_lint(acc, ctx, &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)?;
|
||||||
|
|
|
@ -13,17 +13,10 @@ use crate::{
|
||||||
item::CompletionItem, Completions, ImportEdit,
|
item::CompletionItem, Completions, ImportEdit,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn complete_derive(
|
pub(super) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, attr: &ast::Attr) {
|
||||||
acc: &mut Completions,
|
|
||||||
ctx: &CompletionContext,
|
|
||||||
existing_derives: &[ast::Path],
|
|
||||||
) {
|
|
||||||
let core = ctx.famous_defs().core();
|
let core = ctx.famous_defs().core();
|
||||||
let existing_derives: FxHashSet<_> = existing_derives
|
let existing_derives: FxHashSet<_> =
|
||||||
.into_iter()
|
ctx.sema.resolve_derive_macro(attr).into_iter().flatten().collect();
|
||||||
.filter_map(|path| ctx.scope.speculative_resolve_as_mac(&path))
|
|
||||||
.filter(|mac| mac.kind() == MacroKind::Derive)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for (name, mac) in get_derives_in_scope(ctx) {
|
for (name, mac) in get_derives_in_scope(ctx) {
|
||||||
if existing_derives.contains(&mac) {
|
if existing_derives.contains(&mac) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||||
cov_mark::hit!(no_keyword_completion_in_record_lit);
|
cov_mark::hit!(no_keyword_completion_in_record_lit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ctx.attribute_under_caret.is_some() {
|
if ctx.fake_attribute_under_caret.is_some() {
|
||||||
cov_mark::hit!(no_keyword_completion_in_attr_of_expr);
|
cov_mark::hit!(no_keyword_completion_in_attr_of_expr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
|
|
||||||
/// The parent function of the cursor position if it exists.
|
/// The parent function of the cursor position if it exists.
|
||||||
pub(super) function_def: Option<ast::Fn>,
|
pub(super) function_def: Option<ast::Fn>,
|
||||||
|
pub(super) attr: Option<ast::Attr>,
|
||||||
/// The parent impl of the cursor position if it exists.
|
/// The parent impl of the cursor position if it exists.
|
||||||
pub(super) impl_def: Option<ast::Impl>,
|
pub(super) impl_def: Option<ast::Impl>,
|
||||||
/// The NameLike under the cursor in the original file if it exists.
|
/// The NameLike under the cursor in the original file if it exists.
|
||||||
|
@ -111,7 +112,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
|
|
||||||
pub(super) completion_location: Option<ImmediateLocation>,
|
pub(super) completion_location: Option<ImmediateLocation>,
|
||||||
pub(super) prev_sibling: Option<ImmediatePrevSibling>,
|
pub(super) prev_sibling: Option<ImmediatePrevSibling>,
|
||||||
pub(super) attribute_under_caret: Option<ast::Attr>,
|
pub(super) fake_attribute_under_caret: Option<ast::Attr>,
|
||||||
pub(super) previous_token: Option<SyntaxToken>,
|
pub(super) previous_token: Option<SyntaxToken>,
|
||||||
|
|
||||||
pub(super) lifetime_ctx: Option<LifetimeContext>,
|
pub(super) lifetime_ctx: Option<LifetimeContext>,
|
||||||
|
@ -397,13 +398,14 @@ impl<'a> CompletionContext<'a> {
|
||||||
expected_name: None,
|
expected_name: None,
|
||||||
expected_type: None,
|
expected_type: None,
|
||||||
function_def: None,
|
function_def: None,
|
||||||
|
attr: None,
|
||||||
impl_def: None,
|
impl_def: None,
|
||||||
name_syntax: None,
|
name_syntax: None,
|
||||||
lifetime_ctx: None,
|
lifetime_ctx: None,
|
||||||
pattern_ctx: None,
|
pattern_ctx: None,
|
||||||
completion_location: None,
|
completion_location: None,
|
||||||
prev_sibling: None,
|
prev_sibling: None,
|
||||||
attribute_under_caret: None,
|
fake_attribute_under_caret: None,
|
||||||
previous_token: None,
|
previous_token: None,
|
||||||
path_context: None,
|
path_context: None,
|
||||||
locals,
|
locals,
|
||||||
|
@ -641,7 +643,6 @@ impl<'a> CompletionContext<'a> {
|
||||||
let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
|
let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
|
||||||
let syntax_element = NodeOrToken::Token(fake_ident_token);
|
let syntax_element = NodeOrToken::Token(fake_ident_token);
|
||||||
self.previous_token = previous_token(syntax_element.clone());
|
self.previous_token = previous_token(syntax_element.clone());
|
||||||
self.attribute_under_caret = syntax_element.ancestors().find_map(ast::Attr::cast);
|
|
||||||
self.no_completion_required = {
|
self.no_completion_required = {
|
||||||
let inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone());
|
let inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone());
|
||||||
let fn_is_prev = self.previous_token_is(T![fn]);
|
let fn_is_prev = self.previous_token_is(T![fn]);
|
||||||
|
@ -649,6 +650,13 @@ impl<'a> CompletionContext<'a> {
|
||||||
(fn_is_prev && !inside_impl_trait_block) || for_is_prev2
|
(fn_is_prev && !inside_impl_trait_block) || for_is_prev2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.attr = self
|
||||||
|
.sema
|
||||||
|
.token_ancestors_with_macros(self.token.clone())
|
||||||
|
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
|
||||||
|
.find_map(ast::Attr::cast);
|
||||||
|
self.fake_attribute_under_caret = syntax_element.ancestors().find_map(ast::Attr::cast);
|
||||||
|
|
||||||
self.incomplete_let =
|
self.incomplete_let =
|
||||||
syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
|
syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
|
||||||
it.syntax().text_range().end() == syntax_element.text_range().end()
|
it.syntax().text_range().end() == syntax_element.text_range().end()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue