Workaround missing none group support in builtin macros

This commit is contained in:
Lukas Wirth 2025-06-27 11:39:40 +02:00
parent 5b852da4c3
commit 54c87d8753
4 changed files with 22 additions and 40 deletions

View file

@ -7,6 +7,7 @@ use intern::{
Symbol, Symbol,
sym::{self}, sym::{self},
}; };
use itertools::Itertools;
use mbe::{DelimiterKind, expect_fragment}; use mbe::{DelimiterKind, expect_fragment};
use span::{Edition, FileId, Span}; use span::{Edition, FileId, Span};
use stdx::format_to; use stdx::format_to;
@ -681,11 +682,19 @@ fn relative_file(
} }
fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> { fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
let delimiter = tt.top_subtree().delimiter; let mut tt = TtElement::Subtree(tt.top_subtree(), tt.iter());
tt.iter() (|| {
.next() // FIXME: We wrap expression fragments in parentheses which can break this expectation
.ok_or(delimiter.open.cover(delimiter.close)) // here
.and_then(|tt| match tt { // Remove this once we handle none delims correctly
while let TtElement::Subtree(sub, tt_iter) = &mut tt
&& let DelimiterKind::Parenthesis | DelimiterKind::Invisible = sub.delimiter.kind
{
tt =
tt_iter.exactly_one().map_err(|_| sub.delimiter.open.cover(sub.delimiter.close))?;
}
match tt {
TtElement::Leaf(tt::Leaf::Literal(tt::Literal { TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text, symbol: text,
span, span,
@ -698,35 +707,11 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
kind: tt::LitKind::StrRaw(_), kind: tt::LitKind::StrRaw(_),
suffix: _, suffix: _,
})) => Ok((text.clone(), *span)), })) => Ok((text.clone(), *span)),
// FIXME: We wrap expression fragments in parentheses which can break this expectation
// here
// Remove this once we handle none delims correctly
TtElement::Subtree(tt, mut tt_iter)
if tt.delimiter.kind == DelimiterKind::Parenthesis =>
{
tt_iter
.next()
.and_then(|tt| match tt {
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::Str,
suffix: _,
})) => Some((unescape_symbol(text), *span)),
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
kind: tt::LitKind::StrRaw(_),
suffix: _,
})) => Some((text.clone(), *span)),
_ => None,
})
.ok_or(delimiter.open.cover(delimiter.close))
}
TtElement::Leaf(l) => Err(*l.span()), TtElement::Leaf(l) => Err(*l.span()),
TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)), TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
}) }
.map_err(|span| ExpandError::other(span, "expected string literal")) })()
.map_err(|span| ExpandError::other(span, "expected string literal"))
} }
fn include_expand( fn include_expand(

View file

@ -1526,7 +1526,7 @@ impl Config {
CompletionConfig { CompletionConfig {
enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(), enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(),
enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned() enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
&& self.caps.completion_item_edit_resolve(), && self.caps.has_completion_item_resolve_additionalTextEdits(),
enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(), enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
enable_auto_iter: *self.completion_autoIter_enable(source_root), enable_auto_iter: *self.completion_autoIter_enable(source_root),
enable_auto_await: *self.completion_autoAwait_enable(source_root), enable_auto_await: *self.completion_autoAwait_enable(source_root),
@ -2355,10 +2355,6 @@ impl Config {
.and_then(|it| it.version.as_ref()) .and_then(|it| it.version.as_ref())
} }
pub fn client_is_helix(&self) -> bool {
self.client_info.as_ref().map(|it| it.name == "helix").unwrap_or_default()
}
pub fn client_is_neovim(&self) -> bool { pub fn client_is_neovim(&self) -> bool {
self.client_info.as_ref().map(|it| it.name == "Neovim").unwrap_or_default() self.client_info.as_ref().map(|it| it.name == "Neovim").unwrap_or_default()
} }

View file

@ -42,7 +42,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
hover_provider: Some(HoverProviderCapability::Simple(true)), hover_provider: Some(HoverProviderCapability::Simple(true)),
completion_provider: Some(CompletionOptions { completion_provider: Some(CompletionOptions {
resolve_provider: if config.client_is_neovim() { resolve_provider: if config.client_is_neovim() {
config.completion_item_edit_resolve().then_some(true) config.has_completion_item_resolve_additionalTextEdits().then_some(true)
} else { } else {
Some(config.caps().completions_resolve_provider()) Some(config.caps().completions_resolve_provider())
}, },
@ -207,8 +207,8 @@ impl ClientCapabilities {
serde_json::from_value(self.0.experimental.as_ref()?.get(index)?.clone()).ok() serde_json::from_value(self.0.experimental.as_ref()?.get(index)?.clone()).ok()
} }
/// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports. #[allow(non_snake_case)]
pub fn completion_item_edit_resolve(&self) -> bool { pub fn has_completion_item_resolve_additionalTextEdits(&self) -> bool {
(|| { (|| {
Some( Some(
self.0 self.0

View file

@ -211,6 +211,7 @@ impl<'a, S: Copy> TtIter<'a, S> {
} }
} }
#[derive(Clone)]
pub enum TtElement<'a, S> { pub enum TtElement<'a, S> {
Leaf(&'a Leaf<S>), Leaf(&'a Leaf<S>),
Subtree(&'a Subtree<S>, TtIter<'a, S>), Subtree(&'a Subtree<S>, TtIter<'a, S>),