swc_ecma_ast/
source_map.rs1use 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 fn comment_range(&self) -> Span {
19 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 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}