mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
544b4cfe4d
commit
dbf04a5ee2
106 changed files with 2219 additions and 609 deletions
|
@ -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 = &|_| ();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue