aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/lib.rs')
-rw-r--r--crates/libanalysis/src/lib.rs83
1 files changed, 64 insertions, 19 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index fe2c3c2e6..96d10a087 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -8,13 +8,13 @@ extern crate libsyntax2;
8extern crate libeditor; 8extern crate libeditor;
9extern crate fst; 9extern crate fst;
10extern crate rayon; 10extern crate rayon;
11extern crate relative_path;
11 12
12mod symbol_index; 13mod symbol_index;
13mod module_map; 14mod module_map;
14 15
15use std::{ 16use std::{
16 fmt, 17 fmt,
17 path::{Path, PathBuf},
18 panic, 18 panic,
19 sync::{ 19 sync::{
20 Arc, 20 Arc,
@@ -24,6 +24,7 @@ use std::{
24 time::Instant, 24 time::Instant,
25}; 25};
26 26
27use relative_path::{RelativePath,RelativePathBuf};
27use once_cell::sync::OnceCell; 28use once_cell::sync::OnceCell;
28use rayon::prelude::*; 29use rayon::prelude::*;
29 30
@@ -37,13 +38,16 @@ use libeditor::{Diagnostic, LineIndex, FileSymbol, find_node_at_offset};
37 38
38use self::{ 39use self::{
39 symbol_index::FileSymbols, 40 symbol_index::FileSymbols,
40 module_map::{ModuleMap, ChangeKind}, 41 module_map::{ModuleMap, ChangeKind, Problem},
41}; 42};
42pub use self::symbol_index::Query; 43pub use self::symbol_index::Query;
43 44
44pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 45pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
45 46
46pub type FileResolver = dyn Fn(FileId, &Path) -> Option<FileId> + Send + Sync; 47pub trait FileResolver: Send + Sync + 'static {
48 fn file_stem(&self, id: FileId) -> String;
49 fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
50}
47 51
48#[derive(Debug)] 52#[derive(Debug)]
49pub struct WorldState { 53pub struct WorldState {
@@ -84,7 +88,7 @@ impl WorldState {
84 88
85 pub fn snapshot( 89 pub fn snapshot(
86 &self, 90 &self,
87 file_resolver: impl Fn(FileId, &Path) -> Option<FileId> + 'static + Send + Sync, 91 file_resolver: impl FileResolver,
88 ) -> World { 92 ) -> World {
89 World { 93 World {
90 needs_reindex: AtomicBool::new(false), 94 needs_reindex: AtomicBool::new(false),
@@ -132,8 +136,20 @@ impl WorldState {
132} 136}
133 137
134#[derive(Debug)] 138#[derive(Debug)]
135pub enum QuickFix { 139pub struct QuickFix {
136 CreateFile(PathBuf), 140 pub fs_ops: Vec<FsOp>,
141}
142
143#[derive(Debug)]
144pub enum FsOp {
145 CreateFile {
146 anchor: FileId,
147 path: RelativePathBuf,
148 },
149 MoveFile {
150 file: FileId,
151 path: RelativePathBuf,
152 }
137} 153}
138 154
139impl World { 155impl World {
@@ -221,20 +237,49 @@ impl World {
221 .into_iter() 237 .into_iter()
222 .map(|d| (d, None)) 238 .map(|d| (d, None))
223 .collect::<Vec<_>>(); 239 .collect::<Vec<_>>();
224 for module in syntax.ast().modules() { 240
225 if module.has_semi() && self.resolve_module(file_id, module).is_empty() { 241 self.data.module_map.problems(
226 if let Some(name) = module.name() { 242 file_id,
227 let d = Diagnostic { 243 &*self.file_resolver,
228 range: name.syntax().range(), 244 &|file_id| self.file_syntax(file_id).unwrap(),
229 msg: "unresolved module".to_string(), 245 |name_node, problem| {
230 }; 246 let (diag, fix) = match problem {
231 let quick_fix = self.data.module_map.suggested_child_mod_path(module) 247 Problem::UnresolvedModule { candidate } => {
232 .map(QuickFix::CreateFile); 248 let diag = Diagnostic {
233 249 range: name_node.syntax().range(),
234 res.push((d, quick_fix)) 250 msg: "unresolved module".to_string(),
235 } 251 };
252 let fix = QuickFix {
253 fs_ops: vec![FsOp::CreateFile {
254 anchor: file_id,
255 path: candidate.clone(),
256 }]
257 };
258 (diag, fix)
259 }
260 Problem::NotDirOwner { move_to, candidate } => {
261 let diag = Diagnostic {
262 range: name_node.syntax().range(),
263 msg: "can't declare module at this location".to_string(),
264 };
265 let fix = QuickFix {
266 fs_ops: vec![
267 FsOp::MoveFile {
268 file: file_id,
269 path: move_to.clone(),
270 },
271 FsOp::CreateFile {
272 anchor: file_id,
273 path: move_to.join(candidate),
274 }
275 ],
276 };
277 (diag, fix)
278 }
279 };
280 res.push((diag, Some(fix)))
236 } 281 }
237 } 282 );
238 Ok(res) 283 Ok(res)
239 } 284 }
240 285