clang_ast/
loc.rs

1use crate::intern::InternVisitor;
2use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, MapAccess, Visitor};
3use serde::ser::{Serialize, SerializeMap, Serializer};
4use std::cell::{Cell, RefCell};
5use std::fmt::{self, Debug};
6use std::sync::Arc;
7
8#[derive(#[automatically_derived]
impl ::core::default::Default for SourceRange {
    #[inline]
    fn default() -> SourceRange {
        SourceRange {
            begin: ::core::default::Default::default(),
            end: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for SourceRange {
    #[inline]
    fn clone(&self) -> SourceRange {
        SourceRange {
            begin: ::core::clone::Clone::clone(&self.begin),
            end: ::core::clone::Clone::clone(&self.end),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for SourceRange {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<SourceLocation>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for SourceRange {
    #[inline]
    fn eq(&self, other: &SourceRange) -> bool {
        self.begin == other.begin && self.end == other.end
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SourceRange {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        ::core::hash::Hash::hash(&self.begin, state);
        ::core::hash::Hash::hash(&self.end, state)
    }
}Hash)]
9pub struct SourceRange {
10    pub begin: SourceLocation,
11    pub end: SourceLocation,
12}
13
14#[derive(#[automatically_derived]
impl ::core::default::Default for SourceLocation {
    #[inline]
    fn default() -> SourceLocation {
        SourceLocation {
            spelling_loc: ::core::default::Default::default(),
            expansion_loc: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for SourceLocation {
    #[inline]
    fn clone(&self) -> SourceLocation {
        SourceLocation {
            spelling_loc: ::core::clone::Clone::clone(&self.spelling_loc),
            expansion_loc: ::core::clone::Clone::clone(&self.expansion_loc),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for SourceLocation {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<Option<BareSourceLocation>>;
        let _: ::core::cmp::AssertParamIsEq<Option<BareSourceLocation>>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for SourceLocation {
    #[inline]
    fn eq(&self, other: &SourceLocation) -> bool {
        self.spelling_loc == other.spelling_loc &&
            self.expansion_loc == other.expansion_loc
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SourceLocation {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        ::core::hash::Hash::hash(&self.spelling_loc, state);
        ::core::hash::Hash::hash(&self.expansion_loc, state)
    }
}Hash)]
15pub struct SourceLocation {
16    pub spelling_loc: Option<BareSourceLocation>,
17    pub expansion_loc: Option<BareSourceLocation>,
18}
19
20#[derive(#[automatically_derived]
impl ::core::clone::Clone for BareSourceLocation {
    #[inline]
    fn clone(&self) -> BareSourceLocation {
        BareSourceLocation {
            offset: ::core::clone::Clone::clone(&self.offset),
            file: ::core::clone::Clone::clone(&self.file),
            line: ::core::clone::Clone::clone(&self.line),
            presumed_file: ::core::clone::Clone::clone(&self.presumed_file),
            presumed_line: ::core::clone::Clone::clone(&self.presumed_line),
            col: ::core::clone::Clone::clone(&self.col),
            tok_len: ::core::clone::Clone::clone(&self.tok_len),
            included_from: ::core::clone::Clone::clone(&self.included_from),
            is_macro_arg_expansion: ::core::clone::Clone::clone(&self.is_macro_arg_expansion),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for BareSourceLocation {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<usize>;
        let _: ::core::cmp::AssertParamIsEq<Arc<str>>;
        let _: ::core::cmp::AssertParamIsEq<Option<Arc<str>>>;
        let _: ::core::cmp::AssertParamIsEq<Option<usize>>;
        let _: ::core::cmp::AssertParamIsEq<Option<IncludedFrom>>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for BareSourceLocation {
    #[inline]
    fn eq(&self, other: &BareSourceLocation) -> bool {
        self.is_macro_arg_expansion == other.is_macro_arg_expansion &&
                                        self.offset == other.offset && self.file == other.file &&
                                self.line == other.line &&
                            self.presumed_file == other.presumed_file &&
                        self.presumed_line == other.presumed_line &&
                    self.col == other.col && self.tok_len == other.tok_len &&
            self.included_from == other.included_from
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for BareSourceLocation {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        ::core::hash::Hash::hash(&self.offset, state);
        ::core::hash::Hash::hash(&self.file, state);
        ::core::hash::Hash::hash(&self.line, state);
        ::core::hash::Hash::hash(&self.presumed_file, state);
        ::core::hash::Hash::hash(&self.presumed_line, state);
        ::core::hash::Hash::hash(&self.col, state);
        ::core::hash::Hash::hash(&self.tok_len, state);
        ::core::hash::Hash::hash(&self.included_from, state);
        ::core::hash::Hash::hash(&self.is_macro_arg_expansion, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for BareSourceLocation {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["offset", "file", "line", "presumed_file", "presumed_line",
                        "col", "tok_len", "included_from",
                        "is_macro_arg_expansion"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.offset, &self.file, &self.line, &self.presumed_file,
                        &self.presumed_line, &self.col, &self.tok_len,
                        &self.included_from, &&self.is_macro_arg_expansion];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "BareSourceLocation", names, values)
    }
}Debug)]
21pub struct BareSourceLocation {
22    pub offset: usize,
23    pub file: Arc<str>,
24    pub line: usize,
25    pub presumed_file: Option<Arc<str>>,
26    pub presumed_line: Option<usize>,
27    pub col: usize,
28    pub tok_len: usize,
29    pub included_from: Option<IncludedFrom>,
30    pub is_macro_arg_expansion: bool,
31}
32
33#[derive(#[automatically_derived]
impl ::core::clone::Clone for IncludedFrom {
    #[inline]
    fn clone(&self) -> IncludedFrom {
        IncludedFrom {
            included_from: ::core::clone::Clone::clone(&self.included_from),
            file: ::core::clone::Clone::clone(&self.file),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for IncludedFrom {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {
        let _: ::core::cmp::AssertParamIsEq<Option<Box<IncludedFrom>>>;
        let _: ::core::cmp::AssertParamIsEq<Arc<str>>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for IncludedFrom {
    #[inline]
    fn eq(&self, other: &IncludedFrom) -> bool {
        self.included_from == other.included_from && self.file == other.file
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for IncludedFrom {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        ::core::hash::Hash::hash(&self.included_from, state);
        ::core::hash::Hash::hash(&self.file, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for IncludedFrom {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "IncludedFrom",
            "included_from", &self.included_from, "file", &&self.file)
    }
}Debug)]
34pub struct IncludedFrom {
35    pub included_from: Option<Box<IncludedFrom>>,
36    pub file: Arc<str>,
37}
38
39const LAST_LOC_LINE: ::std::thread::LocalKey<Cell<usize>> =
    {
        const __INIT: Cell<usize> = { Cell::new(0) };
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<Cell<usize>>() {
                            |_|
                                {
                                    #[thread_local]
                                    static VAL:
                                        ::std::thread::local_impl::EagerStorage<Cell<usize>> =
                                        ::std::thread::local_impl::EagerStorage::new(__INIT);
                                    VAL.get()
                                }
                        } else {
                            |_|
                                {
                                    #[thread_local]
                                    static VAL: Cell<usize> = __INIT;
                                    &VAL
                                }
                        }
                    })
        }
    };thread_local! {
40    static LAST_LOC_FILENAME: RefCell<Arc<str>> = RefCell::new(Arc::from(""));
41    static LAST_LOC_LINE: Cell<usize> = const { Cell::new(0) };
42}
43
44pub(crate) fn thread_local_reset() {
45    LAST_LOC_FILENAME.with(|last_loc_filename| {
46        let mut last_loc_filename = last_loc_filename.borrow_mut();
47        if !last_loc_filename.is_empty() {
48            *last_loc_filename = Arc::from("");
49        }
50    });
51    LAST_LOC_LINE.with(|last_loc_line| last_loc_line.set(0));
52}
53
54enum SourceLocationField {
55    SpellingLoc,
56    ExpansionLoc,
57    Offset,
58    File,
59    Line,
60    PresumedFile,
61    PresumedLine,
62    Col,
63    TokLen,
64    IncludedFrom,
65    IsMacroArgExpansion,
66}
67
68impl<'de> Deserialize<'de> for SourceLocation {
69    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        struct SourceLocationVisitor;
74
75        impl<'de> Visitor<'de> for SourceLocationVisitor {
76            type Value = SourceLocation;
77
78            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79                formatter.write_str("struct SourceLocation")
80            }
81
82            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
83            where
84                M: MapAccess<'de>,
85            {
86                match map.next_key()? {
87                    None => Ok(SourceLocation::default()),
88                    Some(SourceLocationField::SpellingLoc) => {
89                        let spelling_loc: BareSourceLocation = map.next_value()?;
90                        match map.next_key()? {
91                            None => Err(Error::missing_field("expansionLoc")),
92                            Some(SourceLocationField::ExpansionLoc) => {
93                                let expansion_loc: BareSourceLocation = map.next_value()?;
94                                Ok(SourceLocation {
95                                    spelling_loc: Some(spelling_loc),
96                                    expansion_loc: Some(expansion_loc),
97                                })
98                            }
99                            Some(other) => Err(other.unexpected()),
100                        }
101                    }
102                    Some(SourceLocationField::Offset) => {
103                        let loc = de_rest_of_bare_source_location(map)?;
104                        Ok(SourceLocation {
105                            spelling_loc: Some(loc.clone()),
106                            expansion_loc: Some(loc),
107                        })
108                    }
109                    Some(other) => Err(other.unexpected()),
110                }
111            }
112        }
113
114        deserializer.deserialize_map(SourceLocationVisitor)
115    }
116}
117
118impl<'de> Deserialize<'de> for BareSourceLocation {
119    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120    where
121        D: Deserializer<'de>,
122    {
123        struct BareSourceLocationVisitor;
124
125        impl<'de> Visitor<'de> for BareSourceLocationVisitor {
126            type Value = BareSourceLocation;
127
128            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
129                formatter.write_str("struct BareSourceLocation")
130            }
131
132            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
133            where
134                M: MapAccess<'de>,
135            {
136                match map.next_key()? {
137                    None => Err(Error::missing_field("offset")),
138                    Some(SourceLocationField::Offset) => de_rest_of_bare_source_location(map),
139                    Some(other) => Err(other.unexpected()),
140                }
141            }
142        }
143
144        deserializer.deserialize_map(BareSourceLocationVisitor)
145    }
146}
147
148impl<'de> Deserialize<'de> for SourceRange {
149    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
150    where
151        D: Deserializer<'de>,
152    {
153        enum SourceRangeField {
154            Begin,
155            End,
156        }
157
158        struct SourceRangeFieldVisitor;
159
160        impl<'de> Visitor<'de> for SourceRangeFieldVisitor {
161            type Value = SourceRangeField;
162
163            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
164                formatter.write_str("field identifier")
165            }
166
167            fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
168            where
169                E: Error,
170            {
171                static FIELDS: &[&str] = &["begin", "end"];
172                match field {
173                    "begin" => Ok(SourceRangeField::Begin),
174                    "end" => Ok(SourceRangeField::End),
175                    _ => Err(E::unknown_field(field, FIELDS)),
176                }
177            }
178        }
179
180        impl<'de> Deserialize<'de> for SourceRangeField {
181            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
182            where
183                D: Deserializer<'de>,
184            {
185                deserializer.deserialize_identifier(SourceRangeFieldVisitor)
186            }
187        }
188
189        struct SourceRangeVisitor;
190
191        impl<'de> Visitor<'de> for SourceRangeVisitor {
192            type Value = SourceRange;
193
194            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
195                formatter.write_str("struct SourceRange")
196            }
197
198            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
199            where
200                M: MapAccess<'de>,
201            {
202                let mut begin = None;
203                let mut end = None;
204                while let Some(key) = map.next_key()? {
205                    match key {
206                        SourceRangeField::Begin => {
207                            if begin.is_some() {
208                                return Err(Error::duplicate_field("begin"));
209                            }
210                            begin = Some(map.next_value()?);
211                        }
212                        SourceRangeField::End => {
213                            if end.is_some() {
214                                return Err(Error::duplicate_field("end"));
215                            }
216                            end = Some(map.next_value()?);
217                        }
218                    }
219                }
220                let begin = begin.ok_or_else(|| Error::missing_field("begin"))?;
221                let end = end.ok_or_else(|| Error::missing_field("end"))?;
222                Ok(SourceRange { begin, end })
223            }
224        }
225
226        deserializer.deserialize_map(SourceRangeVisitor)
227    }
228}
229
230impl<'de> Deserialize<'de> for IncludedFrom {
231    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
232    where
233        D: Deserializer<'de>,
234    {
235        enum IncludedFromField {
236            IncludedFrom,
237            File,
238        }
239
240        struct IncludedFromFieldVisitor;
241
242        impl<'de> Visitor<'de> for IncludedFromFieldVisitor {
243            type Value = IncludedFromField;
244
245            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
246                formatter.write_str("field identifier")
247            }
248
249            fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
250            where
251                E: Error,
252            {
253                static FIELDS: &[&str] = &["includedFrom", "file"];
254                match field {
255                    "includedFrom" => Ok(IncludedFromField::IncludedFrom),
256                    "file" => Ok(IncludedFromField::File),
257                    _ => Err(E::unknown_field(field, FIELDS)),
258                }
259            }
260        }
261
262        impl<'de> Deserialize<'de> for IncludedFromField {
263            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
264            where
265                D: Deserializer<'de>,
266            {
267                deserializer.deserialize_identifier(IncludedFromFieldVisitor)
268            }
269        }
270
271        struct IncludedFromVisitor;
272
273        impl<'de> Visitor<'de> for IncludedFromVisitor {
274            type Value = IncludedFrom;
275
276            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
277                formatter.write_str("struct IncludedFrom")
278            }
279
280            fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
281            where
282                M: MapAccess<'de>,
283            {
284                let mut has_included_from = false;
285                let mut file = None;
286                while let Some(key) = map.next_key()? {
287                    match key {
288                        IncludedFromField::IncludedFrom => {
289                            if has_included_from {
290                                return Err(Error::duplicate_field("includedFrom"));
291                            }
292                            map.next_value::<IgnoredAny>()?;
293                            has_included_from = true;
294                        }
295                        IncludedFromField::File => {
296                            if file.is_some() {
297                                return Err(Error::duplicate_field("file"));
298                            }
299                            file = Some(map.next_value_seed(InternVisitor)?);
300                        }
301                    }
302                }
303                let file = file.ok_or_else(|| Error::missing_field("file"))?;
304                Ok(IncludedFrom {
305                    included_from: None,
306                    file,
307                })
308            }
309        }
310
311        deserializer.deserialize_map(IncludedFromVisitor)
312    }
313}
314
315impl<'de> Deserialize<'de> for SourceLocationField {
316    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
317    where
318        D: Deserializer<'de>,
319    {
320        struct SourceLocationFieldVisitor;
321
322        impl<'de> Visitor<'de> for SourceLocationFieldVisitor {
323            type Value = SourceLocationField;
324
325            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
326                formatter.write_str("field identifier")
327            }
328
329            fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
330            where
331                E: Error,
332            {
333                static FIELDS: &[&str] = &[
334                    "spellingLoc",
335                    "expansionLoc",
336                    "offset",
337                    "file",
338                    "line",
339                    "presumedFile",
340                    "presumedLine",
341                    "col",
342                    "tokLen",
343                    "includedFrom",
344                    "isMacroArgExpansion",
345                ];
346                match field {
347                    "spellingLoc" => Ok(SourceLocationField::SpellingLoc),
348                    "expansionLoc" => Ok(SourceLocationField::ExpansionLoc),
349                    "offset" => Ok(SourceLocationField::Offset),
350                    "file" => Ok(SourceLocationField::File),
351                    "line" => Ok(SourceLocationField::Line),
352                    "presumedFile" => Ok(SourceLocationField::PresumedFile),
353                    "presumedLine" => Ok(SourceLocationField::PresumedLine),
354                    "col" => Ok(SourceLocationField::Col),
355                    "tokLen" => Ok(SourceLocationField::TokLen),
356                    "includedFrom" => Ok(SourceLocationField::IncludedFrom),
357                    "isMacroArgExpansion" => Ok(SourceLocationField::IsMacroArgExpansion),
358                    _ => Err(E::unknown_field(field, FIELDS)),
359                }
360            }
361        }
362
363        deserializer.deserialize_identifier(SourceLocationFieldVisitor)
364    }
365}
366
367fn de_rest_of_bare_source_location<'de, M>(mut map: M) -> Result<BareSourceLocation, M::Error>
368where
369    M: MapAccess<'de>,
370{
371    let offset: usize = map.next_value()?;
372
373    let mut file = None;
374    let mut line = None;
375    let mut presumed_file = None;
376    let mut presumed_line = None;
377    let mut col = None;
378    let mut tok_len = None;
379    let mut included_from = None;
380    let mut is_macro_arg_expansion = false;
381
382    while let Some(field) = map.next_key()? {
383        match field {
384            SourceLocationField::Offset => return Err(Error::duplicate_field("offset")),
385            SourceLocationField::File => file = Some(map.next_value_seed(InternVisitor)?),
386            SourceLocationField::Line => line = Some(map.next_value()?),
387            SourceLocationField::PresumedFile => {
388                presumed_file = Some(map.next_value_seed(InternVisitor)?);
389            }
390            SourceLocationField::PresumedLine => presumed_line = Some(map.next_value()?),
391            SourceLocationField::Col => col = Some(map.next_value()?),
392            SourceLocationField::TokLen => tok_len = Some(map.next_value()?),
393            SourceLocationField::IncludedFrom => included_from = Some(map.next_value()?),
394            SourceLocationField::IsMacroArgExpansion => {
395                is_macro_arg_expansion = map.next_value()?;
396            }
397            SourceLocationField::SpellingLoc | SourceLocationField::ExpansionLoc => {
398                return Err(field.unexpected());
399            }
400        }
401    }
402
403    let file = LAST_LOC_FILENAME.with(|last_loc_filename| match file {
404        Some(file) => {
405            *last_loc_filename.borrow_mut() = Arc::clone(&file);
406            file
407        }
408        None => Arc::clone(&last_loc_filename.borrow()),
409    });
410
411    let line = LAST_LOC_LINE.with(|last_loc_line| match line {
412        Some(line) => {
413            last_loc_line.set(line);
414            line
415        }
416        None => last_loc_line.get(),
417    });
418
419    let col = col.ok_or_else(|| Error::missing_field("col"))?;
420    let tok_len = tok_len.ok_or_else(|| Error::missing_field("tokLen"))?;
421
422    Ok(BareSourceLocation {
423        offset,
424        file,
425        line,
426        presumed_file,
427        presumed_line,
428        col,
429        tok_len,
430        included_from,
431        is_macro_arg_expansion,
432    })
433}
434
435impl SourceLocationField {
436    fn unexpected<E: Error>(&self) -> E {
437        Error::unknown_field(
438            match self {
439                SourceLocationField::SpellingLoc => "spellingLoc",
440                SourceLocationField::ExpansionLoc => "expansionLoc",
441                SourceLocationField::Offset => "offset",
442                SourceLocationField::File => "file",
443                SourceLocationField::Line => "line",
444                SourceLocationField::PresumedFile => "presumedFile",
445                SourceLocationField::PresumedLine => "presumedLine",
446                SourceLocationField::Col => "col",
447                SourceLocationField::TokLen => "tokLen",
448                SourceLocationField::IncludedFrom => "includedFrom",
449                SourceLocationField::IsMacroArgExpansion => "isMacroArgExpansion",
450            },
451            &[
452                "spellingLoc",
453                "expansionLoc",
454                "offset",
455                "file",
456                "line",
457                "presumedFile",
458                "presumedLine",
459                "col",
460                "tokLen",
461                "includedFrom",
462                "isMacroArgExpansion",
463            ],
464        )
465    }
466}
467
468impl Serialize for SourceRange {
469    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
470    where
471        S: Serializer,
472    {
473        let mut map = serializer.serialize_map(None)?;
474        map.serialize_entry("begin", &self.begin)?;
475        map.serialize_entry("end", &self.end)?;
476        map.end()
477    }
478}
479
480impl Serialize for SourceLocation {
481    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
482    where
483        S: Serializer,
484    {
485        fn same_bare_source_location(
486            spelling_loc: &BareSourceLocation,
487            expansion_loc: &BareSourceLocation,
488        ) -> bool {
489            let BareSourceLocation {
490                offset: spelling_offset,
491                file: spelling_file,
492                line: spelling_line,
493                presumed_file: spelling_presumed_file,
494                presumed_line: spelling_presumed_line,
495                col: spelling_col,
496                tok_len: spelling_tok_len,
497                included_from: spelling_included_from,
498                is_macro_arg_expansion: spelling_is_macro_arg_expansion,
499            } = spelling_loc;
500            let BareSourceLocation {
501                offset: expansion_offset,
502                file: expansion_file,
503                line: expansion_line,
504                presumed_file: expansion_presumed_file,
505                presumed_line: expansion_presumed_line,
506                col: expansion_col,
507                tok_len: expansion_tok_len,
508                included_from: expansion_included_from,
509                is_macro_arg_expansion: expansion_is_macro_arg_expansion,
510            } = expansion_loc;
511            spelling_offset == expansion_offset
512                && spelling_file == expansion_file
513                && spelling_line == expansion_line
514                && spelling_presumed_file == expansion_presumed_file
515                && spelling_presumed_line == expansion_presumed_line
516                && spelling_col == expansion_col
517                && spelling_tok_len == expansion_tok_len
518                && same_opt_included_from(
519                    spelling_included_from.as_ref(),
520                    expansion_included_from.as_ref(),
521                )
522                && spelling_is_macro_arg_expansion == expansion_is_macro_arg_expansion
523        }
524
525        fn same_opt_included_from(
526            spelling_included_from: Option<&IncludedFrom>,
527            expansion_included_from: Option<&IncludedFrom>,
528        ) -> bool {
529            spelling_included_from
530                .zip(expansion_included_from)
531                .is_some_and(|(spelling_included_from, expansion_included_from)| {
532                    let IncludedFrom {
533                        included_from: spelling_included_from,
534                        file: spelling_file,
535                    } = spelling_included_from;
536                    let IncludedFrom {
537                        included_from: expansion_included_from,
538                        file: expansion_file,
539                    } = expansion_included_from;
540                    same_opt_included_from(
541                        spelling_included_from.as_ref().map(Box::as_ref),
542                        expansion_included_from.as_ref().map(Box::as_ref),
543                    ) && spelling_file == expansion_file
544                })
545        }
546
547        let serialize_separately = self
548            .spelling_loc
549            .as_ref()
550            .zip(self.expansion_loc.as_ref())
551            .map_or(true, |(spelling_loc, expansion_loc)| {
552                !same_bare_source_location(spelling_loc, expansion_loc)
553            });
554
555        if serialize_separately {
556            let mut map = serializer.serialize_map(None)?;
557            if let Some(spelling_loc) = &self.spelling_loc {
558                map.serialize_entry("spellingLoc", spelling_loc)?;
559            }
560            if let Some(expansion_loc) = &self.expansion_loc {
561                map.serialize_entry("expansionLoc", expansion_loc)?;
562            }
563            map.end()
564        } else {
565            self.spelling_loc.serialize(serializer)
566        }
567    }
568}
569
570impl Serialize for BareSourceLocation {
571    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
572    where
573        S: Serializer,
574    {
575        let mut map = serializer.serialize_map(None)?;
576        map.serialize_entry("offset", &self.offset)?;
577        if LAST_LOC_FILENAME.with(|last_loc_filename| {
578            let mut last_loc_filename = last_loc_filename.borrow_mut();
579            if *last_loc_filename == self.file {
580                false
581            } else {
582                *last_loc_filename = Arc::clone(&self.file);
583                true
584            }
585        }) {
586            map.serialize_entry("file", &*self.file)?;
587            map.serialize_entry("line", &self.line)?;
588        } else if LAST_LOC_LINE.with(|last_loc_line| {
589            if last_loc_line.get() == self.line {
590                false
591            } else {
592                last_loc_line.set(self.line);
593                true
594            }
595        }) {
596            map.serialize_entry("line", &self.line)?;
597        }
598        if let Some(presumed_file) = &self.presumed_file {
599            map.serialize_entry("presumedFile", &**presumed_file)?;
600        }
601        if let Some(presumed_line) = &self.presumed_line {
602            map.serialize_entry("presumedLine", presumed_line)?;
603        }
604        map.serialize_entry("col", &self.col)?;
605        map.serialize_entry("tokLen", &self.tok_len)?;
606        if let Some(included_from) = &self.included_from {
607            map.serialize_entry("includedFrom", included_from)?;
608        }
609        if self.is_macro_arg_expansion {
610            map.serialize_entry("isMacroArgExpansion", &true)?;
611        }
612        map.end()
613    }
614}
615
616impl Serialize for IncludedFrom {
617    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
618    where
619        S: Serializer,
620    {
621        let mut map = serializer.serialize_map(None)?;
622        if let Some(included_from) = &self.included_from {
623            map.serialize_entry("includedFrom", included_from)?;
624        }
625        map.serialize_entry("file", &*self.file)?;
626        map.end()
627    }
628}
629
630impl Debug for SourceRange {
631    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
632        let SourceRange { begin, end } = self;
633        let SourceLocation {
634            spelling_loc: begin_spelling_loc,
635            expansion_loc: begin_expansion_loc,
636        } = begin;
637        let SourceLocation {
638            spelling_loc: end_spelling_loc,
639            expansion_loc: end_expansion_loc,
640        } = end;
641        let mut debug = formatter.debug_struct("SourceRange");
642        if begin_spelling_loc.is_some()
643            || begin_expansion_loc.is_some()
644            || end_spelling_loc.is_some()
645            || end_expansion_loc.is_some()
646        {
647            debug.field("begin", begin).field("end", end);
648        }
649        debug.finish()
650    }
651}
652
653impl Debug for SourceLocation {
654    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
655        let SourceLocation {
656            spelling_loc,
657            expansion_loc,
658        } = self;
659        let mut debug = formatter.debug_struct("SourceLocation");
660        if spelling_loc.is_some() {
661            debug.field("spelling_loc", spelling_loc);
662        }
663        if expansion_loc.is_some() {
664            debug.field("expansion_loc", expansion_loc);
665        }
666        debug.finish()
667    }
668}