Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/lib.rs')
| -rw-r--r-- | crates/hir-def/src/lib.rs | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 4601960c7e..ab897f4e36 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -53,7 +53,7 @@ pub mod find_path; pub mod import_map; pub mod visibility; -use intern::Interned; +use intern::{Interned, sym}; pub use rustc_abi as layout; use triomphe::Arc; @@ -86,6 +86,7 @@ use syntax::{AstNode, ast}; pub use hir_expand::{Intern, Lookup, tt}; use crate::{ + attr::Attrs, builtin_type::BuiltinType, data::adt::VariantData, db::DefDatabase, @@ -1502,3 +1503,81 @@ pub struct UnresolvedMacro { #[derive(Default, Debug, Eq, PartialEq, Clone, Copy)] pub struct SyntheticSyntax; + +// Feature: Completions Attribute +// Crate authors can opt their type out of completions in some cases. +// This is done with the `#[rust_analyzer::completions(...)]` attribute. +// +// All completeable things support `#[rust_analyzer::completions(ignore_flyimport)]`, +// which causes the thing to get excluded from flyimport completion. It will still +// be completed when in scope. This is analogous to the setting `rust-analyzer.completion.autoimport.exclude` +// with `"type": "always"`. +// +// In addition, traits support two more modes: `#[rust_analyzer::completions(ignore_flyimport_methods)]`, +// which means the trait itself may still be flyimported but its methods won't, and +// `#[rust_analyzer::completions(ignore_methods)]`, which means the methods won't be completed even when +// the trait is in scope (but the trait itself may still be completed). The methods will still be completed +// on `dyn Trait`, `impl Trait` or where the trait is specified in bounds. These modes correspond to +// the settings `rust-analyzer.completion.autoimport.exclude` with `"type": "methods"` and +// `rust-analyzer.completion.excludeTraits`, respectively. +// +// Malformed attributes will be ignored without warnings. +// +// Note that users have no way to override this attribute, so be careful and only include things +// users definitely do not want to be completed! + +/// `#[rust_analyzer::completions(...)]` options. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Complete { + /// No `#[rust_analyzer::completions(...)]`. + Yes, + /// `#[rust_analyzer::completions(ignore_flyimport)]`. + IgnoreFlyimport, + /// `#[rust_analyzer::completions(ignore_flyimport_methods)]` (on a trait only). + IgnoreFlyimportMethods, + /// `#[rust_analyzer::completions(ignore_methods)]` (on a trait only). + IgnoreMethods, +} + +impl Complete { + pub fn extract(is_trait: bool, attrs: &Attrs) -> Complete { + let mut do_not_complete = Complete::Yes; + for ra_attr in attrs.rust_analyzer_tool() { + let segments = ra_attr.path.segments(); + if segments.len() != 2 { + continue; + } + let action = segments[1].symbol(); + if *action == sym::completions { + match ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens()) { + Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) => { + if ident.sym == sym::ignore_flyimport { + do_not_complete = Complete::IgnoreFlyimport; + } else if is_trait { + if ident.sym == sym::ignore_methods { + do_not_complete = Complete::IgnoreMethods; + } else if ident.sym == sym::ignore_flyimport_methods { + do_not_complete = Complete::IgnoreFlyimportMethods; + } + } + } + _ => {} + } + } + } + do_not_complete + } + + #[inline] + pub fn for_trait_item(trait_attr: Complete, item_attr: Complete) -> Complete { + match (trait_attr, item_attr) { + ( + Complete::IgnoreFlyimportMethods + | Complete::IgnoreFlyimport + | Complete::IgnoreMethods, + _, + ) => Complete::IgnoreFlyimport, + _ => item_attr, + } + } +} |