mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 05:38:46 +00:00
move
This commit is contained in:
parent
0d6d74e78e
commit
1f2fb4e27f
5 changed files with 101 additions and 96 deletions
|
@ -395,7 +395,7 @@ async function applySourceChange(change: SourceChange) {
|
||||||
let uri = client.protocol2CodeConverter.asUri(toReveal.textDocument.uri)
|
let uri = client.protocol2CodeConverter.asUri(toReveal.textDocument.uri)
|
||||||
let position = client.protocol2CodeConverter.asPosition(toReveal.position)
|
let position = client.protocol2CodeConverter.asPosition(toReveal.position)
|
||||||
let editor = vscode.window.activeTextEditor;
|
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
|
if (!editor.selection.isEmpty) return
|
||||||
editor!.selection = new vscode.Selection(position, position)
|
editor!.selection = new vscode.Selection(position, position)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use relative_path::RelativePathBuf;
|
use relative_path::{RelativePath, RelativePathBuf};
|
||||||
use libsyntax2::{File, TextRange, TextUnit, AtomEdit};
|
use libsyntax2::{File, TextRange, TextUnit, AtomEdit};
|
||||||
use libeditor;
|
use libeditor;
|
||||||
use {imp::AnalysisImpl, FileId, Query};
|
use {imp::{AnalysisImpl, AnalysisHostImpl}, Query};
|
||||||
|
|
||||||
pub use libeditor::{
|
pub use libeditor::{
|
||||||
LocalEdit, StructureNode, LineIndex, FileSymbol,
|
LocalEdit, StructureNode, LineIndex, FileSymbol,
|
||||||
|
@ -109,3 +109,34 @@ impl Analysis {
|
||||||
self.imp.diagnostics(file_id)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -22,9 +22,65 @@ use {
|
||||||
FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
|
FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
|
||||||
module_map::Problem,
|
module_map::Problem,
|
||||||
symbol_index::FileSymbols,
|
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) struct AnalysisImpl {
|
||||||
pub(crate) needs_reindex: AtomicBool,
|
pub(crate) needs_reindex: AtomicBool,
|
||||||
|
|
|
@ -14,92 +14,10 @@ mod module_map;
|
||||||
mod api;
|
mod api;
|
||||||
mod imp;
|
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::symbol_index::Query;
|
||||||
pub use self::api::{
|
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 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use languageserver_types::Url;
|
use languageserver_types::Url;
|
||||||
use libanalysis::{FileId, WorldState, Analysis};
|
use libanalysis::{FileId, AnalysisHost, Analysis};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
Result,
|
Result,
|
||||||
|
@ -15,7 +15,7 @@ use {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ServerWorldState {
|
pub struct ServerWorldState {
|
||||||
pub analysis: WorldState,
|
pub analysis_host: AnalysisHost,
|
||||||
pub path_map: PathMap,
|
pub path_map: PathMap,
|
||||||
pub mem_map: HashMap<FileId, Option<String>>,
|
pub mem_map: HashMap<FileId, Option<String>>,
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ pub struct ServerWorld {
|
||||||
impl ServerWorldState {
|
impl ServerWorldState {
|
||||||
pub fn new() -> ServerWorldState {
|
pub fn new() -> ServerWorldState {
|
||||||
ServerWorldState {
|
ServerWorldState {
|
||||||
analysis: WorldState::new(),
|
analysis_host: AnalysisHost::new(),
|
||||||
path_map: PathMap::new(),
|
path_map: PathMap::new(),
|
||||||
mem_map: HashMap::new(),
|
mem_map: HashMap::new(),
|
||||||
}
|
}
|
||||||
|
@ -58,20 +58,20 @@ impl ServerWorldState {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.analysis.change_files(changes);
|
self.analysis_host.change_files(changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_mem_file(&mut self, path: PathBuf, text: String) {
|
pub fn add_mem_file(&mut self, path: PathBuf, text: String) {
|
||||||
let file_id = self.path_map.get_or_insert(path);
|
let file_id = self.path_map.get_or_insert(path);
|
||||||
self.mem_map.insert(file_id, None);
|
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<()> {
|
pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> {
|
||||||
let file_id = self.path_map.get_id(path).ok_or_else(|| {
|
let file_id = self.path_map.get_id(path).ok_or_else(|| {
|
||||||
format_err!("change to unknown file: {}", path.display())
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +85,13 @@ impl ServerWorldState {
|
||||||
};
|
};
|
||||||
// Do this via file watcher ideally.
|
// Do this via file watcher ideally.
|
||||||
let text = fs::read_to_string(path).ok();
|
let text = fs::read_to_string(path).ok();
|
||||||
self.analysis.change_file(file_id, text);
|
self.analysis_host.change_file(file_id, text);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshot(&self) -> ServerWorld {
|
pub fn snapshot(&self) -> ServerWorld {
|
||||||
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()
|
path_map: self.path_map.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue