mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-25 19:35:06 +00:00
Implement #[rust_analyzer::skip]
for bodies
This commit is contained in:
parent
897f7e579e
commit
f209d50dcf
7 changed files with 86 additions and 2 deletions
|
@ -122,6 +122,11 @@ impl Attrs {
|
|||
AttrQuery { attrs: self, key }
|
||||
}
|
||||
|
||||
pub fn rust_analyzer_tool(&self) -> impl Iterator<Item = &Attr> {
|
||||
self.iter()
|
||||
.filter(|&attr| attr.path.segments().first().is_some_and(|s| *s == sym::rust_analyzer))
|
||||
}
|
||||
|
||||
pub fn cfg(&self) -> Option<CfgExpr> {
|
||||
let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse);
|
||||
let first = cfgs.next()?;
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::mem;
|
|||
use base_db::CrateId;
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
mod_path::tool_path,
|
||||
name::{AsName, Name},
|
||||
span_map::{ExpansionSpanMap, SpanMap},
|
||||
InFile, MacroDefId,
|
||||
|
@ -27,6 +28,7 @@ use text_size::TextSize;
|
|||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
|
||||
builtin_type::BuiltinUint,
|
||||
data::adt::StructKind,
|
||||
|
@ -212,6 +214,43 @@ impl ExprCollector<'_> {
|
|||
body: Option<ast::Expr>,
|
||||
is_async_fn: bool,
|
||||
) -> (Body, BodySourceMap) {
|
||||
let skip_body = match self.owner {
|
||||
DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::ConstId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
|
||||
DefWithBodyId::VariantId(it) => self.db.attrs(it.into()),
|
||||
}
|
||||
.rust_analyzer_tool()
|
||||
.any(|attr| *attr.path() == tool_path![skip]);
|
||||
// If #[rust_analyzer::skip] annotated, only construct enough information for the signature
|
||||
// and skip the body.
|
||||
if skip_body {
|
||||
self.body.body_expr = self.missing_expr();
|
||||
if let Some((param_list, mut attr_enabled)) = param_list {
|
||||
if let Some(self_param) =
|
||||
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
|
||||
{
|
||||
let is_mutable =
|
||||
self_param.mut_token().is_some() && self_param.amp_token().is_none();
|
||||
let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
|
||||
Name::new_symbol_root(sym::self_.clone()),
|
||||
BindingAnnotation::new(is_mutable, false),
|
||||
);
|
||||
self.body.self_param = Some(binding_id);
|
||||
self.source_map.self_param =
|
||||
Some(self.expander.in_file(AstPtr::new(&self_param)));
|
||||
}
|
||||
self.body.params = param_list
|
||||
.params()
|
||||
.zip(attr_enabled)
|
||||
.filter(|(_, enabled)| *enabled)
|
||||
.map(|_| self.missing_pat())
|
||||
.collect();
|
||||
};
|
||||
return (self.body, self.source_map);
|
||||
}
|
||||
|
||||
self.awaitable_context.replace(if is_async_fn {
|
||||
Awaitable::Yes
|
||||
} else {
|
||||
|
|
|
@ -444,3 +444,18 @@ fn foo() {
|
|||
}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_skips_body() {
|
||||
let (db, body, owner) = lower(
|
||||
r#"
|
||||
#[rust_analyzer::skip]
|
||||
async fn foo(a: (), b: i32) -> u32 {
|
||||
0 + 1 + b()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
let printed = body.pretty_print(&db, owner, Edition::CURRENT);
|
||||
expect!["fn foo(<28>: (), <20>: i32) -> impl ::core::future::Future::<Output = u32> <20>"]
|
||||
.assert_eq(&printed);
|
||||
}
|
||||
|
|
|
@ -414,3 +414,14 @@ macro_rules! __path {
|
|||
}
|
||||
|
||||
pub use crate::__path as path;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __tool_path {
|
||||
($start:ident $(:: $seg:ident)*) => ({
|
||||
$crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Plain, vec![
|
||||
$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()),)*
|
||||
])
|
||||
});
|
||||
}
|
||||
|
||||
pub use crate::__tool_path as tool_path;
|
||||
|
|
|
@ -3802,3 +3802,15 @@ fn foo() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_attr_skip() {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
#[rust_analyzer::skip]
|
||||
async fn foo(a: (), b: i32) -> u32 {
|
||||
0 + 1 + b()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,10 @@ pub(crate) fn goto_type_definition(
|
|||
let file: ast::SourceFile = sema.parse_guess_edition(file_id);
|
||||
let token: SyntaxToken =
|
||||
pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
|
||||
IDENT | INT_NUMBER | T![self] => 2,
|
||||
IDENT | INT_NUMBER | T![self] => 3,
|
||||
kind if kind.is_trivia() => 0,
|
||||
_ => 1,
|
||||
T![;] => 1,
|
||||
_ => 2,
|
||||
})?;
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
|
|
@ -429,6 +429,7 @@ define_symbols! {
|
|||
shr,
|
||||
simd,
|
||||
sized,
|
||||
skip,
|
||||
slice_len_fn,
|
||||
Some,
|
||||
start,
|
||||
|
|
Loading…
Reference in a new issue