aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/annotations.rs142
-rw-r--r--crates/ide/src/lib.rs14
2 files changed, 156 insertions, 0 deletions
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 @@
1use hir::Semantics;
2use ide_db::{
3 base_db::{FileId, FilePosition, FileRange, SourceDatabase},
4 RootDatabase, SymbolKind,
5};
6use syntax::TextRange;
7
8use crate::{
9 file_structure::file_structure,
10 fn_references::find_all_methods,
11 goto_implementation::goto_implementation,
12 references::find_all_refs,
13 runnables::{runnables, Runnable},
14 NavigationTarget, RunnableKind,
15};
16
17// Feature: Annotations
18//
19// Provides user with annotations above items for looking up references or impl blocks
20// and running/debugging binaries.
21pub struct Annotation {
22 pub range: TextRange,
23 pub kind: AnnotationKind,
24}
25
26pub enum AnnotationKind {
27 Runnable { debug: bool, runnable: Runnable },
28 HasImpls { position: FilePosition, data: Option<Vec<NavigationTarget>> },
29 HasReferences { position: FilePosition, data: Option<Vec<FileRange>> },
30}
31
32pub struct AnnotationConfig {
33 pub binary_target: bool,
34 pub annotate_runnables: bool,
35 pub annotate_impls: bool,
36 pub annotate_references: bool,
37 pub annotate_method_references: bool,
38 pub run: bool,
39 pub debug: bool,
40}
41
42pub(crate) fn annotations(
43 db: &RootDatabase,
44 file_id: FileId,
45 config: AnnotationConfig,
46) -> Vec<Annotation> {
47 let mut annotations = Vec::default();
48
49 if config.annotate_runnables {
50 for runnable in runnables(db, file_id) {
51 if !matches!(runnable.kind, RunnableKind::Bin) || !config.binary_target {
52 continue;
53 }
54
55 let action = runnable.action();
56 let range = runnable.nav.full_range;
57
58 if config.run {
59 annotations.push(Annotation {
60 range,
61 // FIXME: This one allocates without reason if run is enabled, but debug is disabled
62 kind: AnnotationKind::Runnable { debug: false, runnable: runnable.clone() },
63 });
64 }
65
66 if action.debugee && config.debug {
67 annotations.push(Annotation {
68 range,
69 kind: AnnotationKind::Runnable { debug: true, runnable },
70 });
71 }
72 }
73 }
74
75 file_structure(&db.parse(file_id).tree())
76 .into_iter()
77 .filter(|node| {
78 matches!(
79 node.kind,
80 SymbolKind::Trait
81 | SymbolKind::Struct
82 | SymbolKind::Enum
83 | SymbolKind::Union
84 | SymbolKind::Const
85 )
86 })
87 .for_each(|node| {
88 if config.annotate_impls && node.kind != SymbolKind::Const {
89 annotations.push(Annotation {
90 range: node.node_range,
91 kind: AnnotationKind::HasImpls {
92 position: FilePosition { file_id, offset: node.navigation_range.start() },
93 data: None,
94 },
95 });
96 }
97
98 if config.annotate_references {
99 annotations.push(Annotation {
100 range: node.node_range,
101 kind: AnnotationKind::HasReferences {
102 position: FilePosition { file_id, offset: node.navigation_range.start() },
103 data: None,
104 },
105 });
106 }
107 });
108
109 if config.annotate_method_references {
110 annotations.extend(find_all_methods(db, file_id).into_iter().map(|method| Annotation {
111 range: method.range,
112 kind: AnnotationKind::HasReferences {
113 position: FilePosition { file_id, offset: method.range.start() },
114 data: None,
115 },
116 }));
117 }
118
119 annotations
120}
121
122pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) -> Annotation {
123 match annotation.kind {
124 AnnotationKind::HasImpls { position, ref mut data } => {
125 *data = goto_implementation(db, position).map(|range| range.info);
126 }
127 AnnotationKind::HasReferences { position, ref mut data } => {
128 *data = find_all_refs(&Semantics::new(db), position, None).map(|result| {
129 result
130 .references
131 .into_iter()
132 .map(|(_, access)| access.into_iter())
133 .flatten()
134 .map(|(range, _)| FileRange { file_id: position.file_id, range })
135 .collect()
136 });
137 }
138 _ => {}
139 };
140
141 annotation
142}
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;
22mod prime_caches; 22mod prime_caches;
23mod display; 23mod display;
24 24
25mod annotations;
25mod call_hierarchy; 26mod call_hierarchy;
26mod diagnostics; 27mod diagnostics;
27mod expand_macro; 28mod expand_macro;
@@ -63,6 +64,7 @@ use syntax::SourceFile;
63use crate::display::ToNav; 64use crate::display::ToNav;
64 65
65pub use crate::{ 66pub use crate::{
67 annotations::{Annotation, AnnotationConfig, AnnotationKind},
66 call_hierarchy::CallItem, 68 call_hierarchy::CallItem,
67 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity}, 69 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
68 display::navigation_target::NavigationTarget, 70 display::navigation_target::NavigationTarget,
@@ -555,6 +557,18 @@ impl Analysis {
555 }) 557 })
556 } 558 }
557 559
560 pub fn annotations(
561 &self,
562 file_id: FileId,
563 config: AnnotationConfig,
564 ) -> Cancelable<Vec<Annotation>> {
565 self.with_db(|db| annotations::annotations(db, file_id, config))
566 }
567
568 pub fn resolve_annotation(&self, annotation: Annotation) -> Cancelable<Annotation> {
569 self.with_db(|db| annotations::resolve_annotation(db, annotation))
570 }
571
558 /// Performs an operation on that may be Canceled. 572 /// Performs an operation on that may be Canceled.
559 fn with_db<F, T>(&self, f: F) -> Cancelable<T> 573 fn with_db<F, T>(&self, f: F) -> Cancelable<T>
560 where 574 where