aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis')
-rw-r--r--crates/libanalysis/src/api.rs35
-rw-r--r--crates/libanalysis/src/imp.rs58
-rw-r--r--crates/libanalysis/src/lib.rs86
3 files changed, 92 insertions, 87 deletions
diff --git a/crates/libanalysis/src/api.rs b/crates/libanalysis/src/api.rs
index 02eaf7b1c..ded88cd15 100644
--- a/crates/libanalysis/src/api.rs
+++ b/crates/libanalysis/src/api.rs
@@ -1,7 +1,7 @@
1use relative_path::RelativePathBuf; 1use relative_path::{RelativePath, RelativePathBuf};
2use libsyntax2::{File, TextRange, TextUnit, AtomEdit}; 2use libsyntax2::{File, TextRange, TextUnit, AtomEdit};
3use libeditor; 3use libeditor;
4use {imp::AnalysisImpl, FileId, Query}; 4use {imp::{AnalysisImpl, AnalysisHostImpl}, Query};
5 5
6pub use libeditor::{ 6pub use libeditor::{
7 LocalEdit, StructureNode, LineIndex, FileSymbol, 7 LocalEdit, StructureNode, LineIndex, FileSymbol,
@@ -109,3 +109,34 @@ impl Analysis {
109 self.imp.diagnostics(file_id) 109 self.imp.diagnostics(file_id)
110 } 110 }
111} 111}
112
113pub trait FileResolver: Send + Sync + 'static {
114 fn file_stem(&self, id: FileId) -> String;
115 fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
119pub struct FileId(pub u32);
120
121#[derive(Debug)]
122pub struct AnalysisHost {
123 pub(crate) imp: AnalysisHostImpl
124}
125
126impl AnalysisHost {
127 pub fn new() -> AnalysisHost {
128 AnalysisHost { imp: AnalysisHostImpl::new() }
129 }
130
131 pub fn analysis(&self, file_resolver: impl FileResolver) -> Analysis {
132 Analysis { imp: self.imp.analysis(file_resolver) }
133 }
134
135 pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
136 self.change_files(::std::iter::once((file_id, text)));
137 }
138
139 pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
140 self.imp.change_files(changes)
141 }
142}
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs
index 5f451f53f..06bbc7cf2 100644
--- a/crates/libanalysis/src/imp.rs
+++ b/crates/libanalysis/src/imp.rs
@@ -22,9 +22,65 @@ use {
22 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, 22 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
23 module_map::Problem, 23 module_map::Problem,
24 symbol_index::FileSymbols, 24 symbol_index::FileSymbols,
25 module_map::ModuleMap, 25 module_map::{ModuleMap, ChangeKind},
26}; 26};
27 27
28#[derive(Debug)]
29pub(crate) struct AnalysisHostImpl {
30 data: Arc<WorldData>
31}
32
33impl AnalysisHostImpl {
34 pub fn new() -> AnalysisHostImpl {
35 AnalysisHostImpl {
36 data: Arc::new(WorldData::default()),
37 }
38 }
39
40 pub fn analysis(
41 &self,
42 file_resolver: impl FileResolver,
43 ) -> AnalysisImpl {
44 AnalysisImpl {
45 needs_reindex: AtomicBool::new(false),
46 file_resolver: Arc::new(file_resolver),
47 data: self.data.clone()
48 }
49 }
50
51 pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
52 let data = self.data_mut();
53 for (file_id, text) in changes {
54 let change_kind = if data.file_map.remove(&file_id).is_some() {
55 if text.is_some() {
56 ChangeKind::Update
57 } else {
58 ChangeKind::Delete
59 }
60 } else {
61 ChangeKind::Insert
62 };
63 data.module_map.update_file(file_id, change_kind);
64 data.file_map.remove(&file_id);
65 if let Some(text) = text {
66 let file_data = FileData::new(text);
67 data.file_map.insert(file_id, Arc::new(file_data));
68 } else {
69 data.file_map.remove(&file_id);
70 }
71 }
72 }
73
74 fn data_mut(&mut self) -> &mut WorldData {
75 if Arc::get_mut(&mut self.data).is_none() {
76 self.data = Arc::new(WorldData {
77 file_map: self.data.file_map.clone(),
78 module_map: self.data.module_map.clone(),
79 });
80 }
81 Arc::get_mut(&mut self.data).unwrap()
82 }
83}
28 84
29pub(crate) struct AnalysisImpl { 85pub(crate) struct AnalysisImpl {
30 pub(crate) needs_reindex: AtomicBool, 86 pub(crate) needs_reindex: AtomicBool,
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 027d7439b..a39141941 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -14,92 +14,10 @@ mod module_map;
14mod api; 14mod api;
15mod imp; 15mod imp;
16 16
17use std::{
18 sync::{
19 Arc,
20 atomic::{AtomicBool},
21 },
22};
23
24use relative_path::RelativePath;
25
26use self::{
27 module_map::{ChangeKind},
28 imp::{WorldData, FileData},
29};
30pub use self::symbol_index::Query; 17pub use self::symbol_index::Query;
31pub use self::api::{ 18pub use self::api::{
32 Analysis, SourceChange, SourceFileEdit, FileSystemEdit, Position, Diagnostic, Runnable, RunnableKind 19 AnalysisHost, Analysis, SourceChange, SourceFileEdit, FileSystemEdit, Position, Diagnostic, Runnable, RunnableKind,
20 FileId, FileResolver,
33}; 21};
34 22
35pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 23pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
36
37pub trait FileResolver: Send + Sync + 'static {
38 fn file_stem(&self, id: FileId) -> String;
39 fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
40}
41
42#[derive(Debug)]
43pub struct WorldState {
44 data: Arc<WorldData>
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48pub struct FileId(pub u32);
49
50impl WorldState {
51 pub fn new() -> WorldState {
52 WorldState {
53 data: Arc::new(WorldData::default()),
54 }
55 }
56
57 pub fn analysis(
58 &self,
59 file_resolver: impl FileResolver,
60 ) -> Analysis {
61 let imp = imp::AnalysisImpl {
62 needs_reindex: AtomicBool::new(false),
63 file_resolver: Arc::new(file_resolver),
64 data: self.data.clone()
65 };
66 Analysis { imp }
67 }
68
69 pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
70 self.change_files(::std::iter::once((file_id, text)));
71 }
72
73 pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
74 let data = self.data_mut();
75 for (file_id, text) in changes {
76 let change_kind = if data.file_map.remove(&file_id).is_some() {
77 if text.is_some() {
78 ChangeKind::Update
79 } else {
80 ChangeKind::Delete
81 }
82 } else {
83 ChangeKind::Insert
84 };
85 data.module_map.update_file(file_id, change_kind);
86 data.file_map.remove(&file_id);
87 if let Some(text) = text {
88 let file_data = FileData::new(text);
89 data.file_map.insert(file_id, Arc::new(file_data));
90 } else {
91 data.file_map.remove(&file_id);
92 }
93 }
94 }
95
96 fn data_mut(&mut self) -> &mut WorldData {
97 if Arc::get_mut(&mut self.data).is_none() {
98 self.data = Arc::new(WorldData {
99 file_map: self.data.file_map.clone(),
100 module_map: self.data.module_map.clone(),
101 });
102 }
103 Arc::get_mut(&mut self.data).unwrap()
104 }
105}