move Path

This commit is contained in:
Aleksey Kladov 2018-11-21 17:18:26 +03:00
parent 18000ba864
commit 5a87a24f82
3 changed files with 117 additions and 92 deletions

View File

@ -1,11 +1,12 @@
pub(crate) mod function;
pub(crate) mod module;
mod path;
use std::sync::Arc;
use ra_syntax::{
ast::{self, AstNode, FnDefNode},
TextRange, SmolStr,
ast::{self, FnDefNode},
TextRange,
};
use crate::{
@ -18,6 +19,8 @@
Cancelable,
};
pub(crate) use self::path::{Path, PathKind};
salsa::query_group! {
pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
@ -50,20 +53,6 @@ fn _submodules(source: ModuleSource) -> Cancelable<Arc<Vec<module::imp::Submodul
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Path {
kind: PathKind,
segments: Vec<SmolStr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PathKind {
Abs,
Self_,
Super,
Crate,
}
#[derive(Debug)]
pub struct ReferenceDescriptor {
pub range: TextRange,

View File

@ -195,86 +195,16 @@ fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
}
fn add_use_item(&mut self, item: ast::UseItem) {
if let Some(tree) = item.use_tree() {
self.add_use_tree(None, tree);
}
}
fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
if let Some(use_tree_list) = tree.use_tree_list() {
let prefix = match tree.path() {
None => prefix,
Some(path) => match convert_path(prefix, path) {
Some(it) => Some(it),
None => return, // TODO: report errors somewhere
},
Path::expand_use_item(item, |path, ptr| {
let kind = match ptr {
None => ImportKind::Glob,
Some(ptr) => ImportKind::Named(ptr),
};
for tree in use_tree_list.use_trees() {
self.add_use_tree(prefix.clone(), tree);
}
} else {
if let Some(ast_path) = tree.path() {
if let Some(path) = convert_path(prefix, ast_path) {
let kind = if tree.has_star() {
ImportKind::Glob
} else {
let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax());
ImportKind::Named(ptr)
};
self.imports.push(Import { kind, path })
}
}
}
self.imports.push(Import { kind, path })
})
}
}
fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
let prefix = if let Some(qual) = path.qualifier() {
Some(convert_path(prefix, qual)?)
} else {
None
};
let segment = path.segment()?;
let res = match segment.kind()? {
ast::PathSegmentKind::Name(name) => {
let mut res = prefix.unwrap_or_else(|| Path {
kind: PathKind::Abs,
segments: Vec::with_capacity(1),
});
res.segments.push(name.text());
res
}
ast::PathSegmentKind::CrateKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Crate,
segments: Vec::new(),
}
}
ast::PathSegmentKind::SelfKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Self_,
segments: Vec::new(),
}
}
ast::PathSegmentKind::SuperKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Super,
segments: Vec::new(),
}
}
};
Some(res)
}
impl ModuleItem {
fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
let name = item.name()?.text();

View File

@ -0,0 +1,106 @@
use ra_syntax::{SmolStr, ast, AstNode};
use crate::syntax_ptr::LocalSyntaxPtr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Path {
pub(crate) kind: PathKind,
pub(crate) segments: Vec<SmolStr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PathKind {
Abs,
Self_,
Super,
Crate,
}
impl Path {
pub(crate) fn expand_use_item(
item: ast::UseItem,
mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>),
) {
if let Some(tree) = item.use_tree() {
expand_use_tree(None, tree, &mut cb);
}
}
}
fn expand_use_tree(
prefix: Option<Path>,
tree: ast::UseTree,
cb: &mut impl FnMut(Path, Option<LocalSyntaxPtr>),
) {
if let Some(use_tree_list) = tree.use_tree_list() {
let prefix = match tree.path() {
None => prefix,
Some(path) => match convert_path(prefix, path) {
Some(it) => Some(it),
None => return, // TODO: report errors somewhere
},
};
for tree in use_tree_list.use_trees() {
expand_use_tree(prefix.clone(), tree, cb);
}
} else {
if let Some(ast_path) = tree.path() {
if let Some(path) = convert_path(prefix, ast_path) {
let ptr = if tree.has_star() {
None
} else {
let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax());
Some(ptr)
};
cb(path, ptr)
}
}
}
}
fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
let prefix = if let Some(qual) = path.qualifier() {
Some(convert_path(prefix, qual)?)
} else {
None
};
let segment = path.segment()?;
let res = match segment.kind()? {
ast::PathSegmentKind::Name(name) => {
let mut res = prefix.unwrap_or_else(|| Path {
kind: PathKind::Abs,
segments: Vec::with_capacity(1),
});
res.segments.push(name.text());
res
}
ast::PathSegmentKind::CrateKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Crate,
segments: Vec::new(),
}
}
ast::PathSegmentKind::SelfKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Self_,
segments: Vec::new(),
}
}
ast::PathSegmentKind::SuperKw => {
if prefix.is_some() {
return None;
}
Path {
kind: PathKind::Super,
segments: Vec::new(),
}
}
};
Some(res)
}