⬆️ rust-analyzer

This commit is contained in:
Laurențiu Nicola 2023-03-20 08:31:01 +02:00
parent 544b4cfe4d
commit dbf04a5ee2
106 changed files with 2219 additions and 609 deletions

View file

@ -7,7 +7,7 @@ use std::{
};
use hir::{
db::{AstDatabase, DefDatabase, HirDatabase},
db::{DefDatabase, ExpandDatabase, HirDatabase},
AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
};
use hir_def::{
@ -24,7 +24,7 @@ use ide_db::base_db::{
use itertools::Itertools;
use oorandom::Rand32;
use profile::{Bytes, StopWatch};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
use rayon::prelude::*;
use rustc_hash::FxHashSet;
use stdx::format_to;
@ -57,7 +57,7 @@ impl flags::AnalysisStats {
let mut cargo_config = CargoConfig::default();
cargo_config.sysroot = match self.no_sysroot {
true => None,
false => Some(RustcSource::Discover),
false => Some(RustLibSource::Discover),
};
let no_progress = &|_| ();

View file

@ -1,7 +1,7 @@
//! Analyze all modules in a project for diagnostics. Exits with a non-zero
//! status code if any errors are found.
use project_model::{CargoConfig, RustcSource};
use project_model::{CargoConfig, RustLibSource};
use rustc_hash::FxHashSet;
use hir::{db::HirDatabase, Crate, Module};
@ -16,7 +16,7 @@ use crate::cli::{
impl flags::Diagnostics {
pub fn run(self) -> anyhow::Result<()> {
let mut cargo_config = CargoConfig::default();
cargo_config.sysroot = Some(RustcSource::Discover);
cargo_config.sysroot = Some(RustLibSource::Discover);
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: !self.disable_build_scripts,
with_proc_macro_server: ProcMacroServerChoice::Sysroot,

View file

@ -13,7 +13,7 @@ use ide_db::LineIndexDatabase;
use ide_db::base_db::salsa::{self, ParallelDatabase};
use ide_db::line_index::WideEncoding;
use lsp_types::{self, lsif};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
use vfs::{AbsPathBuf, Vfs};
use crate::cli::load_cargo::ProcMacroServerChoice;
@ -290,7 +290,7 @@ impl flags::Lsif {
eprintln!("Generating LSIF started...");
let now = Instant::now();
let mut cargo_config = CargoConfig::default();
cargo_config.sysroot = Some(RustcSource::Discover);
cargo_config.sysroot = Some(RustLibSource::Discover);
let no_progress = &|_| ();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,

View file

@ -15,7 +15,7 @@ use ide::{
TokenStaticData,
};
use ide_db::LineIndexDatabase;
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
use scip::types as scip_types;
use std::env;
@ -30,7 +30,7 @@ impl flags::Scip {
eprintln!("Generating SCIP start...");
let now = Instant::now();
let mut cargo_config = CargoConfig::default();
cargo_config.sysroot = Some(RustcSource::Discover);
cargo_config.sysroot = Some(RustLibSource::Discover);
let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}"));
let load_cargo_config = LoadCargoConfig {

View file

@ -1,7 +1,7 @@
//! Applies structured search replace rules from the command line.
use ide_ssr::MatchFinder;
use project_model::{CargoConfig, RustcSource};
use project_model::{CargoConfig, RustLibSource};
use crate::cli::{
flags,
@ -13,7 +13,7 @@ impl flags::Ssr {
pub fn run(self) -> Result<()> {
use ide_db::base_db::SourceDatabaseExt;
let mut cargo_config = CargoConfig::default();
cargo_config.sysroot = Some(RustcSource::Discover);
cargo_config.sysroot = Some(RustLibSource::Discover);
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
with_proc_macro_server: ProcMacroServerChoice::Sysroot,

View file

@ -22,7 +22,7 @@ use ide_db::{
use itertools::Itertools;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource,
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource,
UnsetTestCrates,
};
use rustc_hash::{FxHashMap, FxHashSet};
@ -272,7 +272,6 @@ config_data! {
/// The warnings will be indicated by a blue squiggly underline in code
/// and a blue icon in the `Problems Panel`.
diagnostics_warningsAsInfo: Vec<String> = "[]",
/// These directories will be ignored by rust-analyzer. They are
/// relative to the workspace root, and globs are not supported. You may
/// also need to add the folders to Code's `files.watcherExclude`.
@ -895,6 +894,15 @@ impl Config {
}
}
pub fn add_linked_projects(&mut self, linked_projects: Vec<ProjectJsonData>) {
let mut linked_projects = linked_projects
.into_iter()
.map(ManifestOrProjectJson::ProjectJson)
.collect::<Vec<ManifestOrProjectJson>>();
self.data.linkedProjects.append(&mut linked_projects);
}
pub fn did_save_text_document_dynamic_registration(&self) -> bool {
let caps = try_or_def!(self.caps.text_document.as_ref()?.synchronization.clone()?);
caps.did_save == Some(true) && caps.dynamic_registration == Some(true)
@ -1129,16 +1137,16 @@ impl Config {
pub fn cargo(&self) -> CargoConfig {
let rustc_source = self.data.rustc_source.as_ref().map(|rustc_src| {
if rustc_src == "discover" {
RustcSource::Discover
RustLibSource::Discover
} else {
RustcSource::Path(self.root_path.join(rustc_src))
RustLibSource::Path(self.root_path.join(rustc_src))
}
});
let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| {
if sysroot == "discover" {
RustcSource::Discover
RustLibSource::Discover
} else {
RustcSource::Path(self.root_path.join(sysroot))
RustLibSource::Path(self.root_path.join(sysroot))
}
});
let sysroot_src =

View file

@ -87,6 +87,42 @@ impl<'a> RequestDispatcher<'a> {
self
}
/// Dispatches the request onto thread pool
pub(crate) fn on_no_retry<R>(
&mut self,
f: fn(GlobalStateSnapshot, R::Params) -> Result<R::Result>,
) -> &mut Self
where
R: lsp_types::request::Request + 'static,
R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
R::Result: Serialize,
{
let (req, params, panic_context) = match self.parse::<R>() {
Some(it) => it,
None => return self,
};
self.global_state.task_pool.handle.spawn({
let world = self.global_state.snapshot();
move || {
let result = panic::catch_unwind(move || {
let _pctx = stdx::panic_context::enter(panic_context);
f(world, params)
});
match thread_result_to_response::<R>(req.id.clone(), result) {
Ok(response) => Task::Response(response),
Err(_) => Task::Response(lsp_server::Response::new_err(
req.id,
lsp_server::ErrorCode::ContentModified as i32,
"content modified".to_string(),
)),
}
}
});
self
}
/// Dispatches the request onto thread pool
pub(crate) fn on<R>(
&mut self,

View file

@ -29,7 +29,7 @@ use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
use serde_json::json;
use stdx::{format_to, never};
use syntax::{algo, ast, AstNode, TextRange, TextSize};
use vfs::AbsPathBuf;
use vfs::{AbsPath, AbsPathBuf};
use crate::{
cargo_target_spec::CargoTargetSpec,
@ -46,6 +46,7 @@ use crate::{
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<()> {
state.proc_macro_clients.clear();
state.proc_macro_changed = false;
state.fetch_workspaces_queue.request_op("reload workspace request".to_string());
state.fetch_build_data_queue.request_op("reload workspace request".to_string());
Ok(())
@ -84,6 +85,15 @@ pub(crate) fn handle_analyzer_status(
snap.workspaces.len(),
if snap.workspaces.len() == 1 { "" } else { "s" }
);
format_to!(
buf,
"Workspace root folders: {:?}",
snap.workspaces
.iter()
.flat_map(|ws| ws.workspace_definition_path())
.collect::<Vec<&AbsPath>>()
);
}
buf.push_str("\nAnalysis:\n");
buf.push_str(

View file

@ -36,11 +36,41 @@ impl Progress {
}
impl GlobalState {
pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) {
let message = message;
self.send_notification::<lsp_types::notification::ShowMessage>(
lsp_types::ShowMessageParams { typ, message },
)
pub(crate) fn show_message(
&mut self,
typ: lsp_types::MessageType,
message: String,
show_open_log_button: bool,
) {
match self.config.open_server_logs() && show_open_log_button {
true => self.send_request::<lsp_types::request::ShowMessageRequest>(
lsp_types::ShowMessageRequestParams {
typ,
message,
actions: Some(vec![lsp_types::MessageActionItem {
title: "Open server logs".to_owned(),
properties: Default::default(),
}]),
},
|this, resp| {
let lsp_server::Response { error: None, result: Some(result), .. } = resp
else { return };
if let Ok(Some(_item)) = crate::from_json::<
<lsp_types::request::ShowMessageRequest as lsp_types::request::Request>::Result,
>(
lsp_types::request::ShowMessageRequest::METHOD, &result
) {
this.send_notification::<lsp_ext::OpenServerLogs>(());
}
},
),
false => self.send_notification::<lsp_types::notification::ShowMessage>(
lsp_types::ShowMessageParams {
typ,
message,
},
),
}
}
/// Sends a notification to the client containing the error `message`.

View file

@ -406,9 +406,19 @@ impl GlobalState {
if self.config.server_status_notification() {
self.send_notification::<lsp_ext::ServerStatusNotification>(status);
} else if let (lsp_ext::Health::Error, Some(message)) = (status.health, &status.message)
{
self.show_and_log_error(message.clone(), None);
} else if let (health, Some(message)) = (status.health, &status.message) {
let open_log_button = tracing::enabled!(tracing::Level::ERROR)
&& (self.fetch_build_data_error().is_err()
|| self.fetch_workspace_error().is_err());
self.show_message(
match health {
lsp_ext::Health::Ok => lsp_types::MessageType::INFO,
lsp_ext::Health::Warning => lsp_types::MessageType::WARNING,
lsp_ext::Health::Error => lsp_types::MessageType::ERROR,
},
message.clone(),
open_log_button,
);
}
}
}
@ -653,7 +663,7 @@ impl GlobalState {
.on::<lsp_types::request::GotoDeclaration>(handlers::handle_goto_declaration)
.on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)
.on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
.on::<lsp_types::request::InlayHintRequest>(handlers::handle_inlay_hints)
.on_no_retry::<lsp_types::request::InlayHintRequest>(handlers::handle_inlay_hints)
.on::<lsp_types::request::InlayHintResolveRequest>(handlers::handle_inlay_hints_resolve)
.on::<lsp_types::request::Completion>(handlers::handle_completion)
.on::<lsp_types::request::ResolveCompletionItem>(handlers::handle_completion_resolve)
@ -919,6 +929,7 @@ impl GlobalState {
this.show_message(
lsp_types::MessageType::WARNING,
error.to_string(),
false,
);
}
this.update_configuration(config);

View file

@ -90,38 +90,55 @@ impl GlobalState {
quiescent: self.is_quiescent(),
message: None,
};
let mut message = String::new();
if self.proc_macro_changed {
status.health = lsp_ext::Health::Warning;
status.message =
Some("Reload required due to source changes of a procedural macro.".into())
message.push_str("Reload required due to source changes of a procedural macro.\n\n");
}
if let Err(_) = self.fetch_build_data_error() {
status.health = lsp_ext::Health::Warning;
status.message =
Some("Failed to run build scripts of some packages, check the logs.".to_string());
message.push_str("Failed to run build scripts of some packages.\n\n");
}
if !self.config.cargo_autoreload()
&& self.is_quiescent()
&& self.fetch_workspaces_queue.op_requested()
{
status.health = lsp_ext::Health::Warning;
status.message = Some("Workspace reload required".to_string())
message.push_str("Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required.\n\n");
}
if let Err(_) = self.fetch_workspace_error() {
status.health = lsp_ext::Health::Error;
status.message = Some("Failed to load workspaces".to_string())
}
if self.config.linked_projects().is_empty()
&& self.config.detached_files().is_empty()
&& self.config.notifications().cargo_toml_not_found
{
status.health = lsp_ext::Health::Warning;
status.message = Some("Failed to discover workspace".to_string())
message.push_str("Failed to discover workspace.\n\n");
}
for ws in self.workspaces.iter() {
let (ProjectWorkspace::Cargo { sysroot, .. }
| ProjectWorkspace::Json { sysroot, .. }
| ProjectWorkspace::DetachedFiles { sysroot, .. }) = ws;
if let Err(Some(e)) = sysroot {
status.health = lsp_ext::Health::Warning;
message.push_str(e);
message.push_str("\n\n");
}
if let ProjectWorkspace::Cargo { rustc: Err(Some(e)), .. } = ws {
status.health = lsp_ext::Health::Warning;
message.push_str(e);
message.push_str("\n\n");
}
}
if let Err(_) = self.fetch_workspace_error() {
status.health = lsp_ext::Health::Error;
message.push_str("Failed to load workspaces.\n\n");
}
if !message.is_empty() {
status.message = Some(message.trim_end().to_owned());
}
status
}