mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
parent
de278d1649
commit
538ec1122b
2 changed files with 146 additions and 53 deletions
|
@ -1,7 +1,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use ra_db::{FileId, SourceRoot};
|
||||||
use ra_db::FileId;
|
|
||||||
use ra_syntax::{ast, SmolStr};
|
use ra_syntax::{ast, SmolStr};
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::RelativePathBuf;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -106,7 +106,7 @@ where
|
||||||
file_id: file_id.into(),
|
file_id: file_id.into(),
|
||||||
raw_items: &raw_items,
|
raw_items: &raw_items,
|
||||||
}
|
}
|
||||||
.collect(raw_items.items());
|
.collect(None, raw_items.items());
|
||||||
|
|
||||||
// main name resolution fixed-point loop.
|
// main name resolution fixed-point loop.
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -456,7 +456,7 @@ where
|
||||||
let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
|
let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
|
||||||
let raw_items = self.db.raw_items(file_id);
|
let raw_items = self.db.raw_items(file_id);
|
||||||
ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
|
ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
|
||||||
.collect(raw_items.items());
|
.collect(None, raw_items.items());
|
||||||
} else {
|
} else {
|
||||||
log::error!("Too deep macro expansion: {:?}", macro_call_id);
|
log::error!("Too deep macro expansion: {:?}", macro_call_id);
|
||||||
self.def_map.poison_macros.insert(macro_def_id);
|
self.def_map.poison_macros.insert(macro_def_id);
|
||||||
|
@ -482,10 +482,10 @@ impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>>
|
||||||
where
|
where
|
||||||
DB: DefDatabase,
|
DB: DefDatabase,
|
||||||
{
|
{
|
||||||
fn collect(&mut self, items: &[raw::RawItem]) {
|
fn collect(&mut self, parent_module: Option<&Name>, items: &[raw::RawItem]) {
|
||||||
for item in items {
|
for item in items {
|
||||||
match *item {
|
match *item {
|
||||||
raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]),
|
raw::RawItem::Module(m) => self.collect_module(parent_module, &self.raw_items[m]),
|
||||||
raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push((
|
raw::RawItem::Import(import) => self.def_collector.unresolved_imports.push((
|
||||||
self.module_id,
|
self.module_id,
|
||||||
import,
|
import,
|
||||||
|
@ -497,7 +497,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_module(&mut self, module: &raw::ModuleData) {
|
fn collect_module(&mut self, _module: Option<&Name>, module: &raw::ModuleData) {
|
||||||
match module {
|
match module {
|
||||||
// inline module, just recurse
|
// inline module, just recurse
|
||||||
raw::ModuleData::Definition { name, items, ast_id } => {
|
raw::ModuleData::Definition { name, items, ast_id } => {
|
||||||
|
@ -509,7 +509,7 @@ where
|
||||||
file_id: self.file_id,
|
file_id: self.file_id,
|
||||||
raw_items: self.raw_items,
|
raw_items: self.raw_items,
|
||||||
}
|
}
|
||||||
.collect(&*items);
|
.collect(Some(name), &*items);
|
||||||
}
|
}
|
||||||
// out of line module, resolve, parse and recurse
|
// out of line module, resolve, parse and recurse
|
||||||
raw::ModuleData::Declaration { name, ast_id, attr_path } => {
|
raw::ModuleData::Declaration { name, ast_id, attr_path } => {
|
||||||
|
@ -521,6 +521,7 @@ where
|
||||||
name,
|
name,
|
||||||
is_root,
|
is_root,
|
||||||
attr_path.as_ref(),
|
attr_path.as_ref(),
|
||||||
|
_module,
|
||||||
) {
|
) {
|
||||||
Ok(file_id) => {
|
Ok(file_id) => {
|
||||||
let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
|
let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
|
||||||
|
@ -531,7 +532,7 @@ where
|
||||||
file_id: file_id.into(),
|
file_id: file_id.into(),
|
||||||
raw_items: &raw_items,
|
raw_items: &raw_items,
|
||||||
}
|
}
|
||||||
.collect(raw_items.items())
|
.collect(None, raw_items.items())
|
||||||
}
|
}
|
||||||
Err(candidate) => self.def_collector.def_map.diagnostics.push(
|
Err(candidate) => self.def_collector.def_map.diagnostics.push(
|
||||||
DefDiagnostic::UnresolvedModule {
|
DefDiagnostic::UnresolvedModule {
|
||||||
|
@ -636,46 +637,47 @@ fn resolve_submodule(
|
||||||
name: &Name,
|
name: &Name,
|
||||||
is_root: bool,
|
is_root: bool,
|
||||||
attr_path: Option<&SmolStr>,
|
attr_path: Option<&SmolStr>,
|
||||||
|
parent_module: Option<&Name>,
|
||||||
) -> Result<FileId, RelativePathBuf> {
|
) -> Result<FileId, RelativePathBuf> {
|
||||||
// FIXME: handle submodules of inline modules properly
|
|
||||||
let file_id = file_id.original_file(db);
|
let file_id = file_id.original_file(db);
|
||||||
let source_root_id = db.file_source_root(file_id);
|
let source_root_id = db.file_source_root(file_id);
|
||||||
let path = db.file_relative_path(file_id);
|
let path = db.file_relative_path(file_id);
|
||||||
let root = RelativePathBuf::default();
|
let root = RelativePathBuf::default();
|
||||||
let dir_path = path.parent().unwrap_or(&root);
|
let dir_path = path.parent().unwrap_or(&root);
|
||||||
let mod_name = path.file_stem().unwrap_or("unknown");
|
let mod_name = path.file_stem().unwrap_or("unknown");
|
||||||
let is_dir_owner = is_root || mod_name == "mod";
|
|
||||||
|
|
||||||
let file_mod = dir_path.join(format!("{}.rs", name));
|
let resolve_mode = match (attr_path.filter(|p| !p.is_empty()), parent_module) {
|
||||||
let dir_mod = dir_path.join(format!("{}/mod.rs", name));
|
(Some(file_path), Some(parent_name)) => {
|
||||||
let file_dir_mod = dir_path.join(format!("{}/{}.rs", mod_name, name));
|
let file_path = normalize_attribute_path(file_path);
|
||||||
let mut candidates = ArrayVec::<[_; 3]>::new();
|
let path = dir_path.join(format!("{}/{}", parent_name, file_path)).normalize();
|
||||||
let file_attr_mod = attr_path.map(|file_path| {
|
ResolutionMode::InsideInlineModule(InsideInlineModuleMode::WithAttributePath(path))
|
||||||
let file_path = normalize_attribute_path(file_path);
|
}
|
||||||
let file_attr_mod = dir_path.join(file_path.as_ref()).normalize();
|
(Some(file_path), None) => {
|
||||||
candidates.push(file_attr_mod.clone());
|
let file_path = normalize_attribute_path(file_path);
|
||||||
|
let path = dir_path.join(file_path.as_ref()).normalize();
|
||||||
file_attr_mod
|
ResolutionMode::OutOfLine(OutOfLineMode::WithAttributePath(path))
|
||||||
});
|
}
|
||||||
if is_dir_owner {
|
(None, Some(parent_name)) => {
|
||||||
candidates.push(file_mod.clone());
|
let path = dir_path.join(format!("{}/{}.rs", parent_name, name));
|
||||||
candidates.push(dir_mod);
|
ResolutionMode::InsideInlineModule(InsideInlineModuleMode::File(path))
|
||||||
} else {
|
}
|
||||||
candidates.push(file_dir_mod.clone());
|
_ => {
|
||||||
};
|
let is_dir_owner = is_root || mod_name == "mod";
|
||||||
let sr = db.source_root(source_root_id);
|
if is_dir_owner {
|
||||||
let mut points_to = candidates.into_iter().filter_map(|path| sr.files.get(&path)).copied();
|
let file_mod = dir_path.join(format!("{}.rs", name));
|
||||||
// FIXME: handle ambiguity
|
let dir_mod = dir_path.join(format!("{}/mod.rs", name));
|
||||||
match points_to.next() {
|
ResolutionMode::OutOfLine(OutOfLineMode::RootOrModRs {
|
||||||
Some(file_id) => Ok(file_id),
|
file: file_mod,
|
||||||
None => {
|
directory: dir_mod,
|
||||||
if let Some(file_attr_mod) = file_attr_mod {
|
})
|
||||||
Err(file_attr_mod)
|
|
||||||
} else {
|
} else {
|
||||||
Err(if is_dir_owner { file_mod } else { file_dir_mod })
|
let path = dir_path.join(format!("{}/{}.rs", mod_name, name));
|
||||||
|
ResolutionMode::OutOfLine(OutOfLineMode::FileInDirectory(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
resolve_mode.resolve(db.source_root(source_root_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
|
fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
|
||||||
|
@ -693,6 +695,74 @@ fn normalize_attribute_path(file_path: &SmolStr) -> Cow<str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum OutOfLineMode {
|
||||||
|
RootOrModRs { file: RelativePathBuf, directory: RelativePathBuf },
|
||||||
|
FileInDirectory(RelativePathBuf),
|
||||||
|
WithAttributePath(RelativePathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutOfLineMode {
|
||||||
|
pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
|
||||||
|
match self {
|
||||||
|
OutOfLineMode::RootOrModRs { file, directory } => match source_root.files.get(file) {
|
||||||
|
None => resolve_simple_path(source_root, directory).map_err(|_| file.clone()),
|
||||||
|
file_id => resolve_find_result(file_id, file),
|
||||||
|
},
|
||||||
|
OutOfLineMode::FileInDirectory(path) => resolve_simple_path(source_root, path),
|
||||||
|
OutOfLineMode::WithAttributePath(path) => resolve_simple_path(source_root, path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InsideInlineModuleMode {
|
||||||
|
File(RelativePathBuf),
|
||||||
|
WithAttributePath(RelativePathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InsideInlineModuleMode {
|
||||||
|
pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
|
||||||
|
match self {
|
||||||
|
InsideInlineModuleMode::File(path) => resolve_simple_path(source_root, path),
|
||||||
|
InsideInlineModuleMode::WithAttributePath(path) => {
|
||||||
|
resolve_simple_path(source_root, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ResolutionMode {
|
||||||
|
OutOfLine(OutOfLineMode),
|
||||||
|
InsideInlineModule(InsideInlineModuleMode),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResolutionMode {
|
||||||
|
pub fn resolve(&self, source_root: Arc<SourceRoot>) -> Result<FileId, RelativePathBuf> {
|
||||||
|
use self::ResolutionMode::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
OutOfLine(mode) => mode.resolve(source_root),
|
||||||
|
InsideInlineModule(mode) => mode.resolve(source_root),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_simple_path(
|
||||||
|
source_root: Arc<SourceRoot>,
|
||||||
|
path: &RelativePathBuf,
|
||||||
|
) -> Result<FileId, RelativePathBuf> {
|
||||||
|
resolve_find_result(source_root.files.get(path), path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_find_result(
|
||||||
|
file_id: Option<&FileId>,
|
||||||
|
path: &RelativePathBuf,
|
||||||
|
) -> Result<FileId, RelativePathBuf> {
|
||||||
|
match file_id {
|
||||||
|
Some(file_id) => Ok(file_id.clone()),
|
||||||
|
None => Err(path.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
|
|
|
@ -336,10 +336,10 @@ fn module_resolution_explicit_path_mod_rs_with_win_separator() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module() {
|
fn module_resolution_decl_inside_inline_module_with_path_attribute() {
|
||||||
let map = def_map_with_crate_graph(
|
let map = def_map_with_crate_graph(
|
||||||
r###"
|
r###"
|
||||||
//- /main.rs
|
//- /main.rs
|
||||||
|
@ -368,10 +368,39 @@ fn module_resolution_decl_inside_inline_module() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
#[test]
|
||||||
|
fn module_resolution_decl_inside_inline_module() {
|
||||||
|
let map = def_map_with_crate_graph(
|
||||||
|
r###"
|
||||||
|
//- /main.rs
|
||||||
|
mod foo {
|
||||||
|
mod bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /foo/bar.rs
|
||||||
|
pub struct Baz;
|
||||||
|
"###,
|
||||||
|
crate_graph! {
|
||||||
|
"main": ("/main.rs", []),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_snapshot_matches!(map, @r###"
|
||||||
|
⋮crate
|
||||||
|
⋮foo: t
|
||||||
|
⋮
|
||||||
|
⋮crate::foo
|
||||||
|
⋮bar: t
|
||||||
|
⋮
|
||||||
|
⋮crate::foo::bar
|
||||||
|
⋮Baz: t v
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module_2() {
|
fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
|
||||||
let map = def_map_with_crate_graph(
|
let map = def_map_with_crate_graph(
|
||||||
r###"
|
r###"
|
||||||
//- /main.rs
|
//- /main.rs
|
||||||
|
@ -400,7 +429,7 @@ fn module_resolution_decl_inside_inline_module_2() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module_3() {
|
fn module_resolution_decl_inside_inline_module_3() {
|
||||||
|
@ -433,7 +462,7 @@ fn module_resolution_decl_inside_inline_module_3() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module_empty_path() {
|
fn module_resolution_decl_inside_inline_module_empty_path() {
|
||||||
|
@ -491,7 +520,7 @@ fn module_resolution_decl_empty_path() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module_relative_path() {
|
fn module_resolution_decl_inside_inline_module_relative_path() {
|
||||||
|
@ -523,9 +552,7 @@ fn module_resolution_decl_inside_inline_module_relative_path() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn module_resolution_decl_inside_inline_module_in_crate_root() {
|
fn module_resolution_decl_inside_inline_module_in_crate_root() {
|
||||||
let map = def_map_with_crate_graph(
|
let map = def_map_with_crate_graph(
|
||||||
r###"
|
r###"
|
||||||
|
@ -557,9 +584,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn module_resolution_decl_inside_inline_module_in_mod_rs() {
|
fn module_resolution_decl_inside_inline_module_in_mod_rs() {
|
||||||
let map = def_map_with_crate_graph(
|
let map = def_map_with_crate_graph(
|
||||||
r###"
|
r###"
|
||||||
|
@ -597,9 +622,7 @@ fn module_resolution_decl_inside_inline_module_in_mod_rs() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
|
fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
|
||||||
let map = def_map_with_crate_graph(
|
let map = def_map_with_crate_graph(
|
||||||
r###"
|
r###"
|
||||||
|
@ -613,7 +636,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
|
||||||
}
|
}
|
||||||
use self::bar::baz::Baz;
|
use self::bar::baz::Baz;
|
||||||
|
|
||||||
//- /foo/bar/qwe.rs
|
//- /bar/qwe.rs
|
||||||
pub struct Baz;
|
pub struct Baz;
|
||||||
"###,
|
"###,
|
||||||
crate_graph! {
|
crate_graph! {
|
||||||
|
@ -637,7 +660,7 @@ fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: issue #1510. not support out-of-line modules inside inline.
|
// FIXME: issue #1529. not support out-of-line modules inside inline.
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
|
fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue