mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-04 12:44:40 +00:00
move auto-imoprter into IDE
auto-import is purely an IDE concern, so it should be done outside of HIR
This commit is contained in:
parent
200032852b
commit
e01052d1f0
@ -492,7 +492,6 @@ fn apply_auto_import(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
|
||||
let mut ps = Vec::<SmolStr>::with_capacity(10);
|
||||
match path.kind {
|
||||
@ -503,7 +502,7 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
|
||||
hir::PathKind::Super => ps.push("super".into()),
|
||||
}
|
||||
for s in path.segments.iter() {
|
||||
ps.push(s.name.to_smolstr());
|
||||
ps.push(s.name.to_string().into());
|
||||
}
|
||||
ps
|
||||
}
|
||||
@ -511,7 +510,6 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
|
||||
// This function produces sequence of text edits into edit
|
||||
// to import the target path in the most appropriate scope given
|
||||
// the cursor position
|
||||
#[allow(unused)]
|
||||
pub fn auto_import_text_edit(
|
||||
// Ideally the position of the cursor, used to
|
||||
position: &SyntaxNode,
|
||||
|
@ -52,7 +52,7 @@ use crate::{
|
||||
db::{HirDatabase, DefDatabase},
|
||||
name::{AsName, KnownName},
|
||||
source_id::{FileAstId, AstId},
|
||||
resolve::Resolver, resolve::ImportResolver,
|
||||
resolve::Resolver,
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
|
@ -46,8 +46,17 @@ impl Name {
|
||||
Name::new(idx.to_string().into())
|
||||
}
|
||||
|
||||
pub fn to_smolstr(&self) -> SmolStr {
|
||||
self.text.clone()
|
||||
// There's should be no way to extract a string out of `Name`: `Name` in the
|
||||
// future, `Name` will include hygiene information, and you can't encode
|
||||
// hygiene into a String.
|
||||
//
|
||||
// If you need to compare something with `Name`, compare `Name`s directly.
|
||||
//
|
||||
// If you need to render `Name` for the user, use the `Display` impl, but be
|
||||
// aware that it strips hygiene info.
|
||||
#[deprecated(note = "use to_string instead")]
|
||||
pub fn as_smolstr(&self) -> &SmolStr {
|
||||
&self.text
|
||||
}
|
||||
|
||||
pub(crate) fn as_known_name(&self) -> Option<KnownName> {
|
||||
|
@ -23,12 +23,6 @@ pub(crate) struct Resolver {
|
||||
scopes: Vec<Scope>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct ImportResolver {
|
||||
// todo: use fst crate or something like that
|
||||
dummy_names: Vec<(SmolStr, Vec<SmolStr>)>,
|
||||
}
|
||||
|
||||
// FIXME how to store these best
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ModuleItemMap {
|
||||
@ -317,56 +311,3 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportResolver {
|
||||
pub(crate) fn new() -> Self {
|
||||
let dummy_names = vec![
|
||||
(SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]),
|
||||
(SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]),
|
||||
(SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]),
|
||||
(SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]),
|
||||
(
|
||||
SmolStr::new("Debug"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Display"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Hash"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Hasher"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Iterator"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")],
|
||||
),
|
||||
];
|
||||
|
||||
ImportResolver { dummy_names }
|
||||
}
|
||||
|
||||
// Returns a map of importable items filtered by name.
|
||||
// The map associates item name with its full path.
|
||||
// todo: should return Resolutions
|
||||
pub(crate) fn all_names(
|
||||
&self,
|
||||
_db: &impl HirDatabase,
|
||||
name: &Name,
|
||||
) -> FxHashMap<SmolStr, Vec<SmolStr>> {
|
||||
let name = name.to_smolstr();
|
||||
if name.len() > 1 {
|
||||
self.dummy_names
|
||||
.iter()
|
||||
.filter(|(n, _)| n.as_str().contains(name.as_str()))
|
||||
.cloned()
|
||||
.collect()
|
||||
} else {
|
||||
FxHashMap::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,11 @@ use ra_syntax::{
|
||||
ast::{self, AstNode, NameOwner},
|
||||
algo::find_node_at_offset,
|
||||
SyntaxKind::*,
|
||||
SmolStr,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name,
|
||||
AsName, Module, HirFileId, Crate, Trait, Resolver, Ty, ImportResolver,
|
||||
AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,
|
||||
expr::{BodySourceMap, scope::{ScopeId, ExprScopes}},
|
||||
ids::LocationCtx,
|
||||
expr, AstId,
|
||||
@ -171,7 +170,6 @@ fn def_with_body_from_child_node(
|
||||
#[derive(Debug)]
|
||||
pub struct SourceAnalyzer {
|
||||
resolver: Resolver,
|
||||
import_resolver: ImportResolver,
|
||||
body_source_map: Option<Arc<BodySourceMap>>,
|
||||
infer: Option<Arc<crate::ty::InferenceResult>>,
|
||||
scopes: Option<Arc<crate::expr::ExprScopes>>,
|
||||
@ -219,7 +217,6 @@ impl SourceAnalyzer {
|
||||
offset: Option<TextUnit>,
|
||||
) -> SourceAnalyzer {
|
||||
let def_with_body = def_with_body_from_child_node(db, file_id, node);
|
||||
let import_resolver = ImportResolver::new();
|
||||
if let Some(def) = def_with_body {
|
||||
let source_map = def.body_source_map(db);
|
||||
let scopes = db.expr_scopes(def);
|
||||
@ -230,7 +227,6 @@ impl SourceAnalyzer {
|
||||
let resolver = expr::resolver_for_scope(def.body(db), db, scope);
|
||||
SourceAnalyzer {
|
||||
resolver,
|
||||
import_resolver,
|
||||
body_source_map: Some(source_map),
|
||||
infer: Some(def.infer(db)),
|
||||
scopes: Some(scopes),
|
||||
@ -241,7 +237,6 @@ impl SourceAnalyzer {
|
||||
.ancestors()
|
||||
.find_map(|node| try_get_resolver_for_node(db, file_id, node))
|
||||
.unwrap_or_default(),
|
||||
import_resolver,
|
||||
body_source_map: None,
|
||||
infer: None,
|
||||
scopes: None,
|
||||
@ -328,14 +323,6 @@ impl SourceAnalyzer {
|
||||
self.resolver.all_names(db)
|
||||
}
|
||||
|
||||
pub fn all_import_names(
|
||||
&self,
|
||||
db: &impl HirDatabase,
|
||||
name: &Name,
|
||||
) -> FxHashMap<SmolStr, Vec<SmolStr>> {
|
||||
self.import_resolver.all_names(db, name)
|
||||
}
|
||||
|
||||
pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
|
||||
// FIXME: at least, this should work with any DefWithBody, but ideally
|
||||
// this should be hir-based altogether
|
||||
|
@ -1,6 +1,8 @@
|
||||
use rustc_hash::FxHashMap;
|
||||
use ra_text_edit::TextEditBuilder;
|
||||
use ra_syntax::SmolStr;
|
||||
use ra_assists::auto_import;
|
||||
|
||||
use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext};
|
||||
|
||||
pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
@ -10,7 +12,8 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
}
|
||||
|
||||
if let Some(name) = ctx.path_ident.as_ref() {
|
||||
let import_names = ctx.analyzer.all_import_names(ctx.db, name);
|
||||
let import_resolver = ImportResolver::new();
|
||||
let import_names = import_resolver.all_names(&name.to_string());
|
||||
import_names.into_iter().for_each(|(name, path)| {
|
||||
let edit = {
|
||||
let mut builder = TextEditBuilder::default();
|
||||
@ -64,6 +67,56 @@ fn fmt_import_path(path: &Vec<SmolStr>, buf: &mut String) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub(crate) struct ImportResolver {
|
||||
// todo: use fst crate or something like that
|
||||
dummy_names: Vec<(SmolStr, Vec<SmolStr>)>,
|
||||
}
|
||||
|
||||
impl ImportResolver {
|
||||
pub(crate) fn new() -> Self {
|
||||
let dummy_names = vec![
|
||||
(SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]),
|
||||
(SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]),
|
||||
(SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]),
|
||||
(SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]),
|
||||
(
|
||||
SmolStr::new("Debug"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Display"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Hash"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Hasher"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")],
|
||||
),
|
||||
(
|
||||
SmolStr::new("Iterator"),
|
||||
vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")],
|
||||
),
|
||||
];
|
||||
|
||||
ImportResolver { dummy_names }
|
||||
}
|
||||
|
||||
// Returns a map of importable items filtered by name.
|
||||
// The map associates item name with its full path.
|
||||
// todo: should return Resolutions
|
||||
pub(crate) fn all_names(&self, name: &str) -> FxHashMap<SmolStr, Vec<SmolStr>> {
|
||||
if name.len() > 1 {
|
||||
self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect()
|
||||
} else {
|
||||
FxHashMap::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::completion::{CompletionKind, check_completion};
|
||||
|
@ -86,18 +86,6 @@ impl<'a> CompletionContext<'a> {
|
||||
}
|
||||
|
||||
fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
|
||||
// We heed the original NameRef before the "intellijRulezz" hack
|
||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(original_file.syntax(), offset)
|
||||
{
|
||||
if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
|
||||
if let Some(path) = hir::Path::from_ast(path) {
|
||||
if let Some(ident) = path.as_ident() {
|
||||
self.path_ident = Some(ident.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a fake ident to get a valid parse tree. We will use this file
|
||||
// to determine context, though the original_file will be used for
|
||||
// actual completion.
|
||||
|
Loading…
Reference in New Issue
Block a user