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.rs174
1 files changed, 167 insertions, 7 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index a39141941..810228632 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -1,4 +1,3 @@
1extern crate failure;
2extern crate parking_lot; 1extern crate parking_lot;
3#[macro_use] 2#[macro_use]
4extern crate log; 3extern crate log;
@@ -11,13 +10,174 @@ extern crate relative_path;
11 10
12mod symbol_index; 11mod symbol_index;
13mod module_map; 12mod module_map;
14mod api;
15mod imp; 13mod imp;
16 14
17pub use self::symbol_index::Query; 15use relative_path::{RelativePath, RelativePathBuf};
18pub use self::api::{ 16use libsyntax2::{File, TextRange, TextUnit, AtomEdit};
19 AnalysisHost, Analysis, SourceChange, SourceFileEdit, FileSystemEdit, Position, Diagnostic, Runnable, RunnableKind, 17use imp::{AnalysisImpl, AnalysisHostImpl};
20 FileId, FileResolver, 18
19pub use libeditor::{
20 StructureNode, LineIndex, FileSymbol,
21 Runnable, RunnableKind, HighlightedRange, CompletionItem,
21}; 22};
22 23
23pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct FileId(pub u32);
26
27pub trait FileResolver: Send + Sync + 'static {
28 fn file_stem(&self, id: FileId) -> String;
29 fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
30}
31
32#[derive(Debug)]
33pub struct AnalysisHost {
34 pub(crate) imp: AnalysisHostImpl
35}
36
37impl AnalysisHost {
38 pub fn new() -> AnalysisHost {
39 AnalysisHost { imp: AnalysisHostImpl::new() }
40 }
41 pub fn analysis(&self, file_resolver: impl FileResolver) -> Analysis {
42 Analysis { imp: self.imp.analysis(file_resolver) }
43 }
44 pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
45 self.change_files(::std::iter::once((file_id, text)));
46 }
47 pub fn change_files(&mut self, mut changes: impl Iterator<Item=(FileId, Option<String>)>) {
48 self.imp.change_files(&mut changes)
49 }
50}
51
52#[derive(Debug)]
53pub struct SourceChange {
54 pub label: String,
55 pub source_file_edits: Vec<SourceFileEdit>,
56 pub file_system_edits: Vec<FileSystemEdit>,
57 pub cursor_position: Option<Position>,
58}
59
60#[derive(Debug)]
61pub struct Position {
62 pub file_id: FileId,
63 pub offset: TextUnit,
64}
65
66#[derive(Debug)]
67pub struct SourceFileEdit {
68 pub file_id: FileId,
69 pub edits: Vec<AtomEdit>,
70}
71
72#[derive(Debug)]
73pub enum FileSystemEdit {
74 CreateFile {
75 anchor: FileId,
76 path: RelativePathBuf,
77 },
78 MoveFile {
79 file: FileId,
80 path: RelativePathBuf,
81 }
82}
83
84#[derive(Debug)]
85pub struct Diagnostic {
86 pub message: String,
87 pub range: TextRange,
88 pub fix: Option<SourceChange>,
89}
90
91#[derive(Debug)]
92pub struct Query {
93 query: String,
94 lowercased: String,
95 only_types: bool,
96 exact: bool,
97 limit: usize,
98}
99
100impl Query {
101 pub fn new(query: String) -> Query {
102 let lowercased = query.to_lowercase();
103 Query {
104 query,
105 lowercased,
106 only_types: false,
107 exact: false,
108 limit: usize::max_value()
109 }
110 }
111 pub fn only_types(&mut self) {
112 self.only_types = true;
113 }
114 pub fn exact(&mut self) {
115 self.exact = true;
116 }
117 pub fn limit(&mut self, limit: usize) {
118 self.limit = limit
119 }
120}
121
122#[derive(Clone, Debug)]
123pub struct Analysis {
124 pub(crate) imp: AnalysisImpl
125}
126
127impl Analysis {
128 pub fn file_syntax(&self, file_id: FileId) -> File {
129 self.imp.file_syntax(file_id)
130 }
131 pub fn file_line_index(&self, file_id: FileId) -> LineIndex {
132 self.imp.file_line_index(file_id)
133 }
134 pub fn extend_selection(&self, file: &File, range: TextRange) -> TextRange {
135 libeditor::extend_selection(file, range).unwrap_or(range)
136 }
137 pub fn matching_brace(&self, file: &File, offset: TextUnit) -> Option<TextUnit> {
138 libeditor::matching_brace(file, offset)
139 }
140 pub fn syntax_tree(&self, file_id: FileId) -> String {
141 let file = self.file_syntax(file_id);
142 libeditor::syntax_tree(&file)
143 }
144 pub fn join_lines(&self, file_id: FileId, range: TextRange) -> SourceChange {
145 let file = self.file_syntax(file_id);
146 SourceChange::from_local_edit(file_id, "join lines", libeditor::join_lines(&file, range))
147 }
148 pub fn on_eq_typed(&self, file_id: FileId, offset: TextUnit) -> Option<SourceChange> {
149 let file = self.file_syntax(file_id);
150 Some(SourceChange::from_local_edit(file_id, "add semicolon", libeditor::on_eq_typed(&file, offset)?))
151 }
152 pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
153 let file = self.file_syntax(file_id);
154 libeditor::file_structure(&file)
155 }
156 pub fn symbol_search(&self, query: Query) -> Vec<(FileId, FileSymbol)> {
157 self.imp.world_symbols(query)
158 }
159 pub fn approximately_resolve_symbol(&self, file_id: FileId, offset: TextUnit) -> Vec<(FileId, FileSymbol)> {
160 self.imp.approximately_resolve_symbol(file_id, offset)
161 }
162 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
163 self.imp.parent_module(file_id)
164 }
165 pub fn runnables(&self, file_id: FileId) -> Vec<Runnable> {
166 let file = self.file_syntax(file_id);
167 libeditor::runnables(&file)
168 }
169 pub fn highlight(&self, file_id: FileId) -> Vec<HighlightedRange> {
170 let file = self.file_syntax(file_id);
171 libeditor::highlight(&file)
172 }
173 pub fn completions(&self, file_id: FileId, offset: TextUnit) -> Option<Vec<CompletionItem>> {
174 let file = self.file_syntax(file_id);
175 libeditor::scope_completion(&file, offset)
176 }
177 pub fn assists(&self, file_id: FileId, offset: TextUnit) -> Vec<SourceChange> {
178 self.imp.assists(file_id, offset)
179 }
180 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
181 self.imp.diagnostics(file_id)
182 }
183}