mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-31 17:12:53 +00:00
Refactor ide handling for paths in derive inputs
This commit is contained in:
parent
f4ba64ee2a
commit
3018ffd85e
@ -4,7 +4,7 @@ mod intra_doc_links;
|
|||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
|
use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
|
||||||
use pulldown_cmark_to_cmark::{cmark_with_options, Options as CmarkOptions};
|
use pulldown_cmark_to_cmark::{cmark_with_options, Options as CMarkOptions};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Defin
|
|||||||
doc,
|
doc,
|
||||||
&mut out,
|
&mut out,
|
||||||
None,
|
None,
|
||||||
CmarkOptions { code_block_backticks: 3, ..Default::default() },
|
CMarkOptions { code_block_backticks: 3, ..Default::default() },
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
out
|
out
|
||||||
@ -103,7 +103,7 @@ pub(crate) fn remove_links(markdown: &str) -> String {
|
|||||||
doc,
|
doc,
|
||||||
&mut out,
|
&mut out,
|
||||||
None,
|
None,
|
||||||
CmarkOptions { code_block_backticks: 3, ..Default::default() },
|
CMarkOptions { code_block_backticks: 3, ..Default::default() },
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
out
|
out
|
||||||
|
@ -1371,6 +1371,7 @@ impl Twait for Stwuct {
|
|||||||
fn goto_def_derive_input() {
|
fn goto_def_derive_input() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro Copy {}
|
||||||
// ^^^^
|
// ^^^^
|
||||||
@ -1380,6 +1381,7 @@ struct Foo;
|
|||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
mod foo {
|
mod foo {
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro Copy {}
|
||||||
|
@ -3651,6 +3651,7 @@ use crate as foo$0;
|
|||||||
fn hover_attribute_in_macro() {
|
fn hover_attribute_in_macro() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
macro_rules! identity {
|
macro_rules! identity {
|
||||||
($struct:item) => {
|
($struct:item) => {
|
||||||
$struct
|
$struct
|
||||||
@ -3681,6 +3682,7 @@ identity!{
|
|||||||
fn hover_derive_input() {
|
fn hover_derive_input() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro Copy {}
|
||||||
#[derive(Copy$0)]
|
#[derive(Copy$0)]
|
||||||
@ -3700,6 +3702,7 @@ struct Foo;
|
|||||||
);
|
);
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
mod foo {
|
mod foo {
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro Copy {}
|
||||||
|
@ -266,12 +266,10 @@ enum E { X(Foo) }
|
|||||||
fn derives() {
|
fn derives() {
|
||||||
check_all_ranges(
|
check_all_ranges(
|
||||||
r#"
|
r#"
|
||||||
|
//- minicore:derive
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro Copy {}
|
||||||
//^^^^
|
//^^^^
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro derive {}
|
|
||||||
//^^^^^^
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
//^^^^^^ ^^^^
|
//^^^^^^ ^^^^
|
||||||
struct Hello(i32);
|
struct Hello(i32);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use hir::{AsAssocItem, HasVisibility, Semantics};
|
use hir::{AsAssocItem, HasVisibility, Semantics};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
defs::{Definition, NameClass, NameRefClass},
|
defs::{Definition, NameClass, NameRefClass},
|
||||||
helpers::{try_resolve_derive_input_at, FamousDefs},
|
helpers::{try_resolve_derive_input, FamousDefs},
|
||||||
RootDatabase, SymbolKind,
|
RootDatabase, SymbolKind,
|
||||||
};
|
};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@ -56,8 +56,8 @@ fn token(
|
|||||||
T![?] => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
|
T![?] => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
|
||||||
IDENT if parent_matches::<ast::TokenTree>(&token) => {
|
IDENT if parent_matches::<ast::TokenTree>(&token) => {
|
||||||
if let Some(attr) = token.ancestors().nth(2).and_then(ast::Attr::cast) {
|
if let Some(attr) = token.ancestors().nth(2).and_then(ast::Attr::cast) {
|
||||||
match try_resolve_derive_input_at(sema, &attr, &token) {
|
match try_resolve_derive_input(sema, &attr, &ast::Ident::cast(token).unwrap()) {
|
||||||
Some(makro) => highlight_def(sema, krate, Definition::Macro(makro)),
|
Some(res) => highlight_def(sema, krate, Definition::from(res)),
|
||||||
None => HlTag::None.into(),
|
None => HlTag::None.into(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,15 +43,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||||||
<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>
|
<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>
|
||||||
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
|
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
|
||||||
|
|
||||||
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
|
|
||||||
<span class="keyword">macro</span> <span class="macro declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span>
|
|
||||||
|
|
||||||
<span class="comment">// Needed for function consuming vs normal</span>
|
|
||||||
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">marker</span> <span class="brace">{</span>
|
|
||||||
<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>
|
|
||||||
<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>
|
|
||||||
<span class="brace">}</span>
|
|
||||||
|
|
||||||
<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>
|
<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>
|
||||||
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span>
|
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span>
|
||||||
<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>
|
<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 @@ proc_macros::<span class="macro">mirror!</span> <span class="brace">{</span>
|
|||||||
<span class="brace">}</span>
|
<span class="brace">}</span>
|
||||||
<span class="brace">}</span>
|
<span class="brace">}</span>
|
||||||
|
|
||||||
<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>
|
<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>
|
||||||
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
|
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
|
||||||
<span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
|
<span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
|
||||||
<span class="brace">}</span>
|
<span class="brace">}</span>
|
||||||
@ -135,7 +126,7 @@ proc_macros::<span class="macro">mirror!</span> <span class="brace">{</span>
|
|||||||
<span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span>
|
<span class="value_param callable">f</span><span class="parenthesis">(</span><span class="parenthesis">)</span>
|
||||||
<span class="brace">}</span>
|
<span class="brace">}</span>
|
||||||
|
|
||||||
<span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="macro">Copy</span> <span class="brace">{</span><span class="brace">}</span>
|
<span class="keyword">fn</span> <span class="function declaration">foobar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="keyword">impl</span> <span class="trait default_library library">Copy</span> <span class="brace">{</span><span class="brace">}</span>
|
||||||
|
|
||||||
<span class="keyword">fn</span> <span class="function declaration">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
<span class="keyword">fn</span> <span class="function declaration">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
|
||||||
<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>
|
<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>
|
||||||
|
@ -11,19 +11,11 @@ fn test_highlighting() {
|
|||||||
check_highlighting(
|
check_highlighting(
|
||||||
r#"
|
r#"
|
||||||
//- proc_macros: identity, mirror
|
//- proc_macros: identity, mirror
|
||||||
|
//- minicore: derive, copy
|
||||||
//- /main.rs crate:main deps:foo
|
//- /main.rs crate:main deps:foo
|
||||||
use inner::{self as inner_mod};
|
use inner::{self as inner_mod};
|
||||||
mod inner {}
|
mod inner {}
|
||||||
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
macro Copy {}
|
|
||||||
|
|
||||||
// Needed for function consuming vs normal
|
|
||||||
pub mod marker {
|
|
||||||
#[lang = "copy"]
|
|
||||||
pub trait Copy {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macros::identity]
|
#[proc_macros::identity]
|
||||||
pub mod ops {
|
pub mod ops {
|
||||||
#[lang = "fn_once"]
|
#[lang = "fn_once"]
|
||||||
|
@ -3,7 +3,7 @@ use ide_db::helpers::{
|
|||||||
insert_use::{insert_use, ImportScope},
|
insert_use::{insert_use, ImportScope},
|
||||||
mod_path_to_ast,
|
mod_path_to_ast,
|
||||||
};
|
};
|
||||||
use syntax::{ast, AstNode, SyntaxNode};
|
use syntax::{ast, AstNode, AstToken, SyntaxNode};
|
||||||
|
|
||||||
use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
|
use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
|
||||||
|
|
||||||
@ -128,9 +128,10 @@ pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets,
|
|||||||
.find_node_at_offset_with_descend::<ast::IdentPat>()
|
.find_node_at_offset_with_descend::<ast::IdentPat>()
|
||||||
.filter(ast::IdentPat::is_simple_ident)
|
.filter(ast::IdentPat::is_simple_ident)
|
||||||
{
|
{
|
||||||
ImportAssets::for_ident_pat(&pat, &ctx.sema).zip(Some(pat.syntax().clone()))
|
ImportAssets::for_ident_pat(&ctx.sema, &pat).zip(Some(pat.syntax().clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
let ident = ctx.find_token_at_offset()?;
|
||||||
|
ImportAssets::for_derive_ident(&ctx.sema, &ident).zip(ident.syntax().parent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,10 +12,10 @@ use hir::{
|
|||||||
};
|
};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
|
match_ast, AstToken, SyntaxKind, SyntaxNode, SyntaxToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{helpers::try_resolve_derive_input_at, RootDatabase};
|
use crate::{helpers::try_resolve_derive_input, RootDatabase};
|
||||||
|
|
||||||
// FIXME: a more precise name would probably be `Symbol`?
|
// FIXME: a more precise name would probably be `Symbol`?
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||||
@ -38,19 +38,20 @@ impl Definition {
|
|||||||
Some(parent) => parent,
|
Some(parent) => parent,
|
||||||
None => return Default::default(),
|
None => return Default::default(),
|
||||||
};
|
};
|
||||||
let attr = parent
|
if let Some(ident) = ast::Ident::cast(token.clone()) {
|
||||||
.ancestors()
|
let attr = parent
|
||||||
.find_map(ast::TokenTree::cast)
|
.ancestors()
|
||||||
.and_then(|tt| tt.parent_meta())
|
.find_map(ast::TokenTree::cast)
|
||||||
.and_then(|meta| meta.parent_attr());
|
.and_then(|tt| tt.parent_meta())
|
||||||
if let Some(attr) = attr {
|
.and_then(|meta| meta.parent_attr());
|
||||||
try_resolve_derive_input_at(&sema, &attr, &token)
|
if let Some(attr) = attr {
|
||||||
.map(Definition::Macro)
|
return try_resolve_derive_input(&sema, &attr, &ident)
|
||||||
.into_iter()
|
.map(Into::into)
|
||||||
.collect()
|
.into_iter()
|
||||||
} else {
|
.collect();
|
||||||
Self::from_node(sema, &parent)
|
}
|
||||||
}
|
}
|
||||||
|
Self::from_node(sema, &parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_node(sema: &Semantics<RootDatabase>, node: &SyntaxNode) -> ArrayVec<Definition, 2> {
|
pub fn from_node(sema: &Semantics<RootDatabase>, node: &SyntaxNode) -> ArrayVec<Definition, 2> {
|
||||||
|
@ -7,14 +7,16 @@ pub mod merge_imports;
|
|||||||
pub mod node_ext;
|
pub mod node_ext;
|
||||||
pub mod rust_doc;
|
pub mod rust_doc;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::{collections::VecDeque, iter};
|
||||||
|
|
||||||
use base_db::FileId;
|
use base_db::FileId;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{ItemInNs, MacroDef, ModuleDef, Name, Semantics};
|
use hir::{ItemInNs, MacroDef, ModuleDef, Name, PathResolution, Semantics};
|
||||||
|
use itertools::Itertools;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, make, HasLoopBody},
|
ast::{self, make, HasLoopBody, Ident},
|
||||||
AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent, T,
|
AstNode, AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent,
|
||||||
|
T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::RootDatabase;
|
use crate::RootDatabase;
|
||||||
@ -29,33 +31,59 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the path at the cursor token as a derive macro if it inside a token tree of a derive attribute.
|
/// Parses and returns the derive path at the cursor position in the given attribute, if it is a derive.
|
||||||
pub fn try_resolve_derive_input_at(
|
/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
|
||||||
|
///
|
||||||
|
/// The returned path is synthesized from TokenTree tokens and as such cannot be used with the [`Semantics`].
|
||||||
|
pub fn get_path_in_derive_attr(
|
||||||
sema: &hir::Semantics<RootDatabase>,
|
sema: &hir::Semantics<RootDatabase>,
|
||||||
derive_attr: &ast::Attr,
|
attr: &ast::Attr,
|
||||||
cursor: &SyntaxToken,
|
cursor: &Ident,
|
||||||
) -> Option<MacroDef> {
|
) -> Option<ast::Path> {
|
||||||
use itertools::Itertools;
|
let cursor = cursor.syntax();
|
||||||
if cursor.kind() != T![ident] {
|
let path = attr.path()?;
|
||||||
|
let tt = attr.token_tree()?;
|
||||||
|
if !tt.syntax().text_range().contains_range(cursor.text_range()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let tt = match derive_attr.as_simple_call() {
|
let scope = sema.scope(attr.syntax());
|
||||||
Some((name, tt))
|
let resolved_attr = sema.resolve_path(&path)?;
|
||||||
if name == "derive" && tt.syntax().text_range().contains_range(cursor.text_range()) =>
|
let derive = FamousDefs(sema, scope.krate()).core_macros_builtin_derive()?;
|
||||||
{
|
if PathResolution::Macro(derive) != resolved_attr {
|
||||||
tt
|
return None;
|
||||||
}
|
}
|
||||||
_ => return None,
|
|
||||||
};
|
let first = cursor
|
||||||
let tokens: Vec<_> = cursor
|
|
||||||
.siblings_with_tokens(Direction::Prev)
|
.siblings_with_tokens(Direction::Prev)
|
||||||
.flat_map(SyntaxElement::into_token)
|
.filter_map(SyntaxElement::into_token)
|
||||||
.take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
|
.take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
|
||||||
.collect();
|
.last()?;
|
||||||
let path = ast::Path::parse(&tokens.into_iter().rev().join("")).ok()?;
|
let path_tokens = first
|
||||||
sema.scope(tt.syntax())
|
.siblings_with_tokens(Direction::Next)
|
||||||
.speculative_resolve_as_mac(&path)
|
.filter_map(SyntaxElement::into_token)
|
||||||
.filter(|mac| mac.kind() == hir::MacroKind::Derive)
|
.take_while(|tok| tok != cursor);
|
||||||
|
|
||||||
|
ast::Path::parse(&path_tokens.chain(iter::once(cursor.clone())).join("")).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses and resolves the path at the cursor position in the given attribute, if it is a derive.
|
||||||
|
/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
|
||||||
|
pub fn try_resolve_derive_input(
|
||||||
|
sema: &hir::Semantics<RootDatabase>,
|
||||||
|
attr: &ast::Attr,
|
||||||
|
cursor: &Ident,
|
||||||
|
) -> Option<PathResolution> {
|
||||||
|
let path = get_path_in_derive_attr(sema, attr, cursor)?;
|
||||||
|
let scope = sema.scope(attr.syntax());
|
||||||
|
// FIXME: This double resolve shouldn't be necessary
|
||||||
|
// It's only here so we prefer macros over other namespaces
|
||||||
|
match scope.speculative_resolve_as_mac(&path) {
|
||||||
|
Some(mac) if mac.kind() == hir::MacroKind::Derive => Some(PathResolution::Macro(mac)),
|
||||||
|
Some(_) => return None,
|
||||||
|
None => scope
|
||||||
|
.speculative_resolve(&path)
|
||||||
|
.filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Picks the token with the highest rank returned by the passed in function.
|
/// Picks the token with the highest rank returned by the passed in function.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//! See [`FamousDefs`].
|
//! See [`FamousDefs`].
|
||||||
use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
|
use hir::{Crate, Enum, MacroDef, Module, ScopeDef, Semantics, Trait};
|
||||||
|
|
||||||
use crate::RootDatabase;
|
use crate::RootDatabase;
|
||||||
|
|
||||||
@ -80,6 +80,10 @@ impl FamousDefs<'_, '_> {
|
|||||||
self.find_trait("core:marker:Copy")
|
self.find_trait("core:marker:Copy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn core_macros_builtin_derive(&self) -> Option<MacroDef> {
|
||||||
|
self.find_macro("core:macros:builtin:derive")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn alloc(&self) -> Option<Crate> {
|
pub fn alloc(&self) -> Option<Crate> {
|
||||||
self.find_crate("alloc")
|
self.find_crate("alloc")
|
||||||
}
|
}
|
||||||
@ -110,6 +114,13 @@ impl FamousDefs<'_, '_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_macro(&self, path: &str) -> Option<MacroDef> {
|
||||||
|
match self.find_def(path)? {
|
||||||
|
hir::ScopeDef::MacroDef(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn find_enum(&self, path: &str) -> Option<Enum> {
|
fn find_enum(&self, path: &str) -> Option<Enum> {
|
||||||
match self.find_def(path)? {
|
match self.find_def(path)? {
|
||||||
hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
|
hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
|
||||||
|
@ -8,10 +8,11 @@ use rustc_hash::FxHashSet;
|
|||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, HasName},
|
ast::{self, HasName},
|
||||||
utils::path_to_string_stripping_turbo_fish,
|
utils::path_to_string_stripping_turbo_fish,
|
||||||
AstNode, SyntaxNode,
|
AstNode, AstToken, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
helpers::get_path_in_derive_attr,
|
||||||
items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
|
items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
};
|
};
|
||||||
@ -119,7 +120,7 @@ impl ImportAssets {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_ident_pat(pat: &ast::IdentPat, sema: &Semantics<RootDatabase>) -> Option<Self> {
|
pub fn for_ident_pat(sema: &Semantics<RootDatabase>, pat: &ast::IdentPat) -> Option<Self> {
|
||||||
if !pat.is_simple_ident() {
|
if !pat.is_simple_ident() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -132,6 +133,22 @@ impl ImportAssets {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn for_derive_ident(sema: &Semantics<RootDatabase>, ident: &ast::Ident) -> Option<Self> {
|
||||||
|
let attr = ident.syntax().ancestors().find_map(ast::Attr::cast)?;
|
||||||
|
let path = get_path_in_derive_attr(sema, &attr, ident)?;
|
||||||
|
|
||||||
|
if let Some(_) = path.qualifier() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let name = NameToImport::Exact(path.segment()?.name_ref()?.to_string());
|
||||||
|
let candidate_node = attr.syntax().clone();
|
||||||
|
Some(Self {
|
||||||
|
import_candidate: ImportCandidate::Path(PathImportCandidate { qualifier: None, name }),
|
||||||
|
module_with_candidate: sema.scope(&candidate_node).module()?,
|
||||||
|
candidate_node,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn for_fuzzy_path(
|
pub fn for_fuzzy_path(
|
||||||
module_with_candidate: Module,
|
module_with_candidate: Module,
|
||||||
qualifier: Option<ast::Path>,
|
qualifier: Option<ast::Path>,
|
||||||
|
@ -673,7 +673,7 @@ pub(crate) fn location(
|
|||||||
Ok(loc)
|
Ok(loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perefer using `location_link`, if the client has the cap.
|
/// Prefer using `location_link`, if the client has the cap.
|
||||||
pub(crate) fn location_from_nav(
|
pub(crate) fn location_from_nav(
|
||||||
snap: &GlobalStateSnapshot,
|
snap: &GlobalStateSnapshot,
|
||||||
nav: NavigationTarget,
|
nav: NavigationTarget,
|
||||||
|
@ -131,3 +131,24 @@ impl AstToken for FloatNumber {
|
|||||||
}
|
}
|
||||||
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Ident {
|
||||||
|
pub(crate) syntax: SyntaxToken,
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for Ident {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(&self.syntax, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AstToken for Ident {
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
|
||||||
|
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||||
|
if Self::can_cast(syntax.kind()) {
|
||||||
|
Some(Self { syntax })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||||
|
}
|
||||||
|
@ -560,7 +560,7 @@ impl Field {
|
|||||||
|
|
||||||
fn lower(grammar: &Grammar) -> AstSrc {
|
fn lower(grammar: &Grammar) -> AstSrc {
|
||||||
let mut res = AstSrc {
|
let mut res = AstSrc {
|
||||||
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber"
|
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Ident"
|
||||||
.split_ascii_whitespace()
|
.split_ascii_whitespace()
|
||||||
.map(|it| it.to_string())
|
.map(|it| it.to_string())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
Loading…
Reference in New Issue
Block a user