aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/lib.rs')
-rw-r--r--crates/ra_analysis/src/lib.rs153
1 files changed, 92 insertions, 61 deletions
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 9576453ab..54eb2f4d3 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -27,11 +27,9 @@ use ra_syntax::{SourceFileNode, TextRange, TextUnit, SmolStr, SyntaxKind};
27use ra_text_edit::TextEdit; 27use ra_text_edit::TextEdit;
28use rayon::prelude::*; 28use rayon::prelude::*;
29use relative_path::RelativePathBuf; 29use relative_path::RelativePathBuf;
30use salsa::ParallelDatabase;
30 31
31use crate::{ 32use crate::symbol_index::{SymbolIndex, FileSymbol};
32 imp::{AnalysisHostImpl, AnalysisImpl},
33 symbol_index::{SymbolIndex, FileSymbol},
34};
35 33
36pub use crate::{ 34pub use crate::{
37 completion::{CompletionItem, CompletionItemKind, InsertText}, 35 completion::{CompletionItem, CompletionItemKind, InsertText},
@@ -44,7 +42,7 @@ pub use hir::FnSignatureInfo;
44 42
45pub use ra_db::{ 43pub use ra_db::{
46 Canceled, Cancelable, FilePosition, FileRange, 44 Canceled, Cancelable, FilePosition, FileRange,
47 CrateGraph, CrateId, SourceRootId, FileId 45 CrateGraph, CrateId, SourceRootId, FileId, SyntaxDatabase, FilesDatabase
48}; 46};
49 47
50#[derive(Default)] 48#[derive(Default)]
@@ -150,27 +148,6 @@ impl AnalysisChange {
150 } 148 }
151} 149}
152 150
153/// `AnalysisHost` stores the current state of the world.
154#[derive(Debug, Default)]
155pub struct AnalysisHost {
156 imp: AnalysisHostImpl,
157}
158
159impl AnalysisHost {
160 /// Returns a snapshot of the current state, which you can query for
161 /// semantic information.
162 pub fn analysis(&self) -> Analysis {
163 Analysis {
164 imp: self.imp.analysis(),
165 }
166 }
167 /// Applies changes to the current state of the world. If there are
168 /// outstanding snapshots, they will be canceled.
169 pub fn apply_change(&mut self, change: AnalysisChange) {
170 self.imp.apply_change(change)
171 }
172}
173
174#[derive(Debug)] 151#[derive(Debug)]
175pub struct SourceChange { 152pub struct SourceChange {
176 pub label: String, 153 pub label: String,
@@ -287,124 +264,178 @@ impl ReferenceResolution {
287 } 264 }
288} 265}
289 266
267/// `AnalysisHost` stores the current state of the world.
268#[derive(Debug, Default)]
269pub struct AnalysisHost {
270 db: db::RootDatabase,
271}
272
273impl AnalysisHost {
274 /// Returns a snapshot of the current state, which you can query for
275 /// semantic information.
276 pub fn analysis(&self) -> Analysis {
277 Analysis {
278 db: self.db.snapshot(),
279 }
280 }
281 /// Applies changes to the current state of the world. If there are
282 /// outstanding snapshots, they will be canceled.
283 pub fn apply_change(&mut self, change: AnalysisChange) {
284 self.db.apply_change(change)
285 }
286}
287
290/// Analysis is a snapshot of a world state at a moment in time. It is the main 288/// Analysis is a snapshot of a world state at a moment in time. It is the main
291/// entry point for asking semantic information about the world. When the world 289/// entry point for asking semantic information about the world. When the world
292/// state is advanced using `AnalysisHost::apply_change` method, all existing 290/// state is advanced using `AnalysisHost::apply_change` method, all existing
293/// `Analysis` are canceled (most method return `Err(Canceled)`). 291/// `Analysis` are canceled (most method return `Err(Canceled)`).
294#[derive(Debug)] 292#[derive(Debug)]
295pub struct Analysis { 293pub struct Analysis {
296 pub(crate) imp: AnalysisImpl, 294 db: salsa::Snapshot<db::RootDatabase>,
297} 295}
298 296
299impl Analysis { 297impl Analysis {
298 /// Gets the text of the source file.
300 pub fn file_text(&self, file_id: FileId) -> Arc<String> { 299 pub fn file_text(&self, file_id: FileId) -> Arc<String> {
301 self.imp.file_text(file_id) 300 self.db.file_text(file_id)
302 } 301 }
302 /// Gets the syntax tree of the file.
303 pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode { 303 pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode {
304 self.imp.file_syntax(file_id).clone() 304 self.db.source_file(file_id).clone()
305 } 305 }
306 /// Gets the file's `LineIndex`: data structure to convert between absolute
307 /// offsets and line/column representation.
306 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 308 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
307 self.imp.file_line_index(file_id) 309 self.db.file_lines(file_id)
308 } 310 }
311 /// Selects the next syntactic nodes encopasing the range.
309 pub fn extend_selection(&self, frange: FileRange) -> TextRange { 312 pub fn extend_selection(&self, frange: FileRange) -> TextRange {
310 extend_selection::extend_selection(&self.imp.db, frange) 313 extend_selection::extend_selection(&self.db, frange)
311 } 314 }
315 /// Returns position of the mathcing brace (all types of braces are
316 /// supported).
312 pub fn matching_brace(&self, file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> { 317 pub fn matching_brace(&self, file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> {
313 ra_editor::matching_brace(file, offset) 318 ra_editor::matching_brace(file, offset)
314 } 319 }
320 /// Returns a syntax tree represented as `String`, for debug purposes.
321 // FIXME: use a better name here.
315 pub fn syntax_tree(&self, file_id: FileId) -> String { 322 pub fn syntax_tree(&self, file_id: FileId) -> String {
316 let file = self.imp.file_syntax(file_id); 323 let file = self.db.source_file(file_id);
317 ra_editor::syntax_tree(&file) 324 ra_editor::syntax_tree(&file)
318 } 325 }
326 /// Returns an edit to remove all newlines in the range, cleaning up minor
327 /// stuff like trailing commas.
319 pub fn join_lines(&self, frange: FileRange) -> SourceChange { 328 pub fn join_lines(&self, frange: FileRange) -> SourceChange {
320 let file = self.imp.file_syntax(frange.file_id); 329 let file = self.db.source_file(frange.file_id);
321 SourceChange::from_local_edit(frange.file_id, ra_editor::join_lines(&file, frange.range)) 330 SourceChange::from_local_edit(frange.file_id, ra_editor::join_lines(&file, frange.range))
322 } 331 }
332 /// Returns an edit which should be applied when opening a new line, fixing
333 /// up minor stuff like continuing the comment.
323 pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { 334 pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> {
324 let file = self.imp.file_syntax(position.file_id); 335 let file = self.db.source_file(position.file_id);
325 let edit = ra_editor::on_enter(&file, position.offset)?; 336 let edit = ra_editor::on_enter(&file, position.offset)?;
326 let res = SourceChange::from_local_edit(position.file_id, edit); 337 Some(SourceChange::from_local_edit(position.file_id, edit))
327 Some(res)
328 } 338 }
339 /// Returns an edit which should be applied after `=` was typed. Primaraly,
340 /// this works when adding `let =`.
341 // FIXME: use a snippet completion instead of this hack here.
329 pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { 342 pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
330 let file = self.imp.file_syntax(position.file_id); 343 let file = self.db.source_file(position.file_id);
331 Some(SourceChange::from_local_edit( 344 let edit = ra_editor::on_eq_typed(&file, position.offset)?;
332 position.file_id, 345 Some(SourceChange::from_local_edit(position.file_id, edit))
333 ra_editor::on_eq_typed(&file, position.offset)?,
334 ))
335 } 346 }
347 /// Returns a tree representation of symbols in the file. Useful to draw a
348 /// file outline.
336 pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { 349 pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
337 let file = self.imp.file_syntax(file_id); 350 let file = self.db.source_file(file_id);
338 ra_editor::file_structure(&file) 351 ra_editor::file_structure(&file)
339 } 352 }
353 /// Returns the set of folding ranges.
340 pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { 354 pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
341 let file = self.imp.file_syntax(file_id); 355 let file = self.db.source_file(file_id);
342 ra_editor::folding_ranges(&file) 356 ra_editor::folding_ranges(&file)
343 } 357 }
358 /// Fuzzy searches for a symbol.
344 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { 359 pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
345 let res = self 360 let res = symbol_index::world_symbols(&*self.db, query)?
346 .imp
347 .world_symbols(query)?
348 .into_iter() 361 .into_iter()
349 .map(|(file_id, symbol)| NavigationTarget { file_id, symbol }) 362 .map(|(file_id, symbol)| NavigationTarget { file_id, symbol })
350 .collect(); 363 .collect();
351 Ok(res) 364 Ok(res)
352 } 365 }
366 /// Resolves reference to definition, but does not gurantee correctness.
353 pub fn approximately_resolve_symbol( 367 pub fn approximately_resolve_symbol(
354 &self, 368 &self,
355 position: FilePosition, 369 position: FilePosition,
356 ) -> Cancelable<Option<ReferenceResolution>> { 370 ) -> Cancelable<Option<ReferenceResolution>> {
357 self.imp.approximately_resolve_symbol(position) 371 self.db.approximately_resolve_symbol(position)
358 } 372 }
373 /// Finds all usages of the reference at point.
359 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 374 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
360 self.imp.find_all_refs(position) 375 self.db.find_all_refs(position)
361 } 376 }
377 /// Returns documentation string for a given target.
362 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { 378 pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
363 self.imp.doc_text_for(nav) 379 self.db.doc_text_for(nav)
364 } 380 }
381 /// Returns a `mod name;` declaration whihc created the current module.
365 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { 382 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
366 self.imp.parent_module(position) 383 self.db.parent_module(position)
367 } 384 }
385 /// Returns `::` separated path to the current module from the crate root.
368 pub fn module_path(&self, position: FilePosition) -> Cancelable<Option<String>> { 386 pub fn module_path(&self, position: FilePosition) -> Cancelable<Option<String>> {
369 self.imp.module_path(position) 387 self.db.module_path(position)
370 } 388 }
389 /// Returns crates this file belongs too.
371 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 390 pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
372 self.imp.crate_for(file_id) 391 self.db.crate_for(file_id)
373 } 392 }
393 /// Returns the root file of the given crate.
374 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { 394 pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
375 Ok(self.imp.crate_root(crate_id)) 395 Ok(self.db.crate_root(crate_id))
376 } 396 }
397 /// Returns the set of possible targets to run for the current file.
377 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { 398 pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
378 let file = self.imp.file_syntax(file_id); 399 let file = self.db.source_file(file_id);
379 Ok(runnables::runnables(self, &file, file_id)) 400 Ok(runnables::runnables(self, &file, file_id))
380 } 401 }
402 /// Computes syntax highlighting for the given file.
381 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> { 403 pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
382 syntax_highlighting::highlight(&*self.imp.db, file_id) 404 syntax_highlighting::highlight(&*self.db, file_id)
383 } 405 }
406 /// Computes completions at the given position.
384 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { 407 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
385 self.imp.completions(position) 408 let completions = completion::completions(&self.db, position)?;
409 Ok(completions.map(|it| it.into()))
386 } 410 }
411 /// Computes assists (aks code actons aka intentions) for the given
412 /// position.
387 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> { 413 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> {
388 Ok(self.imp.assists(frange)) 414 Ok(self.db.assists(frange))
389 } 415 }
416 /// Computes the set of diagnostics for the given file.
390 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 417 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
391 self.imp.diagnostics(file_id) 418 self.db.diagnostics(file_id)
392 } 419 }
420 /// Computes parameter information for the given call expression.
393 pub fn resolve_callable( 421 pub fn resolve_callable(
394 &self, 422 &self,
395 position: FilePosition, 423 position: FilePosition,
396 ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> { 424 ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> {
397 self.imp.resolve_callable(position) 425 self.db.resolve_callable(position)
398 } 426 }
427 /// Computes the type of the expression at the given position.
399 pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> { 428 pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> {
400 self.imp.type_of(frange) 429 self.db.type_of(frange)
401 } 430 }
431 /// Returns the edit required to rename reference at the position to the new
432 /// name.
402 pub fn rename( 433 pub fn rename(
403 &self, 434 &self,
404 position: FilePosition, 435 position: FilePosition,
405 new_name: &str, 436 new_name: &str,
406 ) -> Cancelable<Vec<SourceFileEdit>> { 437 ) -> Cancelable<Vec<SourceFileEdit>> {
407 self.imp.rename(position, new_name) 438 self.db.rename(position, new_name)
408 } 439 }
409} 440}
410 441