swc_ecma_ast/
source_map.rs

1use std::{rc::Rc, sync::Arc};
2
3use swc_common::{BytePos, SourceMap, SourceMapper, SourceMapperDyn, Span, Spanned};
4
5use crate::list::ListFormat;
6
7pub trait SpanExt: Spanned {
8    #[inline]
9    fn is_synthesized(&self) -> bool {
10        false
11    }
12
13    fn starts_on_new_line(&self, format: ListFormat) -> bool {
14        format.intersects(ListFormat::PreferNewLine)
15    }
16
17    /// Gets a custom text range to use when emitting comments.
18    fn comment_range(&self) -> Span {
19        //TODO
20        self.span()
21    }
22}
23impl<T: Spanned> SpanExt for T {}
24
25pub trait SourceMapperExt {
26    fn get_code_map(&self) -> &dyn SourceMapper;
27
28    fn is_on_same_line(&self, _lo: BytePos, _hi: BytePos) -> bool {
29        // let cm = self.get_code_map();
30
31        // let lo = cm.lookup_char_pos(lo);
32        // let hi = cm.lookup_char_pos(hi);
33
34        // lo.line == hi.line && lo.file.name_hash == hi.file.name_hash
35        false
36    }
37
38    fn should_write_separating_line_terminator(
39        &self,
40        prev: Option<Span>,
41        next: Option<Span>,
42        format: ListFormat,
43    ) -> bool {
44        if format.contains(ListFormat::MultiLine) {
45            return true;
46        }
47
48        if format.contains(ListFormat::PreserveLines) {
49            if let (Some(prev), Some(next)) = (prev, next) {
50                if prev.is_synthesized() || next.is_synthesized() {
51                    return prev.starts_on_new_line(format) || next.starts_on_new_line(format);
52                }
53
54                return !self.is_on_same_line(prev.hi(), next.lo());
55            } else {
56                return false;
57            }
58        }
59
60        false
61    }
62
63    fn should_write_leading_line_terminator(
64        &self,
65        parent_node: Span,
66        first_child: Option<Span>,
67        format: ListFormat,
68    ) -> bool {
69        if format.contains(ListFormat::MultiLine) {
70            return true;
71        }
72
73        if format.contains(ListFormat::PreserveLines) {
74            if format.contains(ListFormat::PreferNewLine) {
75                return true;
76            }
77
78            if first_child.is_none() {
79                return !self.is_on_same_line(parent_node.lo(), parent_node.hi());
80            }
81
82            let first_child = first_child.unwrap();
83            if parent_node.is_synthesized() || first_child.is_synthesized() {
84                return first_child.starts_on_new_line(format);
85            }
86
87            !self.is_on_same_line(parent_node.lo(), first_child.lo())
88        } else {
89            false
90        }
91    }
92
93    fn should_write_closing_line_terminator(
94        &self,
95        parent_node: Span,
96        last_child: Option<Span>,
97        format: ListFormat,
98    ) -> bool {
99        if format.contains(ListFormat::MultiLine) {
100            return (format & ListFormat::NoTrailingNewLine) == ListFormat::None;
101        }
102
103        if format.contains(ListFormat::PreserveLines) {
104            if format.contains(ListFormat::PreferNewLine) {
105                return true;
106            }
107
108            if last_child.is_none() {
109                return !self.is_on_same_line(parent_node.lo(), parent_node.hi());
110            }
111
112            let last_child = last_child.unwrap();
113
114            if parent_node.is_synthesized() || last_child.is_synthesized() {
115                last_child.starts_on_new_line(format)
116            } else {
117                !self.is_on_same_line(parent_node.hi(), last_child.hi())
118            }
119        } else {
120            false
121        }
122    }
123}
124
125impl SourceMapperExt for SourceMap {
126    fn get_code_map(&self) -> &dyn SourceMapper {
127        self
128    }
129}
130
131impl SourceMapperExt for dyn SourceMapper {
132    fn get_code_map(&self) -> &dyn SourceMapper {
133        self
134    }
135}
136
137impl SourceMapperExt for Arc<SourceMapperDyn> {
138    fn get_code_map(&self) -> &dyn SourceMapper {
139        &**self
140    }
141}
142impl SourceMapperExt for Rc<SourceMapperDyn> {
143    fn get_code_map(&self) -> &dyn SourceMapper {
144        &**self
145    }
146}
147
148impl SourceMapperExt for Arc<SourceMap> {
149    fn get_code_map(&self) -> &dyn SourceMapper {
150        &**self
151    }
152}
153
154impl SourceMapperExt for Rc<SourceMap> {
155    fn get_code_map(&self) -> &dyn SourceMapper {
156        &**self
157    }
158}