mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Merge #6150
6150: Move ModPath->ast::Path function to IDE layer r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
81d6816f17
8 changed files with 65 additions and 46 deletions
|
@ -1,13 +1,14 @@
|
||||||
//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
|
//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
|
|
||||||
use hir::{HirDisplay, PathResolution, SemanticsScope};
|
use hir::{HirDisplay, PathResolution, SemanticsScope};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::SyntaxRewriter,
|
algo::SyntaxRewriter,
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::utils::mod_path_to_ast;
|
||||||
|
|
||||||
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
|
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
|
||||||
SyntaxRewriter::from_fn(|element| match element {
|
SyntaxRewriter::from_fn(|element| match element {
|
||||||
syntax::SyntaxElement::Node(n) => {
|
syntax::SyntaxElement::Node(n) => {
|
||||||
|
@ -189,7 +190,7 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
|
||||||
match resolution {
|
match resolution {
|
||||||
PathResolution::Def(def) => {
|
PathResolution::Def(def) => {
|
||||||
let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?;
|
let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?;
|
||||||
let mut path = path_to_ast(found_path);
|
let mut path = mod_path_to_ast(&found_path);
|
||||||
|
|
||||||
let type_args = p
|
let type_args = p
|
||||||
.segment()
|
.segment()
|
||||||
|
@ -210,13 +211,3 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
|
|
||||||
let parse = ast::SourceFile::parse(&path.to_string());
|
|
||||||
parse
|
|
||||||
.tree()
|
|
||||||
.syntax()
|
|
||||||
.descendants()
|
|
||||||
.find_map(ast::Path::cast)
|
|
||||||
.unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path))
|
|
||||||
}
|
|
||||||
|
|
|
@ -820,4 +820,29 @@ impl Tr for () {
|
||||||
}"#,
|
}"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn weird_path() {
|
||||||
|
check_assist(
|
||||||
|
add_missing_impl_members,
|
||||||
|
r#"
|
||||||
|
trait Test {
|
||||||
|
fn foo(&self, x: crate)
|
||||||
|
}
|
||||||
|
impl Test for () {
|
||||||
|
<|>
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
trait Test {
|
||||||
|
fn foo(&self, x: crate)
|
||||||
|
}
|
||||||
|
impl Test for () {
|
||||||
|
fn foo(&self, x: crate) {
|
||||||
|
${0:todo!()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,10 @@ use syntax::{
|
||||||
SyntaxNode,
|
SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{utils::insert_use, AssistContext, AssistId, AssistKind, Assists, GroupLabel};
|
use crate::{
|
||||||
|
utils::insert_use, utils::mod_path_to_ast, AssistContext, AssistId, AssistKind, Assists,
|
||||||
|
GroupLabel,
|
||||||
|
};
|
||||||
|
|
||||||
// Assist: auto_import
|
// Assist: auto_import
|
||||||
//
|
//
|
||||||
|
@ -54,7 +57,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
||||||
range,
|
range,
|
||||||
|builder| {
|
|builder| {
|
||||||
let new_syntax =
|
let new_syntax =
|
||||||
insert_use(&scope, import.to_ast_path(), ctx.config.insert_use.merge);
|
insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use.merge);
|
||||||
builder.replace(syntax.text_range(), new_syntax.to_string())
|
builder.replace(syntax.text_range(), new_syntax.to_string())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,9 +10,10 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assist_context::AssistBuilder, utils::insert_use, AssistContext, AssistId, AssistKind, Assists,
|
assist_context::AssistBuilder,
|
||||||
|
utils::{insert_use, mod_path_to_ast, ImportScope},
|
||||||
|
AssistContext, AssistId, AssistKind, Assists,
|
||||||
};
|
};
|
||||||
use insert_use::ImportScope;
|
|
||||||
|
|
||||||
// Assist: extract_struct_from_enum_variant
|
// Assist: extract_struct_from_enum_variant
|
||||||
//
|
//
|
||||||
|
@ -111,7 +112,8 @@ fn insert_import(
|
||||||
let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
|
let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
|
||||||
let syntax = scope.as_syntax_node();
|
let syntax = scope.as_syntax_node();
|
||||||
|
|
||||||
let new_syntax = insert_use(&scope, mod_path.to_ast_path(), ctx.config.insert_use.merge);
|
let new_syntax =
|
||||||
|
insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge);
|
||||||
// FIXME: this will currently panic as multiple imports will have overlapping text ranges
|
// FIXME: this will currently panic as multiple imports will have overlapping text ranges
|
||||||
builder.replace(syntax.text_range(), new_syntax.to_string())
|
builder.replace(syntax.text_range(), new_syntax.to_string())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
utils::{render_snippet, Cursor, FamousDefs},
|
utils::{mod_path_to_ast, render_snippet, Cursor, FamousDefs},
|
||||||
AssistContext, AssistId, AssistKind, Assists,
|
AssistContext, AssistId, AssistKind, Assists,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ fn resolve_tuple_of_enum_def(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> {
|
fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> {
|
||||||
let path = crate::ast_transform::path_to_ast(module.find_use_path(db, ModuleDef::from(var))?);
|
let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
|
||||||
|
|
||||||
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
|
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
|
||||||
let pat: ast::Pat = match var.source(db).value.kind() {
|
let pat: ast::Pat = match var.source(db).value.kind() {
|
||||||
|
|
|
@ -19,6 +19,27 @@ use crate::assist_config::SnippetCap;
|
||||||
pub use insert_use::MergeBehaviour;
|
pub use insert_use::MergeBehaviour;
|
||||||
pub(crate) use insert_use::{insert_use, ImportScope};
|
pub(crate) use insert_use::{insert_use, ImportScope};
|
||||||
|
|
||||||
|
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
|
||||||
|
let mut segments = Vec::new();
|
||||||
|
let mut is_abs = false;
|
||||||
|
match path.kind {
|
||||||
|
hir::PathKind::Plain => {}
|
||||||
|
hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
|
||||||
|
hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
|
||||||
|
hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
|
||||||
|
segments.push(make::path_segment_crate())
|
||||||
|
}
|
||||||
|
hir::PathKind::Abs => is_abs = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
segments.extend(
|
||||||
|
path.segments
|
||||||
|
.iter()
|
||||||
|
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
|
||||||
|
);
|
||||||
|
make::path_from_segments(segments, is_abs)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
|
pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
|
||||||
extract_trivial_expression(&block)
|
extract_trivial_expression(&block)
|
||||||
.filter(|expr| !expr.syntax().text().contains_char('\n'))
|
.filter(|expr| !expr.syntax().text().contains_char('\n'))
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub use hir_def::{
|
||||||
find_path::PrefixKind,
|
find_path::PrefixKind,
|
||||||
item_scope::ItemInNs,
|
item_scope::ItemInNs,
|
||||||
nameres::ModuleSource,
|
nameres::ModuleSource,
|
||||||
path::ModPath,
|
path::{ModPath, PathKind},
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
};
|
};
|
||||||
pub use hir_expand::{
|
pub use hir_expand::{
|
||||||
|
@ -63,7 +63,4 @@ pub use hir_ty::display::HirDisplay;
|
||||||
// These are negative re-exports: pub using these names is forbidden, they
|
// These are negative re-exports: pub using these names is forbidden, they
|
||||||
// should remain private to hir internals.
|
// should remain private to hir internals.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use {
|
use {hir_def::path::Path, hir_expand::hygiene::Hygiene};
|
||||||
hir_def::path::{Path, PathKind},
|
|
||||||
hir_expand::hygiene::Hygiene,
|
|
||||||
};
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use hir_expand::{
|
||||||
hygiene::Hygiene,
|
hygiene::Hygiene,
|
||||||
name::{AsName, Name},
|
name::{AsName, Name},
|
||||||
};
|
};
|
||||||
use syntax::ast::{self, make};
|
use syntax::ast::{self};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
|
@ -100,26 +100,6 @@ impl ModPath {
|
||||||
}
|
}
|
||||||
self.segments.first()
|
self.segments.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ast_path(&self) -> ast::Path {
|
|
||||||
let mut segments = Vec::new();
|
|
||||||
let mut is_abs = false;
|
|
||||||
match self.kind {
|
|
||||||
PathKind::Plain => {}
|
|
||||||
PathKind::Super(0) => segments.push(make::path_segment_self()),
|
|
||||||
PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
|
|
||||||
PathKind::Crate => segments.push(make::path_segment_crate()),
|
|
||||||
PathKind::Abs => is_abs = true,
|
|
||||||
PathKind::DollarCrate(_) => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
segments.extend(
|
|
||||||
self.segments
|
|
||||||
.iter()
|
|
||||||
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
|
|
||||||
);
|
|
||||||
make::path_from_segments(segments, is_abs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue