summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:29 +0000
commit631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch)
treea1b87c8f8cad01cf18f7c5f57a08f102771ed303 /src/tools/rust-analyzer/crates/ide
parentAdding debian version 1.69.0+dfsg1-1. (diff)
downloadrustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz
rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide')
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/file_structure.rs79
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs25
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs57
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs350
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs51
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs117
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/markup.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/move_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/navigation_target.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs290
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs269
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/view_mir.rs29
29 files changed, 1145 insertions, 297 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index b4a7f2b91..fae25f310 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -107,7 +107,18 @@ pub(crate) fn remove_links(markdown: &str) -> String {
out
}
-/// Retrieve a link to documentation for the given symbol.
+// Feature: Open Docs
+//
+// Retrieve a link to documentation for the given symbol.
+//
+// The simplest way to use this feature is via the context menu. Right-click on
+// the selected item. The context menu opens. Select **Open Docs**.
+//
+// |===
+// | Editor | Action Name
+//
+// | VS Code | **rust-analyzer: Open Docs**
+// |===
pub(crate) fn external_docs(
db: &RootDatabase,
position: &FilePosition,
@@ -181,6 +192,7 @@ pub(crate) fn resolve_doc_path_for_def(
Definition::Const(it) => it.resolve_doc_path(db, link, ns),
Definition::Static(it) => it.resolve_doc_path(db, link, ns),
Definition::Trait(it) => it.resolve_doc_path(db, link, ns),
+ Definition::TraitAlias(it) => it.resolve_doc_path(db, link, ns),
Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
Definition::Field(it) => it.resolve_doc_path(db, link, ns),
@@ -493,6 +505,7 @@ fn filename_and_frag_for_def(
None => String::from("index.html"),
},
Definition::Trait(t) => format!("trait.{}.html", t.name(db)),
+ Definition::TraitAlias(t) => format!("traitalias.{}.html", t.name(db)),
Definition::TypeAlias(t) => format!("type.{}.html", t.name(db)),
Definition::BuiltinType(t) => format!("primitive.{}.html", t.name()),
Definition::Function(f) => format!("fn.{}.html", f.name(db)),
diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
index b23763dce..a32ac3549 100644
--- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
@@ -149,6 +149,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
ast::Enum(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Enum)),
ast::Variant(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Variant)),
ast::Trait(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Trait)),
+ ast::TraitAlias(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::TraitAlias)),
ast::Module(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Module)),
ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::TypeAlias)),
ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Field)),
@@ -262,6 +263,8 @@ enum E { X, Y(i32) }
type T = ();
static S: i32 = 92;
const C: i32 = 92;
+trait Tr {}
+trait Alias = Tr;
impl E {}
@@ -459,9 +462,31 @@ fn g() {}
},
StructureNode {
parent: None,
+ label: "Tr",
+ navigation_range: 239..241,
+ node_range: 233..244,
+ kind: SymbolKind(
+ Trait,
+ ),
+ detail: None,
+ deprecated: false,
+ },
+ StructureNode {
+ parent: None,
+ label: "Alias",
+ navigation_range: 251..256,
+ node_range: 245..262,
+ kind: SymbolKind(
+ TraitAlias,
+ ),
+ detail: None,
+ deprecated: false,
+ },
+ StructureNode {
+ parent: None,
label: "impl E",
- navigation_range: 239..240,
- node_range: 234..243,
+ navigation_range: 269..270,
+ node_range: 264..273,
kind: SymbolKind(
Impl,
),
@@ -471,8 +496,8 @@ fn g() {}
StructureNode {
parent: None,
label: "impl fmt::Debug for E",
- navigation_range: 265..266,
- node_range: 245..269,
+ navigation_range: 295..296,
+ node_range: 275..299,
kind: SymbolKind(
Impl,
),
@@ -482,8 +507,8 @@ fn g() {}
StructureNode {
parent: None,
label: "mc",
- navigation_range: 284..286,
- node_range: 271..303,
+ navigation_range: 314..316,
+ node_range: 301..333,
kind: SymbolKind(
Macro,
),
@@ -493,8 +518,8 @@ fn g() {}
StructureNode {
parent: None,
label: "mcexp",
- navigation_range: 334..339,
- node_range: 305..356,
+ navigation_range: 364..369,
+ node_range: 335..386,
kind: SymbolKind(
Macro,
),
@@ -504,8 +529,8 @@ fn g() {}
StructureNode {
parent: None,
label: "mcexp",
- navigation_range: 387..392,
- node_range: 358..409,
+ navigation_range: 417..422,
+ node_range: 388..439,
kind: SymbolKind(
Macro,
),
@@ -515,8 +540,8 @@ fn g() {}
StructureNode {
parent: None,
label: "obsolete",
- navigation_range: 428..436,
- node_range: 411..441,
+ navigation_range: 458..466,
+ node_range: 441..471,
kind: SymbolKind(
Function,
),
@@ -528,8 +553,8 @@ fn g() {}
StructureNode {
parent: None,
label: "very_obsolete",
- navigation_range: 481..494,
- node_range: 443..499,
+ navigation_range: 511..524,
+ node_range: 473..529,
kind: SymbolKind(
Function,
),
@@ -541,8 +566,8 @@ fn g() {}
StructureNode {
parent: None,
label: "Some region name",
- navigation_range: 501..528,
- node_range: 501..528,
+ navigation_range: 531..558,
+ node_range: 531..558,
kind: Region,
detail: None,
deprecated: false,
@@ -550,8 +575,8 @@ fn g() {}
StructureNode {
parent: None,
label: "m",
- navigation_range: 568..569,
- node_range: 543..606,
+ navigation_range: 598..599,
+ node_range: 573..636,
kind: SymbolKind(
Module,
),
@@ -560,22 +585,22 @@ fn g() {}
},
StructureNode {
parent: Some(
- 20,
+ 22,
),
label: "dontpanic",
- navigation_range: 543..563,
- node_range: 543..563,
+ navigation_range: 573..593,
+ node_range: 573..593,
kind: Region,
detail: None,
deprecated: false,
},
StructureNode {
parent: Some(
- 20,
+ 22,
),
label: "f",
- navigation_range: 575..576,
- node_range: 572..581,
+ navigation_range: 605..606,
+ node_range: 602..611,
kind: SymbolKind(
Function,
),
@@ -586,11 +611,11 @@ fn g() {}
},
StructureNode {
parent: Some(
- 20,
+ 22,
),
label: "g",
- navigation_range: 598..599,
- node_range: 582..604,
+ navigation_range: 628..629,
+ node_range: 612..634,
kind: SymbolKind(
Function,
),
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 93019527f..cf0819a25 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -766,6 +766,13 @@ trait Foo$0 { }
check(
r#"
+trait Foo$0 = ;
+ //^^^
+"#,
+ );
+
+ check(
+ r#"
mod bar$0 { }
//^^^
"#,
@@ -1066,6 +1073,23 @@ fn f() -> impl Sub<Item$0 = u8> {}
}
#[test]
+ fn goto_def_for_module_declaration_in_path_if_types_and_values_same_name() {
+ check(
+ r#"
+mod bar {
+ pub struct Foo {}
+ //^^^
+ pub fn Foo() {}
+}
+
+fn baz() {
+ let _foo_enum: bar::Foo$0 = bar::Foo {};
+}
+ "#,
+ )
+ }
+
+ #[test]
fn unknown_assoc_ty() {
check_unresolved(
r#"
@@ -1406,7 +1430,6 @@ include!("included.rs$0");
);
}
- #[cfg(test)]
mod goto_impl_of_trait_fn {
use super::check;
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
index 190ab80ba..a1a119629 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
@@ -297,6 +297,7 @@ impl Foo<str> {}
//- /lib.rs crate:main deps:core
fn foo(_: bool$0) {{}}
//- /libcore.rs crate:core
+#![rustc_coherence_is_core]
#[lang = "bool"]
impl bool {}
//^^^^
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 55cdb3200..6d2d0bd63 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
@@ -55,7 +55,7 @@ pub(crate) fn goto_type_definition(
ty
} else {
let record_field = ast::RecordPatField::for_field_name_ref(&it)?;
- sema.resolve_record_pat_field(&record_field)?.ty(db)
+ sema.resolve_record_pat_field(&record_field)?.1
}
},
_ => return None,
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index c889eb930..d88ffd25c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -14,7 +14,7 @@ use syntax::{
SyntaxNode, SyntaxToken, TextRange, T,
};
-use crate::{references, NavigationTarget, TryToNav};
+use crate::{navigation_target::ToNav, references, NavigationTarget, TryToNav};
#[derive(PartialEq, Eq, Hash)]
pub struct HighlightedRange {
@@ -98,32 +98,39 @@ fn highlight_references(
category: access,
});
let mut res = FxHashSet::default();
-
- let mut def_to_hl_range = |def| {
- let hl_range = match def {
- Definition::Module(module) => {
- Some(NavigationTarget::from_module_to_decl(sema.db, module))
- }
- def => def.try_to_nav(sema.db),
- }
- .filter(|decl| decl.file_id == file_id)
- .and_then(|decl| decl.focus_range)
- .map(|range| {
- let category =
- references::decl_mutability(&def, node, range).then_some(ReferenceCategory::Write);
- HighlightedRange { range, category }
- });
- if let Some(hl_range) = hl_range {
- res.insert(hl_range);
- }
- };
for &def in &defs {
match def {
- Definition::Local(local) => local
- .associated_locals(sema.db)
- .iter()
- .for_each(|&local| def_to_hl_range(Definition::Local(local))),
- def => def_to_hl_range(def),
+ Definition::Local(local) => {
+ let category = local.is_mut(sema.db).then_some(ReferenceCategory::Write);
+ local
+ .sources(sema.db)
+ .into_iter()
+ .map(|x| x.to_nav(sema.db))
+ .filter(|decl| decl.file_id == file_id)
+ .filter_map(|decl| decl.focus_range)
+ .map(|range| HighlightedRange { range, category })
+ .for_each(|x| {
+ res.insert(x);
+ });
+ }
+ def => {
+ let hl_range = match def {
+ Definition::Module(module) => {
+ Some(NavigationTarget::from_module_to_decl(sema.db, module))
+ }
+ def => def.try_to_nav(sema.db),
+ }
+ .filter(|decl| decl.file_id == file_id)
+ .and_then(|decl| decl.focus_range)
+ .map(|range| {
+ let category = references::decl_mutability(&def, node, range)
+ .then_some(ReferenceCategory::Write);
+ HighlightedRange { range, category }
+ });
+ if let Some(hl_range) = hl_range {
+ res.insert(hl_range);
+ }
+ }
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 5f2c61f5b..64b2221bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -30,6 +30,7 @@ pub struct HoverConfig {
pub documentation: bool,
pub keywords: bool,
pub format: HoverDocFormat,
+ pub interpret_tests: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 22611cfb8..da725ce50 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -3,7 +3,8 @@ use std::fmt::Display;
use either::Either;
use hir::{
- Adt, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo,
+ db::DefDatabase, Adt, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay,
+ MirEvalError, Semantics, TypeInfo,
};
use ide_db::{
base_db::SourceDatabase,
@@ -402,7 +403,20 @@ pub(super) fn definition(
))
}),
Definition::Module(it) => label_and_docs(db, it),
- Definition::Function(it) => label_and_docs(db, it),
+ Definition::Function(it) => label_and_layout_info_and_docs(db, it, |_| {
+ if !config.interpret_tests {
+ return None;
+ }
+ match it.eval(db) {
+ Ok(()) => Some("pass".into()),
+ Err(MirEvalError::Panic) => Some("fail".into()),
+ Err(MirEvalError::MirLowerError(f, e)) => {
+ let name = &db.function_data(f).name;
+ Some(format!("error: fail to lower {name} due {e:?}"))
+ }
+ Err(e) => Some(format!("error: {e:?}")),
+ }
+ }),
Definition::Adt(it) => label_and_layout_info_and_docs(db, it, |&it| {
let layout = it.layout(db).ok()?;
Some(format!("size = {}, align = {}", layout.size.bytes(), layout.align.abi.bytes()))
@@ -410,7 +424,7 @@ pub(super) fn definition(
Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
if !it.parent_enum(db).is_data_carrying(db) {
match it.eval(db) {
- Ok(x) => Some(format!("{x}")),
+ Ok(x) => Some(if x >= 10 { format!("{x} ({x:#X})") } else { format!("{x}") }),
Err(_) => it.value(db).map(|x| format!("{x:?}")),
}
} else {
@@ -418,9 +432,9 @@ pub(super) fn definition(
}
}),
Definition::Const(it) => label_value_and_docs(db, it, |it| {
- let body = it.eval(db);
+ let body = it.render_eval(db);
match body {
- Ok(x) => Some(format!("{x}")),
+ Ok(x) => Some(x),
Err(_) => {
let source = it.source(db)?;
let mut body = source.value.body()?.syntax().clone();
@@ -440,6 +454,7 @@ pub(super) fn definition(
Some(body.to_string())
}),
Definition::Trait(it) => label_and_docs(db, it),
+ Definition::TraitAlias(it) => label_and_docs(db, it),
Definition::TypeAlias(it) => label_and_docs(db, it),
Definition::BuiltinType(it) => {
return famous_defs
@@ -620,8 +635,8 @@ fn local(db: &RootDatabase, it: hir::Local) -> Option<Markup> {
let ty = it.ty(db);
let ty = ty.display_truncated(db, None);
let is_mut = if it.is_mut(db) { "mut " } else { "" };
- let desc = match it.source(db).value {
- Either::Left(ident) => {
+ let desc = match it.primary_source(db).into_ident_pat() {
+ Some(ident) => {
let name = it.name(db);
let let_kw = if ident
.syntax()
@@ -634,7 +649,7 @@ fn local(db: &RootDatabase, it: hir::Local) -> Option<Markup> {
};
format!("{let_kw}{is_mut}{name}: {ty}")
}
- Either::Right(_) => format!("{is_mut}self: {ty}"),
+ None => format!("{is_mut}self: {ty}"),
};
markup(None, desc, None)
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index bd7ce2f1d..57bf0f9ad 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -4,16 +4,19 @@ use syntax::TextRange;
use crate::{fixture, HoverConfig, HoverDocFormat};
+const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
+ links_in_hover: false,
+ documentation: true,
+ format: HoverDocFormat::Markdown,
+ keywords: true,
+ interpret_tests: false,
+};
+
fn check_hover_no_result(ra_fixture: &str) {
let (analysis, position) = fixture::position(ra_fixture);
let hover = analysis
.hover(
- &HoverConfig {
- links_in_hover: true,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
+ &HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG },
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
.unwrap();
@@ -25,12 +28,7 @@ fn check(ra_fixture: &str, expect: Expect) {
let (analysis, position) = fixture::position(ra_fixture);
let hover = analysis
.hover(
- &HoverConfig {
- links_in_hover: true,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
+ &HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG },
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
.unwrap()
@@ -47,12 +45,7 @@ fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
let (analysis, position) = fixture::position(ra_fixture);
let hover = analysis
.hover(
- &HoverConfig {
- links_in_hover: false,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
+ &HOVER_BASE_CONFIG,
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
.unwrap()
@@ -71,9 +64,8 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: true,
- documentation: true,
- keywords: true,
format: HoverDocFormat::PlainText,
+ ..HOVER_BASE_CONFIG
},
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
@@ -91,12 +83,7 @@ fn check_actions(ra_fixture: &str, expect: Expect) {
let (analysis, file_id, position) = fixture::range_or_position(ra_fixture);
let hover = analysis
.hover(
- &HoverConfig {
- links_in_hover: true,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
+ &HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG },
FileRange { file_id, range: position.range_or_empty() },
)
.unwrap()
@@ -106,34 +93,13 @@ fn check_actions(ra_fixture: &str, expect: Expect) {
fn check_hover_range(ra_fixture: &str, expect: Expect) {
let (analysis, range) = fixture::range(ra_fixture);
- let hover = analysis
- .hover(
- &HoverConfig {
- links_in_hover: false,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
- range,
- )
- .unwrap()
- .unwrap();
+ let hover = analysis.hover(&HOVER_BASE_CONFIG, range).unwrap().unwrap();
expect.assert_eq(hover.info.markup.as_str())
}
fn check_hover_range_no_results(ra_fixture: &str) {
let (analysis, range) = fixture::range(ra_fixture);
- let hover = analysis
- .hover(
- &HoverConfig {
- links_in_hover: false,
- documentation: true,
- keywords: true,
- format: HoverDocFormat::Markdown,
- },
- range,
- )
- .unwrap();
+ let hover = analysis.hover(&HOVER_BASE_CONFIG, range).unwrap();
assert!(hover.is_none());
}
@@ -490,7 +456,6 @@ fn hover_field_offset() {
// Hovering over the field when instantiating
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
"#,
expect![[r#"
@@ -512,7 +477,6 @@ fn hover_shows_struct_field_info() {
// Hovering over the field when instantiating
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { field_a: u32 }
fn main() {
@@ -535,7 +499,6 @@ fn main() {
// Hovering over the field in the definition
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { field_a$0: u32 }
fn main() {
@@ -611,6 +574,27 @@ const foo$0: u32 = {
}
#[test]
+fn hover_eval_complex_constants() {
+ check(
+ r#"
+ struct X { f1: (), f2: i32 }
+ const foo$0: (i8, X, i64) = (1, X { f2: 5 - 1, f1: () }, 1 - 2);
+ "#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ const foo: (i8, X, i64) = (1, X { f1: (), f2: 4 }, -1)
+ ```
+ "#]],
+ );
+}
+
+#[test]
fn hover_default_generic_types() {
check(
r#"
@@ -1467,8 +1451,6 @@ fn my() {}
fn test_hover_struct_doc_comment() {
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
-
/// This is an example
/// multiline doc
///
@@ -1527,7 +1509,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar
+ struct Bar // size = 0, align = 1
```
---
@@ -1556,7 +1538,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar
+ struct Bar // size = 0, align = 1
```
---
@@ -1584,7 +1566,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar
+ pub struct Bar // size = 0, align = 1
```
---
@@ -1611,7 +1593,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar
+ pub struct Bar // size = 0, align = 1
```
---
@@ -2913,8 +2895,6 @@ fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
fn hover_field_pat_shorthand_ref_match_ergonomics() {
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
-
struct S {
f: i32,
}
@@ -3506,8 +3486,8 @@ impl<const LEN: usize> Foo<LEN$0> {}
}
#[test]
-fn hover_const_eval_variant() {
- // show hex for <10
+fn hover_const_eval_discriminant() {
+ // Don't show hex for <10
check(
r#"
#[repr(u8)]
@@ -3532,7 +3512,7 @@ enum E {
This is a doc
"#]],
);
- // show hex for >10
+ // Show hex for >10
check(
r#"
#[repr(u8)]
@@ -3656,7 +3636,7 @@ trait T {
}
impl T for i32 {
const AA: A = A {
- i: 2
+ i: 2 + 3
}
}
fn main() {
@@ -3671,9 +3651,7 @@ fn main() {
```
```rust
- const AA: A = A {
- i: 2
- }
+ const AA: A = A { i: 5 }
```
"#]],
);
@@ -3792,7 +3770,6 @@ const FOO$0: usize = 1 << 3;
This is a doc
"#]],
);
- // show hex for >10
check(
r#"
/// This is a doc
@@ -3850,7 +3827,7 @@ const FOO$0: i32 = 2 - 3;
```
```rust
- const FOO: i32 = -1
+ const FOO: i32 = -1 (0xFFFFFFFF)
```
---
@@ -4011,6 +3988,28 @@ const FOO$0: f32 = 1f32;
This is a doc
"#]],
);
+ // Don't show `<ref-not-supported>` in const hover
+ check(
+ r#"
+/// This is a doc
+const FOO$0: &i32 = &2;
+"#,
+ expect![[r#"
+ *FOO*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ const FOO: &i32 = &2
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
//show f64 typecasted from float
check(
r#"
@@ -4354,8 +4353,6 @@ fn main() {
fn hover_intra_doc_links() {
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
-
pub mod theitem {
/// This is the item. Cool!
pub struct TheItem;
@@ -4496,7 +4493,7 @@ trait A where
fn string_shadowed_with_inner_items() {
check(
r#"
-//- /main.rs crate:main deps:alloc target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
+//- /main.rs crate:main deps:alloc
/// Custom `String` type.
struct String;
@@ -5191,7 +5188,7 @@ foo_macro!(
```
```rust
- pub struct Foo
+ pub struct Foo // size = 0, align = 1
```
---
@@ -5205,8 +5202,6 @@ foo_macro!(
fn hover_intra_in_attr() {
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
-
#[doc = "Doc comment for [`Foo$0`]"]
pub struct Foo(i32);
"#,
@@ -5295,7 +5290,7 @@ pub struct Type;
```
```rust
- const KONST: dep::Type = $crate::Type
+ const KONST: dep::Type = Type
```
"#]],
);
@@ -5327,8 +5322,6 @@ enum Enum {
fn hover_record_variant_field() {
check(
r#"
-//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
-
enum Enum {
RecordV { field$0: u32 }
}
@@ -5647,3 +5640,204 @@ fn main() {
"#]],
);
}
+
+#[test]
+fn assoc_fn_in_block_local_impl() {
+ check(
+ r#"
+struct S;
+mod m {
+ const _: () = {
+ impl crate::S {
+ pub(crate) fn foo() {}
+ }
+ };
+}
+fn test() {
+ S::foo$0();
+}
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test::S
+ ```
+
+ ```rust
+ pub(crate) fn foo()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+struct S;
+mod m {
+ const _: () = {
+ const _: () = {
+ impl crate::S {
+ pub(crate) fn foo() {}
+ }
+ };
+ };
+}
+fn test() {
+ S::foo$0();
+}
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test::S
+ ```
+
+ ```rust
+ pub(crate) fn foo()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+struct S;
+mod m {
+ mod inner {
+ const _: () = {
+ impl crate::S {
+ pub(super) fn foo() {}
+ }
+ };
+ }
+
+ fn test() {
+ crate::S::foo$0();
+ }
+}
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test::S
+ ```
+
+ ```rust
+ pub(super) fn foo()
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn assoc_const_in_block_local_impl() {
+ check(
+ r#"
+struct S;
+mod m {
+ const _: () = {
+ impl crate::S {
+ pub(crate) const A: () = ();
+ }
+ };
+}
+fn test() {
+ S::A$0;
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ pub(crate) const A: () = ()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+struct S;
+mod m {
+ const _: () = {
+ const _: () = {
+ impl crate::S {
+ pub(crate) const A: () = ();
+ }
+ };
+ };
+}
+fn test() {
+ S::A$0;
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ pub(crate) const A: () = ()
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+struct S;
+mod m {
+ mod inner {
+ const _: () = {
+ impl crate::S {
+ pub(super) const A: () = ();
+ }
+ };
+ }
+
+ fn test() {
+ crate::S::A$0;
+ }
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ pub(super) const A: () = ()
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn field_as_method_call_fallback() {
+ check(
+ r#"
+struct S { f: u32 }
+fn test() {
+ S { f: 0 }.f$0();
+}
+"#,
+ expect![[r#"
+ *f*
+
+ ```rust
+ test::S
+ ```
+
+ ```rust
+ f: u32 // size = 4, align = 4, offset = 0
+ ```
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
index 188eb7f97..46505b304 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
@@ -31,19 +31,31 @@ pub(super) fn hints(
return None;
}
- // These inherit from the inner expression which would result in duplicate hints
- if let ast::Expr::ParenExpr(_)
- | ast::Expr::IfExpr(_)
- | ast::Expr::BlockExpr(_)
- | ast::Expr::MatchExpr(_) = expr
- {
+ // ParenExpr resolve to their contained expressions HIR so they will dupe these hints
+ if let ast::Expr::ParenExpr(_) = expr {
return None;
}
+ if let ast::Expr::BlockExpr(b) = expr {
+ if !b.is_standalone() {
+ return None;
+ }
+ }
let descended = sema.descend_node_into_attributes(expr.clone()).pop();
let desc_expr = descended.as_ref().unwrap_or(expr);
let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?;
+ if let ast::Expr::BlockExpr(_) | ast::Expr::IfExpr(_) | ast::Expr::MatchExpr(_) = desc_expr {
+ if let [Adjustment { kind: Adjust::Deref(_), source, .. }, Adjustment { kind: Adjust::Borrow(_), source: _, target }] =
+ &*adjustments
+ {
+ // Don't show unnecessary reborrows for these, they will just repeat the inner ones again
+ if source == target {
+ return None;
+ }
+ }
+ }
+
let (postfix, needs_outer_parens, needs_inner_parens) =
mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);
@@ -67,6 +79,7 @@ pub(super) fn hints(
for Adjustment { source, target, kind } in iter {
if source == target {
+ cov_mark::hit!(same_type_adjustment);
continue;
}
@@ -251,7 +264,7 @@ mod tests {
check_with_config(
InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
r#"
-//- minicore: coerce_unsized, fn
+//- minicore: coerce_unsized, fn, eq
fn main() {
let _: u32 = loop {};
//^^^^^^^<never-to-any>
@@ -332,7 +345,7 @@ fn main() {
loop {}
//^^^^^^^<never-to-any>
};
- let _: &mut [u32] = match () { () => &mut [] }
+ let _: &mut [u32] = match () { () => &mut [] };
//^^^^^^^<unsize>
//^^^^^^^&mut $
//^^^^^^^*
@@ -341,6 +354,12 @@ fn main() {
//^^^^^^^^^^<unsize>
//^^^^^^^^^^&mut $
//^^^^^^^^^^*
+ () == ();
+ // ^^&
+ // ^^&
+ (()) == {()};
+ // ^^&
+ // ^^^^&
}
#[derive(Copy, Clone)]
@@ -363,7 +382,7 @@ impl Struct {
..DISABLED_CONFIG
},
r#"
-//- minicore: coerce_unsized, fn
+//- minicore: coerce_unsized, fn, eq
fn main() {
Struct.consume();
@@ -419,7 +438,7 @@ fn main() {
loop {}
//^^^^^^^.<never-to-any>
};
- let _: &mut [u32] = match () { () => &mut [] }
+ let _: &mut [u32] = match () { () => &mut [] };
//^^^^^^^(
//^^^^^^^)
//^^^^^^^.*
@@ -432,6 +451,12 @@ fn main() {
//^^^^^^^^^^.*
//^^^^^^^^^^.&mut
//^^^^^^^^^^.<unsize>
+ () == ();
+ // ^^.&
+ // ^^.&
+ (()) == {()};
+ // ^^.&
+ // ^^^^.&
}
#[derive(Copy, Clone)]
@@ -499,6 +524,7 @@ fn main() {
#[test]
fn never_to_never_is_never_shown() {
+ cov_mark::check!(same_type_adjustment);
check_with_config(
InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
r#"
@@ -606,14 +632,13 @@ fn a() {
}
#[test]
- fn bug() {
+ fn let_stmt_explicit_ty() {
check_with_config(
InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
r#"
fn main() {
- // These should be identical, but they are not...
-
let () = return;
+ //^^^^^^<never-to-any>
let (): () = return;
//^^^^^^<never-to-any>
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index 4af7f9bdb..6a5092733 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -176,15 +176,12 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir
mod tests {
// This module also contains tests for super::closure_ret
- use expect_test::expect;
use syntax::{TextRange, TextSize};
use test_utils::extract_annotations;
use crate::{fixture, inlay_hints::InlayHintsConfig};
- use crate::inlay_hints::tests::{
- check, check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG,
- };
+ use crate::inlay_hints::tests::{check, check_with_config, DISABLED_CONFIG, TEST_CONFIG};
use crate::ClosureReturnTypeHints;
#[track_caller]
@@ -278,8 +275,7 @@ fn main() {
#[test]
fn iterator_hint_regression_issue_12674() {
// Ensure we don't crash while solving the projection type of iterators.
- check_expect(
- InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
+ let (analysis, file_id) = fixture::file(
r#"
//- minicore: iterators
struct S<T>(T);
@@ -302,107 +298,18 @@ impl<'a, T> Iterator for SliceIter<'a, T> {
fn main(a: SliceIter<'_, Container>) {
a
- .filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
- .map(|e| e);
+ .filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
+ .map(|e| e);
}
- "#,
- expect![[r#"
- [
- InlayHint {
- range: 484..554,
- kind: Chaining,
- label: [
- "impl ",
- InlayHintLabelPart {
- text: "Iterator",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 1,
- ),
- range: 2611..2619,
- },
- ),
- tooltip: "",
- },
- "<",
- InlayHintLabelPart {
- text: "Item",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 1,
- ),
- range: 2643..2647,
- },
- ),
- tooltip: "",
- },
- " = impl ",
- InlayHintLabelPart {
- text: "Iterator",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 1,
- ),
- range: 2611..2619,
- },
- ),
- tooltip: "",
- },
- "<",
- InlayHintLabelPart {
- text: "Item",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 1,
- ),
- range: 2643..2647,
- },
- ),
- tooltip: "",
- },
- " = &&str>>",
- ],
- },
- InlayHint {
- range: 484..485,
- kind: Chaining,
- label: [
- "",
- InlayHintLabelPart {
- text: "SliceIter",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 0,
- ),
- range: 289..298,
- },
- ),
- tooltip: "",
- },
- "<",
- InlayHintLabelPart {
- text: "Container",
- linked_location: Some(
- FileRange {
- file_id: FileId(
- 0,
- ),
- range: 238..247,
- },
- ),
- tooltip: "",
- },
- ">",
- ],
- },
- ]
- "#]],
+"#,
);
+ analysis
+ .inlay_hints(
+ &InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
+ file_id,
+ None,
+ )
+ .unwrap();
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index 0c54f084c..1e1771259 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -435,7 +435,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2611..2619,
+ range: 3415..3423,
},
),
tooltip: "",
@@ -448,7 +448,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2643..2647,
+ range: 3447..3451,
},
),
tooltip: "",
@@ -468,7 +468,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2611..2619,
+ range: 3415..3423,
},
),
tooltip: "",
@@ -481,7 +481,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2643..2647,
+ range: 3447..3451,
},
),
tooltip: "",
@@ -501,7 +501,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2611..2619,
+ range: 3415..3423,
},
),
tooltip: "",
@@ -514,7 +514,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 2643..2647,
+ range: 3447..3451,
},
),
tooltip: "",
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
index 5dd51ad11..67eaa553a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
@@ -59,8 +59,14 @@ fn variant_hints(
},
kind: InlayKind::Discriminant,
label: InlayHintLabel::simple(
- match &d {
- Ok(v) => format!("{}", v),
+ match d {
+ Ok(x) => {
+ if x >= 10 {
+ format!("{x} ({x:#X})")
+ } else {
+ format!("{x}")
+ }
+ }
Err(_) => "?".into(),
},
Some(InlayTooltip::String(match &d {
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index f2b535bdc..078b66dd3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -55,6 +55,7 @@ mod syntax_tree;
mod typing;
mod view_crate_graph;
mod view_hir;
+mod view_mir;
mod view_item_tree;
mod shuffle_crate_graph;
@@ -308,6 +309,10 @@ impl Analysis {
self.with_db(|db| view_hir::view_hir(db, position))
}
+ pub fn view_mir(&self, position: FilePosition) -> Cancellable<String> {
+ self.with_db(|db| view_mir::view_mir(db, position))
+ }
+
pub fn view_item_tree(&self, file_id: FileId) -> Cancellable<String> {
self.with_db(|db| view_item_tree::view_item_tree(db, file_id))
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/markup.rs b/src/tools/rust-analyzer/crates/ide/src/markup.rs
index de9fef61a..411eb695f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/markup.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/markup.rs
@@ -32,7 +32,7 @@ impl Markup {
pub fn as_str(&self) -> &str {
self.text.as_str()
}
- pub fn fenced_block(contents: &impl fmt::Display) -> Markup {
+ pub fn fenced_block(contents: impl fmt::Display) -> Markup {
format!("```rust\n{contents}\n```").into()
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index af5e96d23..349e79ecf 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -208,6 +208,9 @@ pub(crate) fn def_to_moniker(
Definition::Trait(trait_) => {
MonikerDescriptor { name: trait_.name(db), desc: MonikerDescriptorKind::Type }
}
+ Definition::TraitAlias(ta) => {
+ MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::Type }
+ }
Definition::TypeAlias(ta) => {
MonikerDescriptor { name: ta.name(db), desc: MonikerDescriptorKind::TypeParameter }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/move_item.rs b/src/tools/rust-analyzer/crates/ide/src/move_item.rs
index ffc4bdd7d..b955ea99f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/move_item.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/move_item.rs
@@ -73,6 +73,7 @@ fn find_ancestors(item: SyntaxElement, direction: Direction, range: TextRange) -
SyntaxKind::MACRO_CALL,
SyntaxKind::TYPE_ALIAS,
SyntaxKind::TRAIT,
+ SyntaxKind::TRAIT_ALIAS,
SyntaxKind::IMPL,
SyntaxKind::MACRO_DEF,
SyntaxKind::STRUCT,
diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
index 3aa799d43..6aae82f98 100644
--- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
@@ -5,7 +5,7 @@ use std::fmt;
use either::Either;
use hir::{
symbols::FileSymbol, AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay,
- InFile, ModuleSource, Semantics,
+ InFile, LocalSource, ModuleSource, Semantics,
};
use ide_db::{
base_db::{FileId, FileRange},
@@ -192,6 +192,7 @@ impl TryToNav for Definition {
Definition::Const(it) => it.try_to_nav(db),
Definition::Static(it) => it.try_to_nav(db),
Definition::Trait(it) => it.try_to_nav(db),
+ Definition::TraitAlias(it) => it.try_to_nav(db),
Definition::TypeAlias(it) => it.try_to_nav(db),
Definition::BuiltinType(_) => None,
Definition::ToolModule(_) => None,
@@ -212,6 +213,7 @@ impl TryToNav for hir::ModuleDef {
hir::ModuleDef::Const(it) => it.try_to_nav(db),
hir::ModuleDef::Static(it) => it.try_to_nav(db),
hir::ModuleDef::Trait(it) => it.try_to_nav(db),
+ hir::ModuleDef::TraitAlias(it) => it.try_to_nav(db),
hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db),
hir::ModuleDef::Macro(it) => it.try_to_nav(db),
hir::ModuleDef::BuiltinType(_) => None,
@@ -249,6 +251,9 @@ impl ToNavFromAst for hir::TypeAlias {
impl ToNavFromAst for hir::Trait {
const KIND: SymbolKind = SymbolKind::Trait;
}
+impl ToNavFromAst for hir::TraitAlias {
+ const KIND: SymbolKind = SymbolKind::TraitAlias;
+}
impl<D> TryToNav for D
where
@@ -382,9 +387,11 @@ impl TryToNav for hir::GenericParam {
}
}
-impl ToNav for hir::Local {
+impl ToNav for LocalSource {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
- let InFile { file_id, value } = self.source(db);
+ let InFile { file_id, value } = &self.source;
+ let file_id = *file_id;
+ let local = self.local;
let (node, name) = match &value {
Either::Left(bind_pat) => (bind_pat.syntax(), bind_pat.name()),
Either::Right(it) => (it.syntax(), it.name()),
@@ -393,10 +400,10 @@ impl ToNav for hir::Local {
let FileRange { file_id, range: full_range } =
InFile::new(file_id, node).original_file_range(db);
- let name = self.name(db).to_smol_str();
- let kind = if self.is_self(db) {
+ let name = local.name(db).to_smol_str();
+ let kind = if local.is_self(db) {
SymbolKind::SelfParam
- } else if self.is_param(db) {
+ } else if local.is_param(db) {
SymbolKind::ValueParam
} else {
SymbolKind::Local
@@ -414,6 +421,12 @@ impl ToNav for hir::Local {
}
}
+impl ToNav for hir::Local {
+ fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
+ self.primary_source(db).to_nav(db)
+ }
+}
+
impl ToNav for hir::Label {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let InFile { file_id, value } = self.source(db);
@@ -544,6 +557,7 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
ast::Struct(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Enum(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Trait(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
+ ast::TraitAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Module(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::TypeAlias(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
ast::Const(it) => sema.to_def(&it).map(|it| it.display(db).to_string()),
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index cabbc2872..3684c1033 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -1356,6 +1356,38 @@ impl Foo {
}
#[test]
+ fn test_trait_alias() {
+ check(
+ r#"
+trait Foo {}
+trait Bar$0 = Foo where Self: ;
+fn foo<T: Bar>(_: impl Bar, _: &dyn Bar) {}
+"#,
+ expect![[r#"
+ Bar TraitAlias FileId(0) 13..42 19..22
+
+ FileId(0) 53..56
+ FileId(0) 66..69
+ FileId(0) 79..82
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_trait_alias_self() {
+ check(
+ r#"
+trait Foo = where Self$0: ;
+"#,
+ expect![[r#"
+ Self TypeParam FileId(0) 6..9 6..9
+
+ FileId(0) 18..22
+ "#]],
+ );
+ }
+
+ #[test]
fn test_attr_differs_from_fn_with_same_name() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index c0237e1ed..e10c46381 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -353,6 +353,11 @@ mod tests {
fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
let ra_fixture_after = &trim_indent(ra_fixture_after);
let (analysis, position) = fixture::position(ra_fixture_before);
+ if !ra_fixture_after.starts_with("error: ") {
+ if let Err(err) = analysis.prepare_rename(position).unwrap() {
+ panic!("Prepare rename to '{new_name}' was failed: {err}")
+ }
+ }
let rename_result = analysis
.rename(position, new_name)
.unwrap_or_else(|err| panic!("Rename to '{new_name}' was cancelled: {err}"));
@@ -1710,6 +1715,23 @@ fn foo(bar: i32) -> Foo {
}
#[test]
+ fn test_rename_local_simple() {
+ check(
+ "i",
+ r#"
+fn foo(bar$0: i32) -> i32 {
+ bar
+}
+"#,
+ r#"
+fn foo(i: i32) -> i32 {
+ i
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_rename_local_put_init_shorthand() {
cov_mark::check!(test_rename_local_put_init_shorthand);
check(
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 5b35262aa..8a8a9151c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -2,7 +2,7 @@ use std::fmt;
use ast::HasName;
use cfg::CfgExpr;
-use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics};
+use hir::{AsAssocItem, HasAttrs, HasSource, Semantics};
use ide_assists::utils::test_related_attribute;
use ide_db::{
base_db::{FilePosition, FileRange},
@@ -195,14 +195,13 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
//
// Provides a sneak peek of all tests where the current item is used.
//
-// The simplest way to use this feature is via the context menu:
-// - Right-click on the selected item. The context menu opens.
-// - Select **Peek related tests**
+// The simplest way to use this feature is via the context menu. Right-click on
+// the selected item. The context menu opens. Select **Peek Related Tests**.
//
// |===
// | Editor | Action Name
//
-// | VS Code | **rust-analyzer: Peek related tests**
+// | VS Code | **rust-analyzer: Peek Related Tests**
// |===
pub(crate) fn related_tests(
db: &RootDatabase,
@@ -371,9 +370,9 @@ pub(crate) fn runnable_impl(
let nav = def.try_to_nav(sema.db)?;
let ty = def.self_ty(sema.db);
let adt_name = ty.as_adt()?.name(sema.db);
- let mut ty_args = ty.type_arguments().peekable();
+ let mut ty_args = ty.generic_parameters(sema.db).peekable();
let params = if ty_args.peek().is_some() {
- format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty.display(sema.db))))
+ format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)))
} else {
String::new()
};
@@ -417,6 +416,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
Definition::Const(it) => it.attrs(db),
Definition::Static(it) => it.attrs(db),
Definition::Trait(it) => it.attrs(db),
+ Definition::TraitAlias(it) => it.attrs(db),
Definition::TypeAlias(it) => it.attrs(db),
Definition::Macro(it) => it.attrs(db),
Definition::SelfType(it) => it.attrs(db),
@@ -437,14 +437,10 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
let ty = imp.self_ty(db);
if let Some(adt) = ty.as_adt() {
let name = adt.name(db);
- let mut ty_args = ty.type_arguments().peekable();
+ let mut ty_args = ty.generic_parameters(db).peekable();
format_to!(path, "{}", name);
if ty_args.peek().is_some() {
- format_to!(
- path,
- "<{}>",
- ty_args.format_with(",", |ty, cb| cb(&ty.display(db)))
- );
+ format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)));
}
format_to!(path, "::{}", def_name);
path.retain(|c| c != ' ');
@@ -1001,6 +997,221 @@ impl Data {
}
#[test]
+ fn test_runnables_doc_test_in_impl_with_lifetime() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<'a>;
+impl Data<'a> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 52..106,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<'a>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_runnables_doc_test_in_impl_with_lifetime_and_types() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<'a, T, U>;
+impl<T, U> Data<'a, T, U> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 70..124,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<'a,T,U>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_runnables_doc_test_in_impl_with_const() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<const N: usize>;
+impl<const N: usize> Data<N> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 79..133,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<N>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_runnables_doc_test_in_impl_with_lifetime_types_and_const() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<'a, T, const N: usize>;
+impl<'a, T, const N: usize> Data<'a, T, N> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 100..154,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<'a,T,N>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+ #[test]
fn test_runnables_module() {
check(
r#"
@@ -2063,6 +2274,59 @@ mod tests {
}
#[test]
+ fn test_runnables_doc_test_in_impl_with_lifetime_type_const_value() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<'a, A, const B: usize, C, const D: u32>;
+impl<A, C, const D: u32> Data<'a, A, 12, C, D> {
+ /// ```
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 121..156,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<'a,A,12,C,D>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
fn doc_test_type_params() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index f70ca55a5..4b2c139f6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -16,7 +16,7 @@ use stdx::format_to;
use syntax::{
algo,
ast::{self, HasArgList},
- match_ast, AstNode, Direction, SyntaxToken, TextRange, TextSize,
+ match_ast, AstNode, Direction, SyntaxElementChildren, SyntaxToken, TextRange, TextSize,
};
use crate::RootDatabase;
@@ -102,6 +102,20 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
}
return signature_help_for_record_lit(&sema, record, token);
},
+ ast::RecordPat(record) => {
+ let cursor_outside = record.record_pat_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
+ if cursor_outside {
+ continue;
+ }
+ return signature_help_for_record_pat(&sema, record, token);
+ },
+ ast::TupleStructPat(tuple_pat) => {
+ let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token);
+ if cursor_outside {
+ continue;
+ }
+ return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token);
+ },
_ => (),
}
}
@@ -172,7 +186,7 @@ fn signature_help_for_call(
res.signature.push('(');
{
- if let Some(self_param) = callable.receiver_param(db) {
+ if let Some((self_param, _)) = callable.receiver_param(db) {
format_to!(res.signature, "{}", self_param)
}
let mut buf = String::new();
@@ -252,6 +266,10 @@ fn signature_help_for_generics(
res.doc = it.docs(db).map(|it| it.into());
format_to!(res.signature, "trait {}", it.name(db));
}
+ hir::GenericDef::TraitAlias(it) => {
+ res.doc = it.docs(db).map(|it| it.into());
+ format_to!(res.signature, "trait {}", it.name(db));
+ }
hir::GenericDef::TypeAlias(it) => {
res.doc = it.docs(db).map(|it| it.into());
format_to!(res.signature, "type {}", it.name(db));
@@ -342,11 +360,112 @@ fn signature_help_for_record_lit(
record: ast::RecordExpr,
token: SyntaxToken,
) -> Option<SignatureHelp> {
- let active_parameter = record
- .record_expr_field_list()?
+ signature_help_for_record_(
+ sema,
+ record.record_expr_field_list()?.syntax().children_with_tokens(),
+ &record.path()?,
+ record
+ .record_expr_field_list()?
+ .fields()
+ .filter_map(|field| sema.resolve_record_field(&field))
+ .map(|(field, _, ty)| (field, ty)),
+ token,
+ )
+}
+
+fn signature_help_for_record_pat(
+ sema: &Semantics<'_, RootDatabase>,
+ record: ast::RecordPat,
+ token: SyntaxToken,
+) -> Option<SignatureHelp> {
+ signature_help_for_record_(
+ sema,
+ record.record_pat_field_list()?.syntax().children_with_tokens(),
+ &record.path()?,
+ record
+ .record_pat_field_list()?
+ .fields()
+ .filter_map(|field| sema.resolve_record_pat_field(&field)),
+ token,
+ )
+}
+
+fn signature_help_for_tuple_struct_pat(
+ sema: &Semantics<'_, RootDatabase>,
+ pat: ast::TupleStructPat,
+ token: SyntaxToken,
+) -> Option<SignatureHelp> {
+ let rest_pat = pat.fields().find(|it| matches!(it, ast::Pat::RestPat(_)));
+ let is_left_of_rest_pat =
+ rest_pat.map_or(true, |it| token.text_range().start() < it.syntax().text_range().end());
+
+ let mut res = SignatureHelp {
+ doc: None,
+ signature: String::new(),
+ parameters: vec![],
+ active_parameter: None,
+ };
+
+ let db = sema.db;
+ let path_res = sema.resolve_path(&pat.path()?)?;
+ let fields: Vec<_> = if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res {
+ let en = variant.parent_enum(db);
+
+ res.doc = en.docs(db).map(|it| it.into());
+ format_to!(res.signature, "enum {}::{} (", en.name(db), variant.name(db));
+ variant.fields(db)
+ } else {
+ let adt = match path_res {
+ PathResolution::SelfType(imp) => imp.self_ty(db).as_adt()?,
+ PathResolution::Def(ModuleDef::Adt(adt)) => adt,
+ _ => return None,
+ };
+
+ match adt {
+ hir::Adt::Struct(it) => {
+ res.doc = it.docs(db).map(|it| it.into());
+ format_to!(res.signature, "struct {} (", it.name(db));
+ it.fields(db)
+ }
+ _ => return None,
+ }
+ };
+ let commas = pat
.syntax()
.children_with_tokens()
.filter_map(syntax::NodeOrToken::into_token)
+ .filter(|t| t.kind() == syntax::T![,]);
+ res.active_parameter = Some(if is_left_of_rest_pat {
+ commas.take_while(|t| t.text_range().start() <= token.text_range().start()).count()
+ } else {
+ let n_commas = commas
+ .collect::<Vec<_>>()
+ .into_iter()
+ .rev()
+ .take_while(|t| t.text_range().start() > token.text_range().start())
+ .count();
+ fields.len().saturating_sub(1).saturating_sub(n_commas)
+ });
+
+ let mut buf = String::new();
+ for ty in fields.into_iter().map(|it| it.ty(db)) {
+ format_to!(buf, "{}", ty.display_truncated(db, Some(20)));
+ res.push_call_param(&buf);
+ buf.clear();
+ }
+ res.signature.push_str(")");
+ Some(res)
+}
+
+fn signature_help_for_record_(
+ sema: &Semantics<'_, RootDatabase>,
+ field_list_children: SyntaxElementChildren,
+ path: &ast::Path,
+ fields2: impl Iterator<Item = (hir::Field, hir::Type)>,
+ token: SyntaxToken,
+) -> Option<SignatureHelp> {
+ let active_parameter = field_list_children
+ .filter_map(syntax::NodeOrToken::into_token)
.filter(|t| t.kind() == syntax::T![,])
.take_while(|t| t.text_range().start() <= token.text_range().start())
.count();
@@ -361,7 +480,7 @@ fn signature_help_for_record_lit(
let fields;
let db = sema.db;
- let path_res = sema.resolve_path(&record.path()?)?;
+ let path_res = sema.resolve_path(path)?;
if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res {
fields = variant.fields(db);
let en = variant.parent_enum(db);
@@ -393,8 +512,7 @@ fn signature_help_for_record_lit(
let mut fields =
fields.into_iter().map(|field| (field.name(db), Some(field))).collect::<FxIndexMap<_, _>>();
let mut buf = String::new();
- for field in record.record_expr_field_list()?.fields() {
- let Some((field, _, ty)) = sema.resolve_record_field(&field) else { continue };
+ for (field, ty) in fields2 {
let name = field.name(db);
format_to!(buf, "{name}: {}", ty.display_truncated(db, Some(20)));
res.push_record_field(&buf);
@@ -435,6 +553,7 @@ mod tests {
(database, FilePosition { file_id, offset })
}
+ #[track_caller]
fn check(ra_fixture: &str, expect: Expect) {
let fixture = format!(
r#"
@@ -887,6 +1006,119 @@ fn main() {
}
#[test]
+ fn tuple_struct_pat() {
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32);
+fn main() {
+ let S(0, $0);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32)
+ --- ^^^
+ "#]],
+ );
+ }
+
+ #[test]
+ fn tuple_struct_pat_rest() {
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16);
+fn main() {
+ let S(0, .., $0);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16)
+ --- --- --- ^^^
+ "#]],
+ );
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16, u8);
+fn main() {
+ let S(0, .., $0, 0);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16, u8)
+ --- --- --- ^^^ --
+ "#]],
+ );
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16);
+fn main() {
+ let S($0, .., 1);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16)
+ ^^^ --- --- ---
+ "#]],
+ );
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16, u8);
+fn main() {
+ let S(1, .., 1, $0, 2);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16, u8)
+ --- --- --- ^^^ --
+ "#]],
+ );
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16);
+fn main() {
+ let S(1, $0.., 1);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16)
+ --- ^^^ --- ---
+ "#]],
+ );
+ check(
+ r#"
+/// A cool tuple struct
+struct S(u32, i32, f32, u16);
+fn main() {
+ let S(1, ..$0, 1);
+}
+"#,
+ expect![[r#"
+ A cool tuple struct
+ ------
+ struct S (u32, i32, f32, u16)
+ --- ^^^ --- ---
+ "#]],
+ );
+ }
+
+ #[test]
fn generic_struct() {
check(
r#"
@@ -1547,6 +1779,29 @@ impl S {
}
#[test]
+ fn record_pat() {
+ check(
+ r#"
+struct Strukt<T, U = ()> {
+ t: T,
+ u: U,
+ unit: (),
+}
+fn f() {
+ let Strukt {
+ u: 0,
+ $0
+ }
+}
+"#,
+ expect![[r#"
+ struct Strukt { u: i32, t: T, unit: () }
+ ------ ^^^^ --------
+ "#]],
+ );
+ }
+
+ #[test]
fn test_enum_in_nested_method_in_lambda() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 3f7f6885f..c97691b14 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -139,6 +139,7 @@ impl StaticIndex<'_> {
documentation: true,
keywords: true,
format: crate::HoverDocFormat::Markdown,
+ interpret_tests: false,
};
let tokens = tokens.filter(|token| {
matches!(
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
index 892e6a9bb..2111baad7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
@@ -217,7 +217,9 @@ fn highlight_name_ref(
// to anything when used.
// We can fix this for derive attributes since derive helpers are recorded, but not for
// general attributes.
- None if name_ref.syntax().ancestors().any(|it| it.kind() == ATTR) => {
+ None if name_ref.syntax().ancestors().any(|it| it.kind() == ATTR)
+ && !sema.hir_file_for(name_ref.syntax()).is_derive_attr_pseudo_expansion(sema.db) =>
+ {
return HlTag::Symbol(SymbolKind::Attribute).into();
}
None => return HlTag::UnresolvedReference.into(),
@@ -410,6 +412,7 @@ fn highlight_def(
h
}
Definition::Trait(_) => Highlight::new(HlTag::Symbol(SymbolKind::Trait)),
+ Definition::TraitAlias(_) => Highlight::new(HlTag::Symbol(SymbolKind::TraitAlias)),
Definition::TypeAlias(type_) => {
let mut h = Highlight::new(HlTag::Symbol(SymbolKind::TypeAlias));
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
index 9139528c7..3c4cfc781 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
@@ -274,6 +274,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag {
Definition::Const(_) => SymbolKind::Const,
Definition::Static(_) => SymbolKind::Static,
Definition::Trait(_) => SymbolKind::Trait,
+ Definition::TraitAlias(_) => SymbolKind::TraitAlias,
Definition::TypeAlias(_) => SymbolKind::TypeAlias,
Definition::BuiltinType(_) => return HlTag::BuiltinType,
Definition::Macro(_) => SymbolKind::Macro,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
index 3949f1189..a81c4ee0c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
@@ -150,6 +150,7 @@ impl HlTag {
SymbolKind::Struct => "struct",
SymbolKind::ToolModule => "tool_module",
SymbolKind::Trait => "trait",
+ SymbolKind::TraitAlias => "trait_alias",
SymbolKind::TypeAlias => "type_alias",
SymbolKind::TypeParam => "type_param",
SymbolKind::Union => "union",
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index 1a4398814..567ab8ccc 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -53,6 +53,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="comment">// This is another normal comment</span>
<span class="comment documentation">/// This is another doc comment</span>
<span class="comment">// This is another normal comment</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="comma attribute">,</span> <span class="unresolved_reference attribute">Unresolved</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
<span class="comment">// The reason for these being here is to test AttrIds</span>
<span class="keyword">struct</span> <span class="struct declaration">Foo</span><span class="semicolon">;</span></code></pre> \ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index fc9b5d3ba..ac9bd8e39 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -34,7 +34,7 @@ fn attributes() {
// This is another normal comment
/// This is another doc comment
// This is another normal comment
-#[derive(Copy)]
+#[derive(Copy, Unresolved)]
// The reason for these being here is to test AttrIds
struct Foo;
"#,
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_mir.rs b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs
new file mode 100644
index 000000000..a36aba58b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs
@@ -0,0 +1,29 @@
+use hir::{DefWithBody, Semantics};
+use ide_db::base_db::FilePosition;
+use ide_db::RootDatabase;
+use syntax::{algo::find_node_at_offset, ast, AstNode};
+
+// Feature: View Mir
+//
+// |===
+// | Editor | Action Name
+//
+// | VS Code | **rust-analyzer: View Mir**
+// |===
+pub(crate) fn view_mir(db: &RootDatabase, position: FilePosition) -> String {
+ body_mir(db, position).unwrap_or_else(|| "Not inside a function body".to_string())
+}
+
+fn body_mir(db: &RootDatabase, position: FilePosition) -> Option<String> {
+ let sema = Semantics::new(db);
+ let source_file = sema.parse(position.file_id);
+
+ let item = find_node_at_offset::<ast::Item>(source_file.syntax(), position.offset)?;
+ let def: DefWithBody = match item {
+ ast::Item::Fn(it) => sema.to_def(&it)?.into(),
+ ast::Item::Const(it) => sema.to_def(&it)?.into(),
+ ast::Item::Static(it) => sema.to_def(&it)?.into(),
+ _ => return None,
+ };
+ Some(def.debug_mir(db))
+}