Skip to content

Commit a49ad47

Browse files
committed
Support cfg attribute on impl blocks
1 parent d2ea776 commit a49ad47

File tree

5 files changed

+90
-13
lines changed

5 files changed

+90
-13
lines changed

crates/ra_hir/src/attr.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
use std::sync::Arc;
2+
13
use mbe::ast_to_token_tree;
4+
use ra_cfg::CfgOptions;
25
use ra_syntax::{
3-
ast::{self, AstNode},
6+
ast::{self, AstNode, AttrsOwner},
47
SmolStr,
58
};
69
use tt::Subtree;
710

8-
use crate::{db::AstDatabase, path::Path, Source};
11+
use crate::{db::AstDatabase, path::Path, HirFileId, Source};
912

1013
#[derive(Debug, Clone, PartialEq, Eq)]
1114
pub(crate) struct Attr {
@@ -40,6 +43,14 @@ impl Attr {
4043
Some(Attr { path, input })
4144
}
4245

46+
pub(crate) fn from_attrs_owner(
47+
file_id: HirFileId,
48+
owner: &impl AttrsOwner,
49+
db: &impl AstDatabase,
50+
) -> Arc<[Attr]> {
51+
owner.attrs().flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect()
52+
}
53+
4354
pub(crate) fn is_simple_atom(&self, name: &str) -> bool {
4455
// FIXME: Avoid cloning
4556
self.path.as_ident().map_or(false, |s| s.to_string() == name)
@@ -55,4 +66,8 @@ impl Attr {
5566
None
5667
}
5768
}
69+
70+
pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> {
71+
cfg_options.is_cfg_enabled(self.as_cfg()?)
72+
}
5873
}

crates/ra_hir/src/impl_block.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ use rustc_hash::FxHashMap;
44
use std::sync::Arc;
55

66
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7+
use ra_cfg::CfgOptions;
78
use ra_syntax::{
89
ast::{self, AstNode},
910
AstPtr,
1011
};
1112

1213
use crate::{
14+
attr::Attr,
1315
code_model::{Module, ModuleSource},
1416
db::{AstDatabase, DefDatabase, HirDatabase},
1517
generics::HasGenericParams,
@@ -176,6 +178,7 @@ pub struct ModuleImplBlocks {
176178
impl ModuleImplBlocks {
177179
fn collect(
178180
db: &(impl DefDatabase + AstDatabase),
181+
cfg_options: &CfgOptions,
179182
module: Module,
180183
source_map: &mut ImplSourceMap,
181184
) -> Self {
@@ -188,11 +191,11 @@ impl ModuleImplBlocks {
188191
let src = m.module.definition_source(db);
189192
match &src.ast {
190193
ModuleSource::SourceFile(node) => {
191-
m.collect_from_item_owner(db, source_map, node, src.file_id)
194+
m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id)
192195
}
193196
ModuleSource::Module(node) => {
194197
let item_list = node.item_list().expect("inline module should have item list");
195-
m.collect_from_item_owner(db, source_map, &item_list, src.file_id)
198+
m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id)
196199
}
197200
};
198201
m
@@ -201,13 +204,19 @@ impl ModuleImplBlocks {
201204
fn collect_from_item_owner(
202205
&mut self,
203206
db: &(impl DefDatabase + AstDatabase),
207+
cfg_options: &CfgOptions,
204208
source_map: &mut ImplSourceMap,
205209
owner: &dyn ast::ModuleItemOwner,
206210
file_id: HirFileId,
207211
) {
208212
for item in owner.items_with_macros() {
209213
match item {
210214
ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
215+
let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db);
216+
if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) {
217+
continue;
218+
}
219+
211220
let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast);
212221
let id = self.impls.alloc(impl_block);
213222
for &impl_item in &self.impls[id].items {
@@ -218,6 +227,11 @@ impl ModuleImplBlocks {
218227
}
219228
ast::ItemOrMacro::Item(_) => (),
220229
ast::ItemOrMacro::Macro(macro_call) => {
230+
let attrs = Attr::from_attrs_owner(file_id, &macro_call, db);
231+
if attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) {
232+
continue;
233+
}
234+
221235
//FIXME: we should really cut down on the boilerplate required to process a macro
222236
let ast_id = db.ast_id_map(file_id).ast_id(&macro_call).with_file_id(file_id);
223237
if let Some(path) = macro_call
@@ -231,7 +245,13 @@ impl ModuleImplBlocks {
231245
if let Some(item_list) =
232246
db.parse_or_expand(file_id).and_then(ast::MacroItems::cast)
233247
{
234-
self.collect_from_item_owner(db, source_map, &item_list, file_id)
248+
self.collect_from_item_owner(
249+
db,
250+
cfg_options,
251+
source_map,
252+
&item_list,
253+
file_id,
254+
)
235255
}
236256
}
237257
}
@@ -246,8 +266,10 @@ pub(crate) fn impls_in_module_with_source_map_query(
246266
module: Module,
247267
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
248268
let mut source_map = ImplSourceMap::default();
269+
let crate_graph = db.crate_graph();
270+
let cfg_options = crate_graph.cfg_options(module.krate.crate_id());
249271

250-
let result = ModuleImplBlocks::collect(db, module, &mut source_map);
272+
let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map);
251273
(Arc::new(result), Arc::new(source_map))
252274
}
253275

crates/ra_hir/src/nameres/collector.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -716,10 +716,7 @@ where
716716
}
717717

718718
fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool {
719-
attrs
720-
.iter()
721-
.flat_map(|attr| attr.as_cfg())
722-
.all(|cfg| self.def_collector.cfg_options.is_cfg_enabled(cfg).unwrap_or(true))
719+
attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
723720
}
724721
}
725722

crates/ra_hir/src/nameres/raw.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
411411
}
412412

413413
fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Arc<[Attr]> {
414-
item.attrs()
415-
.flat_map(|ast| Attr::from_src(Source { ast, file_id: self.file_id }, self.db))
416-
.collect()
414+
Attr::from_attrs_owner(self.file_id, item, self.db)
417415
}
418416
}
419417

crates/ra_hir/src/ty/tests.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::Arc;
33

44
use insta::assert_snapshot;
55

6+
use ra_cfg::CfgOptions;
67
use ra_db::{salsa::Database, FilePosition, SourceDatabase};
78
use ra_syntax::{
89
algo,
@@ -23,6 +24,50 @@ use crate::{
2324
mod never_type;
2425
mod coercion;
2526

27+
#[test]
28+
fn cfg_impl_block() {
29+
let (mut db, pos) = MockDatabase::with_position(
30+
r#"
31+
//- /main.rs
32+
use foo::S as T;
33+
struct S;
34+
35+
#[cfg(test)]
36+
impl S {
37+
fn foo1(&self) -> i32 { 0 }
38+
}
39+
40+
#[cfg(not(test))]
41+
impl S {
42+
fn foo2(&self) -> i32 { 0 }
43+
}
44+
45+
fn test() {
46+
let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
47+
t<|>;
48+
}
49+
50+
//- /foo.rs
51+
struct S;
52+
53+
#[cfg(not(test))]
54+
impl S {
55+
fn foo3(&self) -> i32 { 0 }
56+
}
57+
58+
#[cfg(test)]
59+
impl S {
60+
fn foo4(&self) -> i32 { 0 }
61+
}
62+
"#,
63+
);
64+
db.set_crate_graph_from_fixture(crate_graph! {
65+
"main": ("/main.rs", ["foo"], CfgOptions::default().atom("test".into())),
66+
"foo": ("/foo.rs", []),
67+
});
68+
assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
69+
}
70+
2671
#[test]
2772
fn infer_await() {
2873
let (mut db, pos) = MockDatabase::with_position(

0 commit comments

Comments
 (0)