Merge #4724
4724: Rename WorldState -> GlobalState r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
992e1256d0
@ -4,7 +4,7 @@ use ra_cfg::CfgExpr;
|
||||
use ra_ide::{FileId, RunnableKind, TestId};
|
||||
use ra_project_model::{self, ProjectWorkspace, TargetKind};
|
||||
|
||||
use crate::{world::WorldSnapshot, Result};
|
||||
use crate::{global_state::GlobalStateSnapshot, Result};
|
||||
|
||||
/// Abstract representation of Cargo target.
|
||||
///
|
||||
@ -89,7 +89,7 @@ impl CargoTargetSpec {
|
||||
}
|
||||
|
||||
pub(crate) fn for_file(
|
||||
world: &WorldSnapshot,
|
||||
world: &GlobalStateSnapshot,
|
||||
file_id: FileId,
|
||||
) -> Result<Option<CargoTargetSpec>> {
|
||||
let &crate_id = match world.analysis().crate_for(file_id)?.first() {
|
||||
|
@ -3,7 +3,7 @@ use ra_db::{FileId, FilePosition, FileRange};
|
||||
use ra_ide::{LineCol, LineIndex};
|
||||
use ra_syntax::{TextRange, TextSize};
|
||||
|
||||
use crate::{world::WorldSnapshot, Result};
|
||||
use crate::{global_state::GlobalStateSnapshot, Result};
|
||||
|
||||
pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> TextSize {
|
||||
let line_col = LineCol { line: position.line as u32, col_utf16: position.character as u32 };
|
||||
@ -16,12 +16,12 @@ pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Tex
|
||||
TextRange::new(start, end)
|
||||
}
|
||||
|
||||
pub(crate) fn file_id(world: &WorldSnapshot, url: &lsp_types::Url) -> Result<FileId> {
|
||||
pub(crate) fn file_id(world: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
|
||||
world.uri_to_file_id(url)
|
||||
}
|
||||
|
||||
pub(crate) fn file_position(
|
||||
world: &WorldSnapshot,
|
||||
world: &GlobalStateSnapshot,
|
||||
tdpp: lsp_types::TextDocumentPositionParams,
|
||||
) -> Result<FilePosition> {
|
||||
let file_id = file_id(world, &tdpp.text_document.uri)?;
|
||||
@ -31,7 +31,7 @@ pub(crate) fn file_position(
|
||||
}
|
||||
|
||||
pub(crate) fn file_range(
|
||||
world: &WorldSnapshot,
|
||||
world: &GlobalStateSnapshot,
|
||||
text_document_identifier: lsp_types::TextDocumentIdentifier,
|
||||
range: lsp_types::Range,
|
||||
) -> Result<FileRange> {
|
||||
|
@ -50,13 +50,13 @@ fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) ->
|
||||
})
|
||||
}
|
||||
|
||||
/// `WorldState` is the primary mutable state of the language server
|
||||
/// `GlobalState` is the primary mutable state of the language server
|
||||
///
|
||||
/// The most interesting components are `vfs`, which stores a consistent
|
||||
/// snapshot of the file systems, and `analysis_host`, which stores our
|
||||
/// incremental salsa database.
|
||||
#[derive(Debug)]
|
||||
pub struct WorldState {
|
||||
pub struct GlobalState {
|
||||
pub config: Config,
|
||||
pub local_roots: Vec<PathBuf>,
|
||||
pub workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
@ -70,7 +70,7 @@ pub struct WorldState {
|
||||
}
|
||||
|
||||
/// An immutable snapshot of the world's state at a point in time.
|
||||
pub struct WorldSnapshot {
|
||||
pub struct GlobalStateSnapshot {
|
||||
pub config: Config,
|
||||
pub workspaces: Arc<Vec<ProjectWorkspace>>,
|
||||
pub analysis: Analysis,
|
||||
@ -79,14 +79,14 @@ pub struct WorldSnapshot {
|
||||
vfs: Arc<RwLock<Vfs>>,
|
||||
}
|
||||
|
||||
impl WorldState {
|
||||
impl GlobalState {
|
||||
pub fn new(
|
||||
workspaces: Vec<ProjectWorkspace>,
|
||||
lru_capacity: Option<usize>,
|
||||
exclude_globs: &[Glob],
|
||||
watch: Watch,
|
||||
config: Config,
|
||||
) -> WorldState {
|
||||
) -> GlobalState {
|
||||
let mut change = AnalysisChange::new();
|
||||
|
||||
let extern_dirs: FxHashSet<_> =
|
||||
@ -180,7 +180,7 @@ impl WorldState {
|
||||
|
||||
let mut analysis_host = AnalysisHost::new(lru_capacity);
|
||||
analysis_host.apply_change(change);
|
||||
WorldState {
|
||||
GlobalState {
|
||||
config,
|
||||
local_roots,
|
||||
workspaces: Arc::new(workspaces),
|
||||
@ -255,8 +255,8 @@ impl WorldState {
|
||||
self.analysis_host.apply_change(change);
|
||||
}
|
||||
|
||||
pub fn snapshot(&self) -> WorldSnapshot {
|
||||
WorldSnapshot {
|
||||
pub fn snapshot(&self) -> GlobalStateSnapshot {
|
||||
GlobalStateSnapshot {
|
||||
config: self.config.clone(),
|
||||
workspaces: Arc::clone(&self.workspaces),
|
||||
analysis: self.analysis_host.analysis(),
|
||||
@ -279,7 +279,7 @@ impl WorldState {
|
||||
}
|
||||
}
|
||||
|
||||
impl WorldSnapshot {
|
||||
impl GlobalStateSnapshot {
|
||||
pub fn analysis(&self) -> &Analysis {
|
||||
&self.analysis
|
||||
}
|
@ -26,7 +26,7 @@ mod main_loop;
|
||||
mod markdown;
|
||||
pub mod lsp_ext;
|
||||
pub mod config;
|
||||
mod world;
|
||||
mod global_state;
|
||||
mod diagnostics;
|
||||
mod semantic_tokens;
|
||||
|
||||
|
@ -38,12 +38,13 @@ use threadpool::ThreadPool;
|
||||
use crate::{
|
||||
config::{Config, FilesWatcher},
|
||||
diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask},
|
||||
from_proto, lsp_ext,
|
||||
from_proto,
|
||||
global_state::{GlobalState, GlobalStateSnapshot},
|
||||
lsp_ext,
|
||||
main_loop::{
|
||||
pending_requests::{PendingRequest, PendingRequests},
|
||||
subscriptions::Subscriptions,
|
||||
},
|
||||
world::{WorldSnapshot, WorldState},
|
||||
Result,
|
||||
};
|
||||
|
||||
@ -92,7 +93,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
}
|
||||
|
||||
let mut loop_state = LoopState::default();
|
||||
let mut world_state = {
|
||||
let mut global_state = {
|
||||
let workspaces = {
|
||||
// FIXME: support dynamic workspace loading.
|
||||
let project_roots: FxHashSet<_> = ws_roots
|
||||
@ -163,7 +164,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
connection.sender.send(request.into()).unwrap();
|
||||
}
|
||||
|
||||
WorldState::new(
|
||||
GlobalState::new(
|
||||
workspaces,
|
||||
config.lru_capacity,
|
||||
&globs,
|
||||
@ -172,7 +173,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
)
|
||||
};
|
||||
|
||||
loop_state.roots_total = world_state.vfs.read().n_roots();
|
||||
loop_state.roots_total = global_state.vfs.read().n_roots();
|
||||
|
||||
let pool = ThreadPool::default();
|
||||
let (task_sender, task_receiver) = unbounded::<Task>();
|
||||
@ -190,12 +191,12 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
Err(RecvError) => return Err("client exited without shutdown".into()),
|
||||
},
|
||||
recv(task_receiver) -> task => Event::Task(task.unwrap()),
|
||||
recv(world_state.task_receiver) -> task => match task {
|
||||
recv(global_state.task_receiver) -> task => match task {
|
||||
Ok(task) => Event::Vfs(task),
|
||||
Err(RecvError) => return Err("vfs died".into()),
|
||||
},
|
||||
recv(libdata_receiver) -> data => Event::Lib(data.unwrap()),
|
||||
recv(world_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
|
||||
recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
|
||||
Ok(task) => Event::CheckWatcher(task),
|
||||
Err(RecvError) => return Err("check watcher died".into()),
|
||||
}
|
||||
@ -210,16 +211,16 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
&task_sender,
|
||||
&libdata_sender,
|
||||
&connection,
|
||||
&mut world_state,
|
||||
&mut global_state,
|
||||
&mut loop_state,
|
||||
event,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
world_state.analysis_host.request_cancellation();
|
||||
global_state.analysis_host.request_cancellation();
|
||||
log::info!("waiting for tasks to finish...");
|
||||
task_receiver.into_iter().for_each(|task| {
|
||||
on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut world_state)
|
||||
on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
|
||||
});
|
||||
libdata_receiver.into_iter().for_each(drop);
|
||||
log::info!("...tasks have finished");
|
||||
@ -228,7 +229,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
|
||||
drop(pool);
|
||||
log::info!("...threadpool has finished");
|
||||
|
||||
let vfs = Arc::try_unwrap(world_state.vfs).expect("all snapshots should be dead");
|
||||
let vfs = Arc::try_unwrap(global_state.vfs).expect("all snapshots should be dead");
|
||||
drop(vfs);
|
||||
|
||||
Ok(())
|
||||
@ -319,7 +320,7 @@ fn loop_turn(
|
||||
task_sender: &Sender<Task>,
|
||||
libdata_sender: &Sender<LibraryData>,
|
||||
connection: &Connection,
|
||||
world_state: &mut WorldState,
|
||||
global_state: &mut GlobalState,
|
||||
loop_state: &mut LoopState,
|
||||
event: Event,
|
||||
) -> Result<()> {
|
||||
@ -335,22 +336,22 @@ fn loop_turn(
|
||||
|
||||
match event {
|
||||
Event::Task(task) => {
|
||||
on_task(task, &connection.sender, &mut loop_state.pending_requests, world_state);
|
||||
world_state.maybe_collect_garbage();
|
||||
on_task(task, &connection.sender, &mut loop_state.pending_requests, global_state);
|
||||
global_state.maybe_collect_garbage();
|
||||
}
|
||||
Event::Vfs(task) => {
|
||||
world_state.vfs.write().handle_task(task);
|
||||
global_state.vfs.write().handle_task(task);
|
||||
}
|
||||
Event::Lib(lib) => {
|
||||
world_state.add_lib(lib);
|
||||
world_state.maybe_collect_garbage();
|
||||
global_state.add_lib(lib);
|
||||
global_state.maybe_collect_garbage();
|
||||
loop_state.in_flight_libraries -= 1;
|
||||
loop_state.roots_scanned += 1;
|
||||
}
|
||||
Event::CheckWatcher(task) => on_check_task(task, world_state, task_sender)?,
|
||||
Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?,
|
||||
Event::Msg(msg) => match msg {
|
||||
Message::Request(req) => on_request(
|
||||
world_state,
|
||||
global_state,
|
||||
&mut loop_state.pending_requests,
|
||||
pool,
|
||||
task_sender,
|
||||
@ -359,7 +360,7 @@ fn loop_turn(
|
||||
req,
|
||||
)?,
|
||||
Message::Notification(not) => {
|
||||
on_notification(&connection.sender, world_state, loop_state, not)?;
|
||||
on_notification(&connection.sender, global_state, loop_state, not)?;
|
||||
}
|
||||
Message::Response(resp) => {
|
||||
let removed = loop_state.pending_responses.remove(&resp.id);
|
||||
@ -378,9 +379,9 @@ fn loop_turn(
|
||||
}
|
||||
(None, Some(configs)) => {
|
||||
if let Some(new_config) = configs.get(0) {
|
||||
let mut config = world_state.config.clone();
|
||||
let mut config = global_state.config.clone();
|
||||
config.update(&new_config);
|
||||
world_state.update_configuration(config);
|
||||
global_state.update_configuration(config);
|
||||
}
|
||||
}
|
||||
(None, None) => {
|
||||
@ -393,7 +394,7 @@ fn loop_turn(
|
||||
};
|
||||
|
||||
let mut state_changed = false;
|
||||
if let Some(changes) = world_state.process_changes(&mut loop_state.roots_scanned) {
|
||||
if let Some(changes) = global_state.process_changes(&mut loop_state.roots_scanned) {
|
||||
state_changed = true;
|
||||
loop_state.pending_libraries.extend(changes);
|
||||
}
|
||||
@ -415,7 +416,7 @@ fn loop_turn(
|
||||
}
|
||||
|
||||
let show_progress =
|
||||
!loop_state.workspace_loaded && world_state.config.client_caps.work_done_progress;
|
||||
!loop_state.workspace_loaded && global_state.config.client_caps.work_done_progress;
|
||||
|
||||
if !loop_state.workspace_loaded
|
||||
&& loop_state.roots_scanned == loop_state.roots_total
|
||||
@ -424,7 +425,7 @@ fn loop_turn(
|
||||
{
|
||||
state_changed = true;
|
||||
loop_state.workspace_loaded = true;
|
||||
if let Some(flycheck) = &world_state.flycheck {
|
||||
if let Some(flycheck) = &global_state.flycheck {
|
||||
flycheck.update();
|
||||
}
|
||||
}
|
||||
@ -436,13 +437,13 @@ fn loop_turn(
|
||||
if state_changed && loop_state.workspace_loaded {
|
||||
update_file_notifications_on_threadpool(
|
||||
pool,
|
||||
world_state.snapshot(),
|
||||
global_state.snapshot(),
|
||||
task_sender.clone(),
|
||||
loop_state.subscriptions.subscriptions(),
|
||||
);
|
||||
pool.execute({
|
||||
let subs = loop_state.subscriptions.subscriptions();
|
||||
let snap = world_state.snapshot();
|
||||
let snap = global_state.snapshot();
|
||||
move || snap.analysis().prime_caches(subs).unwrap_or_else(|_: Canceled| ())
|
||||
});
|
||||
}
|
||||
@ -466,7 +467,7 @@ fn on_task(
|
||||
task: Task,
|
||||
msg_sender: &Sender<Message>,
|
||||
pending_requests: &mut PendingRequests,
|
||||
state: &mut WorldState,
|
||||
state: &mut GlobalState,
|
||||
) {
|
||||
match task {
|
||||
Task::Respond(response) => {
|
||||
@ -484,7 +485,7 @@ fn on_task(
|
||||
}
|
||||
|
||||
fn on_request(
|
||||
world: &mut WorldState,
|
||||
global_state: &mut GlobalState,
|
||||
pending_requests: &mut PendingRequests,
|
||||
pool: &ThreadPool,
|
||||
task_sender: &Sender<Task>,
|
||||
@ -495,7 +496,7 @@ fn on_request(
|
||||
let mut pool_dispatcher = PoolDispatcher {
|
||||
req: Some(req),
|
||||
pool,
|
||||
world,
|
||||
global_state,
|
||||
task_sender,
|
||||
msg_sender,
|
||||
pending_requests,
|
||||
@ -551,7 +552,7 @@ fn on_request(
|
||||
|
||||
fn on_notification(
|
||||
msg_sender: &Sender<Message>,
|
||||
state: &mut WorldState,
|
||||
state: &mut GlobalState,
|
||||
loop_state: &mut LoopState,
|
||||
not: Notification,
|
||||
) -> Result<()> {
|
||||
@ -725,7 +726,7 @@ fn apply_document_changes(
|
||||
|
||||
fn on_check_task(
|
||||
task: CheckTask,
|
||||
world_state: &mut WorldState,
|
||||
global_state: &mut GlobalState,
|
||||
task_sender: &Sender<Task>,
|
||||
) -> Result<()> {
|
||||
match task {
|
||||
@ -744,7 +745,7 @@ fn on_check_task(
|
||||
.uri
|
||||
.to_file_path()
|
||||
.map_err(|()| format!("invalid uri: {}", diag.location.uri))?;
|
||||
let file_id = match world_state.vfs.read().path2file(&path) {
|
||||
let file_id = match global_state.vfs.read().path2file(&path) {
|
||||
Some(file) => FileId(file.0),
|
||||
None => {
|
||||
log::error!(
|
||||
@ -764,7 +765,7 @@ fn on_check_task(
|
||||
}
|
||||
|
||||
CheckTask::Status(status) => {
|
||||
if world_state.config.client_caps.work_done_progress {
|
||||
if global_state.config.client_caps.work_done_progress {
|
||||
let progress = match status {
|
||||
Status::Being => {
|
||||
lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
|
||||
@ -803,7 +804,7 @@ fn on_check_task(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: &mut WorldState) {
|
||||
fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state: &mut GlobalState) {
|
||||
let subscriptions = state.diagnostics.handle_task(task);
|
||||
|
||||
for file_id in subscriptions {
|
||||
@ -878,7 +879,7 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
|
||||
struct PoolDispatcher<'a> {
|
||||
req: Option<Request>,
|
||||
pool: &'a ThreadPool,
|
||||
world: &'a mut WorldState,
|
||||
global_state: &'a mut GlobalState,
|
||||
pending_requests: &'a mut PendingRequests,
|
||||
msg_sender: &'a Sender<Message>,
|
||||
task_sender: &'a Sender<Task>,
|
||||
@ -889,7 +890,7 @@ impl<'a> PoolDispatcher<'a> {
|
||||
/// Dispatches the request onto the current thread
|
||||
fn on_sync<R>(
|
||||
&mut self,
|
||||
f: fn(&mut WorldState, R::Params) -> Result<R::Result>,
|
||||
f: fn(&mut GlobalState, R::Params) -> Result<R::Result>,
|
||||
) -> Result<&mut Self>
|
||||
where
|
||||
R: lsp_types::request::Request + 'static,
|
||||
@ -902,18 +903,21 @@ impl<'a> PoolDispatcher<'a> {
|
||||
return Ok(self);
|
||||
}
|
||||
};
|
||||
let world = panic::AssertUnwindSafe(&mut *self.world);
|
||||
let world = panic::AssertUnwindSafe(&mut *self.global_state);
|
||||
let task = panic::catch_unwind(move || {
|
||||
let result = f(world.0, params);
|
||||
result_to_task::<R>(id, result)
|
||||
})
|
||||
.map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
|
||||
on_task(task, self.msg_sender, self.pending_requests, self.world);
|
||||
on_task(task, self.msg_sender, self.pending_requests, self.global_state);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Dispatches the request onto thread pool
|
||||
fn on<R>(&mut self, f: fn(WorldSnapshot, R::Params) -> Result<R::Result>) -> Result<&mut Self>
|
||||
fn on<R>(
|
||||
&mut self,
|
||||
f: fn(GlobalStateSnapshot, R::Params) -> Result<R::Result>,
|
||||
) -> Result<&mut Self>
|
||||
where
|
||||
R: lsp_types::request::Request + 'static,
|
||||
R::Params: DeserializeOwned + Send + 'static,
|
||||
@ -927,7 +931,7 @@ impl<'a> PoolDispatcher<'a> {
|
||||
};
|
||||
|
||||
self.pool.execute({
|
||||
let world = self.world.snapshot();
|
||||
let world = self.global_state.snapshot();
|
||||
let sender = self.task_sender.clone();
|
||||
move || {
|
||||
let result = f(world, params);
|
||||
@ -1011,7 +1015,7 @@ where
|
||||
|
||||
fn update_file_notifications_on_threadpool(
|
||||
pool: &ThreadPool,
|
||||
world: WorldSnapshot,
|
||||
world: GlobalStateSnapshot,
|
||||
task_sender: Sender<Task>,
|
||||
subscriptions: Vec<FileId>,
|
||||
) {
|
||||
|
@ -32,17 +32,16 @@ use crate::{
|
||||
config::RustfmtConfig,
|
||||
diagnostics::DiagnosticTask,
|
||||
from_json, from_proto,
|
||||
global_state::GlobalStateSnapshot,
|
||||
lsp_ext::{self, InlayHint, InlayHintsParams},
|
||||
to_proto,
|
||||
world::WorldSnapshot,
|
||||
LspError, Result,
|
||||
to_proto, LspError, Result,
|
||||
};
|
||||
|
||||
pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
|
||||
pub fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result<String> {
|
||||
let _p = profile("handle_analyzer_status");
|
||||
let mut buf = world.status();
|
||||
let mut buf = snap.status();
|
||||
format_to!(buf, "\n\nrequests:\n");
|
||||
let requests = world.latest_requests.read();
|
||||
let requests = snap.latest_requests.read();
|
||||
for (is_last, r) in requests.iter() {
|
||||
let mark = if is_last { "*" } else { " " };
|
||||
format_to!(buf, "{}{:4} {:<36}{}ms\n", mark, r.id, r.method, r.duration.as_millis());
|
||||
@ -51,37 +50,37 @@ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
|
||||
}
|
||||
|
||||
pub fn handle_syntax_tree(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::SyntaxTreeParams,
|
||||
) -> Result<String> {
|
||||
let _p = profile("handle_syntax_tree");
|
||||
let id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(id)?;
|
||||
let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(id)?;
|
||||
let text_range = params.range.map(|r| from_proto::text_range(&line_index, r));
|
||||
let res = world.analysis().syntax_tree(id, text_range)?;
|
||||
let res = snap.analysis().syntax_tree(id, text_range)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn handle_expand_macro(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::ExpandMacroParams,
|
||||
) -> Result<Option<lsp_ext::ExpandedMacro>> {
|
||||
let _p = profile("handle_expand_macro");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let offset = from_proto::offset(&line_index, params.position);
|
||||
|
||||
let res = world.analysis().expand_macro(FilePosition { file_id, offset })?;
|
||||
let res = snap.analysis().expand_macro(FilePosition { file_id, offset })?;
|
||||
Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion }))
|
||||
}
|
||||
|
||||
pub fn handle_selection_range(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::SelectionRangeParams,
|
||||
) -> Result<Option<Vec<lsp_types::SelectionRange>>> {
|
||||
let _p = profile("handle_selection_range");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let res: Result<Vec<lsp_types::SelectionRange>> = params
|
||||
.positions
|
||||
.into_iter()
|
||||
@ -93,7 +92,7 @@ pub fn handle_selection_range(
|
||||
loop {
|
||||
ranges.push(range);
|
||||
let frange = FileRange { file_id, range };
|
||||
let next = world.analysis().extend_selection(frange)?;
|
||||
let next = snap.analysis().extend_selection(frange)?;
|
||||
if next == range {
|
||||
break;
|
||||
} else {
|
||||
@ -119,18 +118,18 @@ pub fn handle_selection_range(
|
||||
}
|
||||
|
||||
pub fn handle_matching_brace(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::MatchingBraceParams,
|
||||
) -> Result<Vec<Position>> {
|
||||
let _p = profile("handle_matching_brace");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let res = params
|
||||
.positions
|
||||
.into_iter()
|
||||
.map(|position| {
|
||||
let offset = from_proto::offset(&line_index, position);
|
||||
let offset = match world.analysis().matching_brace(FilePosition { file_id, offset }) {
|
||||
let offset = match snap.analysis().matching_brace(FilePosition { file_id, offset }) {
|
||||
Ok(Some(matching_brace_offset)) => matching_brace_offset,
|
||||
Err(_) | Ok(None) => offset,
|
||||
};
|
||||
@ -141,17 +140,17 @@ pub fn handle_matching_brace(
|
||||
}
|
||||
|
||||
pub fn handle_join_lines(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::JoinLinesParams,
|
||||
) -> Result<Vec<lsp_types::TextEdit>> {
|
||||
let _p = profile("handle_join_lines");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let line_endings = world.file_line_endings(file_id);
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let line_endings = snap.file_line_endings(file_id);
|
||||
let mut res = TextEdit::default();
|
||||
for range in params.ranges {
|
||||
let range = from_proto::text_range(&line_index, range);
|
||||
let edit = world.analysis().join_lines(FileRange { file_id, range })?;
|
||||
let edit = snap.analysis().join_lines(FileRange { file_id, range })?;
|
||||
match res.union(edit) {
|
||||
Ok(()) => (),
|
||||
Err(_edit) => {
|
||||
@ -164,37 +163,37 @@ pub fn handle_join_lines(
|
||||
}
|
||||
|
||||
pub fn handle_on_enter(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> Result<Option<Vec<lsp_ext::SnippetTextEdit>>> {
|
||||
let _p = profile("handle_on_enter");
|
||||
let position = from_proto::file_position(&world, params)?;
|
||||
let edit = match world.analysis().on_enter(position)? {
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let edit = match snap.analysis().on_enter(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
let line_index = world.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = world.file_line_endings(position.file_id);
|
||||
let line_index = snap.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = snap.file_line_endings(position.file_id);
|
||||
let edit = to_proto::snippet_text_edit_vec(&line_index, line_endings, true, edit);
|
||||
Ok(Some(edit))
|
||||
}
|
||||
|
||||
// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`.
|
||||
pub fn handle_on_type_formatting(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::DocumentOnTypeFormattingParams,
|
||||
) -> Result<Option<Vec<lsp_types::TextEdit>>> {
|
||||
let _p = profile("handle_on_type_formatting");
|
||||
let mut position = from_proto::file_position(&world, params.text_document_position)?;
|
||||
let line_index = world.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = world.file_line_endings(position.file_id);
|
||||
let mut position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
let line_index = snap.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = snap.file_line_endings(position.file_id);
|
||||
|
||||
// in `ra_ide`, the `on_type` invariant is that
|
||||
// `text.char_at(position) == typed_char`.
|
||||
position.offset -= TextSize::of('.');
|
||||
let char_typed = params.ch.chars().next().unwrap_or('\0');
|
||||
assert!({
|
||||
let text = world.analysis().file_text(position.file_id)?;
|
||||
let text = snap.analysis().file_text(position.file_id)?;
|
||||
text[usize::from(position.offset)..].starts_with(char_typed)
|
||||
});
|
||||
|
||||
@ -206,7 +205,7 @@ pub fn handle_on_type_formatting(
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let edit = world.analysis().on_char_typed(position, char_typed)?;
|
||||
let edit = snap.analysis().on_char_typed(position, char_typed)?;
|
||||
let mut edit = match edit {
|
||||
Some(it) => it,
|
||||
None => return Ok(None),
|
||||
@ -220,16 +219,16 @@ pub fn handle_on_type_formatting(
|
||||
}
|
||||
|
||||
pub fn handle_document_symbol(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::DocumentSymbolParams,
|
||||
) -> Result<Option<lsp_types::DocumentSymbolResponse>> {
|
||||
let _p = profile("handle_document_symbol");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
|
||||
let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
|
||||
|
||||
for symbol in world.analysis().file_structure(file_id)? {
|
||||
for symbol in snap.analysis().file_structure(file_id)? {
|
||||
let doc_symbol = DocumentSymbol {
|
||||
name: symbol.label,
|
||||
detail: symbol.detail,
|
||||
@ -255,10 +254,10 @@ pub fn handle_document_symbol(
|
||||
}
|
||||
}
|
||||
|
||||
let res = if world.config.client_caps.hierarchical_symbols {
|
||||
let res = if snap.config.client_caps.hierarchical_symbols {
|
||||
document_symbols.into()
|
||||
} else {
|
||||
let url = to_proto::url(&world, file_id)?;
|
||||
let url = to_proto::url(&snap, file_id)?;
|
||||
let mut symbol_information = Vec::<SymbolInformation>::new();
|
||||
for symbol in document_symbols {
|
||||
flatten_document_symbol(&symbol, None, &url, &mut symbol_information);
|
||||
@ -288,7 +287,7 @@ pub fn handle_document_symbol(
|
||||
}
|
||||
|
||||
pub fn handle_workspace_symbol(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::WorkspaceSymbolParams,
|
||||
) -> Result<Option<Vec<SymbolInformation>>> {
|
||||
let _p = profile("handle_workspace_symbol");
|
||||
@ -306,22 +305,22 @@ pub fn handle_workspace_symbol(
|
||||
q.limit(128);
|
||||
q
|
||||
};
|
||||
let mut res = exec_query(&world, query)?;
|
||||
let mut res = exec_query(&snap, query)?;
|
||||
if res.is_empty() && !all_symbols {
|
||||
let mut query = Query::new(params.query);
|
||||
query.limit(128);
|
||||
res = exec_query(&world, query)?;
|
||||
res = exec_query(&snap, query)?;
|
||||
}
|
||||
|
||||
return Ok(Some(res));
|
||||
|
||||
fn exec_query(world: &WorldSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
|
||||
fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
|
||||
let mut res = Vec::new();
|
||||
for nav in world.analysis().symbol_search(query)? {
|
||||
for nav in snap.analysis().symbol_search(query)? {
|
||||
let info = SymbolInformation {
|
||||
name: nav.name().to_string(),
|
||||
kind: to_proto::symbol_kind(nav.kind()),
|
||||
location: to_proto::location(world, nav.file_range())?,
|
||||
location: to_proto::location(snap, nav.file_range())?,
|
||||
container_name: nav.container_name().map(|v| v.to_string()),
|
||||
deprecated: None,
|
||||
};
|
||||
@ -332,73 +331,73 @@ pub fn handle_workspace_symbol(
|
||||
}
|
||||
|
||||
pub fn handle_goto_definition(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::GotoDefinitionParams,
|
||||
) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
|
||||
let _p = profile("handle_goto_definition");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let nav_info = match world.analysis().goto_definition(position)? {
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let nav_info = match snap.analysis().goto_definition(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||
let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_goto_implementation(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::request::GotoImplementationParams,
|
||||
) -> Result<Option<lsp_types::request::GotoImplementationResponse>> {
|
||||
let _p = profile("handle_goto_implementation");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let nav_info = match world.analysis().goto_implementation(position)? {
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let nav_info = match snap.analysis().goto_implementation(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||
let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_goto_type_definition(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::request::GotoTypeDefinitionParams,
|
||||
) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> {
|
||||
let _p = profile("handle_goto_type_definition");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let nav_info = match world.analysis().goto_type_definition(position)? {
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let nav_info = match snap.analysis().goto_type_definition(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
let src = FileRange { file_id: position.file_id, range: nav_info.range };
|
||||
let res = to_proto::goto_definition_response(&world, Some(src), nav_info.info)?;
|
||||
let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_parent_module(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
|
||||
let _p = profile("handle_parent_module");
|
||||
let position = from_proto::file_position(&world, params)?;
|
||||
let navs = world.analysis().parent_module(position)?;
|
||||
let res = to_proto::goto_definition_response(&world, None, navs)?;
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let navs = snap.analysis().parent_module(position)?;
|
||||
let res = to_proto::goto_definition_response(&snap, None, navs)?;
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_runnables(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::RunnablesParams,
|
||||
) -> Result<Vec<lsp_ext::Runnable>> {
|
||||
let _p = profile("handle_runnables");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let offset = params.position.map(|it| from_proto::offset(&line_index, it));
|
||||
let mut res = Vec::new();
|
||||
let workspace_root = world.workspace_root_for(file_id);
|
||||
let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
|
||||
for runnable in world.analysis().runnables(file_id)? {
|
||||
let workspace_root = snap.workspace_root_for(file_id);
|
||||
let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?;
|
||||
for runnable in snap.analysis().runnables(file_id)? {
|
||||
if let Some(offset) = offset {
|
||||
if !runnable.nav.full_range().contains_inclusive(offset) {
|
||||
continue;
|
||||
@ -413,7 +412,7 @@ pub fn handle_runnables(
|
||||
}
|
||||
}
|
||||
}
|
||||
res.push(to_proto::runnable(&world, file_id, runnable)?);
|
||||
res.push(to_proto::runnable(&snap, file_id, runnable)?);
|
||||
}
|
||||
|
||||
// Add `cargo check` and `cargo test` for the whole package
|
||||
@ -453,16 +452,16 @@ pub fn handle_runnables(
|
||||
}
|
||||
|
||||
pub fn handle_completion(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::CompletionParams,
|
||||
) -> Result<Option<lsp_types::CompletionResponse>> {
|
||||
let _p = profile("handle_completion");
|
||||
let position = from_proto::file_position(&world, params.text_document_position)?;
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
let completion_triggered_after_single_colon = {
|
||||
let mut res = false;
|
||||
if let Some(ctx) = params.context {
|
||||
if ctx.trigger_character.unwrap_or_default() == ":" {
|
||||
let source_file = world.analysis().parse(position.file_id)?;
|
||||
let source_file = snap.analysis().parse(position.file_id)?;
|
||||
let syntax = source_file.syntax();
|
||||
let text = syntax.text();
|
||||
if let Some(next_char) = text.char_at(position.offset) {
|
||||
@ -480,12 +479,12 @@ pub fn handle_completion(
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let items = match world.analysis().completions(&world.config.completion, position)? {
|
||||
let items = match snap.analysis().completions(&snap.config.completion, position)? {
|
||||
None => return Ok(None),
|
||||
Some(items) => items,
|
||||
};
|
||||
let line_index = world.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = world.file_line_endings(position.file_id);
|
||||
let line_index = snap.analysis().file_line_index(position.file_id)?;
|
||||
let line_endings = snap.file_line_endings(position.file_id);
|
||||
let items: Vec<CompletionItem> = items
|
||||
.into_iter()
|
||||
.map(|item| to_proto::completion_item(&line_index, line_endings, item))
|
||||
@ -495,15 +494,15 @@ pub fn handle_completion(
|
||||
}
|
||||
|
||||
pub fn handle_folding_range(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: FoldingRangeParams,
|
||||
) -> Result<Option<Vec<FoldingRange>>> {
|
||||
let _p = profile("handle_folding_range");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let folds = world.analysis().folding_ranges(file_id)?;
|
||||
let text = world.analysis().file_text(file_id)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let line_folding_only = world.config.client_caps.line_folding_only;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let folds = snap.analysis().folding_ranges(file_id)?;
|
||||
let text = snap.analysis().file_text(file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let line_folding_only = snap.config.client_caps.line_folding_only;
|
||||
let res = folds
|
||||
.into_iter()
|
||||
.map(|it| to_proto::folding_range(&*text, &line_index, line_folding_only, it))
|
||||
@ -512,16 +511,16 @@ pub fn handle_folding_range(
|
||||
}
|
||||
|
||||
pub fn handle_signature_help(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::SignatureHelpParams,
|
||||
) -> Result<Option<lsp_types::SignatureHelp>> {
|
||||
let _p = profile("handle_signature_help");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let call_info = match world.analysis().call_info(position)? {
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let call_info = match snap.analysis().call_info(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
let concise = !world.config.call_info_full;
|
||||
let concise = !snap.config.call_info_full;
|
||||
let mut active_parameter = call_info.active_parameter.map(|it| it as i64);
|
||||
if concise && call_info.signature.has_self_param {
|
||||
active_parameter = active_parameter.map(|it| it.saturating_sub(1));
|
||||
@ -535,14 +534,17 @@ pub fn handle_signature_help(
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn handle_hover(world: WorldSnapshot, params: lsp_types::HoverParams) -> Result<Option<Hover>> {
|
||||
pub fn handle_hover(
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::HoverParams,
|
||||
) -> Result<Option<Hover>> {
|
||||
let _p = profile("handle_hover");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let info = match world.analysis().hover(position)? {
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let info = match snap.analysis().hover(position)? {
|
||||
None => return Ok(None),
|
||||
Some(info) => info,
|
||||
};
|
||||
let line_index = world.analysis.file_line_index(position.file_id)?;
|
||||
let line_index = snap.analysis.file_line_index(position.file_id)?;
|
||||
let range = to_proto::range(&line_index, info.range);
|
||||
let res = Hover {
|
||||
contents: HoverContents::Markup(MarkupContent {
|
||||
@ -555,26 +557,29 @@ pub fn handle_hover(world: WorldSnapshot, params: lsp_types::HoverParams) -> Res
|
||||
}
|
||||
|
||||
pub fn handle_prepare_rename(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> Result<Option<PrepareRenameResponse>> {
|
||||
let _p = profile("handle_prepare_rename");
|
||||
let position = from_proto::file_position(&world, params)?;
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
|
||||
let optional_change = world.analysis().rename(position, "dummy")?;
|
||||
let optional_change = snap.analysis().rename(position, "dummy")?;
|
||||
let range = match optional_change {
|
||||
None => return Ok(None),
|
||||
Some(it) => it.range,
|
||||
};
|
||||
|
||||
let line_index = world.analysis().file_line_index(position.file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(position.file_id)?;
|
||||
let range = to_proto::range(&line_index, range);
|
||||
Ok(Some(PrepareRenameResponse::Range(range)))
|
||||
}
|
||||
|
||||
pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> {
|
||||
pub fn handle_rename(
|
||||
snap: GlobalStateSnapshot,
|
||||
params: RenameParams,
|
||||
) -> Result<Option<WorkspaceEdit>> {
|
||||
let _p = profile("handle_rename");
|
||||
let position = from_proto::file_position(&world, params.text_document_position)?;
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
|
||||
if params.new_name.is_empty() {
|
||||
return Err(LspError::new(
|
||||
@ -584,36 +589,36 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Optio
|
||||
.into());
|
||||
}
|
||||
|
||||
let optional_change = world.analysis().rename(position, &*params.new_name)?;
|
||||
let optional_change = snap.analysis().rename(position, &*params.new_name)?;
|
||||
let source_change = match optional_change {
|
||||
None => return Ok(None),
|
||||
Some(it) => it.info,
|
||||
};
|
||||
let workspace_edit = to_proto::workspace_edit(&world, source_change)?;
|
||||
let workspace_edit = to_proto::workspace_edit(&snap, source_change)?;
|
||||
Ok(Some(workspace_edit))
|
||||
}
|
||||
|
||||
pub fn handle_references(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::ReferenceParams,
|
||||
) -> Result<Option<Vec<Location>>> {
|
||||
let _p = profile("handle_references");
|
||||
let position = from_proto::file_position(&world, params.text_document_position)?;
|
||||
let position = from_proto::file_position(&snap, params.text_document_position)?;
|
||||
|
||||
let refs = match world.analysis().find_all_refs(position, None)? {
|
||||
let refs = match snap.analysis().find_all_refs(position, None)? {
|
||||
None => return Ok(None),
|
||||
Some(refs) => refs,
|
||||
};
|
||||
|
||||
let locations = if params.context.include_declaration {
|
||||
refs.into_iter()
|
||||
.filter_map(|reference| to_proto::location(&world, reference.file_range).ok())
|
||||
.filter_map(|reference| to_proto::location(&snap, reference.file_range).ok())
|
||||
.collect()
|
||||
} else {
|
||||
// Only iterate over the references if include_declaration was false
|
||||
refs.references()
|
||||
.iter()
|
||||
.filter_map(|reference| to_proto::location(&world, reference.file_range).ok())
|
||||
.filter_map(|reference| to_proto::location(&snap, reference.file_range).ok())
|
||||
.collect()
|
||||
};
|
||||
|
||||
@ -621,24 +626,24 @@ pub fn handle_references(
|
||||
}
|
||||
|
||||
pub fn handle_formatting(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: DocumentFormattingParams,
|
||||
) -> Result<Option<Vec<lsp_types::TextEdit>>> {
|
||||
let _p = profile("handle_formatting");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let file = world.analysis().file_text(file_id)?;
|
||||
let crate_ids = world.analysis().crate_for(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let file = snap.analysis().file_text(file_id)?;
|
||||
let crate_ids = snap.analysis().crate_for(file_id)?;
|
||||
|
||||
let file_line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str()));
|
||||
|
||||
let mut rustfmt = match &world.config.rustfmt {
|
||||
let mut rustfmt = match &snap.config.rustfmt {
|
||||
RustfmtConfig::Rustfmt { extra_args } => {
|
||||
let mut cmd = process::Command::new("rustfmt");
|
||||
cmd.args(extra_args);
|
||||
if let Some(&crate_id) = crate_ids.first() {
|
||||
// Assume all crates are in the same edition
|
||||
let edition = world.analysis().crate_edition(crate_id)?;
|
||||
let edition = snap.analysis().crate_edition(crate_id)?;
|
||||
cmd.arg("--edition");
|
||||
cmd.arg(edition.to_string());
|
||||
}
|
||||
@ -697,23 +702,23 @@ pub fn handle_formatting(
|
||||
}
|
||||
|
||||
pub fn handle_code_action(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::CodeActionParams,
|
||||
) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
|
||||
let _p = profile("handle_code_action");
|
||||
// We intentionally don't support command-based actions, as those either
|
||||
// requires custom client-code anyway, or requires server-initiated edits.
|
||||
// Server initiated edits break causality, so we avoid those as well.
|
||||
if !world.config.client_caps.code_action_literals {
|
||||
if !snap.config.client_caps.code_action_literals {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let range = from_proto::text_range(&line_index, params.range);
|
||||
let frange = FileRange { file_id, range };
|
||||
|
||||
let diagnostics = world.analysis().diagnostics(file_id)?;
|
||||
let diagnostics = snap.analysis().diagnostics(file_id)?;
|
||||
let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
|
||||
|
||||
let fixes_from_diagnostics = diagnostics
|
||||
@ -724,13 +729,13 @@ pub fn handle_code_action(
|
||||
|
||||
for fix in fixes_from_diagnostics {
|
||||
let title = fix.label;
|
||||
let edit = to_proto::snippet_workspace_edit(&world, fix.source_change)?;
|
||||
let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?;
|
||||
let action =
|
||||
lsp_ext::CodeAction { title, group: None, kind: None, edit: Some(edit), command: None };
|
||||
res.push(action);
|
||||
}
|
||||
|
||||
for fix in world.check_fixes.get(&file_id).into_iter().flatten() {
|
||||
for fix in snap.check_fixes.get(&file_id).into_iter().flatten() {
|
||||
let fix_range = from_proto::text_range(&line_index, fix.range);
|
||||
if fix_range.intersect(range).is_none() {
|
||||
continue;
|
||||
@ -738,31 +743,31 @@ pub fn handle_code_action(
|
||||
res.push(fix.action.clone());
|
||||
}
|
||||
|
||||
for assist in world.analysis().assists(&world.config.assist, frange)?.into_iter() {
|
||||
res.push(to_proto::code_action(&world, assist)?.into());
|
||||
for assist in snap.analysis().assists(&snap.config.assist, frange)?.into_iter() {
|
||||
res.push(to_proto::code_action(&snap, assist)?.into());
|
||||
}
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_code_lens(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::CodeLensParams,
|
||||
) -> Result<Option<Vec<CodeLens>>> {
|
||||
let _p = profile("handle_code_lens");
|
||||
let mut lenses: Vec<CodeLens> = Default::default();
|
||||
|
||||
if world.config.lens.none() {
|
||||
if snap.config.lens.none() {
|
||||
// early return before any db query!
|
||||
return Ok(Some(lenses));
|
||||
}
|
||||
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let cargo_spec = CargoTargetSpec::for_file(&snap, file_id)?;
|
||||
|
||||
if world.config.lens.runnable() {
|
||||
if snap.config.lens.runnable() {
|
||||
// Gather runnables
|
||||
for runnable in world.analysis().runnables(file_id)? {
|
||||
for runnable in snap.analysis().runnables(file_id)? {
|
||||
let (run_title, debugee) = match &runnable.kind {
|
||||
RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
|
||||
("▶\u{fe0e} Run Test", true)
|
||||
@ -788,8 +793,8 @@ pub fn handle_code_lens(
|
||||
};
|
||||
|
||||
let range = to_proto::range(&line_index, runnable.nav.range());
|
||||
let r = to_proto::runnable(&world, file_id, runnable)?;
|
||||
if world.config.lens.run {
|
||||
let r = to_proto::runnable(&snap, file_id, runnable)?;
|
||||
if snap.config.lens.run {
|
||||
let lens = CodeLens {
|
||||
range,
|
||||
command: Some(Command {
|
||||
@ -802,7 +807,7 @@ pub fn handle_code_lens(
|
||||
lenses.push(lens);
|
||||
}
|
||||
|
||||
if debugee && world.config.lens.debug {
|
||||
if debugee && snap.config.lens.debug {
|
||||
let debug_lens = CodeLens {
|
||||
range,
|
||||
command: Some(Command {
|
||||
@ -817,11 +822,10 @@ pub fn handle_code_lens(
|
||||
}
|
||||
}
|
||||
|
||||
if world.config.lens.impementations {
|
||||
if snap.config.lens.impementations {
|
||||
// Handle impls
|
||||
lenses.extend(
|
||||
world
|
||||
.analysis()
|
||||
snap.analysis()
|
||||
.file_structure(file_id)?
|
||||
.into_iter()
|
||||
.filter(|it| match it.kind {
|
||||
@ -856,14 +860,17 @@ enum CodeLensResolveData {
|
||||
Impls(lsp_types::request::GotoImplementationParams),
|
||||
}
|
||||
|
||||
pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> {
|
||||
pub fn handle_code_lens_resolve(
|
||||
snap: GlobalStateSnapshot,
|
||||
code_lens: CodeLens,
|
||||
) -> Result<CodeLens> {
|
||||
let _p = profile("handle_code_lens_resolve");
|
||||
let data = code_lens.data.unwrap();
|
||||
let resolve = from_json::<Option<CodeLensResolveData>>("CodeLensResolveData", data)?;
|
||||
match resolve {
|
||||
Some(CodeLensResolveData::Impls(lens_params)) => {
|
||||
let locations: Vec<Location> =
|
||||
match handle_goto_implementation(world, lens_params.clone())? {
|
||||
match handle_goto_implementation(snap, lens_params.clone())? {
|
||||
Some(lsp_types::GotoDefinitionResponse::Scalar(loc)) => vec![loc],
|
||||
Some(lsp_types::GotoDefinitionResponse::Array(locs)) => locs,
|
||||
Some(lsp_types::GotoDefinitionResponse::Link(links)) => links
|
||||
@ -902,14 +909,14 @@ pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Re
|
||||
}
|
||||
|
||||
pub fn handle_document_highlight(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::DocumentHighlightParams,
|
||||
) -> Result<Option<Vec<DocumentHighlight>>> {
|
||||
let _p = profile("handle_document_highlight");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let line_index = world.analysis().file_line_index(position.file_id)?;
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
let line_index = snap.analysis().file_line_index(position.file_id)?;
|
||||
|
||||
let refs = match world
|
||||
let refs = match snap
|
||||
.analysis()
|
||||
.find_all_refs(position, Some(SearchScope::single_file(position.file_id)))?
|
||||
{
|
||||
@ -929,19 +936,19 @@ pub fn handle_document_highlight(
|
||||
}
|
||||
|
||||
pub fn handle_ssr(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::SsrParams,
|
||||
) -> Result<lsp_types::WorkspaceEdit> {
|
||||
let _p = profile("handle_ssr");
|
||||
let source_change =
|
||||
world.analysis().structural_search_replace(¶ms.query, params.parse_only)??;
|
||||
to_proto::workspace_edit(&world, source_change)
|
||||
snap.analysis().structural_search_replace(¶ms.query, params.parse_only)??;
|
||||
to_proto::workspace_edit(&snap, source_change)
|
||||
}
|
||||
|
||||
pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> {
|
||||
pub fn publish_diagnostics(snap: &GlobalStateSnapshot, file_id: FileId) -> Result<DiagnosticTask> {
|
||||
let _p = profile("publish_diagnostics");
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let diagnostics: Vec<Diagnostic> = world
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let diagnostics: Vec<Diagnostic> = snap
|
||||
.analysis()
|
||||
.diagnostics(file_id)?
|
||||
.into_iter()
|
||||
@ -959,28 +966,28 @@ pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<Dia
|
||||
}
|
||||
|
||||
pub fn handle_inlay_hints(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: InlayHintsParams,
|
||||
) -> Result<Vec<InlayHint>> {
|
||||
let _p = profile("handle_inlay_hints");
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let analysis = world.analysis();
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let analysis = snap.analysis();
|
||||
let line_index = analysis.file_line_index(file_id)?;
|
||||
Ok(analysis
|
||||
.inlay_hints(file_id, &world.config.inlay_hints)?
|
||||
.inlay_hints(file_id, &snap.config.inlay_hints)?
|
||||
.into_iter()
|
||||
.map(|it| to_proto::inlay_int(&line_index, it))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn handle_call_hierarchy_prepare(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: CallHierarchyPrepareParams,
|
||||
) -> Result<Option<Vec<CallHierarchyItem>>> {
|
||||
let _p = profile("handle_call_hierarchy_prepare");
|
||||
let position = from_proto::file_position(&world, params.text_document_position_params)?;
|
||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||
|
||||
let nav_info = match world.analysis().call_hierarchy(position)? {
|
||||
let nav_info = match snap.analysis().call_hierarchy(position)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
@ -989,24 +996,24 @@ pub fn handle_call_hierarchy_prepare(
|
||||
let res = navs
|
||||
.into_iter()
|
||||
.filter(|it| it.kind() == SyntaxKind::FN_DEF)
|
||||
.map(|it| to_proto::call_hierarchy_item(&world, it))
|
||||
.map(|it| to_proto::call_hierarchy_item(&snap, it))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
Ok(Some(res))
|
||||
}
|
||||
|
||||
pub fn handle_call_hierarchy_incoming(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: CallHierarchyIncomingCallsParams,
|
||||
) -> Result<Option<Vec<CallHierarchyIncomingCall>>> {
|
||||
let _p = profile("handle_call_hierarchy_incoming");
|
||||
let item = params.item;
|
||||
|
||||
let doc = TextDocumentIdentifier::new(item.uri);
|
||||
let frange = from_proto::file_range(&world, doc, item.range)?;
|
||||
let frange = from_proto::file_range(&snap, doc, item.range)?;
|
||||
let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
|
||||
let call_items = match world.analysis().incoming_calls(fpos)? {
|
||||
let call_items = match snap.analysis().incoming_calls(fpos)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
@ -1015,8 +1022,8 @@ pub fn handle_call_hierarchy_incoming(
|
||||
|
||||
for call_item in call_items.into_iter() {
|
||||
let file_id = call_item.target.file_id();
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let item = to_proto::call_hierarchy_item(&world, call_item.target)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let item = to_proto::call_hierarchy_item(&snap, call_item.target)?;
|
||||
res.push(CallHierarchyIncomingCall {
|
||||
from: item,
|
||||
from_ranges: call_item
|
||||
@ -1031,17 +1038,17 @@ pub fn handle_call_hierarchy_incoming(
|
||||
}
|
||||
|
||||
pub fn handle_call_hierarchy_outgoing(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: CallHierarchyOutgoingCallsParams,
|
||||
) -> Result<Option<Vec<CallHierarchyOutgoingCall>>> {
|
||||
let _p = profile("handle_call_hierarchy_outgoing");
|
||||
let item = params.item;
|
||||
|
||||
let doc = TextDocumentIdentifier::new(item.uri);
|
||||
let frange = from_proto::file_range(&world, doc, item.range)?;
|
||||
let frange = from_proto::file_range(&snap, doc, item.range)?;
|
||||
let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
|
||||
|
||||
let call_items = match world.analysis().outgoing_calls(fpos)? {
|
||||
let call_items = match snap.analysis().outgoing_calls(fpos)? {
|
||||
None => return Ok(None),
|
||||
Some(it) => it,
|
||||
};
|
||||
@ -1050,8 +1057,8 @@ pub fn handle_call_hierarchy_outgoing(
|
||||
|
||||
for call_item in call_items.into_iter() {
|
||||
let file_id = call_item.target.file_id();
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let item = to_proto::call_hierarchy_item(&world, call_item.target)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
let item = to_proto::call_hierarchy_item(&snap, call_item.target)?;
|
||||
res.push(CallHierarchyOutgoingCall {
|
||||
to: item,
|
||||
from_ranges: call_item
|
||||
@ -1066,31 +1073,31 @@ pub fn handle_call_hierarchy_outgoing(
|
||||
}
|
||||
|
||||
pub fn handle_semantic_tokens(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: SemanticTokensParams,
|
||||
) -> Result<Option<SemanticTokensResult>> {
|
||||
let _p = profile("handle_semantic_tokens");
|
||||
|
||||
let file_id = from_proto::file_id(&world, ¶ms.text_document.uri)?;
|
||||
let text = world.analysis().file_text(file_id)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?;
|
||||
let text = snap.analysis().file_text(file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(file_id)?;
|
||||
|
||||
let highlights = world.analysis().highlight(file_id)?;
|
||||
let highlights = snap.analysis().highlight(file_id)?;
|
||||
let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
|
||||
Ok(Some(semantic_tokens.into()))
|
||||
}
|
||||
|
||||
pub fn handle_semantic_tokens_range(
|
||||
world: WorldSnapshot,
|
||||
snap: GlobalStateSnapshot,
|
||||
params: SemanticTokensRangeParams,
|
||||
) -> Result<Option<SemanticTokensRangeResult>> {
|
||||
let _p = profile("handle_semantic_tokens_range");
|
||||
|
||||
let frange = from_proto::file_range(&world, params.text_document, params.range)?;
|
||||
let text = world.analysis().file_text(frange.file_id)?;
|
||||
let line_index = world.analysis().file_line_index(frange.file_id)?;
|
||||
let frange = from_proto::file_range(&snap, params.text_document, params.range)?;
|
||||
let text = snap.analysis().file_text(frange.file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(frange.file_id)?;
|
||||
|
||||
let highlights = world.analysis().highlight_range(frange)?;
|
||||
let highlights = snap.analysis().highlight_range(frange)?;
|
||||
let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
|
||||
Ok(Some(semantic_tokens.into()))
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ use ra_syntax::{SyntaxKind, TextRange, TextSize};
|
||||
use ra_vfs::LineEndings;
|
||||
|
||||
use crate::{
|
||||
cargo_target_spec::CargoTargetSpec, lsp_ext, semantic_tokens, world::WorldSnapshot, Result,
|
||||
cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, lsp_ext,
|
||||
semantic_tokens, Result,
|
||||
};
|
||||
|
||||
pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position {
|
||||
@ -384,41 +385,44 @@ pub(crate) fn folding_range(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn url(world: &WorldSnapshot, file_id: FileId) -> Result<lsp_types::Url> {
|
||||
world.file_id_to_uri(file_id)
|
||||
pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> Result<lsp_types::Url> {
|
||||
snap.file_id_to_uri(file_id)
|
||||
}
|
||||
|
||||
pub(crate) fn versioned_text_document_identifier(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
file_id: FileId,
|
||||
version: Option<i64>,
|
||||
) -> Result<lsp_types::VersionedTextDocumentIdentifier> {
|
||||
let res = lsp_types::VersionedTextDocumentIdentifier { uri: url(world, file_id)?, version };
|
||||
let res = lsp_types::VersionedTextDocumentIdentifier { uri: url(snap, file_id)?, version };
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_types::Location> {
|
||||
let url = url(world, frange.file_id)?;
|
||||
let line_index = world.analysis().file_line_index(frange.file_id)?;
|
||||
pub(crate) fn location(
|
||||
snap: &GlobalStateSnapshot,
|
||||
frange: FileRange,
|
||||
) -> Result<lsp_types::Location> {
|
||||
let url = url(snap, frange.file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(frange.file_id)?;
|
||||
let range = range(&line_index, frange.range);
|
||||
let loc = lsp_types::Location::new(url, range);
|
||||
Ok(loc)
|
||||
}
|
||||
|
||||
pub(crate) fn location_link(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
src: Option<FileRange>,
|
||||
target: NavigationTarget,
|
||||
) -> Result<lsp_types::LocationLink> {
|
||||
let origin_selection_range = match src {
|
||||
Some(src) => {
|
||||
let line_index = world.analysis().file_line_index(src.file_id)?;
|
||||
let line_index = snap.analysis().file_line_index(src.file_id)?;
|
||||
let range = range(&line_index, src.range);
|
||||
Some(range)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let (target_uri, target_range, target_selection_range) = location_info(world, target)?;
|
||||
let (target_uri, target_range, target_selection_range) = location_info(snap, target)?;
|
||||
let res = lsp_types::LocationLink {
|
||||
origin_selection_range,
|
||||
target_uri,
|
||||
@ -429,12 +433,12 @@ pub(crate) fn location_link(
|
||||
}
|
||||
|
||||
fn location_info(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
target: NavigationTarget,
|
||||
) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
|
||||
let line_index = world.analysis().file_line_index(target.file_id())?;
|
||||
let line_index = snap.analysis().file_line_index(target.file_id())?;
|
||||
|
||||
let target_uri = url(world, target.file_id())?;
|
||||
let target_uri = url(snap, target.file_id())?;
|
||||
let target_range = range(&line_index, target.full_range());
|
||||
let target_selection_range =
|
||||
target.focus_range().map(|it| range(&line_index, it)).unwrap_or(target_range);
|
||||
@ -442,14 +446,14 @@ fn location_info(
|
||||
}
|
||||
|
||||
pub(crate) fn goto_definition_response(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
src: Option<FileRange>,
|
||||
targets: Vec<NavigationTarget>,
|
||||
) -> Result<lsp_types::GotoDefinitionResponse> {
|
||||
if world.config.client_caps.location_link {
|
||||
if snap.config.client_caps.location_link {
|
||||
let links = targets
|
||||
.into_iter()
|
||||
.map(|nav| location_link(world, src, nav))
|
||||
.map(|nav| location_link(snap, src, nav))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Ok(links.into())
|
||||
} else {
|
||||
@ -457,7 +461,7 @@ pub(crate) fn goto_definition_response(
|
||||
.into_iter()
|
||||
.map(|nav| {
|
||||
location(
|
||||
world,
|
||||
snap,
|
||||
FileRange {
|
||||
file_id: nav.file_id(),
|
||||
range: nav.focus_range().unwrap_or(nav.range()),
|
||||
@ -470,13 +474,13 @@ pub(crate) fn goto_definition_response(
|
||||
}
|
||||
|
||||
pub(crate) fn snippet_text_document_edit(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
is_snippet: bool,
|
||||
source_file_edit: SourceFileEdit,
|
||||
) -> Result<lsp_ext::SnippetTextDocumentEdit> {
|
||||
let text_document = versioned_text_document_identifier(world, source_file_edit.file_id, None)?;
|
||||
let line_index = world.analysis().file_line_index(source_file_edit.file_id)?;
|
||||
let line_endings = world.file_line_endings(source_file_edit.file_id);
|
||||
let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id, None)?;
|
||||
let line_index = snap.analysis().file_line_index(source_file_edit.file_id)?;
|
||||
let line_endings = snap.file_line_endings(source_file_edit.file_id);
|
||||
let edits = source_file_edit
|
||||
.edit
|
||||
.into_iter()
|
||||
@ -486,17 +490,17 @@ pub(crate) fn snippet_text_document_edit(
|
||||
}
|
||||
|
||||
pub(crate) fn resource_op(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
file_system_edit: FileSystemEdit,
|
||||
) -> Result<lsp_types::ResourceOp> {
|
||||
let res = match file_system_edit {
|
||||
FileSystemEdit::CreateFile { source_root, path } => {
|
||||
let uri = world.path_to_uri(source_root, &path)?;
|
||||
let uri = snap.path_to_uri(source_root, &path)?;
|
||||
lsp_types::ResourceOp::Create(lsp_types::CreateFile { uri, options: None })
|
||||
}
|
||||
FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
|
||||
let old_uri = world.file_id_to_uri(src)?;
|
||||
let new_uri = world.path_to_uri(dst_source_root, &dst_path)?;
|
||||
let old_uri = snap.file_id_to_uri(src)?;
|
||||
let new_uri = snap.path_to_uri(dst_source_root, &dst_path)?;
|
||||
lsp_types::ResourceOp::Rename(lsp_types::RenameFile { old_uri, new_uri, options: None })
|
||||
}
|
||||
};
|
||||
@ -504,16 +508,16 @@ pub(crate) fn resource_op(
|
||||
}
|
||||
|
||||
pub(crate) fn snippet_workspace_edit(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
source_change: SourceChange,
|
||||
) -> Result<lsp_ext::SnippetWorkspaceEdit> {
|
||||
let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
|
||||
for op in source_change.file_system_edits {
|
||||
let op = resource_op(&world, op)?;
|
||||
let op = resource_op(&snap, op)?;
|
||||
document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op));
|
||||
}
|
||||
for edit in source_change.source_file_edits {
|
||||
let edit = snippet_text_document_edit(&world, source_change.is_snippet, edit)?;
|
||||
let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?;
|
||||
document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
|
||||
}
|
||||
let workspace_edit =
|
||||
@ -522,11 +526,11 @@ pub(crate) fn snippet_workspace_edit(
|
||||
}
|
||||
|
||||
pub(crate) fn workspace_edit(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
source_change: SourceChange,
|
||||
) -> Result<lsp_types::WorkspaceEdit> {
|
||||
assert!(!source_change.is_snippet);
|
||||
snippet_workspace_edit(world, source_change).map(|it| it.into())
|
||||
snippet_workspace_edit(snap, source_change).map(|it| it.into())
|
||||
}
|
||||
|
||||
impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
|
||||
@ -565,13 +569,13 @@ impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
|
||||
}
|
||||
|
||||
pub fn call_hierarchy_item(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
target: NavigationTarget,
|
||||
) -> Result<lsp_types::CallHierarchyItem> {
|
||||
let name = target.name().to_string();
|
||||
let detail = target.description().map(|it| it.to_string());
|
||||
let kind = symbol_kind(target.kind());
|
||||
let (uri, range, selection_range) = location_info(world, target)?;
|
||||
let (uri, range, selection_range) = location_info(snap, target)?;
|
||||
Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range })
|
||||
}
|
||||
|
||||
@ -619,23 +623,26 @@ fn main() <fold>{
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> {
|
||||
pub(crate) fn code_action(
|
||||
snap: &GlobalStateSnapshot,
|
||||
assist: Assist,
|
||||
) -> Result<lsp_ext::CodeAction> {
|
||||
let res = lsp_ext::CodeAction {
|
||||
title: assist.label,
|
||||
group: if world.config.client_caps.code_action_group { assist.group_label } else { None },
|
||||
group: if snap.config.client_caps.code_action_group { assist.group_label } else { None },
|
||||
kind: Some(String::new()),
|
||||
edit: Some(snippet_workspace_edit(world, assist.source_change)?),
|
||||
edit: Some(snippet_workspace_edit(snap, assist.source_change)?),
|
||||
command: None,
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn runnable(
|
||||
world: &WorldSnapshot,
|
||||
snap: &GlobalStateSnapshot,
|
||||
file_id: FileId,
|
||||
runnable: Runnable,
|
||||
) -> Result<lsp_ext::Runnable> {
|
||||
let spec = CargoTargetSpec::for_file(world, file_id)?;
|
||||
let spec = CargoTargetSpec::for_file(snap, file_id)?;
|
||||
let target = spec.as_ref().map(|s| s.target.clone());
|
||||
let (cargo_args, executable_args) =
|
||||
CargoTargetSpec::runnable_args(spec, &runnable.kind, &runnable.cfg_exprs)?;
|
||||
@ -648,14 +655,14 @@ pub(crate) fn runnable(
|
||||
target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
|
||||
}
|
||||
};
|
||||
let location = location_link(world, None, runnable.nav)?;
|
||||
let location = location_link(snap, None, runnable.nav)?;
|
||||
|
||||
Ok(lsp_ext::Runnable {
|
||||
label,
|
||||
location: Some(location),
|
||||
kind: lsp_ext::RunnableKind::Cargo,
|
||||
args: lsp_ext::CargoRunnable {
|
||||
workspace_root: world.workspace_root_for(file_id).map(|root| root.to_owned()),
|
||||
workspace_root: snap.workspace_root_for(file_id).map(|root| root.to_owned()),
|
||||
cargo_args,
|
||||
executable_args,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user