Skip to content

Commit

Permalink
Merge pull request #1107 from rbartlensky/fix-rust2018-submodule-search
Browse files Browse the repository at this point in the history
Fix #1052.
  • Loading branch information
kngwyu committed Apr 19, 2020
2 parents e19e851 + 5176a63 commit 218682d
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 41 deletions.
108 changes: 67 additions & 41 deletions src/racer/matchers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,48 +352,74 @@ pub fn match_mod(
});
} else {
debug!("found a module declaration: |{}|", blob);

// the name of the file where we found the module declaration (foo.rs)
// without its extension!
let filename = context.filepath.file_stem()?;
let parent_path = context.filepath.parent()?;
let ranged_raw = session.load_raw_src_ranged(&msrc, context.filepath);
// get module from path attribute
if let Some(modpath) =
scopes::get_module_file_from_path(msrc, context.range.start, parent_path, ranged_raw)
{
let doc_src = session.load_raw_file(&modpath);
return Some(Match {
matchstr: s,
filepath: modpath.to_path_buf(),
point: BytePos::ZERO,
coords: Some(Coordinate::start()),
local: false,
mtype: Module,
contextstr: modpath.to_str().unwrap().to_owned(),
docs: find_mod_doc(&doc_src, BytePos::ZERO),
});
}
// get internal module nesting
// e.g. is this in an inline submodule? mod foo{ mod bar; }
// because if it is then we need to search further down the
// directory hierarchy - e.g. <cwd>/foo/bar.rs
let internalpath = scopes::get_local_module_path(msrc, context.range.start);
let mut searchdir = parent_path.to_owned();
for s in internalpath {
searchdir.push(&s);
}
if let Some(modpath) = get_module_file(&s, &searchdir, session) {
let doc_src = session.load_raw_file(&modpath);
let context = modpath.to_str().unwrap().to_owned();
return Some(Match {
matchstr: s,
filepath: modpath,
point: BytePos::ZERO,
coords: Some(Coordinate::start()),
local: false,
mtype: Module,
contextstr: context,
docs: find_mod_doc(&doc_src, BytePos::ZERO),
});
}
// if we found the declaration in `src/foo.rs`, then let's look for the
// submodule in `src/foo/` as well!
let filename_subdir = parent_path.join(filename);
// if we are looking for "foo::bar", we have two cases:
// 1. we found `pub mod bar;` in either `src/foo/mod.rs`
// (or `src/lib.rs`). As such we are going to search for `bar.rs` in
// the same directory (`src/foo/`, or `src/` respectively).
// 2. we found `pub mod bar;` in `src/foo.rs`. This means that we also
// need to seach in `src/foo/` if it exists!
let search_path = if filename_subdir.exists() {
filename_subdir.as_path()
} else {
parent_path
};
match_mod_inner(msrc, context, session, search_path, s)
}
}

fn match_mod_inner(
msrc: Src<'_>,
context: &MatchCxt<'_, '_>,
session: &Session<'_>,
search_path: &Path,
s: String,
) -> Option<Match> {
let ranged_raw = session.load_raw_src_ranged(&msrc, context.filepath);
// get module from path attribute
if let Some(modpath) =
scopes::get_module_file_from_path(msrc, context.range.start, search_path, ranged_raw)
{
let doc_src = session.load_raw_file(&modpath);
return Some(Match {
matchstr: s,
filepath: modpath.to_path_buf(),
point: BytePos::ZERO,
coords: Some(Coordinate::start()),
local: false,
mtype: Module,
contextstr: modpath.to_str().unwrap().to_owned(),
docs: find_mod_doc(&doc_src, BytePos::ZERO),
});
}
// get internal module nesting
// e.g. is this in an inline submodule? mod foo{ mod bar; }
// because if it is then we need to search further down the
// directory hierarchy - e.g. <cwd>/foo/bar.rs
let internalpath = scopes::get_local_module_path(msrc, context.range.start);
let mut searchdir = (*search_path).to_owned();
for s in internalpath {
searchdir.push(&s);
}
if let Some(modpath) = get_module_file(&s, &searchdir, session) {
let doc_src = session.load_raw_file(&modpath);
let context = modpath.to_str().unwrap().to_owned();
return Some(Match {
matchstr: s,
filepath: modpath,
point: BytePos::ZERO,
coords: Some(Coordinate::start()),
local: false,
mtype: Module,
contextstr: context,
docs: find_mod_doc(&doc_src, BytePos::ZERO),
});
}
None
}
Expand Down
3 changes: 3 additions & 0 deletions test_project/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ impl TestStruct {
}

pub(crate) fn name() {}

pub mod submod;
pub mod submod2018;
Empty file added test_project/src/submod/foo.rs
Empty file.
1 change: 1 addition & 0 deletions test_project/src/submod/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod foo;
1 change: 1 addition & 0 deletions test_project/src/submod2018.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod foo2018;
Empty file.
57 changes: 57 additions & 0 deletions tests/module_structure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use racer_testutils::*;

#[test]
fn finds_old_type_of_submodule() {
let src = "
use submod::f~oo;
";

with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_definition(src, Some(srcdir));
assert_eq!(got.matchstr, "foo");
assert!(got.filepath.ends_with("src/submod/foo.rs"));
})
}

#[test]
fn finds_old_type_of_module() {
let src = "
use s~ubmod::foo;
";

with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_definition(src, Some(srcdir));
assert_eq!(got.matchstr, "submod");
assert!(got.filepath.ends_with("src/submod/mod.rs"));
})
}

#[test]
fn finds_new_type_of_module() {
let src = "
use s~ubmod2018::foo2018;
";

with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_definition(src, Some(srcdir));
assert_eq!(got.matchstr, "submod2018");
assert!(got.filepath.ends_with("src/submod2018.rs"));
})
}

#[test]
fn finds_new_type_of_submodule() {
let src = "
use submod2018::f~oo2018;
";

with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_definition(src, Some(srcdir));
assert_eq!(got.matchstr, "foo2018");
assert!(got.filepath.ends_with("src/submod2018/foo2018.rs"));
})
}

0 comments on commit 218682d

Please sign in to comment.