mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
always produce source for import
This commit is contained in:
parent
0a758a2c48
commit
0de89f786f
6 changed files with 70 additions and 29 deletions
|
@ -4,7 +4,7 @@ use ra_db::{CrateId, SourceRootId, Edition};
|
||||||
use ra_syntax::{ast::self, TreeArc};
|
use ra_syntax::{ast::self, TreeArc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Name, ScopesWithSourceMap, Ty, HirFileId,
|
Name, ScopesWithSourceMap, Ty, HirFileId, ImportSource,
|
||||||
HirDatabase, DefDatabase,
|
HirDatabase, DefDatabase,
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
|
nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
|
||||||
|
@ -117,7 +117,7 @@ impl Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the syntax of the last path segment corresponding to this import
|
/// Returns the syntax of the last path segment corresponding to this import
|
||||||
pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> TreeArc<ast::UseTree> {
|
pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> ImportSource {
|
||||||
self.import_source_impl(db, import)
|
self.import_source_impl(db, import)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
Module, ModuleSource, Name, AstId,
|
Module, ModuleSource, Name, AstId,
|
||||||
nameres::{CrateModuleId, ImportId},
|
nameres::{CrateModuleId, ImportId},
|
||||||
HirDatabase, DefDatabase,
|
HirDatabase, DefDatabase,
|
||||||
HirFileId,
|
HirFileId, ImportSource,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ModuleSource {
|
impl ModuleSource {
|
||||||
|
@ -72,7 +72,7 @@ impl Module {
|
||||||
&self,
|
&self,
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
import: ImportId,
|
import: ImportId,
|
||||||
) -> TreeArc<ast::UseTree> {
|
) -> ImportSource {
|
||||||
let (file_id, source) = self.definition_source(db);
|
let (file_id, source) = self.definition_source(db);
|
||||||
let (_, source_map) = db.raw_items_with_source_map(file_id);
|
let (_, source_map) = db.raw_items_with_source_map(file_id);
|
||||||
source_map.get(&source, import)
|
source_map.get(&source, import)
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub use self::{
|
||||||
name::Name,
|
name::Name,
|
||||||
source_id::{AstIdMap, ErasedFileAstId},
|
source_id::{AstIdMap, ErasedFileAstId},
|
||||||
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
|
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
|
||||||
nameres::{PerNs, Namespace},
|
nameres::{PerNs, Namespace, ImportId, ImportSource},
|
||||||
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
|
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
|
||||||
impl_block::{ImplBlock, ImplItem},
|
impl_block::{ImplBlock, ImplItem},
|
||||||
docs::{Docs, Documentation},
|
docs::{Docs, Documentation},
|
||||||
|
|
|
@ -70,9 +70,12 @@ use crate::{
|
||||||
AstId,
|
AstId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
|
pub(crate) use self::raw::{RawItems, ImportSourceMap};
|
||||||
|
|
||||||
pub use self::per_ns::{PerNs, Namespace};
|
pub use self::{
|
||||||
|
per_ns::{PerNs, Namespace},
|
||||||
|
raw::{ImportId, ImportSource},
|
||||||
|
};
|
||||||
|
|
||||||
/// Contans all top-level defs from a macro-expanded crate
|
/// Contans all top-level defs from a macro-expanded crate
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
|
|
@ -31,21 +31,43 @@ pub struct RawItems {
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct ImportSourceMap {
|
pub struct ImportSourceMap {
|
||||||
map: ArenaMap<ImportId, AstPtr<ast::UseTree>>,
|
map: ArenaMap<ImportId, ImportSourcePtr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
enum ImportSourcePtr {
|
||||||
|
UseTree(AstPtr<ast::UseTree>),
|
||||||
|
ExternCrate(AstPtr<ast::ExternCrateItem>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImportSourcePtr {
|
||||||
|
fn to_node(self, file: &SourceFile) -> ImportSource {
|
||||||
|
match self {
|
||||||
|
ImportSourcePtr::UseTree(ptr) => ImportSource::UseTree(ptr.to_node(file).to_owned()),
|
||||||
|
ImportSourcePtr::ExternCrate(ptr) => {
|
||||||
|
ImportSource::ExternCrate(ptr.to_node(file).to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ImportSource {
|
||||||
|
UseTree(TreeArc<ast::UseTree>),
|
||||||
|
ExternCrate(TreeArc<ast::ExternCrateItem>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportSourceMap {
|
impl ImportSourceMap {
|
||||||
fn insert(&mut self, import: ImportId, use_tree: &ast::UseTree) {
|
fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
|
||||||
self.map.insert(import, AstPtr::new(use_tree))
|
self.map.insert(import, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::UseTree> {
|
pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
|
||||||
let file = match source {
|
let file = match source {
|
||||||
ModuleSource::SourceFile(file) => &*file,
|
ModuleSource::SourceFile(file) => &*file,
|
||||||
ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
|
ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.map[import].to_node(file).to_owned()
|
self.map[import].to_node(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,15 +279,13 @@ impl RawItemsCollector {
|
||||||
let is_prelude = use_item.has_atom_attr("prelude_import");
|
let is_prelude = use_item.has_atom_attr("prelude_import");
|
||||||
|
|
||||||
Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
|
Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
|
||||||
let import = self.raw_items.imports.alloc(ImportData {
|
let import_data =
|
||||||
path,
|
ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
|
||||||
alias,
|
self.push_import(
|
||||||
is_glob,
|
current_module,
|
||||||
is_prelude,
|
import_data,
|
||||||
is_extern_crate: false,
|
ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
|
||||||
});
|
);
|
||||||
self.source_map.insert(import, use_tree);
|
|
||||||
self.push_item(current_module, RawItem::Import(import))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,14 +297,18 @@ impl RawItemsCollector {
|
||||||
if let Some(name_ref) = extern_crate.name_ref() {
|
if let Some(name_ref) = extern_crate.name_ref() {
|
||||||
let path = Path::from_name_ref(name_ref);
|
let path = Path::from_name_ref(name_ref);
|
||||||
let alias = extern_crate.alias().and_then(|a| a.name()).map(AsName::as_name);
|
let alias = extern_crate.alias().and_then(|a| a.name()).map(AsName::as_name);
|
||||||
let import = self.raw_items.imports.alloc(ImportData {
|
let import_data = ImportData {
|
||||||
path,
|
path,
|
||||||
alias,
|
alias,
|
||||||
is_glob: false,
|
is_glob: false,
|
||||||
is_prelude: false,
|
is_prelude: false,
|
||||||
is_extern_crate: true,
|
is_extern_crate: true,
|
||||||
});
|
};
|
||||||
self.push_item(current_module, RawItem::Import(import))
|
self.push_import(
|
||||||
|
current_module,
|
||||||
|
import_data,
|
||||||
|
ImportSourcePtr::ExternCrate(AstPtr::new(extern_crate)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +325,17 @@ impl RawItemsCollector {
|
||||||
self.push_item(current_module, RawItem::Macro(m));
|
self.push_item(current_module, RawItem::Macro(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn push_import(
|
||||||
|
&mut self,
|
||||||
|
current_module: Option<Module>,
|
||||||
|
data: ImportData,
|
||||||
|
source: ImportSourcePtr,
|
||||||
|
) {
|
||||||
|
let import = self.raw_items.imports.alloc(data);
|
||||||
|
self.source_map.insert(import, source);
|
||||||
|
self.push_item(current_module, RawItem::Import(import))
|
||||||
|
}
|
||||||
|
|
||||||
fn push_item(&mut self, current_module: Option<Module>, item: RawItem) {
|
fn push_item(&mut self, current_module: Option<Module>, item: RawItem) {
|
||||||
match current_module {
|
match current_module {
|
||||||
Some(module) => match &mut self.raw_items.modules[module] {
|
Some(module) => match &mut self.raw_items.modules[module] {
|
||||||
|
|
|
@ -19,14 +19,17 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
for (name, res) in module_scope.entries() {
|
for (name, res) in module_scope.entries() {
|
||||||
if Some(module) == ctx.module {
|
if Some(module) == ctx.module {
|
||||||
if let Some(import) = res.import {
|
if let Some(import) = res.import {
|
||||||
let path = module.import_source(ctx.db, import);
|
if let hir::ImportSource::UseTree(tree) =
|
||||||
if path.syntax().range().contains_inclusive(ctx.offset) {
|
module.import_source(ctx.db, import)
|
||||||
|
{
|
||||||
|
if tree.syntax().range().contains_inclusive(ctx.offset) {
|
||||||
// for `use self::foo<|>`, don't suggest `foo` as a completion
|
// for `use self::foo<|>`, don't suggest `foo` as a completion
|
||||||
tested_by!(dont_complete_current_use);
|
tested_by!(dont_complete_current_use);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
acc.add_resolution(ctx, name.to_string(), &res.def.map(hir::Resolution::Def));
|
acc.add_resolution(ctx, name.to_string(), &res.def.map(hir::Resolution::Def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue