mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Merge #3214
3214: Fully document ra_lsp_server r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
2768476e49
18 changed files with 109 additions and 86 deletions
|
@ -3,10 +3,15 @@ edition = "2018"
|
|||
name = "ra_lsp_server"
|
||||
version = "0.1.0"
|
||||
authors = ["rust-analyzer developers"]
|
||||
autobins = false
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[[bin]]
|
||||
name = "ra_lsp_server"
|
||||
path = "./src/bin/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
crossbeam-channel = "0.4"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
//! `ra_lsp_server` binary
|
||||
//! Driver for rust-analyzer.
|
||||
//!
|
||||
//! Based on cli flags, either spawns an LSP server, or runs a batch analysis
|
||||
mod args;
|
||||
|
||||
use lsp_server::Connection;
|
|
@ -1,69 +1,74 @@
|
|||
//! FIXME: write short doc here
|
||||
//! See `CargoTargetSpec`
|
||||
|
||||
use ra_ide::{FileId, RunnableKind, TestId};
|
||||
use ra_project_model::{self, ProjectWorkspace, TargetKind};
|
||||
|
||||
use crate::{world::WorldSnapshot, Result};
|
||||
|
||||
pub(crate) fn runnable_args(
|
||||
world: &WorldSnapshot,
|
||||
file_id: FileId,
|
||||
kind: &RunnableKind,
|
||||
) -> Result<Vec<String>> {
|
||||
let spec = CargoTargetSpec::for_file(world, file_id)?;
|
||||
let mut res = Vec::new();
|
||||
match kind {
|
||||
RunnableKind::Test { test_id } => {
|
||||
res.push("test".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(test_id.to_string());
|
||||
if let TestId::Path(_) = test_id {
|
||||
res.push("--exact".to_string());
|
||||
}
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::TestMod { path } => {
|
||||
res.push("test".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(path.to_string());
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::Bench { test_id } => {
|
||||
res.push("bench".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(test_id.to_string());
|
||||
if let TestId::Path(_) = test_id {
|
||||
res.push("--exact".to_string());
|
||||
}
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::Bin => {
|
||||
res.push("run".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub struct CargoTargetSpec {
|
||||
pub package: String,
|
||||
pub target: String,
|
||||
pub target_kind: TargetKind,
|
||||
/// Abstract representation of Cargo target.
|
||||
///
|
||||
/// We use it to cook up the set of cli args we need to pass to Cargo to
|
||||
/// build/test/run the target.
|
||||
pub(crate) struct CargoTargetSpec {
|
||||
pub(crate) package: String,
|
||||
pub(crate) target: String,
|
||||
pub(crate) target_kind: TargetKind,
|
||||
}
|
||||
|
||||
impl CargoTargetSpec {
|
||||
pub fn for_file(world: &WorldSnapshot, file_id: FileId) -> Result<Option<CargoTargetSpec>> {
|
||||
pub(crate) fn runnable_args(
|
||||
spec: Option<CargoTargetSpec>,
|
||||
kind: &RunnableKind,
|
||||
) -> Result<Vec<String>> {
|
||||
let mut res = Vec::new();
|
||||
match kind {
|
||||
RunnableKind::Test { test_id } => {
|
||||
res.push("test".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(test_id.to_string());
|
||||
if let TestId::Path(_) = test_id {
|
||||
res.push("--exact".to_string());
|
||||
}
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::TestMod { path } => {
|
||||
res.push("test".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(path.to_string());
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::Bench { test_id } => {
|
||||
res.push("bench".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
res.push("--".to_string());
|
||||
res.push(test_id.to_string());
|
||||
if let TestId::Path(_) = test_id {
|
||||
res.push("--exact".to_string());
|
||||
}
|
||||
res.push("--nocapture".to_string());
|
||||
}
|
||||
RunnableKind::Bin => {
|
||||
res.push("run".to_string());
|
||||
if let Some(spec) = spec {
|
||||
spec.push_to(&mut res);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn for_file(
|
||||
world: &WorldSnapshot,
|
||||
file_id: FileId,
|
||||
) -> Result<Option<CargoTargetSpec>> {
|
||||
let &crate_id = match world.analysis().crate_for(file_id)?.first() {
|
||||
Some(crate_id) => crate_id,
|
||||
None => return Ok(None),
|
||||
|
@ -84,7 +89,7 @@ impl CargoTargetSpec {
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn push_to(self, buf: &mut Vec<String>) {
|
||||
pub(crate) fn push_to(self, buf: &mut Vec<String>) {
|
||||
buf.push("--package".to_string());
|
||||
buf.push(self.package);
|
||||
match self.target_kind {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! FIXME: write short doc here
|
||||
//! Various batch processing tasks, intended primarily for debugging.
|
||||
|
||||
mod load_cargo;
|
||||
mod analysis_stats;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! FIXME: write short doc here
|
||||
//! Benchmark operations like highlighting or goto definition.
|
||||
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! FIXME: write short doc here
|
||||
//! Fully type-check project and print various stats, like the number of type
|
||||
//! errors.
|
||||
|
||||
use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
//! FIXME: write short doc here
|
||||
//! Loads a Cargo project into a static instance of analysis, without support
|
||||
//! for incorporating changes.
|
||||
|
||||
use std::{collections::HashSet, path::Path};
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use crossbeam_channel::{unbounded, Receiver};
|
||||
use ra_db::{CrateGraph, FileId, SourceRootId};
|
||||
use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags};
|
||||
use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
|
||||
use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use crate::vfs_glob::RustPackageFilterBuilder;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
|
||||
FileId(f.0)
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
|
|||
SourceRootId(r.0)
|
||||
}
|
||||
|
||||
pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
|
||||
pub(crate) fn load_cargo(
|
||||
root: &Path,
|
||||
) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
|
||||
let root = std::env::current_dir()?.join(root);
|
||||
let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
|
||||
let project_roots = ws.to_roots();
|
||||
|
@ -74,7 +76,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
|
|||
Ok((host, source_roots))
|
||||
}
|
||||
|
||||
pub fn load(
|
||||
pub(crate) fn load(
|
||||
source_roots: &FxHashMap<SourceRootId, PackageRoot>,
|
||||
crate_graph: CrateGraph,
|
||||
vfs: &mut Vfs,
|
||||
|
@ -86,7 +88,7 @@ pub fn load(
|
|||
analysis_change.set_crate_graph(crate_graph);
|
||||
|
||||
// wait until Vfs has loaded all roots
|
||||
let mut roots_loaded = HashSet::new();
|
||||
let mut roots_loaded = FxHashSet::default();
|
||||
for task in receiver {
|
||||
vfs.handle_task(task);
|
||||
let mut done = false;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! Convenience module responsible for translating between rust-analyzer's types and LSP types.
|
||||
//! Convenience module responsible for translating between rust-analyzer's types
|
||||
//! and LSP types.
|
||||
|
||||
use lsp_types::{
|
||||
self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! Book keeping for keeping diagnostics easily in sync with the client.
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use lsp_types::{CodeActionOrCommand, Diagnostic, Range};
|
||||
use ra_ide::FileId;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>;
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
//! Implementation of the LSP for rust-analyzer.
|
||||
//!
|
||||
//! This crate takes Rust-specific analysis results from ra_ide and
|
||||
//! translates into LSP types.
|
||||
//! This crate takes Rust-specific analysis results from ra_ide and translates
|
||||
//! into LSP types.
|
||||
//!
|
||||
//! It also is the root of all state. `world` module defines the bulk of the
|
||||
//! state, and `main_loop` module defines the rules for modifying it.
|
||||
//!
|
||||
//! The `cli` submodule implements some batch-processing analysis, primarily as
|
||||
//! a debugging aid.
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
pub mod cli;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! The main loop of `ra_lsp_server` responsible for dispatching LSP requests/replies and
|
||||
//! notifications back to the client.
|
||||
//! The main loop of `ra_lsp_server` responsible for dispatching LSP
|
||||
//! requests/replies and notifications back to the client.
|
||||
|
||||
mod handlers;
|
||||
mod subscriptions;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! This module is responsible for implementing handlers for Lanuage Server Protocol.
|
||||
//! The majority of requests are fulfilled by calling into the `ra_ide` crate.
|
||||
//! This module is responsible for implementing handlers for Language Server
|
||||
//! Protocol. The majority of requests are fulfilled by calling into the
|
||||
//! `ra_ide` crate.
|
||||
|
||||
use std::{
|
||||
collections::hash_map::Entry,
|
||||
|
@ -29,7 +30,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::to_value;
|
||||
|
||||
use crate::{
|
||||
cargo_target_spec::{runnable_args, CargoTargetSpec},
|
||||
cargo_target_spec::CargoTargetSpec,
|
||||
conv::{
|
||||
to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith,
|
||||
TryConvWithToVec,
|
||||
|
@ -921,7 +922,8 @@ fn to_lsp_runnable(
|
|||
file_id: FileId,
|
||||
runnable: Runnable,
|
||||
) -> Result<req::Runnable> {
|
||||
let args = runnable_args(world, file_id, &runnable.kind)?;
|
||||
let spec = CargoTargetSpec::for_file(world, file_id)?;
|
||||
let args = CargoTargetSpec::runnable_args(spec, &runnable.kind)?;
|
||||
let line_index = world.analysis().file_line_index(file_id)?;
|
||||
let label = match &runnable.kind {
|
||||
RunnableKind::Test { test_id } => format!("test {}", test_id),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Datastructures that keep track of inflight requests.
|
||||
//! Data structures that keep track of inflight requests.
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! Keeps track of file subscriptions.
|
||||
//! Keeps track of file subscriptions -- the set of currently opened files for
|
||||
//! which we want to publish diagnostics, syntax highlighting, etc.
|
||||
|
||||
use ra_ide::FileId;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! `ra_vfs_glob` crate implements exclusion rules for vfs.
|
||||
//! Exclusion rules for vfs.
|
||||
//!
|
||||
//! By default, we include only `.rs` files, and skip some know offenders like
|
||||
//! `/target` or `/node_modules` altogether.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! The context or environment in which the language server functions.
|
||||
//! In our server implementation this is know as the `WorldState`.
|
||||
//! The context or environment in which the language server functions. In our
|
||||
//! server implementation this is know as the `WorldState`.
|
||||
//!
|
||||
//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@ fn no_docs_comments() {
|
|||
"ra_hir",
|
||||
"ra_hir_expand",
|
||||
"ra_ide",
|
||||
"ra_lsp_server",
|
||||
"ra_mbe",
|
||||
"ra_parser",
|
||||
"ra_prof",
|
||||
|
|
Loading…
Reference in a new issue