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
93impl CodeLocationExt for pt::VersionComparator {
94    fn loc(&self) -> pt::Loc {
95        match self {
96            Self::Plain { loc, .. } |
97            Self::Operator { loc, .. } |
98            Self::Or { loc, .. } |
99            Self::Range { loc, .. } => *loc,
100        }
101    }
102}
103
104macro_rules! impl_delegate {
105    ($($t:ty),+ $(,)?) => {$(
106        impl CodeLocationExt for $t {
107            #[inline]
108            #[track_caller]
109            fn loc(&self) -> pt::Loc {
110                pt::CodeLocation::loc(self)
111            }
112        }
113    )+};
114}
115
116impl_delegate! {
117    pt::Annotation,
118    pt::Base,
119    pt::ContractDefinition,
120    pt::EnumDefinition,
121    pt::ErrorDefinition,
122    pt::ErrorParameter,
123    pt::EventDefinition,
124    pt::EventParameter,
125    pt::PragmaDirective,
126    // pt::FunctionDefinition,
127    pt::HexLiteral,
128    pt::Identifier,
129    pt::IdentifierPath,
130    pt::NamedArgument,
131    pt::Parameter,
132    // pt::SourceUnit,
133    pt::StringLiteral,
134    pt::StructDefinition,
135    pt::TypeDefinition,
136    pt::Using,
137    pt::UsingFunction,
138    pt::VariableDeclaration,
139    pt::VariableDefinition,
140    pt::YulBlock,
141    pt::YulFor,
142    pt::YulFunctionCall,
143    pt::YulFunctionDefinition,
144    pt::YulSwitch,
145    pt::YulTypedIdentifier,
146
147    pt::CatchClause,
148    pt::Comment,
149    // pt::ContractPart,
150    pt::ContractTy,
151    pt::Expression,
152    pt::FunctionAttribute,
153    // pt::FunctionTy,
154    pt::Import,
155    pt::Loc,
156    pt::Mutability,
157    // pt::SourceUnitPart,
158    pt::Statement,
159    pt::StorageLocation,
160    // pt::Type,
161    // pt::UserDefinedOperator,
162    pt::UsingList,
163    pt::VariableAttribute,
164    // pt::Visibility,
165    pt::YulExpression,
166    pt::YulStatement,
167    pt::YulSwitchOptions,
168}