mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-23 08:48:08 +00:00
Merge pull request #21133 from Veykril/push-olvztmtwzmvv
fix: Do not try to connect via postcard to proc-macro-srv
This commit is contained in:
commit
0f8057ccff
4 changed files with 56 additions and 92 deletions
|
|
@ -22,7 +22,7 @@ use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span};
|
|||
use std::{fmt, io, sync::Arc, time::SystemTime};
|
||||
|
||||
pub use crate::codec::Codec;
|
||||
use crate::{legacy_protocol::SpanMode, process::ProcMacroServerProcess};
|
||||
use crate::process::ProcMacroServerProcess;
|
||||
|
||||
/// The versions of the server protocol
|
||||
pub mod version {
|
||||
|
|
@ -126,11 +126,7 @@ impl ProcMacroClient {
|
|||
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
|
||||
> + Clone,
|
||||
) -> io::Result<ProcMacroClient> {
|
||||
let process = ProcMacroServerProcess::run(
|
||||
process_path,
|
||||
env,
|
||||
process::Protocol::Postcard { mode: SpanMode::Id },
|
||||
)?;
|
||||
let process = ProcMacroServerProcess::run(process_path, env)?;
|
||||
Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() })
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,13 @@ pub(crate) struct ProcMacroServerProcess {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum Protocol {
|
||||
LegacyJson { mode: SpanMode },
|
||||
Postcard { mode: SpanMode },
|
||||
LegacyJson {
|
||||
mode: SpanMode,
|
||||
},
|
||||
#[expect(dead_code)]
|
||||
Postcard {
|
||||
mode: SpanMode,
|
||||
},
|
||||
}
|
||||
|
||||
/// Maintains the state of the proc-macro server process.
|
||||
|
|
@ -49,82 +54,50 @@ impl ProcMacroServerProcess {
|
|||
env: impl IntoIterator<
|
||||
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
|
||||
> + Clone,
|
||||
protocol: Protocol,
|
||||
) -> io::Result<ProcMacroServerProcess> {
|
||||
let mut srv = {
|
||||
let mut process = match Process::run(process_path, env.clone(), &protocol) {
|
||||
Ok(process) => process,
|
||||
Err(e) => {
|
||||
// fallback
|
||||
if matches!(protocol, Protocol::Postcard { .. }) {
|
||||
// retry with json
|
||||
return Self::run(
|
||||
process_path,
|
||||
env,
|
||||
Protocol::LegacyJson { mode: SpanMode::Id },
|
||||
);
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
let create_srv = || {
|
||||
let mut process = Process::run(process_path, env.clone())?;
|
||||
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
|
||||
|
||||
ProcMacroServerProcess {
|
||||
io::Result::Ok(ProcMacroServerProcess {
|
||||
state: Mutex::new(ProcessSrvState { process, stdin, stdout }),
|
||||
version: 0,
|
||||
protocol: protocol.clone(),
|
||||
protocol: Protocol::LegacyJson { mode: SpanMode::Id },
|
||||
exited: OnceLock::new(),
|
||||
}
|
||||
})
|
||||
};
|
||||
let mut srv = create_srv()?;
|
||||
tracing::info!("sending proc-macro server version check");
|
||||
let version = match srv.version_check() {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
if matches!(protocol, Protocol::Postcard { .. }) {
|
||||
// retry with json
|
||||
return Self::run(
|
||||
process_path,
|
||||
env,
|
||||
Protocol::LegacyJson { mode: SpanMode::Id },
|
||||
);
|
||||
}
|
||||
|
||||
tracing::info!(%e, "proc-macro version check failed");
|
||||
return Err(io::Error::other(format!(
|
||||
"proc-macro server version check failed: {e}"
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
if version > version::CURRENT_API_VERSION {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let process_version = Command::new(process_path)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.map(|out| String::from_utf8_lossy(&out.stdout).trim().to_owned())
|
||||
.unwrap_or_else(|_| "unknown version".to_owned());
|
||||
|
||||
return Err(io::Error::other(format!(
|
||||
"Your installed proc-macro server is too new for your rust-analyzer. API version: {}, server version: {process_version}. \
|
||||
match srv.version_check() {
|
||||
Ok(v) if v > version::CURRENT_API_VERSION => {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let process_version = Command::new(process_path)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_owned())
|
||||
.unwrap_or_else(|_| "unknown version".to_owned());
|
||||
Err(io::Error::other(format!(
|
||||
"Your installed proc-macro server is too new for your rust-analyzer. API version: {}, server version: {process_version}. \
|
||||
This will prevent proc-macro expansion from working. Please consider updating your rust-analyzer to ensure compatibility with your current toolchain.",
|
||||
version::CURRENT_API_VERSION
|
||||
)));
|
||||
version::CURRENT_API_VERSION
|
||||
)))
|
||||
}
|
||||
Ok(v) => {
|
||||
tracing::info!("Proc-macro server version: {v}");
|
||||
srv.version = v;
|
||||
if srv.version >= version::RUST_ANALYZER_SPAN_SUPPORT
|
||||
&& let Ok(mode) = srv.enable_rust_analyzer_spans()
|
||||
{
|
||||
srv.protocol = Protocol::LegacyJson { mode };
|
||||
}
|
||||
tracing::info!("Proc-macro server protocol: {:?}", srv.protocol);
|
||||
Ok(srv)
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::info!(%e, "proc-macro version check failed");
|
||||
Err(io::Error::other(format!("proc-macro server version check failed: {e}")))
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("proc-macro server version: {version}");
|
||||
|
||||
srv.version = version;
|
||||
|
||||
if version >= version::RUST_ANALYZER_SPAN_SUPPORT
|
||||
&& let Ok(new_mode) = srv.enable_rust_analyzer_spans()
|
||||
{
|
||||
match &mut srv.protocol {
|
||||
Protocol::Postcard { mode } | Protocol::LegacyJson { mode } => *mode = new_mode,
|
||||
};
|
||||
}
|
||||
|
||||
tracing::info!("proc-macro server protocol: {:?}", srv.protocol);
|
||||
Ok(srv)
|
||||
}
|
||||
|
||||
/// Returns the server error if the process has exited.
|
||||
|
|
@ -247,9 +220,8 @@ impl Process {
|
|||
env: impl IntoIterator<
|
||||
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
|
||||
>,
|
||||
protocol: &Protocol,
|
||||
) -> io::Result<Process> {
|
||||
let child = JodChild(mk_child(path, env, protocol)?);
|
||||
let child = JodChild(mk_child(path, env)?);
|
||||
Ok(Process { child })
|
||||
}
|
||||
|
||||
|
|
@ -269,15 +241,9 @@ fn mk_child<'a>(
|
|||
extra_env: impl IntoIterator<
|
||||
Item = (impl AsRef<std::ffi::OsStr>, &'a Option<impl 'a + AsRef<std::ffi::OsStr>>),
|
||||
>,
|
||||
protocol: &Protocol,
|
||||
) -> io::Result<Child> {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let mut cmd = Command::new(path);
|
||||
if matches!(protocol, Protocol::LegacyJson { .. }) {
|
||||
cmd.args(["--format", "json"]);
|
||||
} else {
|
||||
cmd.args(["--format", "postcard"]);
|
||||
}
|
||||
for env in extra_env {
|
||||
match env {
|
||||
(key, Some(val)) => cmd.env(key, val),
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ fn main() -> std::io::Result<()> {
|
|||
clap::Arg::new("format")
|
||||
.long("format")
|
||||
.action(clap::ArgAction::Set)
|
||||
.default_value("json")
|
||||
.default_value("json-legacy")
|
||||
.value_parser(clap::builder::EnumValueParser::<ProtocolFormat>::new()),
|
||||
clap::Arg::new("version")
|
||||
.long("version")
|
||||
|
|
@ -50,25 +50,27 @@ fn main() -> std::io::Result<()> {
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
enum ProtocolFormat {
|
||||
Json,
|
||||
Postcard,
|
||||
JsonLegacy,
|
||||
PostcardLegacy,
|
||||
}
|
||||
|
||||
impl ValueEnum for ProtocolFormat {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
&[ProtocolFormat::Json, ProtocolFormat::Postcard]
|
||||
&[ProtocolFormat::JsonLegacy, ProtocolFormat::PostcardLegacy]
|
||||
}
|
||||
|
||||
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
|
||||
match self {
|
||||
ProtocolFormat::Json => Some(clap::builder::PossibleValue::new("json")),
|
||||
ProtocolFormat::Postcard => Some(clap::builder::PossibleValue::new("postcard")),
|
||||
ProtocolFormat::JsonLegacy => Some(clap::builder::PossibleValue::new("json-legacy")),
|
||||
ProtocolFormat::PostcardLegacy => {
|
||||
Some(clap::builder::PossibleValue::new("postcard-legacy"))
|
||||
}
|
||||
}
|
||||
}
|
||||
fn from_str(input: &str, _ignore_case: bool) -> Result<Self, String> {
|
||||
match input {
|
||||
"json" => Ok(ProtocolFormat::Json),
|
||||
"postcard" => Ok(ProtocolFormat::Postcard),
|
||||
"json-legacy" => Ok(ProtocolFormat::JsonLegacy),
|
||||
"postcard-legacy" => Ok(ProtocolFormat::PostcardLegacy),
|
||||
_ => Err(format!("unknown protocol format: {input}")),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ impl SpanTransformer for SpanTrans {
|
|||
|
||||
pub(crate) fn run(format: ProtocolFormat) -> io::Result<()> {
|
||||
match format {
|
||||
ProtocolFormat::Json => run_::<JsonProtocol>(),
|
||||
ProtocolFormat::Postcard => run_::<PostcardProtocol>(),
|
||||
ProtocolFormat::JsonLegacy => run_::<JsonProtocol>(),
|
||||
ProtocolFormat::PostcardLegacy => run_::<PostcardProtocol>(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue