use relpaths for module resolve

This commit is contained in:
Aleksey Kladov 2018-12-18 17:22:48 +03:00
parent a422d480a1
commit cb6205c09d
4 changed files with 35 additions and 18 deletions

1
Cargo.lock generated
View file

@ -674,6 +674,7 @@ dependencies = [
name = "ra_hir"
version = "0.1.0"
dependencies = [
"arrayvec 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"id-arena 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -1,6 +1,7 @@
use std::sync::Arc;
use rustc_hash::{FxHashSet, FxHashMap};
use relative_path::RelativePathBuf;
use ra_syntax::SmolStr;
use salsa;
@ -85,10 +86,23 @@ salsa::query_group! {
type FileTextQuery;
storage input;
}
/// Path to a file, relative to the root of its source root.
fn file_relative_path(file_id: FileId) -> RelativePathBuf {
type FileRelativePathQuery;
storage input;
}
fn file_source_root(file_id: FileId) -> SourceRootId {
type FileSourceRootQuery;
storage input;
}
fn source_root_files(id: SourceRootId) -> Arc<FxHashSet<FileId>> {
type SourceRootFilesQuery;
storage input;
}
fn source_root_file_by_path(id: SourceRootId, path: RelativePathBuf) -> Option<FileId> {
type SourceRootFilesByPathQuery;
storage input;
}
fn source_root(id: SourceRootId) -> Arc<SourceRoot> {
type SourceRootQuery;
storage input;

View file

@ -5,6 +5,7 @@ version = "0.1.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
[dependencies]
arrayvec = "0.4.9"
log = "0.4.5"
relative-path = "0.4.0"
salsa = "0.8.0"

View file

@ -4,9 +4,9 @@ use ra_syntax::{
ast::{self, NameOwner},
SmolStr,
};
use relative_path::RelativePathBuf;
use rustc_hash::{FxHashMap, FxHashSet};
use ra_db::{SourceRoot, SourceRootId, FileResolverImp, Cancelable, FileId,};
use arrayvec::ArrayVec;
use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
use crate::{
HirDatabase,
@ -110,8 +110,7 @@ fn build_subtree(
let (points_to, problem) = match sub {
Submodule::Declaration(name) => {
let (points_to, problem) =
resolve_submodule(source, &name, &source_root.file_resolver);
let (points_to, problem) = resolve_submodule(db, source, &name);
let points_to = points_to
.into_iter()
.map(|file_id| match roots.remove(&file_id) {
@ -153,30 +152,32 @@ fn build_subtree(
}
fn resolve_submodule(
db: &impl HirDatabase,
source: ModuleSource,
name: &SmolStr,
file_resolver: &FileResolverImp,
) -> (Vec<FileId>, Option<Problem>) {
// TODO: handle submodules of inline modules properly
// FIXME: handle submodules of inline modules properly
let file_id = source.file_id();
let mod_name = file_resolver.file_stem(file_id);
let source_root_id = db.file_source_root(file_id);
let path = db.file_relative_path(file_id);
let dir_path = path.parent().unwrap();
let mod_name = path.file_stem().unwrap_or("unknown");
let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";
let file_mod = RelativePathBuf::from(format!("../{}.rs", name));
let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name));
let file_dir_mod = RelativePathBuf::from(format!("../{}/{}.rs", mod_name, name));
let tmp1;
let tmp2;
let candidates = if is_dir_owner {
tmp1 = [&file_mod, &dir_mod];
tmp1.iter()
let file_mod = dir_path.join(format!("{}.rs", name));
let dir_mod = dir_path.join(format!("{}/mod.rs", name));
let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
let mut candidates = ArrayVec::<[_; 2]>::new();
if is_dir_owner {
candidates.push(file_mod.clone());
candidates.push(dir_mod);
} else {
tmp2 = [&file_dir_mod];
tmp2.iter()
candidates.push(file_dir_mod.clone());
};
let points_to = candidates
.filter_map(|path| file_resolver.resolve(file_id, path))
.into_iter()
.filter_map(|path| db.source_root_file_by_path(source_root_id, path))
.collect::<Vec<_>>();
let problem = if points_to.is_empty() {
Some(Problem::UnresolvedModule {