about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs39
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs5
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
7 files changed, 86 insertions, 2 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index 37e2a99e60f..710bffcefe9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -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()?;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 49c48a5d590..d7e28da644a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -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 {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
index 65f44dbc35a..edc7c4c1f21 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
@@ -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(�: (), �: i32) -> impl ::core::future::Future::<Output = u32> �"]
+        .assert_eq(&printed);
+}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
index 876919f3ed7..4f2f9ec40d0 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
@@ -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;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index 5f0f341f393..15636604570 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -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()
+}
+        "#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
index 3d827f64f7e..2610d6c8863 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
@@ -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();
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 66b8900109c..131b21a46b8 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -429,6 +429,7 @@ define_symbols! {
     shr,
     simd,
     sized,
+    skip,
     slice_len_fn,
     Some,
     start,