This commit is contained in:
Aleksey Kladov 2018-08-30 12:51:46 +03:00
parent 0d6d74e78e
commit 1f2fb4e27f
5 changed files with 101 additions and 96 deletions

View File

@ -395,7 +395,7 @@ async function applySourceChange(change: SourceChange) {
let uri = client.protocol2CodeConverter.asUri(toReveal.textDocument.uri)
let position = client.protocol2CodeConverter.asPosition(toReveal.position)
let editor = vscode.window.activeTextEditor;
if (!editor || editor.document.uri != uri) return
if (!editor || editor.document.uri.toString() != uri.toString()) return
if (!editor.selection.isEmpty) return
editor!.selection = new vscode.Selection(position, position)
}

View File

@ -1,7 +1,7 @@
use relative_path::RelativePathBuf;
use relative_path::{RelativePath, RelativePathBuf};
use libsyntax2::{File, TextRange, TextUnit, AtomEdit};
use libeditor;
use {imp::AnalysisImpl, FileId, Query};
use {imp::{AnalysisImpl, AnalysisHostImpl}, Query};
pub use libeditor::{
LocalEdit, StructureNode, LineIndex, FileSymbol,
@ -109,3 +109,34 @@ pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
self.imp.diagnostics(file_id)
}
}
pub trait FileResolver: Send + Sync + 'static {
fn file_stem(&self, id: FileId) -> String;
fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);
#[derive(Debug)]
pub struct AnalysisHost {
pub(crate) imp: AnalysisHostImpl
}
impl AnalysisHost {
pub fn new() -> AnalysisHost {
AnalysisHost { imp: AnalysisHostImpl::new() }
}
pub fn analysis(&self, file_resolver: impl FileResolver) -> Analysis {
Analysis { imp: self.imp.analysis(file_resolver) }
}
pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
self.change_files(::std::iter::once((file_id, text)));
}
pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
self.imp.change_files(changes)
}
}

View File

@ -22,9 +22,65 @@
FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
module_map::Problem,
symbol_index::FileSymbols,
module_map::ModuleMap,
module_map::{ModuleMap, ChangeKind},
};
#[derive(Debug)]
pub(crate) struct AnalysisHostImpl {
data: Arc<WorldData>
}
impl AnalysisHostImpl {
pub fn new() -> AnalysisHostImpl {
AnalysisHostImpl {
data: Arc::new(WorldData::default()),
}
}
pub fn analysis(
&self,
file_resolver: impl FileResolver,
) -> AnalysisImpl {
AnalysisImpl {
needs_reindex: AtomicBool::new(false),
file_resolver: Arc::new(file_resolver),
data: self.data.clone()
}
}
pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
let data = self.data_mut();
for (file_id, text) in changes {
let change_kind = if data.file_map.remove(&file_id).is_some() {
if text.is_some() {
ChangeKind::Update
} else {
ChangeKind::Delete
}
} else {
ChangeKind::Insert
};
data.module_map.update_file(file_id, change_kind);
data.file_map.remove(&file_id);
if let Some(text) = text {
let file_data = FileData::new(text);
data.file_map.insert(file_id, Arc::new(file_data));
} else {
data.file_map.remove(&file_id);
}
}
}
fn data_mut(&mut self) -> &mut WorldData {
if Arc::get_mut(&mut self.data).is_none() {
self.data = Arc::new(WorldData {
file_map: self.data.file_map.clone(),
module_map: self.data.module_map.clone(),
});
}
Arc::get_mut(&mut self.data).unwrap()
}
}
pub(crate) struct AnalysisImpl {
pub(crate) needs_reindex: AtomicBool,

View File

@ -14,92 +14,10 @@
mod api;
mod imp;
use std::{
sync::{
Arc,
atomic::{AtomicBool},
},
};
use relative_path::RelativePath;
use self::{
module_map::{ChangeKind},
imp::{WorldData, FileData},
};
pub use self::symbol_index::Query;
pub use self::api::{
Analysis, SourceChange, SourceFileEdit, FileSystemEdit, Position, Diagnostic, Runnable, RunnableKind
AnalysisHost, Analysis, SourceChange, SourceFileEdit, FileSystemEdit, Position, Diagnostic, Runnable, RunnableKind,
FileId, FileResolver,
};
pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
pub trait FileResolver: Send + Sync + 'static {
fn file_stem(&self, id: FileId) -> String;
fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
}
#[derive(Debug)]
pub struct WorldState {
data: Arc<WorldData>
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);
impl WorldState {
pub fn new() -> WorldState {
WorldState {
data: Arc::new(WorldData::default()),
}
}
pub fn analysis(
&self,
file_resolver: impl FileResolver,
) -> Analysis {
let imp = imp::AnalysisImpl {
needs_reindex: AtomicBool::new(false),
file_resolver: Arc::new(file_resolver),
data: self.data.clone()
};
Analysis { imp }
}
pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
self.change_files(::std::iter::once((file_id, text)));
}
pub fn change_files(&mut self, changes: impl Iterator<Item=(FileId, Option<String>)>) {
let data = self.data_mut();
for (file_id, text) in changes {
let change_kind = if data.file_map.remove(&file_id).is_some() {
if text.is_some() {
ChangeKind::Update
} else {
ChangeKind::Delete
}
} else {
ChangeKind::Insert
};
data.module_map.update_file(file_id, change_kind);
data.file_map.remove(&file_id);
if let Some(text) = text {
let file_data = FileData::new(text);
data.file_map.insert(file_id, Arc::new(file_data));
} else {
data.file_map.remove(&file_id);
}
}
}
fn data_mut(&mut self) -> &mut WorldData {
if Arc::get_mut(&mut self.data).is_none() {
self.data = Arc::new(WorldData {
file_map: self.data.file_map.clone(),
module_map: self.data.module_map.clone(),
});
}
Arc::get_mut(&mut self.data).unwrap()
}
}

View File

@ -5,7 +5,7 @@
};
use languageserver_types::Url;
use libanalysis::{FileId, WorldState, Analysis};
use libanalysis::{FileId, AnalysisHost, Analysis};
use {
Result,
@ -15,7 +15,7 @@
#[derive(Debug)]
pub struct ServerWorldState {
pub analysis: WorldState,
pub analysis_host: AnalysisHost,
pub path_map: PathMap,
pub mem_map: HashMap<FileId, Option<String>>,
}
@ -29,7 +29,7 @@ pub struct ServerWorld {
impl ServerWorldState {
pub fn new() -> ServerWorldState {
ServerWorldState {
analysis: WorldState::new(),
analysis_host: AnalysisHost::new(),
path_map: PathMap::new(),
mem_map: HashMap::new(),
}
@ -58,20 +58,20 @@ pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) {
}
});
self.analysis.change_files(changes);
self.analysis_host.change_files(changes);
}
pub fn add_mem_file(&mut self, path: PathBuf, text: String) {
let file_id = self.path_map.get_or_insert(path);
self.mem_map.insert(file_id, None);
self.analysis.change_file(file_id, Some(text));
self.analysis_host.change_file(file_id, Some(text));
}
pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> {
let file_id = self.path_map.get_id(path).ok_or_else(|| {
format_err!("change to unknown file: {}", path.display())
})?;
self.analysis.change_file(file_id, Some(text));
self.analysis_host.change_file(file_id, Some(text));
Ok(())
}
@ -85,13 +85,13 @@ pub fn remove_mem_file(&mut self, path: &Path) -> Result<()> {
};
// Do this via file watcher ideally.
let text = fs::read_to_string(path).ok();
self.analysis.change_file(file_id, text);
self.analysis_host.change_file(file_id, text);
Ok(())
}
pub fn snapshot(&self) -> ServerWorld {
ServerWorld {
analysis: self.analysis.analysis(self.path_map.clone()),
analysis: self.analysis_host.analysis(self.path_map.clone()),
path_map: self.path_map.clone()
}
}