diff options
-rw-r--r-- | crates/base_db/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/mod_resolution.rs | 5 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 6 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 5 | ||||
-rw-r--r-- | crates/hir_expand/src/test_db.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/test_db.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 10 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 8 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 57 | ||||
-rw-r--r-- | crates/ide_db/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ide_db/src/source_change.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 7 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 8 | ||||
-rw-r--r-- | crates/vfs/src/anchored_path.rs | 39 | ||||
-rw-r--r-- | crates/vfs/src/file_set.rs | 8 | ||||
-rw-r--r-- | crates/vfs/src/lib.rs | 6 |
16 files changed, 130 insertions, 72 deletions
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index 5571af495..595f28ada 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs | |||
@@ -18,7 +18,7 @@ pub use crate::{ | |||
18 | }, | 18 | }, |
19 | }; | 19 | }; |
20 | pub use salsa; | 20 | pub use salsa; |
21 | pub use vfs::{file_set::FileSet, FileId, VfsPath}; | 21 | pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; |
22 | 22 | ||
23 | #[macro_export] | 23 | #[macro_export] |
24 | macro_rules! impl_intern_key { | 24 | macro_rules! impl_intern_key { |
@@ -91,12 +91,7 @@ pub const DEFAULT_LRU_CAP: usize = 128; | |||
91 | pub trait FileLoader { | 91 | pub trait FileLoader { |
92 | /// Text of the file. | 92 | /// Text of the file. |
93 | fn file_text(&self, file_id: FileId) -> Arc<String>; | 93 | fn file_text(&self, file_id: FileId) -> Arc<String>; |
94 | /// Note that we intentionally accept a `&str` and not a `&Path` here. This | 94 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId>; |
95 | /// method exists to handle `#[path = "/some/path.rs"] mod foo;` and such, | ||
96 | /// so the input is guaranteed to be utf-8 string. One might be tempted to | ||
97 | /// introduce some kind of "utf-8 path with / separators", but that's a bad idea. Behold | ||
98 | /// `#[path = "C://no/way"]` | ||
99 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId>; | ||
100 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>; | 95 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>; |
101 | } | 96 | } |
102 | 97 | ||
@@ -155,11 +150,11 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> { | |||
155 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 150 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
156 | SourceDatabaseExt::file_text(self.0, file_id) | 151 | SourceDatabaseExt::file_text(self.0, file_id) |
157 | } | 152 | } |
158 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 153 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> { |
159 | // FIXME: this *somehow* should be platform agnostic... | 154 | // FIXME: this *somehow* should be platform agnostic... |
160 | let source_root = self.0.file_source_root(anchor); | 155 | let source_root = self.0.file_source_root(path.anchor); |
161 | let source_root = self.0.source_root(source_root); | 156 | let source_root = self.0.source_root(source_root); |
162 | source_root.file_set.resolve_path(anchor, path) | 157 | source_root.file_set.resolve_path(path) |
163 | } | 158 | } |
164 | 159 | ||
165 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 160 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs index c0c789cae..b4ccd4488 100644 --- a/crates/hir_def/src/nameres/mod_resolution.rs +++ b/crates/hir_def/src/nameres/mod_resolution.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | //! This module resolves `mod foo;` declaration to file. | 1 | //! This module resolves `mod foo;` declaration to file. |
2 | use base_db::FileId; | 2 | use base_db::{AnchoredPath, FileId}; |
3 | use hir_expand::name::Name; | 3 | use hir_expand::name::Name; |
4 | use syntax::SmolStr; | 4 | use syntax::SmolStr; |
5 | use test_utils::mark; | 5 | use test_utils::mark; |
@@ -77,7 +77,8 @@ impl ModDir { | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | for candidate in candidate_files.iter() { | 79 | for candidate in candidate_files.iter() { |
80 | if let Some(file_id) = db.resolve_path(file_id, candidate.as_str()) { | 80 | let path = AnchoredPath { anchor: file_id, path: candidate.as_str() }; |
81 | if let Some(file_id) = db.resolve_path(path) { | ||
81 | let is_mod_rs = candidate.ends_with("mod.rs"); | 82 | let is_mod_rs = candidate.ends_with("mod.rs"); |
82 | 83 | ||
83 | let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { | 84 | let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() { |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index f8b150850..574c0201a 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -5,8 +5,8 @@ use std::{ | |||
5 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use base_db::SourceDatabase; | ||
9 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast}; | 8 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast}; |
9 | use base_db::{AnchoredPath, SourceDatabase}; | ||
10 | use hir_expand::db::AstDatabase; | 10 | use hir_expand::db::AstDatabase; |
11 | use hir_expand::diagnostics::Diagnostic; | 11 | use hir_expand::diagnostics::Diagnostic; |
12 | use hir_expand::diagnostics::DiagnosticSinkBuilder; | 12 | use hir_expand::diagnostics::DiagnosticSinkBuilder; |
@@ -63,8 +63,8 @@ impl FileLoader for TestDB { | |||
63 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 63 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
64 | FileLoaderDelegate(self).file_text(file_id) | 64 | FileLoaderDelegate(self).file_text(file_id) |
65 | } | 65 | } |
66 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 66 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> { |
67 | FileLoaderDelegate(self).resolve_path(anchor, path) | 67 | FileLoaderDelegate(self).resolve_path(path) |
68 | } | 68 | } |
69 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 69 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
70 | FileLoaderDelegate(self).relevant_crates(file_id) | 70 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 79b970850..f60666a54 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -4,7 +4,7 @@ use crate::{ | |||
4 | MacroDefId, MacroDefKind, TextSize, | 4 | MacroDefId, MacroDefKind, TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use base_db::FileId; | 7 | use base_db::{AnchoredPath, FileId}; |
8 | use either::Either; | 8 | use either::Either; |
9 | use mbe::{parse_to_token_tree, ExpandResult}; | 9 | use mbe::{parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 10 | use parser::FragmentKind; |
@@ -324,7 +324,8 @@ fn relative_file( | |||
324 | allow_recursion: bool, | 324 | allow_recursion: bool, |
325 | ) -> Option<FileId> { | 325 | ) -> Option<FileId> { |
326 | let call_site = call_id.as_file().original_file(db); | 326 | let call_site = call_id.as_file().original_file(db); |
327 | let res = db.resolve_path(call_site, path)?; | 327 | let path = AnchoredPath { anchor: call_site, path }; |
328 | let res = db.resolve_path(path)?; | ||
328 | // Prevent include itself | 329 | // Prevent include itself |
329 | if res == call_site && !allow_recursion { | 330 | if res == call_site && !allow_recursion { |
330 | None | 331 | None |
diff --git a/crates/hir_expand/src/test_db.rs b/crates/hir_expand/src/test_db.rs index fca501e1f..7168a9462 100644 --- a/crates/hir_expand/src/test_db.rs +++ b/crates/hir_expand/src/test_db.rs | |||
@@ -5,7 +5,7 @@ use std::{ | |||
5 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate}; | 8 | use base_db::{salsa, AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate}; |
9 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
10 | 10 | ||
11 | #[salsa::database( | 11 | #[salsa::database( |
@@ -40,8 +40,8 @@ impl FileLoader for TestDB { | |||
40 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 40 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
41 | FileLoaderDelegate(self).file_text(file_id) | 41 | FileLoaderDelegate(self).file_text(file_id) |
42 | } | 42 | } |
43 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 43 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> { |
44 | FileLoaderDelegate(self).resolve_path(anchor, path) | 44 | FileLoaderDelegate(self).resolve_path(path) |
45 | } | 45 | } |
46 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 46 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
47 | FileLoaderDelegate(self).relevant_crates(file_id) | 47 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs index 22254b765..646e16bbe 100644 --- a/crates/hir_ty/src/test_db.rs +++ b/crates/hir_ty/src/test_db.rs | |||
@@ -5,7 +5,9 @@ use std::{ | |||
5 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast}; | 8 | use base_db::{ |
9 | salsa, AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast, | ||
10 | }; | ||
9 | use hir_def::{db::DefDatabase, ModuleId}; | 11 | use hir_def::{db::DefDatabase, ModuleId}; |
10 | use hir_expand::db::AstDatabase; | 12 | use hir_expand::db::AstDatabase; |
11 | use rustc_hash::{FxHashMap, FxHashSet}; | 13 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -67,8 +69,8 @@ impl FileLoader for TestDB { | |||
67 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 69 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
68 | FileLoaderDelegate(self).file_text(file_id) | 70 | FileLoaderDelegate(self).file_text(file_id) |
69 | } | 71 | } |
70 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 72 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> { |
71 | FileLoaderDelegate(self).resolve_path(anchor, path) | 73 | FileLoaderDelegate(self).resolve_path(path) |
72 | } | 74 | } |
73 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 75 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
74 | FileLoaderDelegate(self).relevant_crates(file_id) | 76 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index c8453edb3..d09f3a0a1 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -610,10 +610,12 @@ fn test_fn() { | |||
610 | source_file_edits: [], | 610 | source_file_edits: [], |
611 | file_system_edits: [ | 611 | file_system_edits: [ |
612 | CreateFile { | 612 | CreateFile { |
613 | anchor: FileId( | 613 | dst: AnchoredPathBuf { |
614 | 0, | 614 | anchor: FileId( |
615 | ), | 615 | 0, |
616 | dst: "foo.rs", | 616 | ), |
617 | path: "foo.rs", | ||
618 | }, | ||
617 | }, | 619 | }, |
618 | ], | 620 | ], |
619 | is_snippet: false, | 621 | is_snippet: false, |
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index 24d08651e..29c7a040b 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -8,7 +8,7 @@ use hir::{ | |||
8 | }, | 8 | }, |
9 | HasSource, HirDisplay, Semantics, VariantDef, | 9 | HasSource, HirDisplay, Semantics, VariantDef, |
10 | }; | 10 | }; |
11 | use ide_db::base_db::FileId; | 11 | use ide_db::base_db::{AnchoredPathBuf, FileId}; |
12 | use ide_db::{ | 12 | use ide_db::{ |
13 | source_change::{FileSystemEdit, SourceFileEdit}, | 13 | source_change::{FileSystemEdit, SourceFileEdit}, |
14 | RootDatabase, | 14 | RootDatabase, |
@@ -36,8 +36,10 @@ impl DiagnosticWithFix for UnresolvedModule { | |||
36 | Some(Fix::new( | 36 | Some(Fix::new( |
37 | "Create module", | 37 | "Create module", |
38 | FileSystemEdit::CreateFile { | 38 | FileSystemEdit::CreateFile { |
39 | anchor: self.file.original_file(sema.db), | 39 | dst: AnchoredPathBuf { |
40 | dst: self.candidate.clone(), | 40 | anchor: self.file.original_file(sema.db), |
41 | path: self.candidate.clone(), | ||
42 | }, | ||
41 | } | 43 | } |
42 | .into(), | 44 | .into(), |
43 | unresolved_module.syntax().text_range(), | 45 | unresolved_module.syntax().text_range(), |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 64fe8bd65..44081f210 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
9 | use ide_db::base_db::{FileRange, SourceDatabaseExt}; | 9 | use ide_db::base_db::{AnchoredPathBuf, FileRange, SourceDatabaseExt}; |
10 | use ide_db::{ | 10 | use ide_db::{ |
11 | defs::{Definition, NameClass, NameRefClass}, | 11 | defs::{Definition, NameClass, NameRefClass}, |
12 | RootDatabase, | 12 | RootDatabase, |
@@ -182,12 +182,13 @@ fn rename_mod( | |||
182 | match src.value { | 182 | match src.value { |
183 | ModuleSource::SourceFile(..) => { | 183 | ModuleSource::SourceFile(..) => { |
184 | // mod is defined in path/to/dir/mod.rs | 184 | // mod is defined in path/to/dir/mod.rs |
185 | let dst = if module.is_mod_rs(sema.db) { | 185 | let path = if module.is_mod_rs(sema.db) { |
186 | format!("../{}/mod.rs", new_name) | 186 | format!("../{}/mod.rs", new_name) |
187 | } else { | 187 | } else { |
188 | format!("{}.rs", new_name) | 188 | format!("{}.rs", new_name) |
189 | }; | 189 | }; |
190 | let move_file = FileSystemEdit::MoveFile { src: file_id, anchor: file_id, dst }; | 190 | let dst = AnchoredPathBuf { anchor: file_id, path }; |
191 | let move_file = FileSystemEdit::MoveFile { src: file_id, dst }; | ||
191 | file_system_edits.push(move_file); | 192 | file_system_edits.push(move_file); |
192 | } | 193 | } |
193 | ModuleSource::Module(..) => {} | 194 | ModuleSource::Module(..) => {} |
@@ -771,10 +772,12 @@ mod foo<|>; | |||
771 | src: FileId( | 772 | src: FileId( |
772 | 2, | 773 | 2, |
773 | ), | 774 | ), |
774 | anchor: FileId( | 775 | dst: AnchoredPathBuf { |
775 | 2, | 776 | anchor: FileId( |
776 | ), | 777 | 2, |
777 | dst: "foo2.rs", | 778 | ), |
779 | path: "foo2.rs", | ||
780 | }, | ||
778 | }, | 781 | }, |
779 | ], | 782 | ], |
780 | is_snippet: false, | 783 | is_snippet: false, |
@@ -837,10 +840,12 @@ use crate::foo<|>::FooContent; | |||
837 | src: FileId( | 840 | src: FileId( |
838 | 1, | 841 | 1, |
839 | ), | 842 | ), |
840 | anchor: FileId( | 843 | dst: AnchoredPathBuf { |
841 | 1, | 844 | anchor: FileId( |
842 | ), | 845 | 1, |
843 | dst: "quux.rs", | 846 | ), |
847 | path: "quux.rs", | ||
848 | }, | ||
844 | }, | 849 | }, |
845 | ], | 850 | ], |
846 | is_snippet: false, | 851 | is_snippet: false, |
@@ -884,10 +889,12 @@ mod fo<|>o; | |||
884 | src: FileId( | 889 | src: FileId( |
885 | 1, | 890 | 1, |
886 | ), | 891 | ), |
887 | anchor: FileId( | 892 | dst: AnchoredPathBuf { |
888 | 1, | 893 | anchor: FileId( |
889 | ), | 894 | 1, |
890 | dst: "../foo2/mod.rs", | 895 | ), |
896 | path: "../foo2/mod.rs", | ||
897 | }, | ||
891 | }, | 898 | }, |
892 | ], | 899 | ], |
893 | is_snippet: false, | 900 | is_snippet: false, |
@@ -932,10 +939,12 @@ mod outer { mod fo<|>o; } | |||
932 | src: FileId( | 939 | src: FileId( |
933 | 1, | 940 | 1, |
934 | ), | 941 | ), |
935 | anchor: FileId( | 942 | dst: AnchoredPathBuf { |
936 | 1, | 943 | anchor: FileId( |
937 | ), | 944 | 1, |
938 | dst: "bar.rs", | 945 | ), |
946 | path: "bar.rs", | ||
947 | }, | ||
939 | }, | 948 | }, |
940 | ], | 949 | ], |
941 | is_snippet: false, | 950 | is_snippet: false, |
@@ -1016,10 +1025,12 @@ pub mod foo<|>; | |||
1016 | src: FileId( | 1025 | src: FileId( |
1017 | 2, | 1026 | 2, |
1018 | ), | 1027 | ), |
1019 | anchor: FileId( | 1028 | dst: AnchoredPathBuf { |
1020 | 2, | 1029 | anchor: FileId( |
1021 | ), | 1030 | 2, |
1022 | dst: "foo2.rs", | 1031 | ), |
1032 | path: "foo2.rs", | ||
1033 | }, | ||
1023 | }, | 1034 | }, |
1024 | ], | 1035 | ], |
1025 | is_snippet: false, | 1036 | is_snippet: false, |
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs index fceaa089a..118c090d7 100644 --- a/crates/ide_db/src/lib.rs +++ b/crates/ide_db/src/lib.rs | |||
@@ -19,8 +19,8 @@ use std::{fmt, sync::Arc}; | |||
19 | 19 | ||
20 | use base_db::{ | 20 | use base_db::{ |
21 | salsa::{self, Durability}, | 21 | salsa::{self, Durability}, |
22 | Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, | 22 | AnchoredPath, Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, |
23 | Upcast, | 23 | SourceDatabase, Upcast, |
24 | }; | 24 | }; |
25 | use hir::db::{AstDatabase, DefDatabase, HirDatabase}; | 25 | use hir::db::{AstDatabase, DefDatabase, HirDatabase}; |
26 | use rustc_hash::FxHashSet; | 26 | use rustc_hash::FxHashSet; |
@@ -72,8 +72,8 @@ impl FileLoader for RootDatabase { | |||
72 | fn file_text(&self, file_id: FileId) -> Arc<String> { | 72 | fn file_text(&self, file_id: FileId) -> Arc<String> { |
73 | FileLoaderDelegate(self).file_text(file_id) | 73 | FileLoaderDelegate(self).file_text(file_id) |
74 | } | 74 | } |
75 | fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 75 | fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> { |
76 | FileLoaderDelegate(self).resolve_path(anchor, path) | 76 | FileLoaderDelegate(self).resolve_path(path) |
77 | } | 77 | } |
78 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { | 78 | fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { |
79 | FileLoaderDelegate(self).relevant_crates(file_id) | 79 | FileLoaderDelegate(self).relevant_crates(file_id) |
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs index f1590ec66..e87d98dad 100644 --- a/crates/ide_db/src/source_change.rs +++ b/crates/ide_db/src/source_change.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! | 3 | //! |
4 | //! It can be viewed as a dual for `AnalysisChange`. | 4 | //! It can be viewed as a dual for `AnalysisChange`. |
5 | 5 | ||
6 | use base_db::FileId; | 6 | use base_db::{AnchoredPathBuf, FileId}; |
7 | use text_edit::TextEdit; | 7 | use text_edit::TextEdit; |
8 | 8 | ||
9 | #[derive(Default, Debug, Clone)] | 9 | #[derive(Default, Debug, Clone)] |
@@ -44,8 +44,8 @@ impl From<Vec<SourceFileEdit>> for SourceChange { | |||
44 | 44 | ||
45 | #[derive(Debug, Clone)] | 45 | #[derive(Debug, Clone)] |
46 | pub enum FileSystemEdit { | 46 | pub enum FileSystemEdit { |
47 | CreateFile { anchor: FileId, dst: String }, | 47 | CreateFile { dst: AnchoredPathBuf }, |
48 | MoveFile { src: FileId, anchor: FileId, dst: String }, | 48 | MoveFile { src: FileId, dst: AnchoredPathBuf }, |
49 | } | 49 | } |
50 | 50 | ||
51 | impl From<FileSystemEdit> for SourceChange { | 51 | impl From<FileSystemEdit> for SourceChange { |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index a27495d0d..71dc56915 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -13,6 +13,7 @@ use lsp_types::{SemanticTokens, Url}; | |||
13 | use parking_lot::{Mutex, RwLock}; | 13 | use parking_lot::{Mutex, RwLock}; |
14 | use project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; | 14 | use project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
16 | use vfs::AnchoredPathBuf; | ||
16 | 17 | ||
17 | use crate::{ | 18 | use crate::{ |
18 | config::Config, | 19 | config::Config, |
@@ -268,10 +269,10 @@ impl GlobalStateSnapshot { | |||
268 | Some(self.mem_docs.get(&path)?.version) | 269 | Some(self.mem_docs.get(&path)?.version) |
269 | } | 270 | } |
270 | 271 | ||
271 | pub(crate) fn anchored_path(&self, file_id: FileId, path: &str) -> Url { | 272 | pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url { |
272 | let mut base = self.vfs.read().0.file_path(file_id); | 273 | let mut base = self.vfs.read().0.file_path(path.anchor); |
273 | base.pop(); | 274 | base.pop(); |
274 | let path = base.join(path).unwrap(); | 275 | let path = base.join(&path.path).unwrap(); |
275 | let path = path.as_path().unwrap(); | 276 | let path = path.as_path().unwrap(); |
276 | url_from_abs_path(&path) | 277 | url_from_abs_path(&path) |
277 | } | 278 | } |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 01eabe852..715f8927a 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -628,17 +628,17 @@ pub(crate) fn resource_op( | |||
628 | file_system_edit: FileSystemEdit, | 628 | file_system_edit: FileSystemEdit, |
629 | ) -> lsp_types::ResourceOp { | 629 | ) -> lsp_types::ResourceOp { |
630 | match file_system_edit { | 630 | match file_system_edit { |
631 | FileSystemEdit::CreateFile { anchor, dst } => { | 631 | FileSystemEdit::CreateFile { dst } => { |
632 | let uri = snap.anchored_path(anchor, &dst); | 632 | let uri = snap.anchored_path(&dst); |
633 | lsp_types::ResourceOp::Create(lsp_types::CreateFile { | 633 | lsp_types::ResourceOp::Create(lsp_types::CreateFile { |
634 | uri, | 634 | uri, |
635 | options: None, | 635 | options: None, |
636 | annotation: None, | 636 | annotation: None, |
637 | }) | 637 | }) |
638 | } | 638 | } |
639 | FileSystemEdit::MoveFile { src, anchor, dst } => { | 639 | FileSystemEdit::MoveFile { src, dst } => { |
640 | let old_uri = snap.file_id_to_url(src); | 640 | let old_uri = snap.file_id_to_url(src); |
641 | let new_uri = snap.anchored_path(anchor, &dst); | 641 | let new_uri = snap.anchored_path(&dst); |
642 | lsp_types::ResourceOp::Rename(lsp_types::RenameFile { | 642 | lsp_types::ResourceOp::Rename(lsp_types::RenameFile { |
643 | old_uri, | 643 | old_uri, |
644 | new_uri, | 644 | new_uri, |
diff --git a/crates/vfs/src/anchored_path.rs b/crates/vfs/src/anchored_path.rs new file mode 100644 index 000000000..02720a32e --- /dev/null +++ b/crates/vfs/src/anchored_path.rs | |||
@@ -0,0 +1,39 @@ | |||
1 | //! Analysis-level representation of file-system paths. | ||
2 | //! | ||
3 | //! The primary goal of this is to losslessly represent paths like | ||
4 | //! | ||
5 | //! ``` | ||
6 | //! #[path = "./bar.rs"] | ||
7 | //! mod foo; | ||
8 | //! ``` | ||
9 | //! | ||
10 | //! The first approach one might reach for is to use `PathBuf`. The problem here | ||
11 | //! is that `PathBuf` depends on host target (windows or linux), but | ||
12 | //! rust-analyzer should be capable to process `#[path = r"C:\bar.rs"]` on Unix. | ||
13 | //! | ||
14 | //! The second try is to use a `String`. This also fails, however. Consider a | ||
15 | //! hypothetical scenario, where rust-analyzer operates in a | ||
16 | //! networked/distributed mode. There's one global instance of rust-analyzer, | ||
17 | //! which processes requests from different machines. Now, the semantics of | ||
18 | //! `#[path = "/abs/path.rs"]` actually depends on which file-system we are at! | ||
19 | //! That is, even absolute paths exist relative to a file system! | ||
20 | //! | ||
21 | //! A more realistic scenario here is virtual VFS paths we use for testing. More | ||
22 | //! generally, there can be separate "universes" of VFS paths. | ||
23 | //! | ||
24 | //! That's why we use anchored representation -- each path carries an info about | ||
25 | //! a file this path originates from. We can fetch fs/"universe" information | ||
26 | //! from the anchor than. | ||
27 | use crate::FileId; | ||
28 | |||
29 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
30 | pub struct AnchoredPathBuf { | ||
31 | pub anchor: FileId, | ||
32 | pub path: String, | ||
33 | } | ||
34 | |||
35 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
36 | pub struct AnchoredPath<'a> { | ||
37 | pub anchor: FileId, | ||
38 | pub path: &'a str, | ||
39 | } | ||
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs index 9093fbd97..49ca593ac 100644 --- a/crates/vfs/src/file_set.rs +++ b/crates/vfs/src/file_set.rs | |||
@@ -7,7 +7,7 @@ use std::fmt; | |||
7 | use fst::{IntoStreamer, Streamer}; | 7 | use fst::{IntoStreamer, Streamer}; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use crate::{FileId, Vfs, VfsPath}; | 10 | use crate::{AnchoredPath, FileId, Vfs, VfsPath}; |
11 | 11 | ||
12 | #[derive(Default, Clone, Eq, PartialEq)] | 12 | #[derive(Default, Clone, Eq, PartialEq)] |
13 | pub struct FileSet { | 13 | pub struct FileSet { |
@@ -19,10 +19,10 @@ impl FileSet { | |||
19 | pub fn len(&self) -> usize { | 19 | pub fn len(&self) -> usize { |
20 | self.files.len() | 20 | self.files.len() |
21 | } | 21 | } |
22 | pub fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { | 22 | pub fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> { |
23 | let mut base = self.paths[&anchor].clone(); | 23 | let mut base = self.paths[&path.anchor].clone(); |
24 | base.pop(); | 24 | base.pop(); |
25 | let path = base.join(path)?; | 25 | let path = base.join(path.path)?; |
26 | self.files.get(&path).copied() | 26 | self.files.get(&path).copied() |
27 | } | 27 | } |
28 | 28 | ||
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index cdf6f1fd0..a3be579a7 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs | |||
@@ -36,6 +36,7 @@ | |||
36 | //! have a single `FileSet` which unions the two sources. | 36 | //! have a single `FileSet` which unions the two sources. |
37 | mod vfs_path; | 37 | mod vfs_path; |
38 | mod path_interner; | 38 | mod path_interner; |
39 | mod anchored_path; | ||
39 | pub mod file_set; | 40 | pub mod file_set; |
40 | pub mod loader; | 41 | pub mod loader; |
41 | 42 | ||
@@ -43,7 +44,10 @@ use std::{fmt, mem}; | |||
43 | 44 | ||
44 | use crate::path_interner::PathInterner; | 45 | use crate::path_interner::PathInterner; |
45 | 46 | ||
46 | pub use crate::vfs_path::VfsPath; | 47 | pub use crate::{ |
48 | anchored_path::{AnchoredPath, AnchoredPathBuf}, | ||
49 | vfs_path::VfsPath, | ||
50 | }; | ||
47 | pub use paths::{AbsPath, AbsPathBuf}; | 51 | pub use paths::{AbsPath, AbsPathBuf}; |
48 | 52 | ||
49 | #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] | 53 | #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] |