Skip to content

Commit 166c0ac

Browse files
bors[bot]Veykril
andauthored
Merge #10654
10654: internal: Refactor ide handling for paths in derive inputs r=Veykril a=Veykril Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2 parents f4ba64e + 3018ffd commit 166c0ac

File tree

15 files changed

+142
-77
lines changed

15 files changed

+142
-77
lines changed

crates/ide/src/doc_links.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod intra_doc_links;
44

55
use either::Either;
66
use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
7-
use pulldown_cmark_to_cmark::{cmark_with_options, Options as CmarkOptions};
7+
use pulldown_cmark_to_cmark::{cmark_with_options, Options as CMarkOptions};
88
use stdx::format_to;
99
use url::Url;
1010

@@ -65,7 +65,7 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Defin
6565
doc,
6666
&mut out,
6767
None,
68-
CmarkOptions { code_block_backticks: 3, ..Default::default() },
68+
CMarkOptions { code_block_backticks: 3, ..Default::default() },
6969
)
7070
.ok();
7171
out
@@ -103,7 +103,7 @@ pub(crate) fn remove_links(markdown: &str) -> String {
103103
doc,
104104
&mut out,
105105
None,
106-
CmarkOptions { code_block_backticks: 3, ..Default::default() },
106+
CMarkOptions { code_block_backticks: 3, ..Default::default() },
107107
)
108108
.ok();
109109
out

crates/ide/src/goto_definition.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,7 @@ impl Twait for Stwuct {
13711371
fn goto_def_derive_input() {
13721372
check(
13731373
r#"
1374+
//- minicore:derive
13741375
#[rustc_builtin_macro]
13751376
pub macro Copy {}
13761377
// ^^^^
@@ -1380,6 +1381,7 @@ struct Foo;
13801381
);
13811382
check(
13821383
r#"
1384+
//- minicore:derive
13831385
mod foo {
13841386
#[rustc_builtin_macro]
13851387
pub macro Copy {}

crates/ide/src/hover/tests.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,6 +3651,7 @@ use crate as foo$0;
36513651
fn hover_attribute_in_macro() {
36523652
check(
36533653
r#"
3654+
//- minicore:derive
36543655
macro_rules! identity {
36553656
($struct:item) => {
36563657
$struct
@@ -3681,6 +3682,7 @@ identity!{
36813682
fn hover_derive_input() {
36823683
check(
36833684
r#"
3685+
//- minicore:derive
36843686
#[rustc_builtin_macro]
36853687
pub macro Copy {}
36863688
#[derive(Copy$0)]
@@ -3700,6 +3702,7 @@ struct Foo;
37003702
);
37013703
check(
37023704
r#"
3705+
//- minicore:derive
37033706
mod foo {
37043707
#[rustc_builtin_macro]
37053708
pub macro Copy {}

crates/ide/src/static_index.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,10 @@ enum E { X(Foo) }
266266
fn derives() {
267267
check_all_ranges(
268268
r#"
269+
//- minicore:derive
269270
#[rustc_builtin_macro]
270271
pub macro Copy {}
271272
//^^^^
272-
#[rustc_builtin_macro]
273-
pub macro derive {}
274-
//^^^^^^
275273
#[derive(Copy)]
276274
//^^^^^^ ^^^^
277275
struct Hello(i32);

crates/ide/src/syntax_highlighting/highlight.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use hir::{AsAssocItem, HasVisibility, Semantics};
44
use ide_db::{
55
defs::{Definition, NameClass, NameRefClass},
6-
helpers::{try_resolve_derive_input_at, FamousDefs},
6+
helpers::{try_resolve_derive_input, FamousDefs},
77
RootDatabase, SymbolKind,
88
};
99
use rustc_hash::FxHashMap;
@@ -56,8 +56,8 @@ fn token(
5656
T![?] => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
5757
IDENT if parent_matches::<ast::TokenTree>(&token) => {
5858
if let Some(attr) = token.ancestors().nth(2).and_then(ast::Attr::cast) {
59-
match try_resolve_derive_input_at(sema, &attr, &token) {
60-
Some(makro) => highlight_def(sema, krate, Definition::Macro(makro)),
59+
match try_resolve_derive_input(sema, &attr, &ast::Ident::cast(token).unwrap()) {
60+
Some(res) => highlight_def(sema, krate, Definition::from(res)),
6161
None => HlTag::None.into(),
6262
}
6363
} else {

crates/ide/src/syntax_highlighting/test_data/highlighting.html

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@
4343
<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
4444
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
4545

46-
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
47-
<span class="keyword">macro</span> <span class="macro declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span>
48-
49-
<span class="comment">// Needed for function consuming vs normal</span>
50-
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">marker</span> <span class="brace">{</span>
51-
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">lang</span><span class="attribute attribute"> </span><span class="operator attribute">=</span><span class="attribute attribute"> </span><span class="string_literal attribute">"copy"</span><span class="attribute attribute">]</span>
52-
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">Copy</span> <span class="brace">{</span><span class="brace">}</span>
53-
<span class="brace">}</span>
54-
5546
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute">proc_macros</span><span class="operator attribute">::</span><span class="builtin_attr attribute">identity</span><span class="attribute attribute">]</span>
5647
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span>
5748
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span>
@@ -95,7 +86,7 @@
9586
<span class="brace">}</span>
9687
<span class="brace">}</span>
9788

98-
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">derive</span><span class="parenthesis attribute">(</span><span class="macro attribute">Copy</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
89+
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="macro attribute">derive</span><span class="parenthesis attribute">(</span><span class="macro attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute attribute">]</span>
9990
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
10091
<span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
10192
<span class="brace">}</span>
@@ -135,7 +126,7 @@
135126
<span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span>
136127
<span class="brace">}</span>
137128

138-
<span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="keyword">impl</span> <span class="macro">Copy</span> <span class="brace">{</span><span class="brace">}</span>
129+
<span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="keyword">impl</span> <span class="trait default_library library">Copy</span> <span class="brace">{</span><span class="brace">}</span>
139130

140131
<span class="keyword">fn</span> <span class="function declaration">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
141132
<span class="keyword">let</span> <span class="variable declaration">bar</span> <span class="operator">=</span> <span class="function">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>

crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,11 @@ fn test_highlighting() {
1111
check_highlighting(
1212
r#"
1313
//- proc_macros: identity, mirror
14+
//- minicore: derive, copy
1415
//- /main.rs crate:main deps:foo
1516
use inner::{self as inner_mod};
1617
mod inner {}
1718
18-
#[rustc_builtin_macro]
19-
macro Copy {}
20-
21-
// Needed for function consuming vs normal
22-
pub mod marker {
23-
#[lang = "copy"]
24-
pub trait Copy {}
25-
}
26-
2719
#[proc_macros::identity]
2820
pub mod ops {
2921
#[lang = "fn_once"]

crates/ide_assists/src/handlers/auto_import.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use ide_db::helpers::{
33
insert_use::{insert_use, ImportScope},
44
mod_path_to_ast,
55
};
6-
use syntax::{ast, AstNode, SyntaxNode};
6+
use syntax::{ast, AstNode, AstToken, SyntaxNode};
77

88
use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
99

@@ -128,9 +128,10 @@ pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets,
128128
.find_node_at_offset_with_descend::<ast::IdentPat>()
129129
.filter(ast::IdentPat::is_simple_ident)
130130
{
131-
ImportAssets::for_ident_pat(&pat, &ctx.sema).zip(Some(pat.syntax().clone()))
131+
ImportAssets::for_ident_pat(&ctx.sema, &pat).zip(Some(pat.syntax().clone()))
132132
} else {
133-
None
133+
let ident = ctx.find_token_at_offset()?;
134+
ImportAssets::for_derive_ident(&ctx.sema, &ident).zip(ident.syntax().parent())
134135
}
135136
}
136137

crates/ide_db/src/defs.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ use hir::{
1212
};
1313
use syntax::{
1414
ast::{self, AstNode},
15-
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
15+
match_ast, AstToken, SyntaxKind, SyntaxNode, SyntaxToken,
1616
};
1717

18-
use crate::{helpers::try_resolve_derive_input_at, RootDatabase};
18+
use crate::{helpers::try_resolve_derive_input, RootDatabase};
1919

2020
// FIXME: a more precise name would probably be `Symbol`?
2121
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
@@ -38,19 +38,20 @@ impl Definition {
3838
Some(parent) => parent,
3939
None => return Default::default(),
4040
};
41-
let attr = parent
42-
.ancestors()
43-
.find_map(ast::TokenTree::cast)
44-
.and_then(|tt| tt.parent_meta())
45-
.and_then(|meta| meta.parent_attr());
46-
if let Some(attr) = attr {
47-
try_resolve_derive_input_at(&sema, &attr, &token)
48-
.map(Definition::Macro)
49-
.into_iter()
50-
.collect()
51-
} else {
52-
Self::from_node(sema, &parent)
41+
if let Some(ident) = ast::Ident::cast(token.clone()) {
42+
let attr = parent
43+
.ancestors()
44+
.find_map(ast::TokenTree::cast)
45+
.and_then(|tt| tt.parent_meta())
46+
.and_then(|meta| meta.parent_attr());
47+
if let Some(attr) = attr {
48+
return try_resolve_derive_input(&sema, &attr, &ident)
49+
.map(Into::into)
50+
.into_iter()
51+
.collect();
52+
}
5353
}
54+
Self::from_node(sema, &parent)
5455
}
5556

5657
pub fn from_node(sema: &Semantics<RootDatabase>, node: &SyntaxNode) -> ArrayVec<Definition, 2> {

crates/ide_db/src/helpers.rs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ pub mod merge_imports;
77
pub mod node_ext;
88
pub mod rust_doc;
99

10-
use std::collections::VecDeque;
10+
use std::{collections::VecDeque, iter};
1111

1212
use base_db::FileId;
1313
use either::Either;
14-
use hir::{ItemInNs, MacroDef, ModuleDef, Name, Semantics};
14+
use hir::{ItemInNs, MacroDef, ModuleDef, Name, PathResolution, Semantics};
15+
use itertools::Itertools;
1516
use syntax::{
16-
ast::{self, make, HasLoopBody},
17-
AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent, T,
17+
ast::{self, make, HasLoopBody, Ident},
18+
AstNode, AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent,
19+
T,
1820
};
1921

2022
use crate::RootDatabase;
@@ -29,33 +31,59 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
2931
}
3032
}
3133

32-
/// Resolves the path at the cursor token as a derive macro if it inside a token tree of a derive attribute.
33-
pub fn try_resolve_derive_input_at(
34+
/// Parses and returns the derive path at the cursor position in the given attribute, if it is a derive.
35+
/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
36+
///
37+
/// The returned path is synthesized from TokenTree tokens and as such cannot be used with the [`Semantics`].
38+
pub fn get_path_in_derive_attr(
3439
sema: &hir::Semantics<RootDatabase>,
35-
derive_attr: &ast::Attr,
36-
cursor: &SyntaxToken,
37-
) -> Option<MacroDef> {
38-
use itertools::Itertools;
39-
if cursor.kind() != T![ident] {
40+
attr: &ast::Attr,
41+
cursor: &Ident,
42+
) -> Option<ast::Path> {
43+
let cursor = cursor.syntax();
44+
let path = attr.path()?;
45+
let tt = attr.token_tree()?;
46+
if !tt.syntax().text_range().contains_range(cursor.text_range()) {
4047
return None;
4148
}
42-
let tt = match derive_attr.as_simple_call() {
43-
Some((name, tt))
44-
if name == "derive" && tt.syntax().text_range().contains_range(cursor.text_range()) =>
45-
{
46-
tt
47-
}
48-
_ => return None,
49-
};
50-
let tokens: Vec<_> = cursor
49+
let scope = sema.scope(attr.syntax());
50+
let resolved_attr = sema.resolve_path(&path)?;
51+
let derive = FamousDefs(sema, scope.krate()).core_macros_builtin_derive()?;
52+
if PathResolution::Macro(derive) != resolved_attr {
53+
return None;
54+
}
55+
56+
let first = cursor
5157
.siblings_with_tokens(Direction::Prev)
52-
.flat_map(SyntaxElement::into_token)
58+
.filter_map(SyntaxElement::into_token)
5359
.take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
54-
.collect();
55-
let path = ast::Path::parse(&tokens.into_iter().rev().join("")).ok()?;
56-
sema.scope(tt.syntax())
57-
.speculative_resolve_as_mac(&path)
58-
.filter(|mac| mac.kind() == hir::MacroKind::Derive)
60+
.last()?;
61+
let path_tokens = first
62+
.siblings_with_tokens(Direction::Next)
63+
.filter_map(SyntaxElement::into_token)
64+
.take_while(|tok| tok != cursor);
65+
66+
ast::Path::parse(&path_tokens.chain(iter::once(cursor.clone())).join("")).ok()
67+
}
68+
69+
/// Parses and resolves the path at the cursor position in the given attribute, if it is a derive.
70+
/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
71+
pub fn try_resolve_derive_input(
72+
sema: &hir::Semantics<RootDatabase>,
73+
attr: &ast::Attr,
74+
cursor: &Ident,
75+
) -> Option<PathResolution> {
76+
let path = get_path_in_derive_attr(sema, attr, cursor)?;
77+
let scope = sema.scope(attr.syntax());
78+
// FIXME: This double resolve shouldn't be necessary
79+
// It's only here so we prefer macros over other namespaces
80+
match scope.speculative_resolve_as_mac(&path) {
81+
Some(mac) if mac.kind() == hir::MacroKind::Derive => Some(PathResolution::Macro(mac)),
82+
Some(_) => return None,
83+
None => scope
84+
.speculative_resolve(&path)
85+
.filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
86+
}
5987
}
6088

6189
/// Picks the token with the highest rank returned by the passed in function.

0 commit comments

Comments
 (0)