@@ -268,18 +268,27 @@ impl Ast {
268268 /// against the stored source bytes when available.
269269 pub fn source_text ( & self , id : Id ) -> String {
270270 let Some ( node) = self . get_node ( id) else { return String :: new ( ) ; } ;
271- match & node. content {
272- NodeContent :: Range ( range) => {
273- let start = range. start_byte ;
274- let end = range. end_byte ;
275- if end <= self . source . len ( ) && start <= end {
276- String :: from_utf8_lossy ( & self . source [ start..end] ) . into_owned ( )
277- } else {
278- String :: new ( )
279- }
271+ let read_range = |range : & tree_sitter:: Range | {
272+ let start = range. start_byte ;
273+ let end = range. end_byte ;
274+ if end <= self . source . len ( ) && start <= end {
275+ String :: from_utf8_lossy ( & self . source [ start..end] ) . into_owned ( )
276+ } else {
277+ String :: new ( )
280278 }
279+ } ;
280+ match & node. content {
281+ NodeContent :: Range ( range) => read_range ( range) ,
281282 NodeContent :: String ( s) => s. to_string ( ) ,
282- NodeContent :: DynamicString ( s) => s. clone ( ) ,
283+ NodeContent :: DynamicString ( s) if !s. is_empty ( ) => s. clone ( ) ,
284+ // Synthesized nodes (from rule transforms) carry an empty
285+ // `DynamicString`; resolve them against the inherited source
286+ // range so `#{capture}` after a translation still yields the
287+ // original source text.
288+ NodeContent :: DynamicString ( _) => match node. source_range {
289+ Some ( range) => read_range ( & range) ,
290+ None => String :: new ( ) ,
291+ } ,
283292 }
284293 }
285294
0 commit comments