1089: fix a panic with glob-import missing a source map r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-04-02 10:26:43 +00:00
commit 2d680ff93a
5 changed files with 26 additions and 23 deletions

View File

@ -117,11 +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( pub fn import_source(&self, db: &impl HirDatabase, import: ImportId) -> TreeArc<ast::UseTree> {
&self,
db: &impl HirDatabase,
import: ImportId,
) -> TreeArc<ast::PathSegment> {
self.import_source_impl(db, import) self.import_source_impl(db, import)
} }

View File

@ -72,7 +72,7 @@ impl Module {
&self, &self,
db: &impl HirDatabase, db: &impl HirDatabase,
import: ImportId, import: ImportId,
) -> TreeArc<ast::PathSegment> { ) -> TreeArc<ast::UseTree> {
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)

View File

@ -31,15 +31,15 @@ pub struct RawItems {
#[derive(Debug, Default, PartialEq, Eq)] #[derive(Debug, Default, PartialEq, Eq)]
pub struct ImportSourceMap { pub struct ImportSourceMap {
map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, map: ArenaMap<ImportId, AstPtr<ast::UseTree>>,
} }
impl ImportSourceMap { impl ImportSourceMap {
fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { fn insert(&mut self, import: ImportId, use_tree: &ast::UseTree) {
self.map.insert(import, AstPtr::new(segment)) self.map.insert(import, AstPtr::new(use_tree))
} }
pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::UseTree> {
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(),
@ -256,17 +256,15 @@ impl RawItemsCollector {
fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) { fn add_use_item(&mut self, current_module: Option<Module>, use_item: &ast::UseItem) {
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, segment, alias| { Path::expand_use_item(use_item, |path, use_tree, is_glob, alias| {
let import = self.raw_items.imports.alloc(ImportData { let import = self.raw_items.imports.alloc(ImportData {
path, path,
alias, alias,
is_glob: segment.is_none(), is_glob,
is_prelude, is_prelude,
is_extern_crate: false, is_extern_crate: false,
}); });
if let Some(segment) = segment { self.source_map.insert(import, use_tree);
self.source_map.insert(import, segment)
}
self.push_item(current_module, RawItem::Import(import)) self.push_item(current_module, RawItem::Import(import))
}) })
} }

View File

@ -46,7 +46,7 @@ impl Path {
/// Calls `cb` with all paths, represented by this use item. /// Calls `cb` with all paths, represented by this use item.
pub fn expand_use_item<'a>( pub fn expand_use_item<'a>(
item: &'a ast::UseItem, item: &'a ast::UseItem,
mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), mut cb: impl FnMut(Path, &'a ast::UseTree, bool, Option<Name>),
) { ) {
if let Some(tree) = item.use_tree() { if let Some(tree) = item.use_tree() {
expand_use_tree(None, tree, &mut cb); expand_use_tree(None, tree, &mut cb);
@ -156,7 +156,7 @@ impl From<Name> for Path {
fn expand_use_tree<'a>( fn expand_use_tree<'a>(
prefix: Option<Path>, prefix: Option<Path>,
tree: &'a ast::UseTree, tree: &'a ast::UseTree,
cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), cb: &mut impl FnMut(Path, &'a ast::UseTree, bool, Option<Name>),
) { ) {
if let Some(use_tree_list) = tree.use_tree_list() { if let Some(use_tree_list) = tree.use_tree_list() {
let prefix = match tree.path() { let prefix = match tree.path() {
@ -181,18 +181,15 @@ fn expand_use_tree<'a>(
if let Some(segment) = ast_path.segment() { if let Some(segment) = ast_path.segment() {
if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
if let Some(prefix) = prefix { if let Some(prefix) = prefix {
cb(prefix, Some(segment), alias); cb(prefix, tree, false, alias);
return; return;
} }
} }
} }
} }
if let Some(path) = convert_path(prefix, ast_path) { if let Some(path) = convert_path(prefix, ast_path) {
if tree.has_star() { let is_glob = tree.has_star();
cb(path, None, alias) cb(path, tree, is_glob, alias)
} else if let Some(segment) = ast_path.segment() {
cb(path, Some(segment), alias)
};
} }
// FIXME: report errors somewhere // FIXME: report errors somewhere
// We get here if we do // We get here if we do

View File

@ -72,6 +72,18 @@ mod tests {
assert!(completions.is_empty()); assert!(completions.is_empty());
} }
#[test]
fn dont_complete_current_use_in_braces_with_glob() {
let completions = do_completion(
r"
mod foo { pub struct S; }
use self::{foo::*, bar<|>};
",
CompletionKind::Reference,
);
assert_eq!(completions.len(), 2);
}
#[test] #[test]
fn completes_mod_with_docs() { fn completes_mod_with_docs() {
check_reference_completion( check_reference_completion(