@@ -13,6 +13,7 @@ use std::{
13
13
use :: tt:: { TextRange , TextSize } ;
14
14
use proc_macro:: bridge:: { self , server} ;
15
15
use span:: { Span , FIXUP_ERASED_FILE_AST_ID_MARKER } ;
16
+ use syntax:: ast:: { self , HasModuleItem , IsString } ;
16
17
17
18
use crate :: server:: {
18
19
delim_to_external, delim_to_internal, token_stream:: TokenStreamBuilder , LiteralFormatter ,
@@ -70,11 +71,71 @@ impl server::FreeFunctions for RaSpanServer {
70
71
& mut self ,
71
72
s : & str ,
72
73
) -> Result < bridge:: Literal < Self :: Span , Self :: Symbol > , ( ) > {
73
- // FIXME: keep track of LitKind and Suffix
74
+ let input = s. trim ( ) ;
75
+ let source_code = format ! ( "fn f() {{ let _ = {input}; }}" ) ;
76
+
77
+ let parse = ast:: SourceFile :: parse ( & source_code) ;
78
+ let file = parse. tree ( ) ;
79
+
80
+ let Some ( ast:: Item :: Fn ( func) ) = file. items ( ) . next ( ) else { return Err ( ( ) ) } ;
81
+ let Some ( ast:: Stmt :: LetStmt ( stmt) ) =
82
+ func. body ( ) . ok_or ( Err ( ( ) ) ) ?. stmt_list ( ) . ok_or ( Err ( ( ) ) ) ?. statements ( ) . next ( )
83
+ else {
84
+ return Err ( ( ) ) ;
85
+ } ;
86
+ let Some ( ast:: Expr :: Literal ( lit) ) = stmt. initializer ( ) else { return Err ( ( ) ) } ;
87
+
88
+ fn raw_delimiter_count < S : IsString > ( s : S ) -> Option < u8 > {
89
+ let text = s. text ( ) ;
90
+ let quote_range = s. text_range_between_quotes ( ) ?;
91
+ let range_start = s. syntax ( ) . text_range ( ) . start ( ) ;
92
+ text[ TextRange :: up_to ( ( quote_range - range_start) . start ( ) ) ]
93
+ . matches ( '#' )
94
+ . count ( )
95
+ . try_into ( )
96
+ . ok ( )
97
+ }
98
+
99
+ let mut suffix = None ;
100
+ let kind = match lit. kind ( ) {
101
+ ast:: LiteralKind :: String ( data) => {
102
+ if data. is_raw ( ) {
103
+ bridge:: LitKind :: StrRaw ( raw_delimiter_count ( data) . ok_or ( Err ( ( ) ) ) ?)
104
+ } else {
105
+ bridge:: LitKind :: Str
106
+ }
107
+ }
108
+ ast:: LiteralKind :: ByteString ( data) => {
109
+ if data. is_raw ( ) {
110
+ bridge:: LitKind :: ByteStrRaw ( raw_delimiter_count ( data) . ok_or ( Err ( ( ) ) ) ?)
111
+ } else {
112
+ bridge:: LitKind :: ByteStr
113
+ }
114
+ }
115
+ ast:: LiteralKind :: CString ( data) => {
116
+ if data. is_raw ( ) {
117
+ bridge:: LitKind :: CStrRaw ( raw_delimiter_count ( data) . ok_or ( Err ( ( ) ) ) ?)
118
+ } else {
119
+ bridge:: LitKind :: CStr
120
+ }
121
+ }
122
+ ast:: LiteralKind :: IntNumber ( num) => {
123
+ suffix = num. suffix ( ) ;
124
+ bridge:: LitKind :: Integer
125
+ }
126
+ ast:: LiteralKind :: FloatNumber ( num) => {
127
+ suffix = num. suffix ( ) ;
128
+ bridge:: LitKind :: Float
129
+ }
130
+ ast:: LiteralKind :: Char ( _) => bridge:: LitKind :: Char ,
131
+ ast:: LiteralKind :: Byte ( _) => bridge:: LitKind :: Byte ,
132
+ ast:: LiteralKind :: Bool ( _) => unreachable ! ( ) ,
133
+ } ;
134
+
74
135
Ok ( bridge:: Literal {
75
- kind : bridge :: LitKind :: Err ,
136
+ kind,
76
137
symbol : Symbol :: intern ( self . interner , s) ,
77
- suffix : None ,
138
+ suffix,
78
139
span : self . call_site ,
79
140
} )
80
141
}
0 commit comments