⬆️ rust-analyzer

This commit is contained in:
Laurențiu Nicola 2022-08-23 10:05:52 +03:00
parent 134701885d
commit 31519bb394
83 changed files with 2092 additions and 626 deletions

View file

@ -52,7 +52,7 @@ impl Logger {
// merge chalk filter to our main filter (from RA_LOG env).
//
// The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`.
// As the value should only affect chalk crates, we'd better mannually
// As the value should only affect chalk crates, we'd better manually
// specify the target. And for simplicity, CHALK_DEBUG only accept the value
// that specify level.
let chalk_level_dir = std::env::var("CHALK_DEBUG")

View file

@ -45,7 +45,8 @@ mod patch_old_style;
// - foo_command = overrides the subcommand, foo_overrideCommand allows full overwriting, extra args only applies for foo_command
// Defines the server-side configuration of the rust-analyzer. We generate
// *parts* of VS Code's `package.json` config from this.
// *parts* of VS Code's `package.json` config from this. Run `cargo test` to
// re-generate that file.
//
// However, editor specific config, which the server doesn't know about, should
// be specified directly in `package.json`.
@ -120,6 +121,10 @@ config_data! {
/// Cargo, you might also want to change
/// `#rust-analyzer.cargo.buildScripts.overrideCommand#`.
///
/// If there are multiple linked projects, this command is invoked for
/// each of them, with the working directory being the project root
/// (i.e., the folder containing the `Cargo.toml`).
///
/// An example command would be:
///
/// ```bash
@ -243,7 +248,10 @@ config_data! {
hover_actions_run_enable: bool = "true",
/// Whether to show documentation on hover.
hover_documentation_enable: bool = "true",
hover_documentation_enable: bool = "true",
/// Whether to show keyword hover popups. Only applies when
/// `#rust-analyzer.hover.documentation.enable#` is set.
hover_documentation_keywords_enable: bool = "true",
/// Use markdown syntax for links in hover.
hover_links_enable: bool = "true",
@ -1187,6 +1195,7 @@ impl Config {
HoverDocFormat::PlainText
}
}),
keywords: self.data.hover_documentation_keywords_enable,
}
}

View file

@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant};
use crossbeam_channel::{unbounded, Receiver, Sender};
use flycheck::FlycheckHandle;
use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId};
use ide_db::base_db::{CrateId, FileLoader, SourceDatabase, SourceDatabaseExt};
use ide_db::base_db::{CrateId, FileLoader, SourceDatabase};
use lsp_types::{SemanticTokens, Url};
use parking_lot::{Mutex, RwLock};
use proc_macro_api::ProcMacroServer;
@ -176,9 +176,9 @@ impl GlobalState {
pub(crate) fn process_changes(&mut self) -> bool {
let _p = profile::span("GlobalState::process_changes");
let mut fs_refresh_changes = Vec::new();
// A file was added or deleted
let mut has_structure_changes = false;
let mut workspace_structure_change = None;
let (change, changed_files) = {
let mut change = Change::new();
@ -192,7 +192,7 @@ impl GlobalState {
if let Some(path) = vfs.file_path(file.file_id).as_path() {
let path = path.to_path_buf();
if reload::should_refresh_for_change(&path, file.change_kind) {
fs_refresh_changes.push((path, file.file_id));
workspace_structure_change = Some(path);
}
if file.is_created_or_deleted() {
has_structure_changes = true;
@ -227,11 +227,10 @@ impl GlobalState {
{
let raw_database = self.analysis_host.raw_database();
let workspace_structure_change =
fs_refresh_changes.into_iter().find(|&(_, file_id)| {
!raw_database.source_root(raw_database.file_source_root(file_id)).is_library
});
if let Some((path, _)) = workspace_structure_change {
// FIXME: ideally we should only trigger a workspace fetch for non-library changes
// but somethings going wrong with the source root business when we add a new local
// crate see https://github.com/rust-lang/rust-analyzer/issues/13029
if let Some(path) = workspace_structure_change {
self.fetch_workspaces_queue
.request_op(format!("workspace vfs file change: {}", path.display()));
}

View file

@ -51,6 +51,12 @@ pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<
Ok(())
}
pub(crate) fn handle_cancel_flycheck(state: &mut GlobalState, _: ()) -> Result<()> {
let _p = profile::span("handle_stop_flycheck");
state.flycheck.iter().for_each(|flycheck| flycheck.cancel());
Ok(())
}
pub(crate) fn handle_analyzer_status(
snap: GlobalStateSnapshot,
params: lsp_ext::AnalyzerStatusParams,
@ -703,10 +709,8 @@ pub(crate) fn handle_runnables(
let mut res = Vec::new();
for runnable in snap.analysis.runnables(file_id)? {
if let Some(offset) = offset {
if !runnable.nav.full_range.contains_inclusive(offset) {
continue;
}
if should_skip_for_offset(&runnable, offset) {
continue;
}
if should_skip_target(&runnable, cargo_spec.as_ref()) {
continue;
@ -772,6 +776,14 @@ pub(crate) fn handle_runnables(
Ok(res)
}
fn should_skip_for_offset(runnable: &Runnable, offset: Option<TextSize>) -> bool {
match offset {
None => false,
_ if matches!(&runnable.kind, RunnableKind::TestMod { .. }) => false,
Some(offset) => !runnable.nav.full_range.contains_inclusive(offset),
}
}
pub(crate) fn handle_related_tests(
snap: GlobalStateSnapshot,
params: lsp_types::TextDocumentPositionParams,
@ -1765,7 +1777,7 @@ fn run_rustfmt(
let line_index = snap.file_line_index(file_id)?;
let mut rustfmt = match snap.config.rustfmt() {
let mut command = match snap.config.rustfmt() {
RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
let mut cmd = process::Command::new(toolchain::rustfmt());
cmd.args(extra_args);
@ -1830,12 +1842,12 @@ fn run_rustfmt(
}
};
let mut rustfmt = rustfmt
let mut rustfmt = command
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.context(format!("Failed to spawn {:?}", rustfmt))?;
.context(format!("Failed to spawn {:?}", command))?;
rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?;
@ -1854,7 +1866,11 @@ fn run_rustfmt(
// formatting because otherwise an error is surfaced to the user on top of the
// syntax error diagnostics they're already receiving. This is especially jarring
// if they have format on save enabled.
tracing::info!("rustfmt exited with status 1, assuming parse error and ignoring");
tracing::warn!(
?command,
%captured_stderr,
"rustfmt exited with status 1"
);
Ok(None)
}
_ => {

View file

@ -129,6 +129,14 @@ pub struct ExpandedMacro {
pub expansion: String,
}
pub enum CancelFlycheck {}
impl Request for CancelFlycheck {
type Params = ();
type Result = ();
const METHOD: &'static str = "rust-analyzer/cancelFlycheck";
}
pub enum MatchingBrace {}
impl Request for MatchingBrace {

View file

@ -288,7 +288,7 @@ impl GlobalState {
if became_quiescent {
// Project has loaded properly, kick off initial flycheck
self.flycheck.iter().for_each(FlycheckHandle::update);
self.flycheck.iter().for_each(FlycheckHandle::restart);
if self.config.prefill_caches() {
self.prime_caches_queue.request_op("became quiescent".to_string());
}
@ -590,6 +590,7 @@ impl GlobalState {
.on_sync_mut::<lsp_ext::ReloadWorkspace>(handlers::handle_workspace_reload)
.on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)
.on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)
.on_sync_mut::<lsp_ext::CancelFlycheck>(handlers::handle_cancel_flycheck)
.on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)
.on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)
.on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)
@ -779,7 +780,7 @@ impl GlobalState {
for (id, _) in workspace_ids.clone() {
if id == flycheck.id() {
updated = true;
flycheck.update();
flycheck.restart();
continue;
}
}
@ -798,7 +799,7 @@ impl GlobalState {
// No specific flycheck was triggered, so let's trigger all of them.
if !updated {
for flycheck in &this.flycheck {
flycheck.update();
flycheck.restart();
}
}
Ok(())