1092: always produce source for import r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-04-02 14:58:27 +00:00
commit 9e46400e0c
6 changed files with 70 additions and 29 deletions

View file

@ -4,7 +4,7 @@ use ra_db::{CrateId, SourceRootId, Edition};
use ra_syntax::{ast::self, TreeArc};
use crate::{
Name, ScopesWithSourceMap, Ty, HirFileId,
Name, ScopesWithSourceMap, Ty, HirFileId, ImportSource,
HirDatabase, DefDatabase,
type_ref::TypeRef,
nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
@ -117,7 +117,7 @@ impl Module {
}
/// 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)
}

View file

@ -5,7 +5,7 @@ use crate::{
Module, ModuleSource, Name, AstId,
nameres::{CrateModuleId, ImportId},
HirDatabase, DefDatabase,
HirFileId,
HirFileId, ImportSource,
};
impl ModuleSource {
@ -72,7 +72,7 @@ impl Module {
&self,
db: &impl HirDatabase,
import: ImportId,
) -> TreeArc<ast::UseTree> {
) -> ImportSource {
let (file_id, source) = self.definition_source(db);
let (_, source_map) = db.raw_items_with_source_map(file_id);
source_map.get(&source, import)

View file

@ -56,7 +56,7 @@ pub use self::{
name::Name,
source_id::{AstIdMap, ErasedFileAstId},
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
nameres::{PerNs, Namespace},
nameres::{PerNs, Namespace, ImportId, ImportSource},
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
impl_block::{ImplBlock, ImplItem},
docs::{Docs, Documentation},

View file

@ -70,9 +70,12 @@ use crate::{
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
#[derive(Debug, PartialEq, Eq)]

View file

@ -31,21 +31,43 @@ pub struct RawItems {
#[derive(Debug, Default, PartialEq, Eq)]
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 {
fn insert(&mut self, import: ImportId, use_tree: &ast::UseTree) {
self.map.insert(import, AstPtr::new(use_tree))
fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
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 {
ModuleSource::SourceFile(file) => &*file,
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");
Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
let import = self.raw_items.imports.alloc(ImportData {
path,
alias,
is_glob,
is_prelude,
is_extern_crate: false,
});
self.source_map.insert(import, use_tree);
self.push_item(current_module, RawItem::Import(import))
let import_data =
ImportData { path, alias, is_glob, is_prelude, is_extern_crate: false };
self.push_import(
current_module,
import_data,
ImportSourcePtr::UseTree(AstPtr::new(use_tree)),
);
})
}
@ -277,14 +297,18 @@ impl RawItemsCollector {
if let Some(name_ref) = extern_crate.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 import = self.raw_items.imports.alloc(ImportData {
let import_data = ImportData {
path,
alias,
is_glob: false,
is_prelude: false,
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));
}
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) {
match current_module {
Some(module) => match &mut self.raw_items.modules[module] {

View file

@ -19,11 +19,14 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
for (name, res) in module_scope.entries() {
if Some(module) == ctx.module {
if let Some(import) = res.import {
let path = module.import_source(ctx.db, import);
if path.syntax().range().contains_inclusive(ctx.offset) {
// for `use self::foo<|>`, don't suggest `foo` as a completion
tested_by!(dont_complete_current_use);
continue;
if let hir::ImportSource::UseTree(tree) =
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
tested_by!(dont_complete_current_use);
continue;
}
}
}
}