diff options
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | crates/ra_db/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_db/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/mod_resolution.rs | 116 | ||||
-rw-r--r-- | crates/ra_ide_db/src/change.rs | 7 |
5 files changed, 90 insertions, 42 deletions
diff --git a/Cargo.lock b/Cargo.lock index 385e7a7bc..242fca700 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1020,7 +1020,6 @@ dependencies = [ | |||
1020 | "ra_prof", | 1020 | "ra_prof", |
1021 | "ra_syntax", | 1021 | "ra_syntax", |
1022 | "ra_tt", | 1022 | "ra_tt", |
1023 | "relative-path", | ||
1024 | "rustc-hash", | 1023 | "rustc-hash", |
1025 | "salsa", | 1024 | "salsa", |
1026 | "stdx", | 1025 | "stdx", |
@@ -1409,12 +1408,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
1409 | checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" | 1408 | checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" |
1410 | 1409 | ||
1411 | [[package]] | 1410 | [[package]] |
1412 | name = "relative-path" | ||
1413 | version = "1.2.1" | ||
1414 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
1415 | checksum = "c602122c47b382cd045b10866a084b184035d45d8c2609cdd3762852ddfae2a1" | ||
1416 | |||
1417 | [[package]] | ||
1418 | name = "remove_dir_all" | 1411 | name = "remove_dir_all" |
1419 | version = "0.5.3" | 1412 | version = "0.5.3" |
1420 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" |
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml index ef85266db..889142442 100644 --- a/crates/ra_db/Cargo.toml +++ b/crates/ra_db/Cargo.toml | |||
@@ -9,7 +9,6 @@ doctest = false | |||
9 | 9 | ||
10 | [dependencies] | 10 | [dependencies] |
11 | salsa = "0.15.0" | 11 | salsa = "0.15.0" |
12 | relative-path = "1.0.0" | ||
13 | rustc-hash = "1.1.0" | 12 | rustc-hash = "1.1.0" |
14 | 13 | ||
15 | ra_syntax = { path = "../ra_syntax" } | 14 | ra_syntax = { path = "../ra_syntax" } |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 3a8fd44c4..f25be24fe 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -16,7 +16,6 @@ pub use crate::{ | |||
16 | SourceRoot, SourceRootId, | 16 | SourceRoot, SourceRootId, |
17 | }, | 17 | }, |
18 | }; | 18 | }; |
19 | pub use relative_path::{RelativePath, RelativePathBuf}; | ||
20 | pub use salsa; | 19 | pub use salsa; |
21 | pub use vfs::{file_set::FileSet, VfsPath}; | 20 | pub use vfs::{file_set::FileSet, VfsPath}; |
22 | 21 | ||
diff --git a/crates/ra_hir_def/src/nameres/mod_resolution.rs b/crates/ra_hir_def/src/nameres/mod_resolution.rs index 39e9a6d97..953961632 100644 --- a/crates/ra_hir_def/src/nameres/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/mod_resolution.rs | |||
@@ -1,23 +1,24 @@ | |||
1 | //! This module resolves `mod foo;` declaration to file. | 1 | //! This module resolves `mod foo;` declaration to file. |
2 | use hir_expand::name::Name; | 2 | use hir_expand::name::Name; |
3 | use ra_db::{FileId, RelativePathBuf}; | 3 | use ra_db::FileId; |
4 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
5 | 5 | ||
6 | use crate::{db::DefDatabase, HirFileId}; | 6 | use crate::{db::DefDatabase, HirFileId}; |
7 | 7 | ||
8 | #[derive(Clone, Debug)] | 8 | #[derive(Clone, Debug)] |
9 | pub(super) struct ModDir { | 9 | pub(super) struct ModDir { |
10 | /// `.` for `mod.rs`, `lib.rs` | 10 | /// `` for `mod.rs`, `lib.rs` |
11 | /// `./foo` for `foo.rs` | 11 | /// `foo/` for `foo.rs` |
12 | /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs` | 12 | /// `foo/bar/` for `mod bar { mod x; }` nested in `foo.rs` |
13 | path: RelativePathBuf, | 13 | /// Invariant: path.is_empty() || path.ends_with('/') |
14 | dir_path: DirPath, | ||
14 | /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/` | 15 | /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/` |
15 | root_non_dir_owner: bool, | 16 | root_non_dir_owner: bool, |
16 | } | 17 | } |
17 | 18 | ||
18 | impl ModDir { | 19 | impl ModDir { |
19 | pub(super) fn root() -> ModDir { | 20 | pub(super) fn root() -> ModDir { |
20 | ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false } | 21 | ModDir { dir_path: DirPath::empty(), root_non_dir_owner: false } |
21 | } | 22 | } |
22 | 23 | ||
23 | pub(super) fn descend_into_definition( | 24 | pub(super) fn descend_into_definition( |
@@ -25,17 +26,21 @@ impl ModDir { | |||
25 | name: &Name, | 26 | name: &Name, |
26 | attr_path: Option<&SmolStr>, | 27 | attr_path: Option<&SmolStr>, |
27 | ) -> ModDir { | 28 | ) -> ModDir { |
28 | let mut path = self.path.clone(); | 29 | let path = match attr_path.map(|it| it.as_str()) { |
29 | match attr_to_path(attr_path) { | 30 | None => { |
30 | None => path.push(&name.to_string()), | 31 | let mut path = self.dir_path.clone(); |
32 | path.push(&name.to_string()); | ||
33 | path | ||
34 | } | ||
31 | Some(attr_path) => { | 35 | Some(attr_path) => { |
32 | if self.root_non_dir_owner { | 36 | let mut path = self.dir_path.join_attr(attr_path, self.root_non_dir_owner); |
33 | assert!(path.pop()); | 37 | if !(path.is_empty() || path.ends_with('/')) { |
38 | path.push('/') | ||
34 | } | 39 | } |
35 | path.push(attr_path); | 40 | DirPath::new(path) |
36 | } | 41 | } |
37 | } | 42 | }; |
38 | ModDir { path, root_non_dir_owner: false } | 43 | ModDir { dir_path: path, root_non_dir_owner: false } |
39 | } | 44 | } |
40 | 45 | ||
41 | pub(super) fn resolve_declaration( | 46 | pub(super) fn resolve_declaration( |
@@ -48,34 +53,87 @@ impl ModDir { | |||
48 | let file_id = file_id.original_file(db.upcast()); | 53 | let file_id = file_id.original_file(db.upcast()); |
49 | 54 | ||
50 | let mut candidate_files = Vec::new(); | 55 | let mut candidate_files = Vec::new(); |
51 | match attr_to_path(attr_path) { | 56 | match attr_path { |
52 | Some(attr_path) => { | 57 | Some(attr_path) => { |
53 | let base = | 58 | candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) |
54 | if self.root_non_dir_owner { self.path.parent().unwrap() } else { &self.path }; | ||
55 | candidate_files.push(base.join(attr_path).to_string()) | ||
56 | } | 59 | } |
57 | None => { | 60 | None => { |
58 | candidate_files.push(self.path.join(&format!("{}.rs", name)).to_string()); | 61 | candidate_files.push(format!("{}{}.rs", self.dir_path.0, name)); |
59 | candidate_files.push(self.path.join(&format!("{}/mod.rs", name)).to_string()); | 62 | candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name)); |
60 | } | 63 | } |
61 | }; | 64 | }; |
62 | 65 | ||
63 | for candidate in candidate_files.iter() { | 66 | for candidate in candidate_files.iter() { |
64 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { | 67 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { |
65 | let mut root_non_dir_owner = false; | ||
66 | let mut mod_path = RelativePathBuf::new(); | ||
67 | let is_mod_rs = candidate.ends_with("mod.rs"); | 68 | let is_mod_rs = candidate.ends_with("mod.rs"); |
68 | if !(is_mod_rs || attr_path.is_some()) { | 69 | |
69 | root_non_dir_owner = true; | 70 | let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { |
70 | mod_path.push(&name.to_string()); | 71 | (DirPath::empty(), false) |
71 | } | 72 | } else { |
72 | return Ok((file_id, is_mod_rs, ModDir { path: mod_path, root_non_dir_owner })); | 73 | (DirPath::new(format!("{}/", name)), true) |
74 | }; | ||
75 | return Ok((file_id, is_mod_rs, ModDir { dir_path, root_non_dir_owner })); | ||
73 | } | 76 | } |
74 | } | 77 | } |
75 | Err(candidate_files.remove(0)) | 78 | Err(candidate_files.remove(0)) |
76 | } | 79 | } |
77 | } | 80 | } |
78 | 81 | ||
79 | fn attr_to_path(attr: Option<&SmolStr>) -> Option<RelativePathBuf> { | 82 | #[derive(Clone, Debug)] |
80 | attr.and_then(|it| RelativePathBuf::from_path(&it.replace("\\", "/")).ok()) | 83 | struct DirPath(String); |
84 | |||
85 | impl DirPath { | ||
86 | fn assert_invariant(&self) { | ||
87 | assert!(self.0.is_empty() || self.0.ends_with('/')); | ||
88 | } | ||
89 | fn new(repr: String) -> DirPath { | ||
90 | let res = DirPath(repr); | ||
91 | res.assert_invariant(); | ||
92 | res | ||
93 | } | ||
94 | fn empty() -> DirPath { | ||
95 | DirPath::new(String::new()) | ||
96 | } | ||
97 | fn push(&mut self, name: &str) { | ||
98 | self.0.push_str(name); | ||
99 | self.0.push('/'); | ||
100 | self.assert_invariant(); | ||
101 | } | ||
102 | fn parent(&self) -> Option<&str> { | ||
103 | if self.0.is_empty() { | ||
104 | return None; | ||
105 | }; | ||
106 | let idx = | ||
107 | self.0[..self.0.len() - '/'.len_utf8()].rfind('/').map_or(0, |it| it + '/'.len_utf8()); | ||
108 | Some(&self.0[..idx]) | ||
109 | } | ||
110 | /// So this is the case which doesn't really work I think if we try to be | ||
111 | /// 100% platform agnostic: | ||
112 | /// | ||
113 | /// ``` | ||
114 | /// mod a { | ||
115 | /// #[path="C://sad/face"] | ||
116 | /// mod b { mod c; } | ||
117 | /// } | ||
118 | /// ``` | ||
119 | /// | ||
120 | /// Here, we need to join logical dir path to a string path from an | ||
121 | /// attribute. Ideally, we should somehow losslessly communicate the whole | ||
122 | /// construction to `FileLoader`. | ||
123 | fn join_attr(&self, mut attr: &str, relative_to_parent: bool) -> String { | ||
124 | let base = if relative_to_parent { self.parent().unwrap() } else { &self.0 }; | ||
125 | |||
126 | if attr.starts_with("./") { | ||
127 | attr = &attr["./".len()..]; | ||
128 | } | ||
129 | let tmp; | ||
130 | let attr = if attr.contains('\\') { | ||
131 | tmp = attr.replace('\\', "/"); | ||
132 | &tmp | ||
133 | } else { | ||
134 | attr | ||
135 | }; | ||
136 | let res = format!("{}{}", base, attr); | ||
137 | res | ||
138 | } | ||
81 | } | 139 | } |
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index 84c6f40ff..d1a255dcf 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -5,8 +5,7 @@ use std::{fmt, sync::Arc, time}; | |||
5 | 5 | ||
6 | use ra_db::{ | 6 | use ra_db::{ |
7 | salsa::{Database, Durability, SweepStrategy}, | 7 | salsa::{Database, Durability, SweepStrategy}, |
8 | CrateGraph, FileId, RelativePathBuf, SourceDatabase, SourceDatabaseExt, SourceRoot, | 8 | CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, |
9 | SourceRootId, | ||
10 | }; | 9 | }; |
11 | use ra_prof::{memory_usage, profile, Bytes}; | 10 | use ra_prof::{memory_usage, profile, Bytes}; |
12 | use rustc_hash::FxHashSet; | 11 | use rustc_hash::FxHashSet; |
@@ -57,14 +56,14 @@ impl AnalysisChange { | |||
57 | #[derive(Debug)] | 56 | #[derive(Debug)] |
58 | struct AddFile { | 57 | struct AddFile { |
59 | file_id: FileId, | 58 | file_id: FileId, |
60 | path: RelativePathBuf, | 59 | path: String, |
61 | text: Arc<String>, | 60 | text: Arc<String>, |
62 | } | 61 | } |
63 | 62 | ||
64 | #[derive(Debug)] | 63 | #[derive(Debug)] |
65 | struct RemoveFile { | 64 | struct RemoveFile { |
66 | file_id: FileId, | 65 | file_id: FileId, |
67 | path: RelativePathBuf, | 66 | path: String, |
68 | } | 67 | } |
69 | 68 | ||
70 | #[derive(Default)] | 69 | #[derive(Default)] |