diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index da523ba8a23..151ca3da51f 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -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" diff --git a/crates/ra_lsp_server/src/args.rs b/crates/ra_lsp_server/src/bin/args.rs similarity index 100% rename from crates/ra_lsp_server/src/args.rs rename to crates/ra_lsp_server/src/bin/args.rs diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/bin/main.rs similarity index 96% rename from crates/ra_lsp_server/src/main.rs rename to crates/ra_lsp_server/src/bin/main.rs index a549e5ff124..e25d54a0d6e 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/bin/main.rs @@ -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; diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs index 5fd1e7b6b3c..53751aafb70 100644 --- a/crates/ra_lsp_server/src/cargo_target_spec.rs +++ b/crates/ra_lsp_server/src/cargo_target_spec.rs @@ -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> { - 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> { + pub(crate) fn runnable_args( + spec: Option, + kind: &RunnableKind, + ) -> Result> { + 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> { let &crate_id = match world.analysis().crate_for(file_id)?.first() { Some(crate_id) => crate_id, None => return Ok(None), @@ -84,7 +89,7 @@ pub fn for_file(world: &WorldSnapshot, file_id: FileId) -> Result) { + pub(crate) fn push_to(self, buf: &mut Vec) { buf.push("--package".to_string()); buf.push(self.package); match self.target_kind { diff --git a/crates/ra_lsp_server/src/cli.rs b/crates/ra_lsp_server/src/cli.rs index 3c7b8e2509a..c9738d1010b 100644 --- a/crates/ra_lsp_server/src/cli.rs +++ b/crates/ra_lsp_server/src/cli.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Various batch processing tasks, intended primarily for debugging. mod load_cargo; mod analysis_stats; diff --git a/crates/ra_lsp_server/src/cli/analysis_bench.rs b/crates/ra_lsp_server/src/cli/analysis_bench.rs index e00f8107348..91855e59252 100644 --- a/crates/ra_lsp_server/src/cli/analysis_bench.rs +++ b/crates/ra_lsp_server/src/cli/analysis_bench.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Benchmark operations like highlighting or goto definition. use std::{ path::{Path, PathBuf}, diff --git a/crates/ra_lsp_server/src/cli/analysis_stats.rs b/crates/ra_lsp_server/src/cli/analysis_stats.rs index c27fabe3c4b..99ab6e44372 100644 --- a/crates/ra_lsp_server/src/cli/analysis_stats.rs +++ b/crates/ra_lsp_server/src/cli/analysis_stats.rs @@ -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}; diff --git a/crates/ra_lsp_server/src/cli/load_cargo.rs b/crates/ra_lsp_server/src/cli/load_cargo.rs index bb3e1513b87..8cd08ecb6f4 100644 --- a/crates/ra_lsp_server/src/cli/load_cargo.rs +++ b/crates/ra_lsp_server/src/cli/load_cargo.rs @@ -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)> { +pub(crate) fn load_cargo( + root: &Path, +) -> Result<(AnalysisHost, FxHashMap)> { 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, 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; diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 8af74b2112c..90ef74056b0 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -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, diff --git a/crates/ra_lsp_server/src/diagnostics.rs b/crates/ra_lsp_server/src/diagnostics.rs index ea08bce24bc..e7924f0a30f 100644 --- a/crates/ra_lsp_server/src/diagnostics.rs +++ b/crates/ra_lsp_server/src/diagnostics.rs @@ -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>>; diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 958c70fe5fa..0dae30e46ec 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs @@ -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; diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 944074118df..67d8a5f6fab 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -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; diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index ae51141cbf7..bb7bab37294 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -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_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 { - 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), diff --git a/crates/ra_lsp_server/src/main_loop/pending_requests.rs b/crates/ra_lsp_server/src/main_loop/pending_requests.rs index 2d221346418..73b33e41942 100644 --- a/crates/ra_lsp_server/src/main_loop/pending_requests.rs +++ b/crates/ra_lsp_server/src/main_loop/pending_requests.rs @@ -1,4 +1,4 @@ -//! Datastructures that keep track of inflight requests. +//! Data structures that keep track of inflight requests. use std::time::{Duration, Instant}; diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs index b0bae90f5c1..bee6437cf34 100644 --- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs +++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs @@ -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; diff --git a/crates/ra_lsp_server/src/vfs_glob.rs b/crates/ra_lsp_server/src/vfs_glob.rs index 12401d75a82..91b33f94e86 100644 --- a/crates/ra_lsp_server/src/vfs_glob.rs +++ b/crates/ra_lsp_server/src/vfs_glob.rs @@ -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. diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 71c95d4af00..96efab844d5 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -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`. diff --git a/xtask/tests/tidy-tests/docs.rs b/xtask/tests/tidy-tests/docs.rs index b2571df2582..62c4f844139 100644 --- a/xtask/tests/tidy-tests/docs.rs +++ b/xtask/tests/tidy-tests/docs.rs @@ -77,7 +77,6 @@ fn no_docs_comments() { "ra_hir", "ra_hir_expand", "ra_ide", - "ra_lsp_server", "ra_mbe", "ra_parser", "ra_prof",