From 185da286d26ea7f892097c48b79a28acd7e5f172 Mon Sep 17 00:00:00 2001 From: ivan770 Date: Sat, 13 Feb 2021 13:07:47 +0200 Subject: Moved CodeLens to ide crate --- crates/ide/src/annotations.rs | 142 ++++++++++++++++++++++++++++++++++++++++++ crates/ide/src/lib.rs | 14 +++++ 2 files changed, 156 insertions(+) create mode 100644 crates/ide/src/annotations.rs (limited to 'crates/ide') diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs new file mode 100644 index 000000000..6d54b6b57 --- /dev/null +++ b/crates/ide/src/annotations.rs @@ -0,0 +1,142 @@ +use hir::Semantics; +use ide_db::{ + base_db::{FileId, FilePosition, FileRange, SourceDatabase}, + RootDatabase, SymbolKind, +}; +use syntax::TextRange; + +use crate::{ + file_structure::file_structure, + fn_references::find_all_methods, + goto_implementation::goto_implementation, + references::find_all_refs, + runnables::{runnables, Runnable}, + NavigationTarget, RunnableKind, +}; + +// Feature: Annotations +// +// Provides user with annotations above items for looking up references or impl blocks +// and running/debugging binaries. +pub struct Annotation { + pub range: TextRange, + pub kind: AnnotationKind, +} + +pub enum AnnotationKind { + Runnable { debug: bool, runnable: Runnable }, + HasImpls { position: FilePosition, data: Option> }, + HasReferences { position: FilePosition, data: Option> }, +} + +pub struct AnnotationConfig { + pub binary_target: bool, + pub annotate_runnables: bool, + pub annotate_impls: bool, + pub annotate_references: bool, + pub annotate_method_references: bool, + pub run: bool, + pub debug: bool, +} + +pub(crate) fn annotations( + db: &RootDatabase, + file_id: FileId, + config: AnnotationConfig, +) -> Vec { + let mut annotations = Vec::default(); + + if config.annotate_runnables { + for runnable in runnables(db, file_id) { + if !matches!(runnable.kind, RunnableKind::Bin) || !config.binary_target { + continue; + } + + let action = runnable.action(); + let range = runnable.nav.full_range; + + if config.run { + annotations.push(Annotation { + range, + // FIXME: This one allocates without reason if run is enabled, but debug is disabled + kind: AnnotationKind::Runnable { debug: false, runnable: runnable.clone() }, + }); + } + + if action.debugee && config.debug { + annotations.push(Annotation { + range, + kind: AnnotationKind::Runnable { debug: true, runnable }, + }); + } + } + } + + file_structure(&db.parse(file_id).tree()) + .into_iter() + .filter(|node| { + matches!( + node.kind, + SymbolKind::Trait + | SymbolKind::Struct + | SymbolKind::Enum + | SymbolKind::Union + | SymbolKind::Const + ) + }) + .for_each(|node| { + if config.annotate_impls && node.kind != SymbolKind::Const { + annotations.push(Annotation { + range: node.node_range, + kind: AnnotationKind::HasImpls { + position: FilePosition { file_id, offset: node.navigation_range.start() }, + data: None, + }, + }); + } + + if config.annotate_references { + annotations.push(Annotation { + range: node.node_range, + kind: AnnotationKind::HasReferences { + position: FilePosition { file_id, offset: node.navigation_range.start() }, + data: None, + }, + }); + } + }); + + if config.annotate_method_references { + annotations.extend(find_all_methods(db, file_id).into_iter().map(|method| Annotation { + range: method.range, + kind: AnnotationKind::HasReferences { + position: FilePosition { file_id, offset: method.range.start() }, + data: None, + }, + })); + } + + annotations +} + +pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) -> Annotation { + match annotation.kind { + AnnotationKind::HasImpls { position, ref mut data } => { + *data = goto_implementation(db, position).map(|range| range.info); + } + AnnotationKind::HasReferences { position, ref mut data } => { + *data = find_all_refs(&Semantics::new(db), position, None).map(|result| { + result + .references + .into_iter() + .map(|(_, access)| access.into_iter()) + .flatten() + .map(|(range, _)| FileRange { file_id: position.file_id, range }) + .collect() + }); + } + _ => {} + }; + + annotation +} diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 592b12925..89e7bef7d 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -22,6 +22,7 @@ mod markup; mod prime_caches; mod display; +mod annotations; mod call_hierarchy; mod diagnostics; mod expand_macro; @@ -63,6 +64,7 @@ use syntax::SourceFile; use crate::display::ToNav; pub use crate::{ + annotations::{Annotation, AnnotationConfig, AnnotationKind}, call_hierarchy::CallItem, diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity}, display::navigation_target::NavigationTarget, @@ -555,6 +557,18 @@ impl Analysis { }) } + pub fn annotations( + &self, + file_id: FileId, + config: AnnotationConfig, + ) -> Cancelable> { + self.with_db(|db| annotations::annotations(db, file_id, config)) + } + + pub fn resolve_annotation(&self, annotation: Annotation) -> Cancelable { + self.with_db(|db| annotations::resolve_annotation(db, annotation)) + } + /// Performs an operation on that may be Canceled. fn with_db(&self, f: F) -> Cancelable where -- cgit v1.2.3