mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Lookup lang attribute on assoc item trait directly
This commit is contained in:
parent
94b369faa3
commit
4901ea3eef
@ -255,6 +255,10 @@ impl Attrs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn lang(&self) -> Option<&SmolStr> {
|
||||||
|
self.by_key("lang").string_value()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn docs(&self) -> Option<Documentation> {
|
pub fn docs(&self) -> Option<Documentation> {
|
||||||
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::Literal(s) => Some(s),
|
AttrInput::Literal(s) => Some(s),
|
||||||
@ -754,20 +758,20 @@ impl Attr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct AttrQuery<'a> {
|
pub struct AttrQuery<'attr> {
|
||||||
attrs: &'a Attrs,
|
attrs: &'attr Attrs,
|
||||||
key: &'static str,
|
key: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AttrQuery<'a> {
|
impl<'attr> AttrQuery<'attr> {
|
||||||
pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
|
pub fn tt_values(self) -> impl Iterator<Item = &'attr Subtree> {
|
||||||
self.attrs().filter_map(|attr| match attr.input.as_deref()? {
|
self.attrs().filter_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::TokenTree(it, _) => Some(it),
|
AttrInput::TokenTree(it, _) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_value(self) -> Option<&'a SmolStr> {
|
pub fn string_value(self) -> Option<&'attr SmolStr> {
|
||||||
self.attrs().find_map(|attr| match attr.input.as_deref()? {
|
self.attrs().find_map(|attr| match attr.input.as_deref()? {
|
||||||
AttrInput::Literal(it) => Some(it),
|
AttrInput::Literal(it) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -778,7 +782,7 @@ impl<'a> AttrQuery<'a> {
|
|||||||
self.attrs().next().is_some()
|
self.attrs().next().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attrs(self) -> impl Iterator<Item = &'a Attr> + Clone {
|
pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
|
||||||
let key = self.key;
|
let key = self.key;
|
||||||
self.attrs
|
self.attrs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -3,14 +3,13 @@
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use base_db::SourceDatabaseExt;
|
use base_db::SourceDatabaseExt;
|
||||||
use hir::{known, Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
|
use hir::{HasAttrs, Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
active_parameter::ActiveParameter,
|
active_parameter::ActiveParameter,
|
||||||
base_db::{FilePosition, SourceDatabase},
|
base_db::{FilePosition, SourceDatabase},
|
||||||
helpers::FamousDefs,
|
helpers::FamousDefs,
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
use rustc_hash::FxHashSet;
|
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::find_node_at_offset,
|
algo::find_node_at_offset,
|
||||||
ast::{self, HasName, NameOrNameRef},
|
ast::{self, HasName, NameOrNameRef},
|
||||||
@ -124,8 +123,6 @@ pub(crate) struct CompletionContext<'a> {
|
|||||||
pub(super) path_context: Option<PathCompletionContext>,
|
pub(super) path_context: Option<PathCompletionContext>,
|
||||||
|
|
||||||
pub(super) locals: Vec<(Name, Local)>,
|
pub(super) locals: Vec<(Name, Local)>,
|
||||||
/// Operator traits defined in the project
|
|
||||||
pub(super) ops_traits: FxHashSet<hir::Trait>,
|
|
||||||
|
|
||||||
no_completion_required: bool,
|
no_completion_required: bool,
|
||||||
}
|
}
|
||||||
@ -315,7 +312,10 @@ impl<'a> CompletionContext<'a> {
|
|||||||
|
|
||||||
/// Whether the given trait is an operator trait or not.
|
/// Whether the given trait is an operator trait or not.
|
||||||
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
|
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
|
||||||
self.ops_traits.contains(&trait_)
|
match trait_.attrs(self.db).lang() {
|
||||||
|
Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
|
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
|
||||||
@ -398,16 +398,6 @@ impl<'a> CompletionContext<'a> {
|
|||||||
locals.push((name, local));
|
locals.push((name, local));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let mut ops_traits =
|
|
||||||
FxHashSet::with_capacity_and_hasher(OP_TRAIT_LANG_NAMES.len(), Default::default());
|
|
||||||
if let Some(krate) = krate {
|
|
||||||
let _p = profile::span("CompletionContext::new ops");
|
|
||||||
for trait_ in
|
|
||||||
OP_TRAIT_LANG_NAMES.iter().filter_map(|item| hir::Trait::lang(db, krate, item))
|
|
||||||
{
|
|
||||||
ops_traits.insert(trait_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ctx = CompletionContext {
|
let mut ctx = CompletionContext {
|
||||||
sema,
|
sema,
|
||||||
@ -434,7 +424,6 @@ impl<'a> CompletionContext<'a> {
|
|||||||
locals,
|
locals,
|
||||||
incomplete_let: false,
|
incomplete_let: false,
|
||||||
no_completion_required: false,
|
no_completion_required: false,
|
||||||
ops_traits,
|
|
||||||
};
|
};
|
||||||
ctx.expand_and_fill(
|
ctx.expand_and_fill(
|
||||||
original_file.syntax().clone(),
|
original_file.syntax().clone(),
|
||||||
@ -938,36 +927,36 @@ fn has_ref(token: &SyntaxToken) -> bool {
|
|||||||
token.kind() == T![&]
|
token.kind() == T![&]
|
||||||
}
|
}
|
||||||
|
|
||||||
const OP_TRAIT_LANG_NAMES: &[hir::Name] = &[
|
const OP_TRAIT_LANG_NAMES: &[&str] = &[
|
||||||
known::add_assign,
|
"add_assign",
|
||||||
known::add,
|
"add",
|
||||||
known::bitand_assign,
|
"bitand_assign",
|
||||||
known::bitand,
|
"bitand",
|
||||||
known::bitor_assign,
|
"bitor_assign",
|
||||||
known::bitor,
|
"bitor",
|
||||||
known::bitxor_assign,
|
"bitxor_assign",
|
||||||
known::bitxor,
|
"bitxor",
|
||||||
known::deref_mut,
|
"deref_mut",
|
||||||
known::deref,
|
"deref",
|
||||||
known::div_assign,
|
"div_assign",
|
||||||
known::div,
|
"div",
|
||||||
known::fn_mut,
|
"fn_mut",
|
||||||
known::fn_once,
|
"fn_once",
|
||||||
known::r#fn,
|
"fn",
|
||||||
known::index_mut,
|
"index_mut",
|
||||||
known::index,
|
"index",
|
||||||
known::mul_assign,
|
"mul_assign",
|
||||||
known::mul,
|
"mul",
|
||||||
known::neg,
|
"neg",
|
||||||
known::not,
|
"not",
|
||||||
known::rem_assign,
|
"rem_assign",
|
||||||
known::rem,
|
"rem",
|
||||||
known::shl_assign,
|
"shl_assign",
|
||||||
known::shl,
|
"shl",
|
||||||
known::shr_assign,
|
"shr_assign",
|
||||||
known::shr,
|
"shr",
|
||||||
known::sub,
|
"sub",
|
||||||
known::sub,
|
"sub",
|
||||||
];
|
];
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -177,6 +177,7 @@ pub enum CompletionRelevanceTypeMatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CompletionRelevance {
|
impl CompletionRelevance {
|
||||||
|
const BASE_LINE: u32 = 1;
|
||||||
/// Provides a relevance score. Higher values are more relevant.
|
/// Provides a relevance score. Higher values are more relevant.
|
||||||
///
|
///
|
||||||
/// The absolute value of the relevance score is not meaningful, for
|
/// The absolute value of the relevance score is not meaningful, for
|
||||||
@ -187,7 +188,7 @@ impl CompletionRelevance {
|
|||||||
/// See is_relevant if you need to make some judgement about score
|
/// See is_relevant if you need to make some judgement about score
|
||||||
/// in an absolute sense.
|
/// in an absolute sense.
|
||||||
pub fn score(&self) -> u32 {
|
pub fn score(&self) -> u32 {
|
||||||
let mut score = 0;
|
let mut score = Self::BASE_LINE;
|
||||||
|
|
||||||
if self.exact_name_match {
|
if self.exact_name_match {
|
||||||
score += 1;
|
score += 1;
|
||||||
@ -213,7 +214,7 @@ impl CompletionRelevance {
|
|||||||
/// some threshold such that we think it is especially likely
|
/// some threshold such that we think it is especially likely
|
||||||
/// to be relevant.
|
/// to be relevant.
|
||||||
pub fn is_relevant(&self) -> bool {
|
pub fn is_relevant(&self) -> bool {
|
||||||
self.score() > 0
|
self.score() > (Self::BASE_LINE + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,6 +564,7 @@ mod tests {
|
|||||||
// This test asserts that the relevance score for these items is ascending, and
|
// This test asserts that the relevance score for these items is ascending, and
|
||||||
// that any items in the same vec have the same score.
|
// that any items in the same vec have the same score.
|
||||||
let expected_relevance_order = vec![
|
let expected_relevance_order = vec![
|
||||||
|
vec![CompletionRelevance { is_op_method: true, ..CompletionRelevance::default() }],
|
||||||
vec![CompletionRelevance::default()],
|
vec![CompletionRelevance::default()],
|
||||||
vec![
|
vec![
|
||||||
CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },
|
CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },
|
||||||
|
@ -400,6 +400,7 @@ mod tests {
|
|||||||
(relevance.exact_name_match, "name"),
|
(relevance.exact_name_match, "name"),
|
||||||
(relevance.is_local, "local"),
|
(relevance.is_local, "local"),
|
||||||
(relevance.exact_postfix_snippet_match, "snippet"),
|
(relevance.exact_postfix_snippet_match, "snippet"),
|
||||||
|
(relevance.is_op_method, "op_method"),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
|
.filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
|
||||||
@ -1352,6 +1353,23 @@ fn main() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_method_relevances() {
|
||||||
|
check_relevance(
|
||||||
|
r#"
|
||||||
|
#[lang = "sub"]
|
||||||
|
trait Sub {
|
||||||
|
fn sub(self, other: Self) -> Self { self }
|
||||||
|
}
|
||||||
|
impl Sub for u32 {}
|
||||||
|
fn foo(a: u32) { a.$0 }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
me sub(…) (as Sub) [op_method]
|
||||||
|
"#]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn struct_field_method_ref() {
|
fn struct_field_method_ref() {
|
||||||
check_kinds(
|
check_kinds(
|
||||||
|
Loading…
Reference in New Issue
Block a user