From 69d07df201307fb7c539cdb20b8f1c1c12840386 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 24 Oct 2018 18:37:25 +0300 Subject: Complete crate:: paths --- crates/ra_analysis/src/completion.rs | 61 ++++++++++++++++++++++++++++++++++++ crates/ra_analysis/src/imp.rs | 22 ++++++++++++- crates/ra_analysis/src/lib.rs | 4 +-- crates/ra_analysis/src/roots.rs | 3 -- 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 crates/ra_analysis/src/completion.rs (limited to 'crates/ra_analysis/src') diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs new file mode 100644 index 000000000..a0fd6828d --- /dev/null +++ b/crates/ra_analysis/src/completion.rs @@ -0,0 +1,61 @@ +use ra_editor::{CompletionItem, find_node_at_offset, complete_module_items}; +use ra_syntax::{ + AtomEdit, File, TextUnit, AstNode, + ast::{self, ModuleItemOwner}, +}; + +use crate::{ + FileId, Cancelable, + db::{self, SyntaxDatabase}, + descriptors::module::{ModulesDatabase, ModuleTree, ModuleId}, +}; + +pub(crate) fn resolve_based_completion(db: &db::RootDatabase, file_id: FileId, offset: TextUnit) -> Cancelable>> { + let file = db.file_syntax(file_id); + let module_tree = db.module_tree()?; + let file = { + let edit = AtomEdit::insert(offset, "intellijRulezz".to_string()); + file.reparse(&edit) + }; + let target_file = match find_target_module(&module_tree, file_id, &file, offset) { + None => return Ok(None), + Some(target_module) => { + let file_id = target_module.file_id(&module_tree); + db.file_syntax(file_id) + } + }; + let mut res = Vec::new(); + complete_module_items(target_file.ast().items(), None, &mut res); + Ok(Some(res)) +} + +pub(crate) fn find_target_module(module_tree: &ModuleTree, file_id: FileId, file: &File, offset: TextUnit) -> Option { + let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?; + let mut crate_path = crate_path(name_ref)?; + let module_id = module_tree.any_module_for_file(file_id)?; + crate_path.pop(); + let mut target_module = module_id.root(&module_tree); + for name in crate_path { + target_module = target_module.child(module_tree, name.text().as_str())?; + } + Some(target_module) +} + +fn crate_path(name_ref: ast::NameRef) -> Option> { + let mut path = name_ref.syntax() + .parent().and_then(ast::PathSegment::cast)? + .parent_path(); + let mut res = Vec::new(); + loop { + let segment = path.segment()?; + match segment.kind()? { + ast::PathSegmentKind::Name(name) => res.push(name), + ast::PathSegmentKind::CrateKw => break, + ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => + return None, + } + path = path.qualifier()?; + } + res.reverse(); + Some(res) +} diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index f142b6c43..f3e5b2887 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -5,7 +5,7 @@ use std::{ sync::Arc, }; -use ra_editor::{self, find_node_at_offset, resolve_local_name, FileSymbol, LineIndex, LocalEdit}; +use ra_editor::{self, find_node_at_offset, resolve_local_name, FileSymbol, LineIndex, LocalEdit, CompletionItem}; use ra_syntax::{ ast::{self, ArgListOwner, Expr, NameOwner}, AstNode, File, SmolStr, @@ -197,6 +197,26 @@ impl AnalysisImpl { pub fn crate_root(&self, crate_id: CrateId) -> FileId { self.data.crate_graph.crate_roots[&crate_id] } + pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable>> { + let mut res = Vec::new(); + let mut has_completions = false; + let file = self.file_syntax(file_id); + if let Some(scope_based) = ra_editor::scope_completion(&file, offset) { + res.extend(scope_based); + has_completions = true; + } + let root = self.root(file_id); + if let Some(scope_based) = crate::completion::resolve_based_completion(root.db(), file_id, offset)? { + res.extend(scope_based); + has_completions = true; + } + let res = if has_completions { + Some(res) + } else { + None + }; + Ok(res) + } pub fn approximately_resolve_symbol( &self, file_id: FileId, diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 67a239a5c..7078e2d31 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -11,6 +11,7 @@ mod descriptors; mod imp; mod roots; mod symbol_index; +mod completion; use std::{fmt::Debug, sync::Arc}; @@ -246,8 +247,7 @@ impl Analysis { Ok(ra_editor::highlight(&file)) } pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Cancelable>> { - let file = self.imp.file_syntax(file_id); - Ok(ra_editor::scope_completion(&file, offset)) + self.imp.completions(file_id, offset) } pub fn assists(&self, file_id: FileId, range: TextRange) -> Cancelable> { Ok(self.imp.assists(file_id, range)) diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index aa0243720..1e9e613ac 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs @@ -1,7 +1,5 @@ use std::{sync::Arc}; -use ra_editor::LineIndex; -use ra_syntax::File; use rustc_hash::FxHashSet; use rayon::prelude::*; use salsa::Database; @@ -10,7 +8,6 @@ use crate::{ Cancelable, db::{self, FilesDatabase, SyntaxDatabase}, imp::FileResolverImp, - descriptors::module::{ModulesDatabase, ModuleTree}, symbol_index::SymbolIndex, FileId, }; -- cgit v1.2.3