Skip to content

Commit 31a9f20

Browse files
Allow crate authors to control completion of their things
Via the new `#[rust_analyzer::do_not_complete(...)]` attribute. Also fix a bug with existing settings for that where the paths wouldn't resolve correctly.
1 parent 78aee2a commit 31a9f20

File tree

22 files changed

+923
-221
lines changed

22 files changed

+923
-221
lines changed

crates/hir-def/src/data.rs

Lines changed: 327 additions & 44 deletions
Large diffs are not rendered by default.

crates/hir-def/src/data/adt.rs

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ bitflags! {
4949
const IS_MANUALLY_DROP = 1 << 6;
5050
/// Indicates whether this struct is `UnsafeCell`.
5151
const IS_UNSAFE_CELL = 1 << 7;
52+
/// `#[rust_analyzer::do_not_complete(flyimport)]`
53+
const DO_NOT_COMPLETE_FLYIMPORT = 1 << 7;
5254
}
5355
}
5456

@@ -58,6 +60,8 @@ pub struct EnumData {
5860
pub repr: Option<ReprOptions>,
5961
pub visibility: RawVisibility,
6062
pub rustc_has_incoherent_inherent_impls: bool,
63+
/// `#[rust_analyzer::do_not_complete(flyimport)]`.
64+
pub do_not_complete_flyimport: bool,
6165
}
6266

6367
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -208,6 +212,23 @@ impl StructData {
208212
}
209213
}
210214

215+
for ra_attr in attrs.rust_analyzer_tool() {
216+
let segments = ra_attr.path.segments();
217+
if segments.len() != 2 {
218+
continue;
219+
}
220+
let action = segments[1].symbol();
221+
if *action == sym::do_not_complete {
222+
if let Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) =
223+
ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens())
224+
{
225+
if ident.sym == sym::flyimport {
226+
flags |= StructFlags::DO_NOT_COMPLETE_FLYIMPORT;
227+
}
228+
}
229+
}
230+
}
231+
211232
let strukt = &item_tree[loc.id.value];
212233
Arc::new(StructData {
213234
name: strukt.name.clone(),
@@ -225,13 +246,31 @@ impl StructData {
225246
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
226247
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
227248
let mut flags = StructFlags::NO_FLAGS;
249+
228250
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
229251
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
230252
}
231253
if attrs.by_key(&sym::fundamental).exists() {
232254
flags |= StructFlags::IS_FUNDAMENTAL;
233255
}
234256

257+
for ra_attr in attrs.rust_analyzer_tool() {
258+
let segments = ra_attr.path.segments();
259+
if segments.len() != 2 {
260+
continue;
261+
}
262+
let action = segments[1].symbol();
263+
if *action == sym::do_not_complete {
264+
if let Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) =
265+
ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens())
266+
{
267+
if ident.sym == sym::flyimport {
268+
flags |= StructFlags::DO_NOT_COMPLETE_FLYIMPORT;
269+
}
270+
}
271+
}
272+
}
273+
235274
let union = &item_tree[loc.id.value];
236275

237276
Arc::new(StructData {
@@ -289,10 +328,28 @@ impl EnumData {
289328
let krate = loc.container.krate;
290329
let item_tree = loc.id.item_tree(db);
291330
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
292-
let rustc_has_incoherent_inherent_impls = item_tree
293-
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
294-
.by_key(&sym::rustc_has_incoherent_inherent_impls)
295-
.exists();
331+
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
332+
333+
let rustc_has_incoherent_inherent_impls =
334+
attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
335+
336+
let mut do_not_complete_flyimport = false;
337+
for ra_attr in attrs.rust_analyzer_tool() {
338+
let segments = ra_attr.path.segments();
339+
if segments.len() != 2 {
340+
continue;
341+
}
342+
let action = segments[1].symbol();
343+
if *action == sym::do_not_complete {
344+
if let Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) =
345+
ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens())
346+
{
347+
if ident.sym == sym::flyimport {
348+
do_not_complete_flyimport = true;
349+
}
350+
}
351+
}
352+
}
296353

297354
let enum_ = &item_tree[loc.id.value];
298355

@@ -301,6 +358,7 @@ impl EnumData {
301358
repr,
302359
visibility: item_tree[enum_.visibility].clone(),
303360
rustc_has_incoherent_inherent_impls,
361+
do_not_complete_flyimport,
304362
})
305363
}
306364

crates/hir-def/src/item_scope.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,20 @@ impl ItemScope {
460460
pub fn iter_macro_invoc(&self) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> {
461461
self.macro_invocations.iter()
462462
}
463+
464+
pub fn get_including_legacy_macros(&self, name: &Name) -> PerNs {
465+
PerNs {
466+
types: self.types.get(name).copied(),
467+
values: self.values.get(name).copied(),
468+
macros: self.macros.get(name).copied().or_else(|| {
469+
self.legacy_macros.get(name).and_then(|macros| macros.first()).map(|&m| Item {
470+
def: m,
471+
vis: Visibility::Public,
472+
import: None,
473+
})
474+
}),
475+
}
476+
}
463477
}
464478

465479
impl ItemScope {

crates/hir-def/src/item_tree.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ pub struct Param {
937937

938938
bitflags::bitflags! {
939939
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
940-
pub(crate) struct FnFlags: u16 {
940+
pub struct FnFlags: u16 {
941941
const HAS_SELF_PARAM = 1 << 0;
942942
const HAS_BODY = 1 << 1;
943943
const HAS_DEFAULT_KW = 1 << 2;
@@ -952,6 +952,9 @@ bitflags::bitflags! {
952952
/// it if needed.
953953
const HAS_TARGET_FEATURE = 1 << 8;
954954
const DEPRECATED_SAFE_2024 = 1 << 9;
955+
const RUSTC_ALLOW_INCOHERENT_IMPL = 1 << 10;
956+
/// `#[rust_analyzer::do_not_complete(flyimport)]`.
957+
const DO_NOT_COMPLETE_FLYIMPORT = 1 << 11;
955958
}
956959
}
957960

@@ -1024,15 +1027,24 @@ pub struct Const {
10241027
pub struct Static {
10251028
pub name: Name,
10261029
pub visibility: RawVisibilityId,
1027-
// TODO: use bitflags when we have more flags
1028-
pub mutable: bool,
1029-
pub has_safe_kw: bool,
1030-
pub has_unsafe_kw: bool,
1030+
pub flags: StaticFlags,
10311031
pub type_ref: TypeRefId,
10321032
pub ast_id: FileAstId<ast::Static>,
10331033
pub types_map: Arc<TypesMap>,
10341034
}
10351035

1036+
bitflags::bitflags! {
1037+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1038+
pub struct StaticFlags: u8 {
1039+
const MUTABLE = 1 << 0;
1040+
const IS_EXTERN = 1 << 1;
1041+
const HAS_SAFE_KW = 1 << 2;
1042+
const HAS_UNSAFE_KW = 1 << 3;
1043+
/// `#[rust_analyzer::do_not_complete(flyimport)]`.
1044+
const DO_NOT_COMPLETE_FLYIMPORT = 1 << 4;
1045+
}
1046+
}
1047+
10361048
#[derive(Debug, Clone, Eq, PartialEq)]
10371049
pub struct Trait {
10381050
pub name: Name,

crates/hir-def/src/item_tree/lower.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ use crate::{
2929
GenericModItem, Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData,
3030
ItemTreeSourceMaps, ItemTreeSourceMapsBuilder, Macro2, MacroCall, MacroRules, Mod, ModItem,
3131
ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
32-
Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
33-
Variant,
32+
Static, StaticFlags, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree,
33+
UseTreeKind, Variant,
3434
},
3535
lower::LowerCtx,
3636
path::AssociatedTypeBinding,
@@ -620,22 +620,23 @@ impl<'a> Ctx<'a> {
620620
let name = static_.name()?.as_name();
621621
let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty());
622622
let visibility = self.lower_visibility(static_);
623-
let mutable = static_.mut_token().is_some();
624-
let has_safe_kw = static_.safe_token().is_some();
625-
let has_unsafe_kw = static_.unsafe_token().is_some();
623+
624+
let mut flags = StaticFlags::empty();
625+
if static_.mut_token().is_some() {
626+
flags |= StaticFlags::MUTABLE;
627+
}
628+
if static_.safe_token().is_some() {
629+
flags |= StaticFlags::HAS_SAFE_KW;
630+
}
631+
if static_.unsafe_token().is_some() {
632+
flags |= StaticFlags::HAS_UNSAFE_KW;
633+
}
634+
626635
let ast_id = self.source_ast_id_map.ast_id(static_);
627636
types_map.shrink_to_fit();
628637
types_source_map.shrink_to_fit();
629-
let res = Static {
630-
name,
631-
visibility,
632-
mutable,
633-
type_ref,
634-
ast_id,
635-
has_safe_kw,
636-
has_unsafe_kw,
637-
types_map: Arc::new(types_map),
638-
};
638+
let res =
639+
Static { name, visibility, type_ref, ast_id, flags, types_map: Arc::new(types_map) };
639640
self.source_maps.statics.push(types_source_map);
640641
Some(id(self.data().statics.alloc(res)))
641642
}

crates/hir-def/src/item_tree/pretty.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use crate::{
1111
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
1212
FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl,
1313
ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path, RawAttrs,
14-
RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, Union, Use,
15-
UseTree, UseTreeKind, Variant,
14+
RawVisibilityId, Static, StaticFlags, Struct, Trait, TraitAlias, TypeAlias, TypeBound,
15+
Union, Use, UseTree, UseTreeKind, Variant,
1616
},
1717
pretty::{print_path, print_type_bounds, print_type_ref},
1818
type_ref::{TypeRefId, TypesMap},
@@ -408,26 +408,18 @@ impl Printer<'_> {
408408
wln!(self, " = _;");
409409
}
410410
ModItem::Static(it) => {
411-
let Static {
412-
name,
413-
visibility,
414-
mutable,
415-
type_ref,
416-
ast_id,
417-
has_safe_kw,
418-
has_unsafe_kw,
419-
types_map,
420-
} = &self.tree[it];
411+
let Static { name, visibility, type_ref, ast_id, types_map, flags } =
412+
&self.tree[it];
421413
self.print_ast_id(ast_id.erase());
422414
self.print_visibility(*visibility);
423-
if *has_safe_kw {
415+
if flags.contains(StaticFlags::HAS_SAFE_KW) {
424416
w!(self, "safe ");
425417
}
426-
if *has_unsafe_kw {
418+
if flags.contains(StaticFlags::HAS_UNSAFE_KW) {
427419
w!(self, "unsafe ");
428420
}
429421
w!(self, "static ");
430-
if *mutable {
422+
if flags.contains(StaticFlags::MUTABLE) {
431423
w!(self, "mut ");
432424
}
433425
w!(self, "{}: ", name.display(self.db.upcast(), self.edition));

crates/hir-def/src/nameres.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ pub struct ModuleData {
355355
pub parent: Option<LocalModuleId>,
356356
pub children: FxIndexMap<Name, LocalModuleId>,
357357
pub scope: ItemScope,
358+
/// Whether the module has `#[rust_analyzer::do_not_complete(flyimport)]`.
359+
pub do_not_complete_flyimport: bool,
358360
}
359361

360362
impl DefMap {
@@ -388,6 +390,7 @@ impl DefMap {
388390
let module_data = ModuleData::new(
389391
ModuleOrigin::CrateRoot { definition: krate.root_file_id() },
390392
Visibility::Public,
393+
false,
391394
);
392395

393396
let def_map = DefMap::empty(
@@ -413,8 +416,11 @@ impl DefMap {
413416
ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
414417
VisibilityExplicitness::Implicit,
415418
);
416-
let module_data =
417-
ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
419+
let module_data = ModuleData::new(
420+
ModuleOrigin::BlockExpr { block: ast_id, id: block_id },
421+
visibility,
422+
false,
423+
);
418424

419425
let (crate_map, crate_local_map) = db.crate_local_def_map(module.krate);
420426
let def_map = DefMap::empty(
@@ -714,13 +720,18 @@ impl DefMap {
714720
}
715721

716722
impl ModuleData {
717-
pub(crate) fn new(origin: ModuleOrigin, visibility: Visibility) -> Self {
723+
pub(crate) fn new(
724+
origin: ModuleOrigin,
725+
visibility: Visibility,
726+
do_not_complete_flyimport: bool,
727+
) -> Self {
718728
ModuleData {
719729
origin,
720730
visibility,
721731
parent: None,
722732
children: Default::default(),
723733
scope: ItemScope::default(),
734+
do_not_complete_flyimport,
724735
}
725736
}
726737

crates/hir-def/src/nameres/collector.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,7 @@ impl ModCollector<'_, '_> {
20602060
None,
20612061
&self.item_tree[module.visibility],
20622062
module_id,
2063+
attrs,
20632064
);
20642065

20652066
let Some(mod_dir) =
@@ -2113,6 +2114,7 @@ impl ModCollector<'_, '_> {
21132114
Some((file_id, is_mod_rs)),
21142115
&self.item_tree[module.visibility],
21152116
module_id,
2117+
attrs,
21162118
);
21172119
ModCollector {
21182120
def_collector: self.def_collector,
@@ -2141,6 +2143,7 @@ impl ModCollector<'_, '_> {
21412143
None,
21422144
&self.item_tree[module.visibility],
21432145
module_id,
2146+
attrs,
21442147
);
21452148
self.def_collector.def_map.diagnostics.push(
21462149
DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
@@ -2158,6 +2161,7 @@ impl ModCollector<'_, '_> {
21582161
definition: Option<(EditionedFileId, bool)>,
21592162
visibility: &crate::visibility::RawVisibility,
21602163
mod_tree_id: FileItemTreeId<Mod>,
2164+
attrs: &Attrs,
21612165
) -> LocalModuleId {
21622166
let def_map = &mut self.def_collector.def_map;
21632167
let vis = def_map
@@ -2185,8 +2189,26 @@ impl ModCollector<'_, '_> {
21852189
},
21862190
};
21872191

2192+
let mut do_not_complete_flyimport = false;
2193+
for ra_attr in attrs.rust_analyzer_tool() {
2194+
let segments = ra_attr.path.segments();
2195+
if segments.len() != 2 {
2196+
continue;
2197+
}
2198+
let action = segments[1].symbol();
2199+
if *action == sym::do_not_complete {
2200+
if let Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) =
2201+
ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens())
2202+
{
2203+
if ident.sym == sym::flyimport {
2204+
do_not_complete_flyimport = true;
2205+
}
2206+
}
2207+
}
2208+
}
2209+
21882210
let modules = &mut def_map.modules;
2189-
let res = modules.alloc(ModuleData::new(origin, vis));
2211+
let res = modules.alloc(ModuleData::new(origin, vis, do_not_complete_flyimport));
21902212
modules[res].parent = Some(self.module_id);
21912213

21922214
if let Some((target, source)) = Self::borrow_modules(modules.as_mut(), res, self.module_id)
@@ -2615,7 +2637,7 @@ mod tests {
26152637
let def_map = DefMap::empty(
26162638
krate,
26172639
Arc::new(DefMapCrateData::new(edition)),
2618-
ModuleData::new(module_origin, Visibility::Public),
2640+
ModuleData::new(module_origin, Visibility::Public, false),
26192641
None,
26202642
);
26212643
do_collect_defs(&db, def_map)

0 commit comments

Comments
 (0)