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:
bors[bot] 2020-10-06 14:21:05 +00:00 committed by GitHub
commit 81d6816f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 65 additions and 46 deletions

View File

@ -1,13 +1,14 @@
//! `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 rustc_hash::FxHashMap;
use syntax::{
algo::SyntaxRewriter,
ast::{self, AstNode},
SyntaxNode,
};
use crate::utils::mod_path_to_ast;
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
SyntaxRewriter::from_fn(|element| match element {
syntax::SyntaxElement::Node(n) => {
@ -189,7 +190,7 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
match resolution {
PathResolution::Def(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
.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))
}

View File

@ -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!()}
}
}
"#,
)
}
}

View File

@ -13,7 +13,10 @@ use syntax::{
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
//
@ -54,7 +57,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
range,
|builder| {
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())
},
);

View File

@ -10,9 +10,10 @@ use syntax::{
};
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
//
@ -111,7 +112,8 @@ fn insert_import(
let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
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
builder.replace(syntax.text_range(), new_syntax.to_string())
}

View File

@ -7,7 +7,7 @@ use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
use test_utils::mark;
use crate::{
utils::{render_snippet, Cursor, FamousDefs},
utils::{mod_path_to_ast, render_snippet, Cursor, FamousDefs},
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> {
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
let pat: ast::Pat = match var.source(db).value.kind() {

View File

@ -19,6 +19,27 @@ use crate::assist_config::SnippetCap;
pub use insert_use::MergeBehaviour;
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 {
extract_trivial_expression(&block)
.filter(|expr| !expr.syntax().text().contains_char('\n'))

View File

@ -51,7 +51,7 @@ pub use hir_def::{
find_path::PrefixKind,
item_scope::ItemInNs,
nameres::ModuleSource,
path::ModPath,
path::{ModPath, PathKind},
type_ref::{Mutability, TypeRef},
};
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
// should remain private to hir internals.
#[allow(unused)]
use {
hir_def::path::{Path, PathKind},
hir_expand::hygiene::Hygiene,
};
use {hir_def::path::Path, hir_expand::hygiene::Hygiene};

View File

@ -13,7 +13,7 @@ use hir_expand::{
hygiene::Hygiene,
name::{AsName, Name},
};
use syntax::ast::{self, make};
use syntax::ast::{self};
use crate::{
type_ref::{TypeBound, TypeRef},
@ -100,26 +100,6 @@ impl ModPath {
}
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)]