forge_fmt/solang_ext/
loc.rs

1use solang_parser::pt;
2use std::{borrow::Cow, rc::Rc, sync::Arc};
3
4/// Returns the code location.
5///
6/// Patched version of [`pt::CodeLocation`]: includes the block of a [`pt::FunctionDefinition`] in
7/// its `loc`.
8pub trait CodeLocationExt {
9    /// Returns the code location of `self`.
10    fn loc(&self) -> pt::Loc;
11}
12
13impl<T: ?Sized + CodeLocationExt> CodeLocationExt for &T {
14    fn loc(&self) -> pt::Loc {
15        (**self).loc()
16    }
17}
18
19impl<T: ?Sized + CodeLocationExt> CodeLocationExt for &mut T {
20    fn loc(&self) -> pt::Loc {
21        (**self).loc()
22    }
23}
24
25impl<T: ?Sized + ToOwned + CodeLocationExt> CodeLocationExt for Cow<'_, T> {
26    fn loc(&self) -> pt::Loc {
27        (**self).loc()
28    }
29}
30
31impl<T: ?Sized + CodeLocationExt> CodeLocationExt for Box<T> {
32    fn loc(&self) -> pt::Loc {
33        (**self).loc()
34    }
35}
36
37impl<T: ?Sized + CodeLocationExt> CodeLocationExt for Rc<T> {
38    fn loc(&self) -> pt::Loc {
39        (**self).loc()
40    }
41}
42
43impl<T: ?Sized + CodeLocationExt> CodeLocationExt for Arc<T> {
44    fn loc(&self) -> pt::Loc {
45        (**self).loc()
46    }
47}
48
49// FunctionDefinition patch
50impl CodeLocationExt for pt::FunctionDefinition {
51    #[inline]
52    #[track_caller]
53    fn loc(&self) -> pt::Loc {
54        let mut loc = self.loc;
55        if let Some(ref body) = self.body {
56            loc.use_end_from(&pt::CodeLocation::loc(body));
57        }
58        loc
59    }
60}
61
62impl CodeLocationExt for pt::ContractPart {
63    #[inline]
64    #[track_caller]
65    fn loc(&self) -> pt::Loc {
66        match self {
67            Self::FunctionDefinition(f) => f.loc(),
68            _ => pt::CodeLocation::loc(self),
69        }
70    }
71}
72
73impl CodeLocationExt for pt::SourceUnitPart {
74    #[inline]
75    #[track_caller]
76    fn loc(&self) -> pt::Loc {
77        match self {
78            Self::FunctionDefinition(f) => f.loc(),
79            _ => pt::CodeLocation::loc(self),
80        }
81    }
82}
83
84impl CodeLocationExt for pt::ImportPath {
85    fn loc(&self) -> pt::Loc {
86        match self {
87            Self::Filename(s) => s.loc(),
88            Self::Path(i) => i.loc(),
89        }
90    }
91}
92
93macro_rules! impl_delegate {
94    ($($t:ty),+ $(,)?) => {$(
95        impl CodeLocationExt for $t {
96            #[inline]
97            #[track_caller]
98            fn loc(&self) -> pt::Loc {
99                pt::CodeLocation::loc(self)
100            }
101        }
102    )+};
103}
104
105impl_delegate! {
106    pt::Annotation,
107    pt::Base,
108    pt::ContractDefinition,
109    pt::EnumDefinition,
110    pt::ErrorDefinition,
111    pt::ErrorParameter,
112    pt::EventDefinition,
113    pt::EventParameter,
114    // pt::FunctionDefinition,
115    pt::HexLiteral,
116    pt::Identifier,
117    pt::IdentifierPath,
118    pt::NamedArgument,
119    pt::Parameter,
120    // pt::SourceUnit,
121    pt::StringLiteral,
122    pt::StructDefinition,
123    pt::TypeDefinition,
124    pt::Using,
125    pt::UsingFunction,
126    pt::VariableDeclaration,
127    pt::VariableDefinition,
128    pt::YulBlock,
129    pt::YulFor,
130    pt::YulFunctionCall,
131    pt::YulFunctionDefinition,
132    pt::YulSwitch,
133    pt::YulTypedIdentifier,
134
135    pt::CatchClause,
136    pt::Comment,
137    // pt::ContractPart,
138    pt::ContractTy,
139    pt::Expression,
140    pt::FunctionAttribute,
141    // pt::FunctionTy,
142    pt::Import,
143    pt::Loc,
144    pt::Mutability,
145    // pt::SourceUnitPart,
146    pt::Statement,
147    pt::StorageLocation,
148    // pt::Type,
149    // pt::UserDefinedOperator,
150    pt::UsingList,
151    pt::VariableAttribute,
152    // pt::Visibility,
153    pt::YulExpression,
154    pt::YulStatement,
155    pt::YulSwitchOptions,
156}