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.rs91
1 files changed, 59 insertions, 32 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 96d10a087..ec20d106f 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -12,6 +12,7 @@ extern crate relative_path;
12 12
13mod symbol_index; 13mod symbol_index;
14mod module_map; 14mod module_map;
15mod api;
15 16
16use std::{ 17use std::{
17 fmt, 18 fmt,
@@ -34,13 +35,14 @@ use libsyntax2::{
34 ast::{self, AstNode, NameOwner}, 35 ast::{self, AstNode, NameOwner},
35 SyntaxKind::*, 36 SyntaxKind::*,
36}; 37};
37use libeditor::{Diagnostic, LineIndex, FileSymbol, find_node_at_offset}; 38use libeditor::{LineIndex, FileSymbol, find_node_at_offset};
38 39
39use self::{ 40use self::{
40 symbol_index::FileSymbols, 41 symbol_index::FileSymbols,
41 module_map::{ModuleMap, ChangeKind, Problem}, 42 module_map::{ModuleMap, ChangeKind, Problem},
42}; 43};
43pub use self::symbol_index::Query; 44pub use self::symbol_index::Query;
45pub use self::api::*;
44 46
45pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 47pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
46 48
@@ -97,6 +99,13 @@ impl WorldState {
97 } 99 }
98 } 100 }
99 101
102 pub fn analysis(
103 &self,
104 file_resolver: impl FileResolver,
105 ) -> Analysis {
106 Analysis { imp: self.snapshot(file_resolver) }
107 }
108
100 pub fn change_file(&mut self, file_id: FileId, text: Option<String>) { 109 pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
101 self.change_files(::std::iter::once((file_id, text))); 110 self.change_files(::std::iter::once((file_id, text)));
102 } 111 }
@@ -231,11 +240,11 @@ impl World {
231 Ok(vec![]) 240 Ok(vec![])
232 } 241 }
233 242
234 pub fn diagnostics(&self, file_id: FileId) -> Result<Vec<(Diagnostic, Option<QuickFix>)>> { 243 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
235 let syntax = self.file_syntax(file_id)?; 244 let syntax = self.file_syntax(file_id).unwrap();
236 let mut res = libeditor::diagnostics(&syntax) 245 let mut res = libeditor::diagnostics(&syntax)
237 .into_iter() 246 .into_iter()
238 .map(|d| (d, None)) 247 .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None })
239 .collect::<Vec<_>>(); 248 .collect::<Vec<_>>();
240 249
241 self.data.module_map.problems( 250 self.data.module_map.problems(
@@ -243,44 +252,62 @@ impl World {
243 &*self.file_resolver, 252 &*self.file_resolver,
244 &|file_id| self.file_syntax(file_id).unwrap(), 253 &|file_id| self.file_syntax(file_id).unwrap(),
245 |name_node, problem| { 254 |name_node, problem| {
246 let (diag, fix) = match problem { 255 let diag = match problem {
247 Problem::UnresolvedModule { candidate } => { 256 Problem::UnresolvedModule { candidate } => {
248 let diag = Diagnostic { 257 let create_file = FileSystemEdit::CreateFile {
249 range: name_node.syntax().range(), 258 anchor: file_id,
250 msg: "unresolved module".to_string(), 259 path: candidate.clone(),
251 }; 260 };
252 let fix = QuickFix { 261 let fix = SourceChange {
253 fs_ops: vec![FsOp::CreateFile { 262 label: "create module".to_string(),
254 anchor: file_id, 263 source_file_edits: Vec::new(),
255 path: candidate.clone(), 264 file_system_edits: vec![create_file],
256 }] 265 cursor_position: None,
257 }; 266 };
258 (diag, fix) 267 Diagnostic {
268 range: name_node.syntax().range(),
269 message: "unresolved module".to_string(),
270 fix: Some(fix),
271 }
259 } 272 }
260 Problem::NotDirOwner { move_to, candidate } => { 273 Problem::NotDirOwner { move_to, candidate } => {
261 let diag = Diagnostic { 274 let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() };
262 range: name_node.syntax().range(), 275 let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) };
263 msg: "can't declare module at this location".to_string(), 276 let fix = SourceChange {
277 label: "move file and create module".to_string(),
278 source_file_edits: Vec::new(),
279 file_system_edits: vec![move_file, create_file],
280 cursor_position: None,
264 }; 281 };
265 let fix = QuickFix { 282 Diagnostic {
266 fs_ops: vec![ 283 range: name_node.syntax().range(),
267 FsOp::MoveFile { 284 message: "can't declare module at this location".to_string(),
268 file: file_id, 285 fix: Some(fix),
269 path: move_to.clone(), 286 }
270 },
271 FsOp::CreateFile {
272 anchor: file_id,
273 path: move_to.join(candidate),
274 }
275 ],
276 };
277 (diag, fix)
278 } 287 }
279 }; 288 };
280 res.push((diag, Some(fix))) 289 res.push(diag)
281 } 290 }
282 ); 291 );
283 Ok(res) 292 res
293 }
294
295 pub fn assists(&self, file_id: FileId, offset: TextUnit) -> Vec<SourceChange> {
296 let file = self.file_syntax(file_id).unwrap();
297 let actions = vec![
298 ("flip comma", libeditor::flip_comma(&file, offset).map(|f| f())),
299 ("add `#[derive]`", libeditor::add_derive(&file, offset).map(|f| f())),
300 ("add impl", libeditor::add_impl(&file, offset).map(|f| f())),
301 ];
302 let mut res = Vec::new();
303 for (name, local_edit) in actions {
304 if let Some(local_edit) = local_edit {
305 res.push(SourceChange::from_local_edit(
306 file_id, name, local_edit
307 ))
308 }
309 }
310 res
284 } 311 }
285 312
286 fn index_resolve(&self, name_ref: ast::NameRef) -> Vec<(FileId, FileSymbol)> { 313 fn index_resolve(&self, name_ref: ast::NameRef) -> Vec<(FileId, FileSymbol)> {