mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
Implement literal_from_str
for proc macro srv
This commit is contained in:
parent
3770f73bd6
commit
68365513f3
2 changed files with 128 additions and 6 deletions
|
@ -13,6 +13,7 @@ use std::{
|
||||||
use ::tt::{TextRange, TextSize};
|
use ::tt::{TextRange, TextSize};
|
||||||
use proc_macro::bridge::{self, server};
|
use proc_macro::bridge::{self, server};
|
||||||
use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
|
use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
|
||||||
|
use syntax::ast::{self, HasModuleItem, IsString};
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter,
|
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter,
|
||||||
|
@ -70,11 +71,71 @@ impl server::FreeFunctions for RaSpanServer {
|
||||||
&mut self,
|
&mut self,
|
||||||
s: &str,
|
s: &str,
|
||||||
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
||||||
// FIXME: keep track of LitKind and Suffix
|
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 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!(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(bridge::Literal {
|
Ok(bridge::Literal {
|
||||||
kind: bridge::LitKind::Err,
|
kind,
|
||||||
symbol: Symbol::intern(self.interner, s),
|
symbol: Symbol::intern(self.interner, s),
|
||||||
suffix: None,
|
suffix,
|
||||||
span: self.call_site,
|
span: self.call_site,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use proc_macro::bridge::{self, server};
|
use proc_macro::bridge::{self, server};
|
||||||
|
use syntax::ast::{self, HasModuleItem, IsString};
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter,
|
delim_to_external, delim_to_internal, token_stream::TokenStreamBuilder, LiteralFormatter,
|
||||||
|
@ -62,11 +63,71 @@ impl server::FreeFunctions for TokenIdServer {
|
||||||
&mut self,
|
&mut self,
|
||||||
s: &str,
|
s: &str,
|
||||||
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
) -> Result<bridge::Literal<Self::Span, Self::Symbol>, ()> {
|
||||||
// FIXME: keep track of LitKind and Suffix
|
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 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!(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(bridge::Literal {
|
Ok(bridge::Literal {
|
||||||
kind: bridge::LitKind::Err,
|
kind,
|
||||||
symbol: Symbol::intern(self.interner, s),
|
symbol: Symbol::intern(self.interner, s),
|
||||||
suffix: None,
|
suffix,
|
||||||
span: self.call_site,
|
span: self.call_site,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue