Skip to content

Commit 4f35021

Browse files
authored
Merge pull request #18907 from Veykril/push-uqlzpttmvurv
Implement `#[rust_analyzer::skip]` for bodies
2 parents e8ad0c0 + f209d50 commit 4f35021

File tree

7 files changed

+86
-2
lines changed

7 files changed

+86
-2
lines changed

crates/hir-def/src/attr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ impl Attrs {
122122
AttrQuery { attrs: self, key }
123123
}
124124

125+
pub fn rust_analyzer_tool(&self) -> impl Iterator<Item = &Attr> {
126+
self.iter()
127+
.filter(|&attr| attr.path.segments().first().is_some_and(|s| *s == sym::rust_analyzer))
128+
}
129+
125130
pub fn cfg(&self) -> Option<CfgExpr> {
126131
let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse);
127132
let first = cfgs.next()?;

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::mem;
88
use base_db::CrateId;
99
use either::Either;
1010
use hir_expand::{
11+
mod_path::tool_path,
1112
name::{AsName, Name},
1213
span_map::{ExpansionSpanMap, SpanMap},
1314
InFile, MacroDefId,
@@ -27,6 +28,7 @@ use text_size::TextSize;
2728
use triomphe::Arc;
2829

2930
use crate::{
31+
attr::Attrs,
3032
body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
3133
builtin_type::BuiltinUint,
3234
data::adt::StructKind,
@@ -212,6 +214,43 @@ impl ExprCollector<'_> {
212214
body: Option<ast::Expr>,
213215
is_async_fn: bool,
214216
) -> (Body, BodySourceMap) {
217+
let skip_body = match self.owner {
218+
DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
219+
DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
220+
DefWithBodyId::ConstId(it) => self.db.attrs(it.into()),
221+
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
222+
DefWithBodyId::VariantId(it) => self.db.attrs(it.into()),
223+
}
224+
.rust_analyzer_tool()
225+
.any(|attr| *attr.path() == tool_path![skip]);
226+
// If #[rust_analyzer::skip] annotated, only construct enough information for the signature
227+
// and skip the body.
228+
if skip_body {
229+
self.body.body_expr = self.missing_expr();
230+
if let Some((param_list, mut attr_enabled)) = param_list {
231+
if let Some(self_param) =
232+
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
233+
{
234+
let is_mutable =
235+
self_param.mut_token().is_some() && self_param.amp_token().is_none();
236+
let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
237+
Name::new_symbol_root(sym::self_.clone()),
238+
BindingAnnotation::new(is_mutable, false),
239+
);
240+
self.body.self_param = Some(binding_id);
241+
self.source_map.self_param =
242+
Some(self.expander.in_file(AstPtr::new(&self_param)));
243+
}
244+
self.body.params = param_list
245+
.params()
246+
.zip(attr_enabled)
247+
.filter(|(_, enabled)| *enabled)
248+
.map(|_| self.missing_pat())
249+
.collect();
250+
};
251+
return (self.body, self.source_map);
252+
}
253+
215254
self.awaitable_context.replace(if is_async_fn {
216255
Awaitable::Yes
217256
} else {

crates/hir-def/src/body/tests.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,18 @@ fn foo() {
444444
}"#
445445
);
446446
}
447+
448+
#[test]
449+
fn skip_skips_body() {
450+
let (db, body, owner) = lower(
451+
r#"
452+
#[rust_analyzer::skip]
453+
async fn foo(a: (), b: i32) -> u32 {
454+
0 + 1 + b()
455+
}
456+
"#,
457+
);
458+
let printed = body.pretty_print(&db, owner, Edition::CURRENT);
459+
expect!["fn foo(�: (), �: i32) -> impl ::core::future::Future::<Output = u32> �"]
460+
.assert_eq(&printed);
461+
}

crates/hir-expand/src/mod_path.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,14 @@ macro_rules! __path {
414414
}
415415

416416
pub use crate::__path as path;
417+
418+
#[macro_export]
419+
macro_rules! __tool_path {
420+
($start:ident $(:: $seg:ident)*) => ({
421+
$crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Plain, vec![
422+
$crate::name::Name::new_symbol_root(intern::sym::rust_analyzer.clone()), $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)*
423+
])
424+
});
425+
}
426+
427+
pub use crate::__tool_path as tool_path;

crates/hir-ty/src/tests/simple.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3802,3 +3802,15 @@ fn foo() {
38023802
"#,
38033803
);
38043804
}
3805+
3806+
#[test]
3807+
fn tool_attr_skip() {
3808+
check_no_mismatches(
3809+
r#"
3810+
#[rust_analyzer::skip]
3811+
async fn foo(a: (), b: i32) -> u32 {
3812+
0 + 1 + b()
3813+
}
3814+
"#,
3815+
);
3816+
}

crates/ide/src/goto_type_definition.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ pub(crate) fn goto_type_definition(
2424
let file: ast::SourceFile = sema.parse_guess_edition(file_id);
2525
let token: SyntaxToken =
2626
pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
27-
IDENT | INT_NUMBER | T![self] => 2,
27+
IDENT | INT_NUMBER | T![self] => 3,
2828
kind if kind.is_trivia() => 0,
29-
_ => 1,
29+
T![;] => 1,
30+
_ => 2,
3031
})?;
3132

3233
let mut res = Vec::new();

crates/intern/src/symbol/symbols.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ define_symbols! {
429429
shr,
430430
simd,
431431
sized,
432+
skip,
432433
slice_len_fn,
433434
Some,
434435
start,

0 commit comments

Comments
 (0)