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 function;
pub(crate) mod module; pub(crate) mod module;
mod path;
use std::sync::Arc; use std::sync::Arc;
use ra_syntax::{ use ra_syntax::{
ast::{self, AstNode, FnDefNode}, ast::{self, FnDefNode},
TextRange, SmolStr, TextRange,
}; };
use crate::{ use crate::{
@ -18,6 +19,8 @@ use crate::{
Cancelable, Cancelable,
}; };
pub(crate) use self::path::{Path, PathKind};
salsa::query_group! { salsa::query_group! {
pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> {
@ -50,20 +53,6 @@ salsa::query_group! {
} }
} }
#[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)] #[derive(Debug)]
pub struct ReferenceDescriptor { pub struct ReferenceDescriptor {
pub range: TextRange, pub range: TextRange,

View file

@ -195,85 +195,15 @@ impl InputModuleItems {
} }
fn add_use_item(&mut self, item: ast::UseItem) { fn add_use_item(&mut self, item: ast::UseItem) {
if let Some(tree) = item.use_tree() { Path::expand_use_item(item, |path, ptr| {
self.add_use_tree(None, tree); let kind = match ptr {
} None => ImportKind::Glob,
} Some(ptr) => ImportKind::Named(ptr),
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
},
};
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 { impl ModuleItem {
fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {

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)
}