summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide')
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/annotations.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs63
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs47
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/extend_selection.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs54
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs127
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/navigation_target.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs61
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/status.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html58
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/typing.rs248
42 files changed, 782 insertions, 252 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index f994c284c..fb79b5dc2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -94,10 +94,9 @@ pub(crate) fn annotations(
enum_
.variants(db)
.into_iter()
- .map(|variant| {
+ .filter_map(|variant| {
variant.source(db).and_then(|node| name_range(db, node, file_id))
})
- .flatten()
.for_each(|range| {
let (annotation_range, target_position) = mk_ranges(range);
annotations.push(Annotation {
diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
index dd1d0d75c..f834f2ce5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
@@ -74,18 +74,20 @@ pub(crate) fn incoming_calls(
Some(calls.into_items())
}
-pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> {
+pub(crate) fn outgoing_calls(
+ db: &RootDatabase,
+ FilePosition { file_id, offset }: FilePosition,
+) -> Option<Vec<CallItem>> {
let sema = Semantics::new(db);
- let file_id = position.file_id;
let file = sema.parse(file_id);
let file = file.syntax();
- let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
+ let token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
IDENT => 1,
_ => 0,
})?;
let mut calls = CallLocations::default();
- sema.descend_into_macros(token)
+ sema.descend_into_macros(token, offset)
.into_iter()
.filter_map(|it| it.parent_ancestors().nth(1).and_then(ast::Item::cast))
.filter_map(|item| match item {
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 d240127f3..37a177622 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -16,6 +16,7 @@ use hir::{db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, HasA
use ide_db::{
base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, SourceDatabase},
defs::{Definition, NameClass, NameRefClass},
+ documentation::{docs_with_rangemap, Documentation, HasDocs},
helpers::pick_best_token,
RootDatabase,
};
@@ -131,19 +132,19 @@ pub(crate) fn remove_links(markdown: &str) -> String {
// |===
pub(crate) fn external_docs(
db: &RootDatabase,
- position: &FilePosition,
+ FilePosition { file_id, offset }: FilePosition,
target_dir: Option<&OsStr>,
sysroot: Option<&OsStr>,
) -> Option<DocumentationLinks> {
let sema = &Semantics::new(db);
- let file = sema.parse(position.file_id).syntax().clone();
- let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
+ let file = sema.parse(file_id).syntax().clone();
+ let token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
IDENT | INT_NUMBER | T![self] => 3,
T!['('] | T![')'] => 2,
kind if kind.is_trivia() => 0,
_ => 1,
})?;
- let token = sema.descend_into_macros_single(token);
+ let token = sema.descend_into_macros_single(token, offset);
let node = token.parent()?;
let definition = match_ast! {
@@ -171,7 +172,7 @@ pub(crate) fn external_docs(
/// Extracts all links from a given markdown text returning the definition text range, link-text
/// and the namespace if known.
pub(crate) fn extract_definitions_from_docs(
- docs: &hir::Documentation,
+ docs: &Documentation,
) -> Vec<(TextRange, String, Option<hir::Namespace>)> {
Parser::new_with_broken_link_callback(
docs.as_str(),
@@ -285,7 +286,7 @@ impl DocCommentToken {
let original_start = doc_token.text_range().start();
let relative_comment_offset = offset - original_start - prefix_len;
- sema.descend_into_macros(doc_token).into_iter().find_map(|t| {
+ sema.descend_into_macros(doc_token, offset).into_iter().find_map(|t| {
let (node, descended_prefix_len) = match_ast! {
match t {
ast::Comment(comment) => (t.parent()?, TextSize::try_from(comment.prefix().len()).ok()?),
@@ -297,7 +298,7 @@ impl DocCommentToken {
let abs_in_expansion_offset = token_start + relative_comment_offset + descended_prefix_len;
let (attributes, def) = doc_attributes(sema, &node)?;
- let (docs, doc_mapping) = attributes.docs_with_rangemap(sema.db)?;
+ let (docs, doc_mapping) = docs_with_rangemap(sema.db, &attributes)?;
let (in_expansion_range, link, ns) =
extract_definitions_from_docs(&docs).into_iter().find_map(|(range, link, ns)| {
let mapped = doc_mapping.map(range)?;
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
index 05a64b33b..9ae70ae66 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
@@ -1,10 +1,11 @@
use std::ffi::OsStr;
use expect_test::{expect, Expect};
-use hir::{HasAttrs, Semantics};
+use hir::Semantics;
use ide_db::{
base_db::{FilePosition, FileRange},
defs::Definition,
+ documentation::{Documentation, HasDocs},
RootDatabase,
};
use itertools::Itertools;
@@ -78,7 +79,7 @@ fn check_doc_links(ra_fixture: &str) {
fn def_under_cursor(
sema: &Semantics<'_, RootDatabase>,
position: &FilePosition,
-) -> (Definition, hir::Documentation) {
+) -> (Definition, Documentation) {
let (docs, def) = sema
.parse(position.file_id)
.syntax()
@@ -96,7 +97,7 @@ fn def_under_cursor(
fn node_to_def(
sema: &Semantics<'_, RootDatabase>,
node: &SyntaxNode,
-) -> Option<Option<(Option<hir::Documentation>, Definition)>> {
+) -> Option<Option<(Option<Documentation>, Definition)>> {
Some(match_ast! {
match node {
ast::SourceFile(it) => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
@@ -518,6 +519,62 @@ fn function();
}
#[test]
+fn doc_links_field() {
+ check_doc_links(
+ r#"
+/// [`S::f`]
+/// [`S2::f`]
+/// [`T::0`]
+/// [`U::a`]
+/// [`E::A::f`]
+/// [`E::B::0`]
+struct S$0 {
+ f: i32,
+ //^ S::f
+ //^ S2::f
+}
+type S2 = S;
+struct T(i32);
+ //^^^ T::0
+union U {
+ a: i32,
+ //^ U::a
+}
+enum E {
+ A { f: i32 },
+ //^ E::A::f
+ B(i32),
+ //^^^ E::B::0
+}
+"#,
+ );
+}
+
+#[test]
+fn doc_links_field_via_self() {
+ check_doc_links(
+ r#"
+/// [`Self::f`]
+struct S$0 {
+ f: i32,
+ //^ Self::f
+}
+"#,
+ );
+}
+
+#[test]
+fn doc_links_tuple_field_via_self() {
+ check_doc_links(
+ r#"
+/// [`Self::0`]
+struct S$0(i32);
+ //^^^ Self::0
+"#,
+ );
+}
+
+#[test]
fn rewrite_html_root_url() {
check_rewrite(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index d6bbf2bf7..119a9c7c3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -40,28 +40,33 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
// struct Bar;
// ```
- let derive = sema.descend_into_macros(tok.clone()).into_iter().find_map(|descended| {
- let hir_file = sema.hir_file_for(&descended.parent()?);
- if !hir_file.is_derive_attr_pseudo_expansion(db) {
- return None;
- }
+ let derive =
+ sema.descend_into_macros(tok.clone(), 0.into()).into_iter().find_map(|descended| {
+ let hir_file = sema.hir_file_for(&descended.parent()?);
+ if !hir_file.is_derive_attr_pseudo_expansion(db) {
+ return None;
+ }
- let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string();
- // up map out of the #[derive] expansion
- let token = hir::InFile::new(hir_file, descended).upmap(db)?.value;
- let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
- let expansions = sema.expand_derive_macro(&attr)?;
- let idx = attr
- .token_tree()?
- .token_trees_and_tokens()
- .filter_map(NodeOrToken::into_token)
- .take_while(|it| it != &token)
- .filter(|it| it.kind() == T![,])
- .count();
- let expansion =
- format(db, SyntaxKind::MACRO_ITEMS, position.file_id, expansions.get(idx).cloned()?);
- Some(ExpandedMacro { name, expansion })
- });
+ let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string();
+ // up map out of the #[derive] expansion
+ let token = hir::InFile::new(hir_file, descended).upmap(db)?.value;
+ let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
+ let expansions = sema.expand_derive_macro(&attr)?;
+ let idx = attr
+ .token_tree()?
+ .token_trees_and_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .take_while(|it| it != &token)
+ .filter(|it| it.kind() == T![,])
+ .count();
+ let expansion = format(
+ db,
+ SyntaxKind::MACRO_ITEMS,
+ position.file_id,
+ expansions.get(idx).cloned()?,
+ );
+ Some(ExpandedMacro { name, expansion })
+ });
if derive.is_some() {
return derive;
diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
index f90618222..3d89599c5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
@@ -17,8 +17,6 @@ use crate::FileRange;
// Extends or shrinks the current selection to the encompassing syntactic construct
// (expression, statement, item, module, etc). It works with multiple cursors.
//
-// This is a standard LSP feature and not a protocol extension.
-//
// |===
// | Editor | Shortcut
//
@@ -142,8 +140,10 @@ fn extend_tokens_from_range(
// compute original mapped token range
let extended = {
- let fst_expanded = sema.descend_into_macros_single(first_token.clone());
- let lst_expanded = sema.descend_into_macros_single(last_token.clone());
+ let fst_expanded =
+ sema.descend_into_macros_single(first_token.clone(), original_range.start());
+ let lst_expanded =
+ sema.descend_into_macros_single(last_token.clone(), original_range.end());
let mut lca =
algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?;
lca = shallowest_node(&lca);
@@ -154,13 +154,16 @@ fn extend_tokens_from_range(
};
// Compute parent node range
- let validate = |token: &SyntaxToken| -> bool {
- let expanded = sema.descend_into_macros_single(token.clone());
- let parent = match expanded.parent() {
- Some(it) => it,
- None => return false,
- };
- algo::least_common_ancestor(&extended, &parent).as_ref() == Some(&extended)
+ let validate = |offset: TextSize| {
+ let extended = &extended;
+ move |token: &SyntaxToken| -> bool {
+ let expanded = sema.descend_into_macros_single(token.clone(), offset);
+ let parent = match expanded.parent() {
+ Some(it) => it,
+ None => return false,
+ };
+ algo::least_common_ancestor(extended, &parent).as_ref() == Some(extended)
+ }
};
// Find the first and last text range under expanded parent
@@ -168,14 +171,14 @@ fn extend_tokens_from_range(
let token = token.prev_token()?;
skip_trivia_token(token, Direction::Prev)
})
- .take_while(validate)
+ .take_while(validate(original_range.start()))
.last()?;
let last = successors(Some(last_token), |token| {
let token = token.next_token()?;
skip_trivia_token(token, Direction::Next)
})
- .take_while(validate)
+ .take_while(validate(original_range.end()))
.last()?;
let range = first.text_range().cover(last.text_range());
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
index c39c696cf..7e0fab426 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
@@ -20,16 +20,16 @@ use crate::{
// - fields in patterns will navigate to the field declaration of the struct, union or variant
pub(crate) fn goto_declaration(
db: &RootDatabase,
- position: FilePosition,
+ position @ FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = Semantics::new(db);
- let file = sema.parse(position.file_id).syntax().clone();
+ let file = sema.parse(file_id).syntax().clone();
let original_token = file
- .token_at_offset(position.offset)
+ .token_at_offset(offset)
.find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?;
let range = original_token.text_range();
let info: Vec<NavigationTarget> = sema
- .descend_into_macros(original_token)
+ .descend_into_macros(original_token, offset)
.iter()
.filter_map(|token| {
let parent = token.parent()?;
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 21471ab2a..e09b9f391 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -29,45 +29,39 @@ use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T};
// image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[]
pub(crate) fn goto_definition(
db: &RootDatabase,
- position: FilePosition,
+ FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = &Semantics::new(db);
- let file = sema.parse(position.file_id).syntax().clone();
- let original_token =
- pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
- IDENT
- | INT_NUMBER
- | LIFETIME_IDENT
- | T![self]
- | T![super]
- | T![crate]
- | T![Self]
- | COMMENT => 4,
- // index and prefix ops
- T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
- kind if kind.is_keyword() => 2,
- T!['('] | T![')'] => 2,
- kind if kind.is_trivia() => 0,
- _ => 1,
- })?;
+ let file = sema.parse(file_id).syntax().clone();
+ let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
+ IDENT
+ | INT_NUMBER
+ | LIFETIME_IDENT
+ | T![self]
+ | T![super]
+ | T![crate]
+ | T![Self]
+ | COMMENT => 4,
+ // index and prefix ops
+ T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
+ kind if kind.is_keyword() => 2,
+ T!['('] | T![')'] => 2,
+ kind if kind.is_trivia() => 0,
+ _ => 1,
+ })?;
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
- return doc_comment.get_definition_with_descend_at(
- sema,
- position.offset,
- |def, _, link_range| {
- let nav = def.try_to_nav(db)?;
- Some(RangeInfo::new(link_range, vec![nav]))
- },
- );
+ return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, link_range| {
+ let nav = def.try_to_nav(db)?;
+ Some(RangeInfo::new(link_range, vec![nav]))
+ });
}
let navs = sema
- .descend_into_macros(original_token.clone())
+ .descend_into_macros(original_token.clone(), offset)
.into_iter()
.filter_map(|token| {
let parent = token.parent()?;
if let Some(tt) = ast::TokenTree::cast(parent) {
- if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), position.file_id)
- {
+ if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), file_id) {
return Some(vec![x]);
}
}
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 37166bdbd..544c6b423 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
@@ -22,20 +22,19 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
// image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
pub(crate) fn goto_implementation(
db: &RootDatabase,
- position: FilePosition,
+ FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = Semantics::new(db);
- let source_file = sema.parse(position.file_id);
+ let source_file = sema.parse(file_id);
let syntax = source_file.syntax().clone();
- let original_token =
- pick_best_token(syntax.token_at_offset(position.offset), |kind| match kind {
- IDENT | T![self] | INT_NUMBER => 1,
- _ => 0,
- })?;
+ let original_token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
+ IDENT | T![self] | INT_NUMBER => 1,
+ _ => 0,
+ })?;
let range = original_token.text_range();
let navs =
- sema.descend_into_macros(original_token)
+ sema.descend_into_macros(original_token, offset)
.into_iter()
.filter_map(|token| token.parent().and_then(ast::NameLike::cast))
.filter_map(|node| match &node {
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 6048990f7..955923d76 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
@@ -16,13 +16,13 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
// image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[]
pub(crate) fn goto_type_definition(
db: &RootDatabase,
- position: FilePosition,
+ FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = hir::Semantics::new(db);
- let file: ast::SourceFile = sema.parse(position.file_id);
+ let file: ast::SourceFile = sema.parse(file_id);
let token: SyntaxToken =
- pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
+ pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
IDENT | INT_NUMBER | T![self] => 2,
kind if kind.is_trivia() => 0,
_ => 1,
@@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition(
}
};
let range = token.text_range();
- sema.descend_into_macros(token)
+ sema.descend_into_macros(token, offset)
.into_iter()
.filter_map(|token| {
let ty = sema
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 43e89a334..46a0464e9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -15,6 +15,7 @@ use syntax::{
SyntaxKind::{self, IDENT, INT_NUMBER},
SyntaxNode, SyntaxToken, TextRange, T,
};
+use text_edit::TextSize;
use crate::{navigation_target::ToNav, references, NavigationTarget, TryToNav};
@@ -51,7 +52,7 @@ pub struct HighlightRelatedConfig {
pub(crate) fn highlight_related(
sema: &Semantics<'_, RootDatabase>,
config: HighlightRelatedConfig,
- FilePosition { offset, file_id }: FilePosition,
+ pos @ FilePosition { offset, file_id }: FilePosition,
) -> Option<Vec<HighlightedRange>> {
let _p = profile::span("highlight_related");
let syntax = sema.parse(file_id).syntax().clone();
@@ -79,7 +80,7 @@ pub(crate) fn highlight_related(
}
T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
- _ if config.references => highlight_references(sema, &syntax, token, file_id),
+ _ if config.references => highlight_references(sema, &syntax, token, pos),
_ => None,
}
}
@@ -129,9 +130,9 @@ fn highlight_references(
sema: &Semantics<'_, RootDatabase>,
node: &SyntaxNode,
token: SyntaxToken,
- file_id: FileId,
+ FilePosition { file_id, offset }: FilePosition,
) -> Option<Vec<HighlightedRange>> {
- let defs = find_defs(sema, token.clone());
+ let defs = find_defs(sema, token.clone(), offset);
let usages = defs
.iter()
.filter_map(|&d| {
@@ -455,8 +456,12 @@ fn cover_range(r0: Option<TextRange>, r1: Option<TextRange>) -> Option<TextRange
}
}
-fn find_defs(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> FxHashSet<Definition> {
- sema.descend_into_macros(token)
+fn find_defs(
+ sema: &Semantics<'_, RootDatabase>,
+ token: SyntaxToken,
+ offset: TextSize,
+) -> FxHashSet<Definition> {
+ sema.descend_into_macros(token, offset)
.into_iter()
.filter_map(|token| IdentClass::classify_token(sema, &token))
.map(IdentClass::definitions_no_ops)
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 40659e6c2..21934b948 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -162,9 +162,9 @@ fn hover_simple(
// prefer descending the same token kind in attribute expansions, in normal macros text
// equivalency is more important
let descended = if in_attr {
- [sema.descend_into_macros_with_kind_preference(original_token.clone())].into()
+ [sema.descend_into_macros_with_kind_preference(original_token.clone(), offset)].into()
} else {
- sema.descend_into_macros_with_same_text(original_token.clone())
+ sema.descend_into_macros_with_same_text(original_token.clone(), offset)
};
let descended = || descended.iter();
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 a33a6ee18..f72ce37d1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -3,12 +3,13 @@ use std::fmt::Display;
use either::Either;
use hir::{
- Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasSource, HirDisplay, Layout,
- LayoutError, Semantics, TypeInfo,
+ Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasSource, HirDisplay, Layout, LayoutError,
+ Semantics, TypeInfo,
};
use ide_db::{
base_db::SourceDatabase,
defs::Definition,
+ documentation::{Documentation, HasDocs},
famous_defs::FamousDefs,
generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES},
syntax_helpers::insert_whitespace_into_node,
@@ -470,7 +471,7 @@ pub(super) fn definition(
Definition::SelfType(impl_def) => {
impl_def.self_ty(db).as_adt().map(|adt| label_and_docs(db, adt))?
}
- Definition::GenericParam(it) => label_and_docs(db, it),
+ Definition::GenericParam(it) => (it.display(db).to_string(), None),
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db).display(db))),
Definition::ExternCrateDecl(it) => label_and_docs(db, it),
// FIXME: We should be able to show more info about these
@@ -616,9 +617,9 @@ fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Mark
markup(Some(docs.replace('*', "\\*")), desc, None)
}
-fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<hir::Documentation>)
+fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<Documentation>)
where
- D: HasAttrs + HirDisplay,
+ D: HasDocs + HirDisplay,
{
let label = def.display(db).to_string();
let docs = def.docs(db);
@@ -631,9 +632,9 @@ fn label_and_layout_info_and_docs<D, E, E2>(
config: &HoverConfig,
layout_extractor: E,
layout_offset_extractor: E2,
-) -> (String, Option<hir::Documentation>)
+) -> (String, Option<Documentation>)
where
- D: HasAttrs + HirDisplay,
+ D: HasDocs + HirDisplay,
E: Fn(&D) -> Result<Layout, LayoutError>,
E2: Fn(&Layout) -> Option<u64>,
{
@@ -657,9 +658,9 @@ fn label_value_and_layout_info_and_docs<D, E, E2, E3, V>(
value_extractor: E,
layout_extractor: E2,
layout_tag_extractor: E3,
-) -> (String, Option<hir::Documentation>)
+) -> (String, Option<Documentation>)
where
- D: HasAttrs + HirDisplay,
+ D: HasDocs + HirDisplay,
E: Fn(&D) -> Option<V>,
E2: Fn(&D) -> Result<Layout, LayoutError>,
E3: Fn(&Layout) -> Option<usize>,
@@ -686,9 +687,9 @@ fn label_value_and_docs<D, E, V>(
db: &RootDatabase,
def: D,
value_extractor: E,
-) -> (String, Option<hir::Documentation>)
+) -> (String, Option<Documentation>)
where
- D: HasAttrs + HirDisplay,
+ D: HasDocs + HirDisplay,
E: Fn(&D) -> Option<V>,
V: Display,
{
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 ddc71dffa..81d6db564 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -1557,6 +1557,49 @@ fn test_hover_function_show_types() {
}
#[test]
+fn test_hover_function_associated_type_params() {
+ check(
+ r#"
+trait Foo { type Bar; }
+impl Foo for i32 { type Bar = i64; }
+fn foo(arg: <i32 as Foo>::Bar) {}
+fn main() { foo$0; }
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ fn foo(arg: <i32 as Foo>::Bar)
+ ```
+ "#]],
+ );
+
+ check(
+ r#"
+trait Foo<T> { type Bar<U>; }
+impl Foo<i64> for i32 { type Bar<U> = i32; }
+fn foo(arg: <<i32 as Foo<i64>>::Bar<i8> as Foo<i64>>::Bar<i8>) {}
+fn main() { foo$0; }
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ fn foo(arg: <<i32 as Foo<i64>>::Bar<i8> as Foo<i64>>::Bar<i8>)
+ ```
+ "#]],
+ );
+}
+
+#[test]
fn test_hover_function_pointer_show_identifiers() {
check(
r#"type foo$0 = fn(a: i32, b: i32) -> i32;"#,
@@ -3292,7 +3335,50 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
```
```rust
- struct ST<const C: usize, T = Foo>
+ struct ST<const C: usize = 1, T = Foo>
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn const_generic_default_value() {
+ check(
+ r#"
+struct Foo;
+struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
+"#,
+ expect![[r#"
+ *ST*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ struct ST<const C: usize = {const}, T = Foo>
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn const_generic_default_value_2() {
+ check(
+ r#"
+struct Foo;
+const VAL = 1;
+struct S$0T<const C: usize = VAL, T = Foo>(T);
+"#,
+ expect![[r#"
+ *ST*
+
+ ```rust
+ test
+ ```
+
+ ```rust
+ struct ST<const C: usize = VAL, T = Foo>
```
"#]],
);
@@ -6469,3 +6555,42 @@ fn test() {
"#]],
);
}
+
+#[test]
+fn generic_params_disabled_by_cfg() {
+ check(
+ r#"
+struct S<#[cfg(never)] T>;
+fn test() {
+ let s$0: S = S;
+}
+"#,
+ expect![[r#"
+ *s*
+
+ ```rust
+ let s: S // size = 0, align = 1
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn format_args_arg() {
+ check(
+ r#"
+//- minicore: fmt
+fn test() {
+ let foo = 0;
+ format_args!("{}", foo$0);
+}
+"#,
+ expect![[r#"
+ *foo*
+
+ ```rust
+ let foo: i32 // size = 4, align = 4
+ ```
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 292591674..a5d070fe7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -52,6 +52,28 @@ pub struct InlayHintsConfig {
pub closure_style: ClosureStyle,
pub max_length: Option<usize>,
pub closing_brace_hints_min_lines: Option<usize>,
+ pub fields_to_resolve: InlayFieldsToResolve,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct InlayFieldsToResolve {
+ pub resolve_text_edits: bool,
+ pub resolve_hint_tooltip: bool,
+ pub resolve_label_tooltip: bool,
+ pub resolve_label_location: bool,
+ pub resolve_label_command: bool,
+}
+
+impl InlayFieldsToResolve {
+ pub const fn empty() -> Self {
+ Self {
+ resolve_text_edits: false,
+ resolve_hint_tooltip: false,
+ resolve_label_tooltip: false,
+ resolve_label_location: false,
+ resolve_label_command: false,
+ }
+ }
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -123,11 +145,13 @@ pub struct InlayHint {
pub label: InlayHintLabel,
/// Text edit to apply when "accepting" this inlay hint.
pub text_edit: Option<TextEdit>,
+ pub needs_resolve: bool,
}
impl InlayHint {
fn closing_paren_after(kind: InlayKind, range: TextRange) -> InlayHint {
InlayHint {
+ needs_resolve: false,
range,
kind,
label: InlayHintLabel::from(")"),
@@ -139,6 +163,7 @@ impl InlayHint {
}
fn opening_paren_before(kind: InlayKind, range: TextRange) -> InlayHint {
InlayHint {
+ needs_resolve: false,
range,
kind,
label: InlayHintLabel::from("("),
@@ -196,6 +221,10 @@ impl InlayHintLabel {
}),
}
}
+
+ pub fn needs_resolve(&self) -> bool {
+ self.parts.iter().any(|part| part.linked_location.is_some() || part.tooltip.is_some())
+ }
}
impl From<String> for InlayHintLabel {
@@ -529,6 +558,7 @@ fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
#[cfg(test)]
mod tests {
+
use expect_test::Expect;
use hir::ClosureStyle;
use itertools::Itertools;
@@ -538,7 +568,7 @@ mod tests {
use crate::DiscriminantHints;
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
- use super::ClosureReturnTypeHints;
+ use super::{ClosureReturnTypeHints, InlayFieldsToResolve};
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
discriminant_hints: DiscriminantHints::Never,
@@ -559,6 +589,7 @@ mod tests {
param_names_for_lifetime_elision_hints: false,
max_length: None,
closing_brace_hints_min_lines: None,
+ fields_to_resolve: InlayFieldsToResolve::empty(),
};
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
type_hints: true,
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 6d6bd315e..631807d99 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
@@ -137,21 +137,23 @@ pub(super) fn hints(
}
_ => continue,
};
+ let label = InlayHintLabel::simple(
+ if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
+ Some(InlayTooltip::Markdown(format!(
+ "`{}` → `{}` ({coercion} coercion)",
+ source.display(sema.db),
+ target.display(sema.db),
+ ))),
+ None,
+ );
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve(),
range: expr.syntax().text_range(),
pad_left: false,
pad_right: false,
position: if postfix { InlayHintPosition::After } else { InlayHintPosition::Before },
kind: InlayKind::Adjustment,
- label: InlayHintLabel::simple(
- if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
- Some(InlayTooltip::Markdown(format!(
- "`{}` → `{}` ({coercion} coercion)",
- source.display(sema.db),
- target.display(sema.db),
- ))),
- None,
- ),
+ label,
text_edit: None,
});
}
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 07b9f9cc1..680035c72 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
@@ -99,6 +99,7 @@ pub(super) fn hints(
None => pat.syntax().text_range(),
};
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve() || text_edit.is_some(),
range: match type_ascriptable {
Some(Some(t)) => text_range.cover(t.text_range()),
_ => text_range,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
index 343cf17e5..35504ffa7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
@@ -50,9 +50,10 @@ pub(super) fn hints(
_ => return,
};
acc.push(InlayHint {
+ needs_resolve: false,
range,
kind: InlayKind::BindingMode,
- label: r.to_string().into(),
+ label: r.into(),
text_edit: None,
position: InlayHintPosition::Before,
pad_left: false,
@@ -68,9 +69,10 @@ pub(super) fn hints(
hir::BindingMode::Ref(Mutability::Shared) => "ref",
};
acc.push(InlayHint {
+ needs_resolve: false,
range: pat.syntax().text_range(),
kind: InlayKind::BindingMode,
- label: bm.to_string().into(),
+ label: bm.into(),
text_edit: None,
position: InlayHintPosition::Before,
pad_left: false,
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 b621a8dda..12e46c0f8 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
@@ -57,10 +57,12 @@ pub(super) fn hints(
}
}
}
+ let label = label_of_ty(famous_defs, config, &ty)?;
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve(),
range: expr.syntax().text_range(),
kind: InlayKind::Chaining,
- label: label_of_ty(famous_defs, config, &ty)?,
+ label,
text_edit: None,
position: InlayHintPosition::After,
pad_left: true,
@@ -128,6 +130,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 147..154,
@@ -152,6 +155,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
@@ -221,6 +225,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 143..179,
@@ -245,6 +250,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
@@ -298,6 +304,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 143..179,
@@ -322,6 +329,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
@@ -389,6 +397,7 @@ fn main() {
"<i32, bool>>",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 246..265,
@@ -426,6 +435,7 @@ fn main() {
"<i32, bool>>",
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
@@ -474,7 +484,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9289..9297,
+ range: 10739..10747,
},
),
tooltip: "",
@@ -487,7 +497,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9321..9325,
+ range: 10771..10775,
},
),
tooltip: "",
@@ -495,6 +505,7 @@ fn main() {
" = ()>",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 174..224,
@@ -511,7 +522,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9289..9297,
+ range: 10739..10747,
},
),
tooltip: "",
@@ -524,7 +535,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9321..9325,
+ range: 10771..10775,
},
),
tooltip: "",
@@ -532,6 +543,7 @@ fn main() {
" = ()>",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 174..206,
@@ -548,7 +560,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9289..9297,
+ range: 10739..10747,
},
),
tooltip: "",
@@ -561,7 +573,7 @@ fn main() {
file_id: FileId(
1,
),
- range: 9321..9325,
+ range: 10771..10775,
},
),
tooltip: "",
@@ -569,6 +581,7 @@ fn main() {
" = ()>",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 174..189,
@@ -593,6 +606,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
@@ -655,6 +669,7 @@ fn main() {
],
},
),
+ needs_resolve: true,
},
InlayHint {
range: 145..185,
@@ -679,6 +694,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 145..168,
@@ -703,6 +719,7 @@ fn main() {
"",
],
text_edit: None,
+ needs_resolve: true,
},
InlayHint {
range: 222..228,
@@ -725,6 +742,7 @@ fn main() {
},
],
text_edit: None,
+ needs_resolve: true,
},
]
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index 2cefd5acd..2b68538c1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -109,6 +109,7 @@ pub(super) fn hints(
let linked_location = name_range.map(|range| FileRange { file_id, range });
acc.push(InlayHint {
+ needs_resolve: linked_location.is_some(),
range: closing_token.text_range(),
kind: InlayKind::ClosingBrace,
label: InlayHintLabel::simple(label, None, linked_location),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
index 9d5defcbb..d691303c1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
@@ -31,9 +31,10 @@ pub(super) fn hints(
let range = closure.syntax().first_token()?.prev_token()?.text_range();
let range = TextRange::new(range.end() - TextSize::from(1), range.end());
acc.push(InlayHint {
+ needs_resolve: false,
range,
kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::simple("move", None, None),
+ label: InlayHintLabel::from("move"),
text_edit: None,
position: InlayHintPosition::After,
pad_left: false,
@@ -43,6 +44,7 @@ pub(super) fn hints(
}
};
acc.push(InlayHint {
+ needs_resolve: false,
range: move_kw_range,
kind: InlayKind::ClosureCapture,
label: InlayHintLabel::from("("),
@@ -59,23 +61,25 @@ pub(super) fn hints(
// force cache the source file, otherwise sema lookup will potentially panic
_ = sema.parse_or_expand(source.file());
+ let label = InlayHintLabel::simple(
+ format!(
+ "{}{}",
+ match capture.kind() {
+ hir::CaptureKind::SharedRef => "&",
+ hir::CaptureKind::UniqueSharedRef => "&unique ",
+ hir::CaptureKind::MutableRef => "&mut ",
+ hir::CaptureKind::Move => "",
+ },
+ capture.display_place(sema.db)
+ ),
+ None,
+ source.name().and_then(|name| name.syntax().original_file_range_opt(sema.db)),
+ );
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve(),
range: move_kw_range,
kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::simple(
- format!(
- "{}{}",
- match capture.kind() {
- hir::CaptureKind::SharedRef => "&",
- hir::CaptureKind::UniqueSharedRef => "&unique ",
- hir::CaptureKind::MutableRef => "&mut ",
- hir::CaptureKind::Move => "",
- },
- capture.display_place(sema.db)
- ),
- None,
- source.name().and_then(|name| name.syntax().original_file_range_opt(sema.db)),
- ),
+ label,
text_edit: None,
position: InlayHintPosition::After,
pad_left: false,
@@ -84,9 +88,10 @@ pub(super) fn hints(
if idx != last {
acc.push(InlayHint {
+ needs_resolve: false,
range: move_kw_range,
kind: InlayKind::ClosureCapture,
- label: InlayHintLabel::simple(", ", None, None),
+ label: InlayHintLabel::from(", "),
text_edit: None,
position: InlayHintPosition::After,
pad_left: false,
@@ -95,6 +100,7 @@ pub(super) fn hints(
}
}
acc.push(InlayHint {
+ needs_resolve: false,
range: move_kw_range,
kind: InlayKind::ClosureCapture,
label: InlayHintLabel::from(")"),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
index 3b41db0f1..204967cd7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
@@ -64,6 +64,7 @@ pub(super) fn hints(
};
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve() || text_edit.is_some(),
range: param_list.syntax().text_range(),
kind: InlayKind::Type,
label,
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 c4d2ac75c..26dc6fa8b 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
@@ -79,6 +79,7 @@ fn variant_hints(
None,
);
acc.push(InlayHint {
+ needs_resolve: label.needs_resolve(),
range: match eq_token {
Some(t) => range.cover(t.text_range()),
_ => range,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
index 5fce11b78..7b05e32ad 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
@@ -22,6 +22,7 @@ pub(super) fn hints(
}
let mk_lt_hint = |t: SyntaxToken, label: String| InlayHint {
+ needs_resolve: false,
range: t.text_range(),
kind: InlayKind::Lifetime,
label: label.into(),
@@ -185,6 +186,7 @@ pub(super) fn hints(
let angle_tok = gpl.l_angle_token()?;
let is_empty = gpl.generic_params().next().is_none();
acc.push(InlayHint {
+ needs_resolve: false,
range: angle_tok.text_range(),
kind: InlayKind::Lifetime,
label: format!(
@@ -200,6 +202,7 @@ pub(super) fn hints(
});
}
(None, allocated_lifetimes) => acc.push(InlayHint {
+ needs_resolve: false,
range: func.name()?.syntax().text_range(),
kind: InlayKind::GenericParamList,
label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
index fc297a8d8..f18e6421c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
@@ -31,9 +31,10 @@ pub(super) fn hints(
if ty.lifetime().is_none() {
let t = ty.amp_token()?;
acc.push(InlayHint {
+ needs_resolve: false,
range: t.text_range(),
kind: InlayKind::Lifetime,
- label: "'static".to_owned().into(),
+ label: "'static".into(),
text_edit: None,
position: InlayHintPosition::After,
pad_left: false,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
index c4f43f411..b4260d825 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
@@ -57,6 +57,7 @@ pub(super) fn hints(
let label =
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location);
InlayHint {
+ needs_resolve: label.needs_resolve(),
range,
kind: InlayKind::Parameter,
label,
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index bf77d55d5..aee03d218 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -91,9 +91,9 @@ pub use crate::{
MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
},
inlay_hints::{
- AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
- InlayHintLabel, InlayHintLabelPart, InlayHintPosition, InlayHintsConfig, InlayKind,
- InlayTooltip, LifetimeElisionHints,
+ AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
+ InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition,
+ InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
},
join_lines::JoinLinesConfig,
markup::Markup,
@@ -111,7 +111,7 @@ pub use crate::{
HighlightConfig, HlRange,
},
};
-pub use hir::{Documentation, Semantics};
+pub use hir::Semantics;
pub use ide_assists::{
Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy, SingleResolve,
};
@@ -124,6 +124,7 @@ pub use ide_db::{
Cancelled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange,
SourceRoot, SourceRootId,
},
+ documentation::Documentation,
label::Label,
line_index::{LineCol, LineIndex},
search::{ReferenceCategory, SearchScope},
@@ -484,7 +485,7 @@ impl Analysis {
sysroot: Option<&OsStr>,
) -> Cancellable<doc_links::DocumentationLinks> {
self.with_db(|db| {
- doc_links::external_docs(db, &position, target_dir, sysroot).unwrap_or_default()
+ doc_links::external_docs(db, position, target_dir, sysroot).unwrap_or_default()
})
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 17f3771b1..2ca2b5b1d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -99,7 +99,7 @@ pub(crate) fn moniker(
});
}
let navs = sema
- .descend_into_macros(original_token.clone())
+ .descend_into_macros(original_token.clone(), offset)
.into_iter()
.filter_map(|token| {
IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops).map(|it| {
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 d1479dd1e..32f211c6b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
@@ -4,14 +4,15 @@ use std::fmt;
use either::Either;
use hir::{
- symbols::FileSymbol, AssocItem, Documentation, FieldSource, HasAttrs, HasContainer, HasSource,
- HirDisplay, HirFileId, InFile, LocalSource, ModuleSource,
+ symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasSource, HirDisplay, HirFileId,
+ InFile, LocalSource, ModuleSource,
};
use ide_db::{
base_db::{FileId, FileRange},
- SymbolKind,
+ defs::Definition,
+ documentation::{Documentation, HasDocs},
+ RootDatabase, SymbolKind,
};
-use ide_db::{defs::Definition, RootDatabase};
use stdx::never;
use syntax::{
ast::{self, HasName},
@@ -175,8 +176,12 @@ impl TryToNav for FileSymbol {
Some(NavigationTarget {
file_id: full_range.file_id,
- name: if self.is_alias { self.def.name(db)?.to_smol_str() } else { self.name.clone() },
- alias: if self.is_alias { Some(self.name.clone()) } else { None },
+ name: self
+ .is_alias
+ .then(|| self.def.name(db))
+ .flatten()
+ .map_or_else(|| self.name.clone(), |it| it.to_smol_str()),
+ alias: self.is_alias.then(|| self.name.clone()),
kind: Some(hir::ModuleDefId::from(self.def).into()),
full_range: full_range.range,
focus_range,
@@ -323,7 +328,7 @@ impl ToNavFromAst for hir::TraitAlias {
impl<D> TryToNav for D
where
- D: HasSource + ToNavFromAst + Copy + HasAttrs + HirDisplay,
+ D: HasSource + ToNavFromAst + Copy + HasDocs + HirDisplay,
D::Ast: ast::HasName,
{
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 813f9ed94..2d0295692 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -126,7 +126,7 @@ pub(crate) fn find_defs<'a>(
)
});
token.map(|token| {
- sema.descend_into_macros_with_same_text(token)
+ sema.descend_into_macros_with_same_text(token, offset)
.into_iter()
.filter_map(|it| ast::NameLike::cast(it.parent()?))
.filter_map(move |name_like| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index dae8e71e8..ac9df5ed6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -2634,4 +2634,33 @@ use qux as frob;
// ",
// );
}
+
+ #[test]
+ fn disallow_renaming_for_non_local_definition() {
+ check(
+ "Baz",
+ r#"
+//- /lib.rs crate:lib new_source_root:library
+pub struct S;
+//- /main.rs crate:main deps:lib new_source_root:local
+use lib::S$0;
+"#,
+ "error: Cannot rename a non-local definition.",
+ );
+ }
+
+ #[test]
+ fn disallow_renaming_for_builtin_macros() {
+ check(
+ "Baz",
+ r#"
+//- minicore: derive, hash
+//- /main.rs crate:main
+use core::hash::Hash;
+#[derive(H$0ash)]
+struct A;
+ "#,
+ "error: Cannot rename a non-local definition.",
+ )
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 5f87a7855..2d528c642 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -7,6 +7,7 @@ use ide_assists::utils::test_related_attribute;
use ide_db::{
base_db::{FilePosition, FileRange},
defs::Definition,
+ documentation::docs_from_attrs,
helpers::visit_file_defs,
search::SearchScope,
FxHashMap, FxHashSet, RootDatabase, SymbolKind,
@@ -496,7 +497,7 @@ const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
&["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
- attrs.docs().map_or(false, |doc| {
+ docs_from_attrs(attrs).map_or(false, |doc| {
let mut in_code_block = false;
for line in String::from(doc).lines() {
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 7795be54e..e020b52e1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -4,12 +4,11 @@
use std::collections::BTreeSet;
use either::Either;
-use hir::{
- AssocItem, GenericParam, HasAttrs, HirDisplay, ModuleDef, PathResolution, Semantics, Trait,
-};
+use hir::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait};
use ide_db::{
active_parameter::{callable_for_node, generic_def_for_node},
base_db::FilePosition,
+ documentation::{Documentation, HasDocs},
FxIndexMap,
};
use stdx::format_to;
@@ -28,7 +27,7 @@ use crate::RootDatabase;
/// edited.
#[derive(Debug)]
pub struct SignatureHelp {
- pub doc: Option<String>,
+ pub doc: Option<Documentation>,
pub signature: String,
pub active_parameter: Option<usize>,
parameters: Vec<TextRange>,
@@ -67,17 +66,20 @@ impl SignatureHelp {
}
/// Computes parameter information for the given position.
-pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Option<SignatureHelp> {
+pub(crate) fn signature_help(
+ db: &RootDatabase,
+ FilePosition { file_id, offset }: FilePosition,
+) -> Option<SignatureHelp> {
let sema = Semantics::new(db);
- let file = sema.parse(position.file_id);
+ let file = sema.parse(file_id);
let file = file.syntax();
let token = file
- .token_at_offset(position.offset)
+ .token_at_offset(offset)
.left_biased()
// if the cursor is sandwiched between two space tokens and the call is unclosed
// this prevents us from leaving the CallExpression
.and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
- let token = sema.descend_into_macros_single(token);
+ let token = sema.descend_into_macros_single(token, offset);
for node in token.parent_ancestors() {
match_ast! {
@@ -176,7 +178,7 @@ fn signature_help_for_call(
let mut fn_params = None;
match callable.kind() {
hir::CallableKind::Function(func) => {
- res.doc = func.docs(db).map(|it| it.into());
+ res.doc = func.docs(db);
format_to!(res.signature, "fn {}", func.name(db).display(db));
fn_params = Some(match callable.receiver_param(db) {
Some(_self) => func.params_without_self(db),
@@ -184,11 +186,11 @@ fn signature_help_for_call(
});
}
hir::CallableKind::TupleStruct(strukt) => {
- res.doc = strukt.docs(db).map(|it| it.into());
+ res.doc = strukt.docs(db);
format_to!(res.signature, "struct {}", strukt.name(db).display(db));
}
hir::CallableKind::TupleEnumVariant(variant) => {
- res.doc = variant.docs(db).map(|it| it.into());
+ res.doc = variant.docs(db);
format_to!(
res.signature,
"enum {}::{}",
@@ -202,7 +204,7 @@ fn signature_help_for_call(
res.signature.push('(');
{
if let Some((self_param, _)) = callable.receiver_param(db) {
- format_to!(res.signature, "{}", self_param)
+ format_to!(res.signature, "{}", self_param.display(db))
}
let mut buf = String::new();
for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
@@ -262,38 +264,38 @@ fn signature_help_for_generics(
let db = sema.db;
match generics_def {
hir::GenericDef::Function(it) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "fn {}", it.name(db).display(db));
}
hir::GenericDef::Adt(hir::Adt::Enum(it)) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "enum {}", it.name(db).display(db));
}
hir::GenericDef::Adt(hir::Adt::Struct(it)) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "struct {}", it.name(db).display(db));
}
hir::GenericDef::Adt(hir::Adt::Union(it)) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "union {}", it.name(db).display(db));
}
hir::GenericDef::Trait(it) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "trait {}", it.name(db).display(db));
}
hir::GenericDef::TraitAlias(it) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "trait {}", it.name(db).display(db));
}
hir::GenericDef::TypeAlias(it) => {
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
format_to!(res.signature, "type {}", it.name(db).display(db));
}
hir::GenericDef::Variant(it) => {
// In paths, generics of an enum can be specified *after* one of its variants.
// eg. `None::<u8>`
// We'll use the signature of the enum, but include the docs of the variant.
- res.doc = it.docs(db).map(|it| it.into());
+ res.doc = it.docs(db);
let enum_ = it.parent_enum(db);
format_to!(res.signature, "enum {}", enum_.name(db).display(db));
generics_def = enum_.into();
@@ -1315,6 +1317,25 @@ id! {
}
#[test]
+ fn fn_signature_for_method_call_defined_in_macro() {
+ check(
+ r#"
+macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
+struct S;
+id! {
+ impl S {
+ fn foo<'a>(&'a mut self) {}
+ }
+}
+fn test() { S.foo($0); }
+"#,
+ expect![[r#"
+ fn foo(&'a mut self)
+ "#]],
+ );
+ }
+
+ #[test]
fn call_info_for_lambdas() {
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 d8696198d..aabd26da2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -12,6 +12,7 @@ use ide_db::{
};
use syntax::{AstNode, SyntaxKind::*, TextRange, T};
+use crate::inlay_hints::InlayFieldsToResolve;
use crate::{
hover::hover_for_definition,
inlay_hints::AdjustmentHintsMode,
@@ -125,6 +126,7 @@ impl StaticIndex<'_> {
max_length: Some(25),
closure_capture_hints: false,
closing_brace_hints_min_lines: Some(25),
+ fields_to_resolve: InlayFieldsToResolve::empty(),
},
file_id,
None,
diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs
index d2c77e2dc..c9ee460a1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/status.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/status.rs
@@ -66,6 +66,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
None => format!("{}", krate.into_raw()),
};
format_to!(buf, "Crate: {}\n", display_crate(krate));
+ format_to!(buf, "Enabled cfgs: {:?}\n", crate_graph[krate].cfg_options);
let deps = crate_graph[krate]
.dependencies
.iter()
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index ae9723640..bb01c81d6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -395,10 +395,10 @@ fn traverse(
NodeOrToken::Token(token) if token.kind() != COMMENT => {
let token = match attr_or_derive_item {
Some(AttrOrDerive::Attr(_)) => {
- sema.descend_into_macros_with_kind_preference(token)
+ sema.descend_into_macros_with_kind_preference(token, 0.into())
}
Some(AttrOrDerive::Derive(_)) | None => {
- sema.descend_into_macros_single(token)
+ sema.descend_into_macros_single(token, 0.into())
}
};
match token.parent().and_then(ast::NameLike::cast) {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
index 2ed57e201..2ef131594 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
@@ -17,6 +17,7 @@ pub(super) fn highlight_format_string(
return;
}
+ // FIXME: Replace this with the HIR info we have now.
lex_format_specifiers(string, &mut |piece_range, kind| {
if let Some(highlight) = highlight_format_specifier(kind) {
stack.add(HlRange {
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 8e96bfa01..7d00282fc 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
@@ -617,6 +617,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
CONST => SymbolKind::Const,
STATIC => SymbolKind::Static,
IDENT_PAT => SymbolKind::Local,
+ FORMAT_ARGS_ARG => SymbolKind::Local,
_ => return default.into(),
};
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 2657a6414..71f4d0724 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
@@ -5,8 +5,8 @@ use std::mem;
use either::Either;
use hir::{InFile, Semantics};
use ide_db::{
- active_parameter::ActiveParameter, base_db::FileId, defs::Definition, rust_doc::is_rust_fence,
- SymbolKind,
+ active_parameter::ActiveParameter, base_db::FileId, defs::Definition,
+ documentation::docs_with_rangemap, rust_doc::is_rust_fence, SymbolKind,
};
use syntax::{
ast::{self, AstNode, IsString, QuoteOffsets},
@@ -118,7 +118,7 @@ pub(super) fn doc_comment(
let src_file_id = src_file_id.into();
// Extract intra-doc links and emit highlights for them.
- if let Some((docs, doc_mapping)) = attributes.docs_with_rangemap(sema.db) {
+ if let Some((docs, doc_mapping)) = docs_with_rangemap(sema.db, &attributes) {
extract_definitions_from_docs(&docs)
.into_iter()
.filter_map(|(range, link, ns)| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 3ac8aa9cc..64e614cec 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -45,17 +45,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
</style>
<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
- <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span><span class="parenthesis">)</span>
<span class="brace">}</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">const_format_args</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">mod</span> <span class="module declaration">panic</span> <span class="brace">{</span>
@@ -75,7 +69,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_display<span class="parenthesis">(</span><span class="punctuation">&</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
<span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="colon">:</span>expr<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
- <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_fmt<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>const_format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
+ <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_fmt<span class="parenthesis">(</span>const_format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
<span class="brace">}</span>
<span class="brace">}</span>
@@ -92,7 +86,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
- <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -114,18 +108,18 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "Hello, world!"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "The number is 1"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "(3, 4)"</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "4"</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "4"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "1 2"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "0042" with leading zerosV</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "2 1 1 2"</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "test"</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="none macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "2 1"</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="none macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="none macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "a 3 b"</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "test"</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "2 1"</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "a 3 b"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// =&gt; "{2}"</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="none macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
@@ -140,10 +134,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="none macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="none macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="none macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span>
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span>
@@ -167,16 +161,24 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
<span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"mov eax, </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">concat</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
- <span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="none macro">format_args</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="none macro">toho</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more {}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{} asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
+ <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
+ <span class="macro unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+ <span class="string_literal macro">"mov {0}, {1}"</span><span class="comma macro">,</span>
+ <span class="string_literal macro">"add {0}, 5"</span><span class="comma macro">,</span>
+ <span class="none macro">out</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">o</span><span class="comma macro">,</span>
+ <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">i</span><span class="comma macro">,</span>
+ <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+
+ <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+ <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
<span class="brace">}</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 8749d355c..542d89925 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
@@ -401,19 +401,14 @@ fn test_string_highlighting() {
// thus, we have to copy the macro definition from `std`
check_highlighting(
r#"
+//- minicore: fmt
macro_rules! println {
($($arg:tt)*) => ({
- $crate::io::_print($crate::format_args_nl!($($arg)*));
+ $crate::io::_print(format_args_nl!($($arg)*));
})
}
#[rustc_builtin_macro]
#[macro_export]
-macro_rules! format_args {}
-#[rustc_builtin_macro]
-#[macro_export]
-macro_rules! const_format_args {}
-#[rustc_builtin_macro]
-#[macro_export]
macro_rules! format_args_nl {}
mod panic {
@@ -433,7 +428,7 @@ mod panic {
$crate::panicking::panic_display(&$arg)
),
($fmt:expr, $($arg:tt)+) => (
- $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
+ $crate::panicking::panic_fmt(const_format_args!($fmt, $($arg)+))
),
}
}
@@ -450,7 +445,7 @@ macro_rules! concat {}
macro_rules! toho {
() => ($crate::panic!("not yet implemented"));
- ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
+ ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", format_args!($($arg)+)));
}
fn main() {
@@ -534,7 +529,15 @@ fn main() {
assert!(true, "{}", 1);
assert!(true, "{} asdasd", 1);
toho!("{}fmt", 0);
- asm!("mov eax, {0}");
+ let i: u64 = 3;
+ let o: u64;
+ asm!(
+ "mov {0}, {1}",
+ "add {0}, 5",
+ out(reg) o,
+ in(reg) i,
+ );
+
format_args!(concat!("{}"), "{}");
format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash);
}"#,
diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs
index c7e403f6b..b40509715 100644
--- a/src/tools/rust-analyzer/crates/ide/src/typing.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs
@@ -32,7 +32,7 @@ use crate::SourceChange;
pub(crate) use on_enter::on_enter;
// Don't forget to add new trigger characters to `server_capabilities` in `caps.rs`.
-pub(crate) const TRIGGER_CHARS: &str = ".=<>{";
+pub(crate) const TRIGGER_CHARS: &str = ".=<>{(";
struct ExtendedTextEdit {
edit: TextEdit,
@@ -86,45 +86,57 @@ fn on_char_typed_inner(
if !stdx::always!(TRIGGER_CHARS.contains(char_typed)) {
return None;
}
- return match char_typed {
+ let conv = |text_edit: Option<TextEdit>| {
+ Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
+ };
+ match char_typed {
'.' => conv(on_dot_typed(&file.tree(), offset)),
'=' => conv(on_eq_typed(&file.tree(), offset)),
'<' => on_left_angle_typed(&file.tree(), offset),
'>' => conv(on_right_angle_typed(&file.tree(), offset)),
- '{' => conv(on_opening_brace_typed(file, offset)),
- _ => return None,
- };
-
- fn conv(text_edit: Option<TextEdit>) -> Option<ExtendedTextEdit> {
- Some(ExtendedTextEdit { edit: text_edit?, is_snippet: false })
+ '{' => conv(on_opening_bracket_typed(file, offset, '{')),
+ '(' => conv(on_opening_bracket_typed(file, offset, '(')),
+ _ => None,
}
}
-/// Inserts a closing `}` when the user types an opening `{`, wrapping an existing expression in a
-/// block, or a part of a `use` item.
-fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option<TextEdit> {
- if !stdx::always!(file.tree().syntax().text().char_at(offset) == Some('{')) {
+/// Inserts a closing bracket when the user types an opening bracket, wrapping an existing expression in a
+/// block, or a part of a `use` item (for `{`).
+fn on_opening_bracket_typed(
+ file: &Parse<SourceFile>,
+ offset: TextSize,
+ opening_bracket: char,
+) -> Option<TextEdit> {
+ let (closing_bracket, expected_ast_bracket) = match opening_bracket {
+ '{' => ('}', SyntaxKind::L_CURLY),
+ '(' => (')', SyntaxKind::L_PAREN),
+ _ => return None,
+ };
+
+ if !stdx::always!(file.tree().syntax().text().char_at(offset) == Some(opening_bracket)) {
return None;
}
let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?;
- if brace_token.kind() != SyntaxKind::L_CURLY {
+ if brace_token.kind() != expected_ast_bracket {
return None;
}
- // Remove the `{` to get a better parse tree, and reparse.
+ // Remove the opening bracket to get a better parse tree, and reparse.
let range = brace_token.text_range();
- if !stdx::always!(range.len() == TextSize::of('{')) {
+ if !stdx::always!(range.len() == TextSize::of(opening_bracket)) {
return None;
}
let file = file.reparse(&Indel::delete(range));
- if let Some(edit) = brace_expr(&file.tree(), offset) {
+ if let Some(edit) = bracket_expr(&file.tree(), offset, opening_bracket, closing_bracket) {
return Some(edit);
}
- if let Some(edit) = brace_use_path(&file.tree(), offset) {
- return Some(edit);
+ if closing_bracket == '}' {
+ if let Some(edit) = brace_use_path(&file.tree(), offset) {
+ return Some(edit);
+ }
}
return None;
@@ -143,7 +155,12 @@ fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option<
))
}
- fn brace_expr(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
+ fn bracket_expr(
+ file: &SourceFile,
+ offset: TextSize,
+ opening_bracket: char,
+ closing_bracket: char,
+ ) -> Option<TextEdit> {
let mut expr: ast::Expr = find_node_at_offset(file.syntax(), offset)?;
if expr.syntax().text_range().start() != offset {
return None;
@@ -166,10 +183,10 @@ fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option<
return None;
}
- // Insert `}` right after the expression.
+ // Insert the closing bracket right after the expression.
Some(TextEdit::insert(
- expr.syntax().text_range().end() + TextSize::of("{"),
- "}".to_string(),
+ expr.syntax().text_range().end() + TextSize::of(opening_bracket),
+ closing_bracket.to_string(),
))
}
}
@@ -938,6 +955,193 @@ use some::pa$0th::to::Item;
}
#[test]
+ fn adds_closing_parenthesis_for_expr() {
+ type_char(
+ '(',
+ r#"
+fn f() { match () { _ => $0() } }
+ "#,
+ r#"
+fn f() { match () { _ => (()) } }
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+fn f() { $0() }
+ "#,
+ r#"
+fn f() { (()) }
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+fn f() { let x = $0(); }
+ "#,
+ r#"
+fn f() { let x = (()); }
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+fn f() { let x = $0a.b(); }
+ "#,
+ r#"
+fn f() { let x = (a.b()); }
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+const S: () = $0();
+fn f() {}
+ "#,
+ r#"
+const S: () = (());
+fn f() {}
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+const S: () = $0a.b();
+fn f() {}
+ "#,
+ r#"
+const S: () = (a.b());
+fn f() {}
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+fn f() {
+ match x {
+ 0 => $0(),
+ 1 => (),
+ }
+}
+ "#,
+ r#"
+fn f() {
+ match x {
+ 0 => (()),
+ 1 => (),
+ }
+}
+ "#,
+ );
+ type_char(
+ '(',
+ r#"
+ fn f() {
+ let z = Some($03);
+ }
+ "#,
+ r#"
+ fn f() {
+ let z = Some((3));
+ }
+ "#,
+ );
+ }
+
+ #[test]
+ fn parenthesis_noop_in_string_literal() {
+ // Regression test for #9351
+ type_char_noop(
+ '(',
+ r##"
+fn check_with(ra_fixture: &str, expect: Expect) {
+ let base = r#"
+enum E { T(), R$0, C }
+use self::E::X;
+const Z: E = E::C;
+mod m {}
+asdasdasdasdasdasda
+sdasdasdasdasdasda
+sdasdasdasdasd
+"#;
+ let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
+ expect.assert_eq(&actual)
+}
+ "##,
+ );
+ }
+
+ #[test]
+ fn parenthesis_noop_in_item_position_with_macro() {
+ type_char_noop('(', r#"$0println!();"#);
+ type_char_noop(
+ '(',
+ r#"
+fn main() $0println!("hello");
+}"#,
+ );
+ }
+
+ #[test]
+ fn parenthesis_noop_in_use_tree() {
+ type_char_noop(
+ '(',
+ r#"
+use some::$0Path;
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use some::{Path, $0Other};
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use some::{$0Path, Other};
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use some::path::$0to::Item;
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use some::$0path::to::Item;
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use $0some::path::to::Item;
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use some::path::$0to::{Item};
+ "#,
+ );
+ type_char_noop(
+ '(',
+ r#"
+use $0Thing as _;
+ "#,
+ );
+
+ type_char_noop(
+ '(',
+ r#"
+use some::pa$0th::to::Item;
+ "#,
+ );
+ }
+
+ #[test]
fn adds_closing_angle_bracket_for_generic_args() {
type_char(
'<',