rusty_source_map/
consumer.rs

1use crate::array_set::ArraySet;
2use crate::generator::SourceMapGenerator;
3use crate::mapping::Mapping;
4use crate::source_map::{Position, SourceMapJson};
5use crate::{binary_search, util};
6use rayon::prelude::*;
7use source_map_mappings::Bias;
8use std::cell::RefCell;
9use std::collections::HashMap;
10use std::panic;
11use std::rc::Rc;
12use std::sync::{Arc, Mutex};
13
14///
15/// You should always use this function to create consumer
16///
17pub fn create_consumer(
18    source_map_raw: &str,
19    source_map_url: Option<&str>,
20) -> Result<Consumer, serde_json::Error> {
21    let source_map = serde_json::from_str::<SourceMapJson>(source_map_raw)?;
22    if source_map.sections.is_some() {
23        Ok(Consumer::IndexedConsumer(
24            IndexedConsumer::from_source_map_json(source_map, source_map_url),
25        ))
26    } else {
27        Ok(Consumer::BasicConsumer(
28            BasicConsumer::from_source_map_json(source_map, source_map_url),
29        ))
30    }
31}
32
33pub enum Consumer {
34    BasicConsumer(BasicConsumer),
35    IndexedConsumer(IndexedConsumer),
36}
37
38impl Consumer {
39    pub fn as_basic_consumer(&self) -> &BasicConsumer {
40        if let Self::BasicConsumer(ref consumer) = self {
41            consumer
42        } else {
43            panic!("The consumer is not a basic consumer");
44        }
45    }
46
47    pub fn as_indexed_consumer(&self) -> &IndexedConsumer {
48        if let Self::IndexedConsumer(ref consumer) = self {
49            consumer
50        } else {
51            panic!("The consumer is not a basic consumer");
52        }
53    }
54
55    pub fn as_basic_consumer_mut(&mut self) -> &mut BasicConsumer {
56        if let Self::BasicConsumer(ref mut consumer) = self {
57            consumer
58        } else {
59            panic!("The consumer is not a basic consumer");
60        }
61    }
62
63    pub fn as_indexed_consumer_mut(&mut self) -> &mut IndexedConsumer {
64        if let Self::IndexedConsumer(ref mut consumer) = self {
65            consumer
66        } else {
67            panic!("The consumer is not a basic consumer");
68        }
69    }
70
71    pub fn try_as_basic_consumer(&self) -> Option<&BasicConsumer> {
72        if let Self::BasicConsumer(ref consumer) = self {
73            Some(consumer)
74        } else {
75            None
76        }
77    }
78
79    pub fn try_as_indexed_consumer(&self) -> Option<&IndexedConsumer> {
80        if let Self::IndexedConsumer(ref consumer) = self {
81            Some(consumer)
82        } else {
83            None
84        }
85    }
86
87    pub fn try_as_basic_consumer_mut(&mut self) -> Option<&mut BasicConsumer> {
88        if let Self::BasicConsumer(ref mut consumer) = self {
89            Some(consumer)
90        } else {
91            None
92        }
93    }
94
95    pub fn try_as_indexed_consumer_mut(&mut self) -> Option<&mut IndexedConsumer> {
96        if let Self::IndexedConsumer(ref mut consumer) = self {
97            Some(consumer)
98        } else {
99            None
100        }
101    }
102}
103
104#[derive(Clone)]
105pub enum IterOrd {
106    GeneratedOrd,
107    OriginalOrd,
108}
109
110pub trait ConsumerTrait: Sized {
111    fn consume(source_map_raw: String, source_map_url: String, f: impl FnOnce(Self));
112    fn each_mapping(&mut self, f: impl Fn(&source_map_mappings::Mapping), ord: IterOrd);
113}
114
115pub struct BasicConsumer {
116    pub source_map: SourceMapJson,
117    pub(crate) source_lookup_cache: HashMap<String, i32>,
118    pub(crate) absolute_sources: ArraySet,
119    pub(crate) source_map_url: Option<String>,
120    pub(crate) mappings: Option<source_map_mappings::Mappings>,
121    pub(crate) computed_column_spans: bool,
122}
123impl BasicConsumer {
124    pub fn new(source_map_raw: &str, source_map_url: Option<&str>) -> Self {
125        let source_map = serde_json::from_str::<SourceMapJson>(source_map_raw).unwrap();
126        BasicConsumer {
127            source_map: source_map.clone(),
128            source_lookup_cache: Default::default(),
129            source_map_url: source_map_url.map(|it| it.to_string()),
130            absolute_sources: ArraySet::from_array(
131                source_map
132                    .sources
133                    .as_ref()
134                    .unwrap()
135                    .iter()
136                    .map(|it| {
137                        util::compute_source_url(
138                            source_map.source_root.as_deref(),
139                            it,
140                            source_map_url,
141                        )
142                    })
143                    .collect(),
144                true,
145            ),
146            mappings: None,
147            computed_column_spans: false,
148        }
149    }
150
151    pub fn from_source_map_json(source_map: SourceMapJson, source_map_url: Option<&str>) -> Self {
152        BasicConsumer {
153            source_map: source_map.clone(),
154            source_lookup_cache: Default::default(),
155            source_map_url: None,
156            absolute_sources: ArraySet::from_array(
157                source_map
158                    .sources
159                    .as_ref()
160                    .unwrap()
161                    .iter()
162                    .map(|it| {
163                        util::compute_source_url(
164                            source_map.source_root.as_deref(),
165                            it,
166                            source_map_url,
167                        )
168                    })
169                    .collect(),
170                true,
171            ),
172            mappings: None,
173            computed_column_spans: false,
174        }
175    }
176
177    pub fn from_source_map(
178        source_map: &mut SourceMapGenerator,
179        source_map_url: Option<&str>,
180    ) -> Self {
181        BasicConsumer::new(source_map.as_string().as_str(), source_map_url)
182    }
183
184    fn find_source_index(&mut self, source: &str) -> Option<i32> {
185        let cached_index = self.source_lookup_cache.get(source);
186        if let Some(&index) = cached_index {
187            return Some(index);
188        }
189
190        // Treat the source as map-relative overall by default.
191        let source_as_map_relative =
192            util::compute_source_url(None, source, self.source_map_url.as_deref());
193        if self.absolute_sources.has(source_as_map_relative.clone()) {
194            let index = self
195                .absolute_sources
196                .index_of(source_as_map_relative)
197                .unwrap();
198
199            self.source_lookup_cache
200                .insert(source.to_string(), index as i32);
201            return Some(index as i32);
202        }
203
204        // Fall back to treating the source as sourceRoot-relative.
205        let source_as_source_root_relative = util::compute_source_url(
206            self.source_map.source_root.as_deref(),
207            source,
208            self.source_map_url.as_deref(),
209        );
210        if self
211            .absolute_sources
212            .has(source_as_source_root_relative.clone())
213        {
214            let index = self
215                .absolute_sources
216                .index_of(source_as_source_root_relative)
217                .unwrap();
218            self.source_lookup_cache
219                .insert(source.to_string(), index as i32);
220            return Some(index as i32);
221        }
222
223        None
224    }
225
226    pub fn get_sources(&self) -> Vec<String> {
227        self.absolute_sources.to_vec()
228    }
229
230    fn parse_mappings(&self) -> Result<source_map_mappings::Mappings, source_map_mappings::Error> {
231        source_map_mappings::parse_mappings::<()>(
232            self.source_map.mappings.as_ref().unwrap().as_bytes(),
233        )
234    }
235
236    pub fn all_generated_position_for(
237        &mut self,
238        source: &str,
239        original_line: i32,
240        original_column: Option<i32>,
241    ) -> Vec<source_map_mappings::Mapping> {
242        let original_column = if let Some(r) = original_column { r } else { 0 };
243        let source = self.find_source_index(source);
244        if source.is_none() {
245            return vec![];
246        }
247
248        let source = source.unwrap();
249
250        if source < 0 {
251            return vec![];
252        }
253
254        if original_line < 1 {
255            panic!("Line numbers must be >= 1");
256        }
257
258        if original_column < 0 {
259            panic!("Column numbers must be >= 0");
260        }
261
262        if self.mappings.is_none() {
263            self.mappings = self.parse_mappings().ok();
264        }
265
266        let mappings = self.mappings.as_mut().unwrap();
267
268        mappings
269            .all_generated_locations_for(
270                source as u32,
271                original_line as u32,
272                Some(original_column as u32),
273            )
274            .cloned()
275            .collect()
276    }
277
278    pub fn compute_column_spans(&mut self) {
279        if self.computed_column_spans {
280            return;
281        }
282
283        if self.mappings.is_none() {
284            self.mappings = self.parse_mappings().ok();
285        }
286
287        let mappings = self.mappings.as_mut().unwrap();
288        mappings.compute_column_spans();
289        self.computed_column_spans = true;
290    }
291
292    pub fn original_position_for(
293        &mut self,
294        generated: Position,
295        bias: Option<source_map_mappings::Bias>,
296    ) -> Option<Mapping> {
297        let generated_line = generated.line;
298        let generated_column = generated.column;
299        if generated_line < 1 {
300            panic!("Line numbers must be >= 1");
301        }
302
303        if generated_column < 0 {
304            panic!("Column numbers must be >= 0");
305        }
306
307        let bias = bias.unwrap_or(source_map_mappings::Bias::GreatestLowerBound);
308
309        if self.mappings.is_none() {
310            self.mappings = self.parse_mappings().ok();
311        }
312
313        let mappings = self.mappings.as_mut().unwrap();
314
315        let mapping = mappings
316            .original_location_for((generated_line - 1) as u32, generated_column as u32, bias)
317            .cloned();
318
319        match mapping {
320            Some(mapping) => {
321                if mapping.generated_line as i32 == generated_line {
322                    mapping.original.clone().map(|original| Mapping {
323                        name: original
324                            .name
325                            .map(|it| self.source_map.names.as_ref().unwrap()[it as usize].clone()),
326                        source: self.absolute_sources.at(original.source as i32),
327                        original: Some(Position {
328                            line: (original.original_line + 1) as i32,
329                            column: original.original_column as i32,
330                        }),
331                        generated: Position {
332                            line: (mapping.generated_line + 1) as i32,
333                            column: mapping.generated_column as i32,
334                        },
335                        last_generated_column: mapping.last_generated_column.map(|it| it as i32),
336                    })
337                } else {
338                    None
339                }
340            }
341            None => None,
342        }
343    }
344
345    pub fn has_contents_of_all_sources(&self) -> bool {
346        match self.source_map.sources_content {
347            Some(ref s) => s.len() >= self.source_map.sources.as_ref().unwrap().len(),
348            None => false,
349        }
350    }
351
352    pub fn source_content_for(
353        &mut self,
354        source: &str,
355        panic_on_missing: Option<bool>,
356    ) -> Option<String> {
357        self.source_map.sources_content.as_ref()?;
358
359        let sources_content = self.source_map.sources_content.clone().unwrap();
360        let panic_on_missing = panic_on_missing.unwrap_or(true);
361
362        let index = self.find_source_index(source);
363        return match index {
364            Some(i) => Some(sources_content[i as usize].clone()),
365            None => {
366                if panic_on_missing {
367                    panic!(r#""{}" is not in the SourceMap."#, source);
368                } else {
369                    None
370                }
371            }
372        };
373    }
374
375    pub fn generated_position_for(
376        &mut self,
377        source: &str,
378        original_line: i32,
379        original_column: i32,
380        bias: Option<source_map_mappings::Bias>,
381    ) -> Option<Mapping> {
382        let source = match self.find_source_index(source) {
383            Some(s) => s,
384            None => return None,
385        };
386
387        if original_line < 1 {
388            panic!("Line numbers must be >= 1")
389        }
390
391        if original_column < 0 {
392            panic!("Column numbers must be >= 0")
393        }
394
395        let bias = bias.unwrap_or(source_map_mappings::Bias::GreatestLowerBound);
396
397        if self.mappings.is_none() {
398            self.mappings = self.parse_mappings().ok();
399        }
400
401        let mappings = self.mappings.as_mut().unwrap();
402
403        let mapping = mappings
404            .generated_location_for(
405                source as u32,
406                (original_line - 1) as u32,
407                original_column as u32,
408                bias,
409            )
410            .cloned();
411
412        match mapping {
413            Some(mapping) => {
414                if mapping.original.as_ref().unwrap().source as i32 == source {
415                    let last_column = mapping.last_generated_column;
416                    let last_column = if self.computed_column_spans && last_column.is_none() {
417                        Some(-1)
418                    } else {
419                        last_column.map(|it| it as i32)
420                    };
421
422                    Some(Mapping {
423                        generated: Position {
424                            line: (mapping.generated_line + 1) as i32,
425                            column: mapping.generated_column as i32,
426                        },
427                        original: mapping.original.as_ref().map(|it| Position {
428                            line: it.original_line as i32,
429                            column: it.original_column as i32,
430                        }),
431                        source: mapping
432                            .original
433                            .as_ref()
434                            .map(|it| self.absolute_sources.at(it.source as i32))
435                            .flatten(),
436                        name: mapping.original.as_ref().map(|it| {
437                            self.source_map.names.as_ref().unwrap()[it.source as usize].clone()
438                        }),
439                        last_generated_column: last_column,
440                    })
441                } else {
442                    None
443                }
444            }
445            None => None,
446        }
447    }
448}
449
450impl ConsumerTrait for BasicConsumer {
451    fn consume(source_map_raw: String, source_map_url: String, f: impl FnOnce(Self)) {
452        let consumer = BasicConsumer::new(source_map_raw.as_str(), Some(source_map_url.as_str()));
453        f(consumer);
454    }
455
456    fn each_mapping(&mut self, f: impl Fn(&source_map_mappings::Mapping), ord: IterOrd) {
457        if self.mappings.is_none() {
458            match self.parse_mappings() {
459                Ok(mappings) => self.mappings = Some(mappings),
460                Err(_) => return,
461            }
462        }
463        let mappings = self.mappings.as_mut().unwrap();
464
465        match ord {
466            IterOrd::OriginalOrd => mappings.by_original_location().for_each(f),
467            IterOrd::GeneratedOrd => mappings.by_generated_location().iter().for_each(f),
468        }
469    }
470}
471
472pub struct Section {
473    generated_offset: Position,
474    consumer: BasicConsumer,
475}
476
477pub struct IndexedConsumer {
478    pub source_map: SourceMapJson,
479    // pub(crate) source_lookup_cache: HashMap<String, i32>,
480    // pub(crate) absolute_sources: ArraySet,
481    // pub(crate) source_map_url: Option<String>,
482    // pub(crate) mappings: Option<source_map_mappings::Mappings>,
483    // pub(crate) computed_column_spans: bool,
484    pub(crate) sections: Rc<RefCell<Vec<Section>>>,
485}
486
487const SUPPORTED_SOURCE_MAP_VERSION: i32 = 3;
488
489impl IndexedConsumer {
490    pub fn new(source_map_raw: &str, source_map_url: Option<&str>) -> Self {
491        let source_map = serde_json::from_str::<SourceMapJson>(source_map_raw).unwrap();
492        Self::from_source_map_json(source_map, source_map_url)
493    }
494
495    pub fn from_source_map_json(source_map: SourceMapJson, source_map_url: Option<&str>) -> Self {
496        let version = source_map.version;
497
498        // Once again, Sass deviates from the spec and supplies the version as a
499        // string rather than a number, so we use loose equality checking here.
500        if version != SUPPORTED_SOURCE_MAP_VERSION {
501            panic!("Unsupported version: {}", version);
502        }
503
504        let last_offset = Arc::new(Mutex::new(Position {
505            line: -1,
506            column: 0,
507        }));
508
509        IndexedConsumer {
510            source_map: source_map.clone(),
511            // source_lookup_cache: Default::default(),
512            // source_map_url: source_map_url.map(|it| it.to_string()),
513            // absolute_sources: ArraySet::from_array(
514            //     source_map
515            //         .sources
516            //         .as_ref()
517            //         .unwrap()
518            //         .iter()
519            //         .map(|it| {
520            //             util::compute_source_url(
521            //                 source_map.source_root.as_deref(),
522            //                 it,
523            //                 source_map_url,
524            //             )
525            //         })
526            //         .collect(),
527            //     true,
528            // ),
529            // mappings: None,
530            // computed_column_spans: false,
531            sections: Rc::new(RefCell::new(
532                source_map
533                    .sections
534                    .unwrap()
535                    .par_iter()
536                    .map({
537                        let last_offset = last_offset;
538                        move |section| {
539                            if section.url.is_some() {
540                                panic!("Section with url is not supported.");
541                            }
542
543                            let line = section.offset.line;
544                            let colum = section.offset.column;
545
546                            let mut last_offset = last_offset.lock().unwrap();
547
548                            if line < last_offset.line
549                                || (line == last_offset.line && colum < last_offset.column)
550                            {
551                                panic!("Section offsets must be ordered and non-overlapping.")
552                            }
553
554                            *last_offset = section.offset.clone();
555
556                            Section {
557                                generated_offset: Position {
558                                    // The offset fields are 0-based, but we use 1-based indices when
559                                    // encoding/decoding from VLQ.
560                                    line: line + 1,
561                                    column: colum + 1,
562                                },
563                                consumer: BasicConsumer::from_source_map_json(
564                                    *section.map.clone(),
565                                    source_map_url,
566                                ),
567                            }
568                        }
569                    })
570                    .collect(),
571            )),
572        }
573    }
574
575    /// The list of original sources.
576    pub fn get_sources(&self) -> Vec<String> {
577        let mut sources: Vec<String> = vec![];
578
579        for i in 0..(*self.sections).borrow().len() {
580            for j in 0..(*self.sections).borrow()[i]
581                .consumer
582                .source_map
583                .sources
584                .as_ref()
585                .unwrap()
586                .len()
587            {
588                sources.push(
589                    (*self.sections).borrow()[i]
590                        .consumer
591                        .source_map
592                        .sources
593                        .as_ref()
594                        .unwrap()[j]
595                        .clone(),
596                );
597            }
598        }
599
600        sources
601    }
602
603    pub fn original_position_for(
604        &mut self,
605        input: Position,
606        bias: Option<Bias>,
607    ) -> Option<Mapping> {
608        let needle = input;
609
610        let section_index = binary_search::search(
611            needle.clone(),
612            &(*self.sections).borrow(),
613            |a, b| {
614                if a.line - b.generated_offset.line != 0 {
615                    a.line - b.generated_offset.line
616                } else {
617                    a.column - b.generated_offset.column
618                }
619            },
620            |a, b| {
621                if a.generated_offset.line - b.generated_offset.line != 0 {
622                    a.generated_offset.line - b.generated_offset.line
623                } else {
624                    a.generated_offset.column - b.generated_offset.column
625                }
626            },
627            None,
628        );
629
630        (&*self.sections)
631            .borrow_mut()
632            .get_mut(section_index as usize)
633            .map(|it| {
634                it.consumer.original_position_for(
635                    Position {
636                        line: needle.line - (it.generated_offset.line - 1),
637                        column: needle.column
638                            - if it.generated_offset.line == needle.line {
639                                it.generated_offset.column - 1
640                            } else {
641                                0
642                            },
643                    },
644                    bias,
645                )
646            })
647            .flatten()
648    }
649
650    /// Return true if we have the source content for every source in the source
651    /// map, false otherwise.
652    pub fn has_contents_of_all_sources(&self) -> bool {
653        (*self.sections)
654            .borrow()
655            .iter()
656            .all(|it| it.consumer.has_contents_of_all_sources())
657    }
658
659    /// Returns the original source content. The only argument is the url of the
660    /// original source file. Returns null if no original source content is
661    /// available.
662    pub fn source_content_for(
663        &mut self,
664        source: &str,
665        panic_on_missing: Option<bool>,
666    ) -> Option<String> {
667        for section in (*self.sections).borrow_mut().iter_mut() {
668            if let Some(it) = section
669                .consumer
670                .source_content_for(source, panic_on_missing)
671            {
672                return Some(it);
673            }
674        }
675
676        let panic_on_missing = panic_on_missing.unwrap_or(true);
677        if panic_on_missing {
678            panic!("\"{}\"is not in the SourceMap.", source)
679        } else {
680            None
681        }
682    }
683
684    fn find_source_index(&mut self, source: &str) -> Option<i32> {
685        for i in 0..(*self.sections).borrow().len() {
686            let consumer = &mut (*self.sections).borrow_mut()[i].consumer;
687            if let Some(index) = consumer.find_source_index(source) {
688                return Some(index);
689            }
690        }
691
692        None
693    }
694
695    ///
696    /// Returns the generated line and column information for the original source,
697    /// line, and column positions provided. The only argument is an object with
698    /// the following properties:
699    ///
700    pub fn generated_position_for(
701        &mut self,
702        source: &str,
703        original_line: i32,
704        original_column: i32,
705        bias: Option<Bias>,
706    ) -> Option<Position> {
707        let index = self.find_source_index(source);
708        if let Some(index) = index {
709            if let Some(section) = (*self.sections).borrow_mut().get_mut(index as usize) {
710                let mut generated_position = section.consumer.generated_position_for(
711                    source,
712                    original_line,
713                    original_column,
714                    bias,
715                );
716                if let Some(ref mut generated_position) = generated_position {
717                    let line_shift = generated_position.generated.line - 1;
718                    let column_shift = generated_position.generated.column - 1;
719
720                    if generated_position.generated.line == 1 {
721                        generated_position.generated.column += column_shift;
722                        if let Some(g) = &mut generated_position.last_generated_column {
723                            *g += column_shift;
724                        }
725                    }
726
727                    if let (Some(last_column), Some(next_section)) = (
728                        generated_position.last_generated_column,
729                        (*self.sections).borrow().get(index as usize + 1),
730                    ) {
731                        if last_column == -1
732                            && generated_position.generated.line
733                                == next_section.generated_offset.line
734                        {
735                            generated_position
736                                .last_generated_column
737                                .replace(next_section.generated_offset.column - 2);
738                        }
739                        generated_position.generated.line += line_shift;
740
741                        return Some(Position {
742                            line: generated_position.generated.line,
743                            column: generated_position.generated.column,
744                        });
745                    }
746                }
747            }
748        }
749
750        None
751    }
752
753    pub fn all_generated_position_for(
754        &mut self,
755        source: &str,
756        original_line: i32,
757        original_column: Option<i32>,
758    ) -> Vec<source_map_mappings::Mapping> {
759        let index = self.find_source_index(source);
760        if let Some(index) = index {
761            if let Some(section) = (*self.sections).borrow_mut().get_mut(index as usize) {
762                section
763                    .consumer
764                    .all_generated_position_for(source, original_line, original_column)
765                    .iter()
766                    .map(|mapping| {
767                        let mut mapping = mapping.clone();
768                        let line_shift = mapping.generated_line - 1;
769                        let column_shift = mapping.generated_column - 1;
770
771                        if mapping.generated_line == 1 {
772                            mapping.generated_column += column_shift;
773                            if let Some(g) = &mut mapping.last_generated_column {
774                                *g += column_shift;
775                            } else {
776                            }
777                        }
778
779                        if mapping.last_generated_column.is_some() {
780                            // TODO(CGQAQ): is it OK to be u8?
781                            // if last_column == -1
782                            let sections_ref = (*self.sections).borrow();
783                            let next_section = sections_ref.get(index as usize + 1);
784                            if let Some(next_section) = next_section {
785                                if mapping.generated_line
786                                    == next_section.generated_offset.line as u32
787                                {
788                                    mapping
789                                        .last_generated_column
790                                        .replace((next_section.generated_offset.column - 2) as u32);
791                                }
792                            }
793                            mapping.generated_line += line_shift;
794                        }
795
796                        mapping
797                    })
798                    .collect()
799            } else {
800                vec![]
801            }
802        } else {
803            vec![]
804        }
805    }
806
807    pub fn computed_column_spans(&mut self) {
808        for ele in (*self.sections).borrow_mut().iter_mut() {
809            ele.consumer.compute_column_spans()
810        }
811    }
812}
813
814impl ConsumerTrait for IndexedConsumer {
815    fn consume(source_map_raw: String, source_map_url: String, f: impl FnOnce(Self)) {
816        let consumer = IndexedConsumer::new(source_map_raw.as_str(), Some(source_map_url.as_str()));
817        f(consumer);
818    }
819
820    fn each_mapping(&mut self, f: impl Fn(&source_map_mappings::Mapping), ord: IterOrd) {
821        (*self.sections)
822            .borrow_mut()
823            .iter_mut()
824            .enumerate()
825            .for_each({
826                let sections = &self.sections;
827                let f = &f;
828
829                move |(index, section)| {
830                    //     const nextSection =
831                    //     index + 1 < this._sections.length ? this._sections[index + 1] : null;
832                    // const { generatedOffset } = section;
833
834                    // const lineShift = generatedOffset.generatedLine - 1;
835                    // const columnShift = generatedOffset.generatedColumn - 1;
836
837                    let generated_offset = &mut section.generated_offset;
838                    let line_shift = generated_offset.line - 1;
839                    let column_shift = generated_offset.column - 1;
840                    section.consumer.each_mapping(
841                        {
842                            let sections_ref = (**sections).borrow();
843                            move |mapping| {
844                                let next_section = sections_ref.get(index + 1);
845
846                                let mut mapping = mapping.clone();
847                                if mapping.generated_line == 1 {
848                                    mapping.generated_column += column_shift as u32;
849                                    if let Some(it) = &mut mapping.last_generated_column {
850                                        *it += column_shift as u32;
851                                    }
852                                }
853
854                                if let Some(next_section) = next_section {
855                                    if mapping.generated_line
856                                        == next_section.generated_offset.line as u32
857                                    {
858                                        mapping.last_generated_column.replace(
859                                            next_section.generated_offset.column as u32 - 2,
860                                        );
861                                    }
862                                }
863                                mapping.generated_line += line_shift as u32;
864                                f(&mapping);
865                            }
866                        },
867                        ord.clone(),
868                    )
869                }
870            })
871    }
872}