Skip to content

Commit 130318b

Browse files
authored
Merge pull request #4548 from bnjjj/fix_4464
add support of feature flag for runnables
2 parents f26b792 + 27ed376 commit 130318b

File tree

9 files changed

+234
-19
lines changed

9 files changed

+234
-19
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_cfg/src/cfg_expr.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,17 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
8888
mod tests {
8989
use super::*;
9090

91-
use mbe::ast_to_token_tree;
91+
use mbe::{ast_to_token_tree, TokenMap};
9292
use ra_syntax::ast::{self, AstNode};
9393

94-
fn assert_parse_result(input: &str, expected: CfgExpr) {
94+
fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) {
9595
let source_file = ast::SourceFile::parse(input).ok().unwrap();
9696
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
97-
let (tt, _) = ast_to_token_tree(&tt).unwrap();
97+
ast_to_token_tree(&tt).unwrap()
98+
}
99+
100+
fn assert_parse_result(input: &str, expected: CfgExpr) {
101+
let (tt, _) = get_token_tree_generated(input);
98102
assert_eq!(parse_cfg(&tt), expected);
99103
}
100104

crates/ra_hir/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub use crate::{
6262

6363
pub use hir_def::{
6464
adt::StructKind,
65+
attr::Attrs,
6566
body::scope::ExprScopes,
6667
builtin_type::BuiltinType,
6768
docs::Documentation,

crates/ra_hir_def/src/attr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl Attrs {
8181
}
8282
}
8383

84-
fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
84+
pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
8585
let hygiene = Hygiene::new(db.upcast(), owner.file_id);
8686
Attrs::new(owner.value, &hygiene)
8787
}

crates/ra_hir_def/src/body.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::{
2929
AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
3030
};
3131

32-
/// A subset of Exander that only deals with cfg attributes. We only need it to
32+
/// A subset of Expander that only deals with cfg attributes. We only need it to
3333
/// avoid cyclic queries in crate def map during enum processing.
3434
pub(crate) struct CfgExpander {
3535
cfg_options: CfgOptions,

crates/ra_ide/src/runnables.rs

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! FIXME: write short doc here
22
3-
use hir::{AsAssocItem, Semantics};
3+
use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
44
use itertools::Itertools;
55
use ra_ide_db::RootDatabase;
66
use ra_syntax::{
@@ -10,12 +10,14 @@ use ra_syntax::{
1010

1111
use crate::FileId;
1212
use ast::DocCommentsOwner;
13+
use ra_cfg::CfgExpr;
1314
use std::fmt::Display;
1415

1516
#[derive(Debug)]
1617
pub struct Runnable {
1718
pub range: TextRange,
1819
pub kind: RunnableKind,
20+
pub cfg_exprs: Vec<CfgExpr>,
1921
}
2022

2123
#[derive(Debug)]
@@ -45,20 +47,24 @@ pub enum RunnableKind {
4547
pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
4648
let sema = Semantics::new(db);
4749
let source_file = sema.parse(file_id);
48-
source_file.syntax().descendants().filter_map(|i| runnable(&sema, i)).collect()
50+
source_file.syntax().descendants().filter_map(|i| runnable(&sema, i, file_id)).collect()
4951
}
5052

51-
fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
53+
fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode, file_id: FileId) -> Option<Runnable> {
5254
match_ast! {
5355
match item {
54-
ast::FnDef(it) => runnable_fn(sema, it),
55-
ast::Module(it) => runnable_mod(sema, it),
56+
ast::FnDef(it) => runnable_fn(sema, it, file_id),
57+
ast::Module(it) => runnable_mod(sema, it, file_id),
5658
_ => None,
5759
}
5860
}
5961
}
6062

61-
fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Runnable> {
63+
fn runnable_fn(
64+
sema: &Semantics<RootDatabase>,
65+
fn_def: ast::FnDef,
66+
file_id: FileId,
67+
) -> Option<Runnable> {
6268
let name_string = fn_def.name()?.text().to_string();
6369

6470
let kind = if name_string == "main" {
@@ -111,7 +117,12 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run
111117
return None;
112118
}
113119
};
114-
Some(Runnable { range: fn_def.syntax().text_range(), kind })
120+
121+
let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def));
122+
let cfg_exprs =
123+
attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
124+
125+
Some(Runnable { range: fn_def.syntax().text_range(), kind, cfg_exprs })
115126
}
116127

117128
#[derive(Debug)]
@@ -147,7 +158,11 @@ fn has_doc_test(fn_def: &ast::FnDef) -> bool {
147158
fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
148159
}
149160

150-
fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
161+
fn runnable_mod(
162+
sema: &Semantics<RootDatabase>,
163+
module: ast::Module,
164+
file_id: FileId,
165+
) -> Option<Runnable> {
151166
let has_test_function = module
152167
.item_list()?
153168
.items()
@@ -160,11 +175,20 @@ fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<R
160175
return None;
161176
}
162177
let range = module.syntax().text_range();
163-
let module = sema.to_def(&module)?;
178+
let module_def = sema.to_def(&module)?;
179+
180+
let path = module_def
181+
.path_to_root(sema.db)
182+
.into_iter()
183+
.rev()
184+
.filter_map(|it| it.name(sema.db))
185+
.join("::");
186+
187+
let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module));
188+
let cfg_exprs =
189+
attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect();
164190

165-
let path =
166-
module.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
167-
Some(Runnable { range, kind: RunnableKind::TestMod { path } })
191+
Some(Runnable { range, kind: RunnableKind::TestMod { path }, cfg_exprs })
168192
}
169193

170194
#[cfg(test)]
@@ -196,6 +220,7 @@ mod tests {
196220
Runnable {
197221
range: 1..21,
198222
kind: Bin,
223+
cfg_exprs: [],
199224
},
200225
Runnable {
201226
range: 22..46,
@@ -207,6 +232,7 @@ mod tests {
207232
ignore: false,
208233
},
209234
},
235+
cfg_exprs: [],
210236
},
211237
Runnable {
212238
range: 47..81,
@@ -218,6 +244,7 @@ mod tests {
218244
ignore: true,
219245
},
220246
},
247+
cfg_exprs: [],
221248
},
222249
]
223250
"###
@@ -245,6 +272,7 @@ mod tests {
245272
Runnable {
246273
range: 1..21,
247274
kind: Bin,
275+
cfg_exprs: [],
248276
},
249277
Runnable {
250278
range: 22..64,
@@ -253,6 +281,7 @@ mod tests {
253281
"foo",
254282
),
255283
},
284+
cfg_exprs: [],
256285
},
257286
]
258287
"###
@@ -283,6 +312,7 @@ mod tests {
283312
Runnable {
284313
range: 1..21,
285314
kind: Bin,
315+
cfg_exprs: [],
286316
},
287317
Runnable {
288318
range: 51..105,
@@ -291,6 +321,7 @@ mod tests {
291321
"Data::foo",
292322
),
293323
},
324+
cfg_exprs: [],
294325
},
295326
]
296327
"###
@@ -318,6 +349,7 @@ mod tests {
318349
kind: TestMod {
319350
path: "test_mod",
320351
},
352+
cfg_exprs: [],
321353
},
322354
Runnable {
323355
range: 28..57,
@@ -329,6 +361,7 @@ mod tests {
329361
ignore: false,
330362
},
331363
},
364+
cfg_exprs: [],
332365
},
333366
]
334367
"###
@@ -358,6 +391,7 @@ mod tests {
358391
kind: TestMod {
359392
path: "foo::test_mod",
360393
},
394+
cfg_exprs: [],
361395
},
362396
Runnable {
363397
range: 46..79,
@@ -369,6 +403,7 @@ mod tests {
369403
ignore: false,
370404
},
371405
},
406+
cfg_exprs: [],
372407
},
373408
]
374409
"###
@@ -400,6 +435,7 @@ mod tests {
400435
kind: TestMod {
401436
path: "foo::bar::test_mod",
402437
},
438+
cfg_exprs: [],
403439
},
404440
Runnable {
405441
range: 68..105,
@@ -411,6 +447,89 @@ mod tests {
411447
ignore: false,
412448
},
413449
},
450+
cfg_exprs: [],
451+
},
452+
]
453+
"###
454+
);
455+
}
456+
457+
#[test]
458+
fn test_runnables_with_feature() {
459+
let (analysis, pos) = analysis_and_position(
460+
r#"
461+
//- /lib.rs crate:foo cfg:feature=foo
462+
<|> //empty
463+
#[test]
464+
#[cfg(feature = "foo")]
465+
fn test_foo1() {}
466+
"#,
467+
);
468+
let runnables = analysis.runnables(pos.file_id).unwrap();
469+
assert_debug_snapshot!(&runnables,
470+
@r###"
471+
[
472+
Runnable {
473+
range: 1..58,
474+
kind: Test {
475+
test_id: Name(
476+
"test_foo1",
477+
),
478+
attr: TestAttr {
479+
ignore: false,
480+
},
481+
},
482+
cfg_exprs: [
483+
KeyValue {
484+
key: "feature",
485+
value: "foo",
486+
},
487+
],
488+
},
489+
]
490+
"###
491+
);
492+
}
493+
494+
#[test]
495+
fn test_runnables_with_features() {
496+
let (analysis, pos) = analysis_and_position(
497+
r#"
498+
//- /lib.rs crate:foo cfg:feature=foo,feature=bar
499+
<|> //empty
500+
#[test]
501+
#[cfg(all(feature = "foo", feature = "bar"))]
502+
fn test_foo1() {}
503+
"#,
504+
);
505+
let runnables = analysis.runnables(pos.file_id).unwrap();
506+
assert_debug_snapshot!(&runnables,
507+
@r###"
508+
[
509+
Runnable {
510+
range: 1..80,
511+
kind: Test {
512+
test_id: Name(
513+
"test_foo1",
514+
),
515+
attr: TestAttr {
516+
ignore: false,
517+
},
518+
},
519+
cfg_exprs: [
520+
All(
521+
[
522+
KeyValue {
523+
key: "feature",
524+
value: "foo",
525+
},
526+
KeyValue {
527+
key: "feature",
528+
value: "bar",
529+
},
530+
],
531+
),
532+
],
414533
},
415534
]
416535
"###

crates/rust-analyzer/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ra_project_model = { path = "../ra_project_model" }
4040
ra_syntax = { path = "../ra_syntax" }
4141
ra_text_edit = { path = "../ra_text_edit" }
4242
ra_vfs = "0.6.0"
43+
ra_cfg = { path = "../ra_cfg"}
4344

4445
# This should only be used in CLI
4546
ra_db = { path = "../ra_db" }
@@ -55,6 +56,8 @@ winapi = "0.3.8"
5556
tempfile = "3.1.0"
5657
insta = "0.16.0"
5758
test_utils = { path = "../test_utils" }
59+
mbe = { path = "../ra_mbe", package = "ra_mbe" }
60+
tt = { path = "../ra_tt", package = "ra_tt" }
5861

5962
[features]
6063
jemalloc = [ "ra_prof/jemalloc" ]

0 commit comments

Comments
 (0)