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