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

View File

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

@ -31,15 +31,15 @@ pub struct RawItems {
#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImportSourceMap {
map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>,
map: ArenaMap<ImportId, AstPtr<ast::UseTree>>,
}
impl ImportSourceMap {
fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) {
self.map.insert(import, AstPtr::new(segment))
fn insert(&mut self, import: ImportId, use_tree: &ast::UseTree) {
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 {
ModuleSource::SourceFile(file) => &*file,
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) {
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 {
path,
alias,
is_glob: segment.is_none(),
is_glob,
is_prelude,
is_extern_crate: false,
});
if let Some(segment) = segment {
self.source_map.insert(import, segment)
}
self.source_map.insert(import, use_tree);
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.
pub fn expand_use_item<'a>(
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() {
expand_use_tree(None, tree, &mut cb);
@ -156,7 +156,7 @@ impl From<Name> for Path {
fn expand_use_tree<'a>(
prefix: Option<Path>,
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() {
let prefix = match tree.path() {
@ -181,18 +181,15 @@ fn expand_use_tree<'a>(
if let Some(segment) = ast_path.segment() {
if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
if let Some(prefix) = prefix {
cb(prefix, Some(segment), alias);
cb(prefix, tree, false, alias);
return;
}
}
}
}
if let Some(path) = convert_path(prefix, ast_path) {
if tree.has_star() {
cb(path, None, alias)
} else if let Some(segment) = ast_path.segment() {
cb(path, Some(segment), alias)
};
let is_glob = tree.has_star();
cb(path, tree, is_glob, alias)
}
// FIXME: report errors somewhere
// We get here if we do

View File

@ -72,6 +72,18 @@ mod tests {
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]
fn completes_mod_with_docs() {
check_reference_completion(