Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-srv/src/server/rust_analyzer_span.rs')
-rw-r--r--crates/proc-macro-srv/src/server/rust_analyzer_span.rs74
1 files changed, 12 insertions, 62 deletions
diff --git a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
index f7bbbcc09d..4a2ad40ad9 100644
--- a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
+++ b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
@@ -4,6 +4,7 @@
//! It is an unfortunate result of how the proc-macro API works that we need to look into the
//! concrete representation of the spans, and as such, RustRover cannot make use of this unless they
//! change their representation to be compatible with rust-analyzer's.
+use core::num;
use std::{
collections::{HashMap, HashSet},
iter,
@@ -13,11 +14,11 @@ use std::{
use ::tt::{TextRange, TextSize};
use proc_macro::bridge::{self, server};
use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
-use syntax::ast::{self, HasModuleItem, IsString};
+use syntax::ast;
use crate::server::{
- delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter,
- Symbol, SymbolInternerRef, SYMBOL_INTERNER,
+ delim_to_external, delim_to_internal, literal_to_external, str_to_lit_node,
+ token_stream::TokenStreamBuilder, LiteralFormatter, Symbol, SymbolInternerRef, SYMBOL_INTERNER,
};
mod tt {
pub use ::tt::*;
@@ -71,66 +72,15 @@ impl server::FreeFunctions for RaSpanServer {
&mut self,
s: &str,
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
- let input = s.trim();
- let source_code = format!("fn f() {{ let _ = {input}; }}");
-
- let parse = ast::SourceFile::parse(&source_code);
- let file = parse.tree();
-
- let Some(ast::Item::Fn(func)) = file.items().next() else { return Err(()) };
- let Some(ast::Stmt::LetStmt(stmt)) =
- func.body().ok_or(Err(()))?.stmt_list().ok_or(Err(()))?.statements().next()
- else {
- return Err(());
- };
- let Some(ast::Expr::Literal(lit)) = stmt.initializer() else { return Err(()) };
-
- fn raw_delimiter_count<S: IsString>(s: S) -> Option<u8> {
- let text = s.text();
- let quote_range = s.text_range_between_quotes()?;
- let range_start = s.syntax().text_range().start();
- text[TextRange::up_to((quote_range - range_start).start())]
- .matches('#')
- .count()
- .try_into()
- .ok()
- }
+ let literal = str_to_lit_node(s).ok_or(Err(()))?;
- let mut suffix = None;
- let kind = match lit.kind() {
- ast::LiteralKind::String(data) => {
- if data.is_raw() {
- bridge::LitKind::StrRaw(raw_delimiter_count(data).ok_or(Err(()))?)
- } else {
- bridge::LitKind::Str
- }
- }
- ast::LiteralKind::ByteString(data) => {
- if data.is_raw() {
- bridge::LitKind::ByteStrRaw(raw_delimiter_count(data).ok_or(Err(()))?)
- } else {
- bridge::LitKind::ByteStr
- }
- }
- ast::LiteralKind::CString(data) => {
- if data.is_raw() {
- bridge::LitKind::CStrRaw(raw_delimiter_count(data).ok_or(Err(()))?)
- } else {
- bridge::LitKind::CStr
- }
- }
- ast::LiteralKind::IntNumber(num) => {
- suffix = num.suffix();
- bridge::LitKind::Integer
- }
- ast::LiteralKind::FloatNumber(num) => {
- suffix = num.suffix();
- bridge::LitKind::Float
- }
- ast::LiteralKind::Char(_) => bridge::LitKind::Char,
- ast::LiteralKind::Byte(_) => bridge::LitKind::Byte,
- ast::LiteralKind::Bool(_) => unreachable!(),
- };
+ let kind = literal_to_external(literal.kind()).ok_or(Err(()))?;
+
+ let suffix = match literal.kind() {
+ ast::LiteralKind::FloatNumber(num) | ast::LiteralKind::IntNumber(num) => num.suffix(),
+ _ => None,
+ }
+ .map(|suffix| Symbol::intern(self.interner, suffix));
Ok(bridge::Literal {
kind,