1use crate::lexer::LexicalError;
4use crate::pt::{self, Loc};
5use std::sync::Arc;
6use std::{borrow::Cow, rc::Rc};
7
8pub trait OptionalCodeLocation {
10 fn loc_opt(&self) -> Option<Loc>;
12}
13
14impl<T: CodeLocation> OptionalCodeLocation for Option<T> {
15 fn loc_opt(&self) -> Option<Loc> {
16 self.as_ref().map(CodeLocation::loc)
17 }
18}
19
20impl OptionalCodeLocation for pt::Visibility {
21 fn loc_opt(&self) -> Option<Loc> {
22 match self {
23 Self::Internal(l, ..)
24 | Self::External(l, ..)
25 | Self::Private(l, ..)
26 | Self::Public(l, ..) => *l,
27 }
28 }
29}
30
31impl OptionalCodeLocation for pt::SourceUnit {
32 #[inline]
33 fn loc_opt(&self) -> Option<Loc> {
34 self.0.loc_opt()
35 }
36}
37
38impl<T: CodeLocation> OptionalCodeLocation for [T] {
39 fn loc_opt(&self) -> Option<Loc> {
41 self.first().map(CodeLocation::loc)
42 }
43}
44
45impl<T: CodeLocation> OptionalCodeLocation for Vec<T> {
46 fn loc_opt(&self) -> Option<Loc> {
47 (**self).loc_opt()
48 }
49}
50
51impl<'a, T: ?Sized + OptionalCodeLocation> OptionalCodeLocation for &'a T {
52 fn loc_opt(&self) -> Option<Loc> {
53 (**self).loc_opt()
54 }
55}
56
57impl<'a, T: ?Sized + OptionalCodeLocation> OptionalCodeLocation for &'a mut T {
58 fn loc_opt(&self) -> Option<Loc> {
59 (**self).loc_opt()
60 }
61}
62
63impl<'a, T: ?Sized + ToOwned + OptionalCodeLocation> OptionalCodeLocation for Cow<'a, T> {
64 fn loc_opt(&self) -> Option<Loc> {
65 (**self).loc_opt()
66 }
67}
68
69impl<T: ?Sized + OptionalCodeLocation> OptionalCodeLocation for Box<T> {
70 fn loc_opt(&self) -> Option<Loc> {
71 (**self).loc_opt()
72 }
73}
74
75impl<T: ?Sized + OptionalCodeLocation> OptionalCodeLocation for Rc<T> {
76 fn loc_opt(&self) -> Option<Loc> {
77 (**self).loc_opt()
78 }
79}
80
81impl<T: ?Sized + OptionalCodeLocation> OptionalCodeLocation for Arc<T> {
82 fn loc_opt(&self) -> Option<Loc> {
83 (**self).loc_opt()
84 }
85}
86
87macro_rules! impl_optional_for_pt {
90 ($($t:ty),+ $(,)?) => {
91 $(
92 impl OptionalCodeLocation for $t {
93 #[inline]
94 fn loc_opt(&self) -> Option<Loc> {
95 Some(<$t as CodeLocation>::loc(self))
96 }
97 }
98 )+
99 };
100}
101
102impl_optional_for_pt!(
103 pt::Annotation,
105 pt::Base,
106 pt::ContractDefinition,
107 pt::EnumDefinition,
108 pt::ErrorDefinition,
109 pt::ErrorParameter,
110 pt::EventDefinition,
111 pt::EventParameter,
112 pt::FunctionDefinition,
113 pt::HexLiteral,
114 pt::Identifier,
115 pt::IdentifierPath,
116 pt::NamedArgument,
117 pt::Parameter,
118 pt::StringLiteral,
119 pt::StructDefinition,
120 pt::TypeDefinition,
121 pt::Using,
122 pt::UsingFunction,
123 pt::VariableDeclaration,
124 pt::VariableDefinition,
125 pt::YulBlock,
126 pt::YulFor,
127 pt::YulFunctionCall,
128 pt::YulFunctionDefinition,
129 pt::YulSwitch,
130 pt::YulTypedIdentifier,
131 pt::CatchClause,
133 pt::Comment,
134 pt::ContractPart,
135 pt::ContractTy,
136 pt::Expression,
137 pt::FunctionAttribute,
138 pt::Import,
139 pt::Loc,
140 pt::Mutability,
141 pt::SourceUnitPart,
142 pt::Statement,
143 pt::StorageLocation,
144 pt::UsingList,
145 pt::VariableAttribute,
146 pt::YulExpression,
147 pt::YulStatement,
148 pt::YulSwitchOptions,
149 LexicalError,
151);
152
153pub trait CodeLocation {
155 fn loc(&self) -> Loc;
157}
158
159impl CodeLocation for Loc {
160 #[inline]
161 fn loc(&self) -> Loc {
162 *self
163 }
164}
165
166impl<'a, T: ?Sized + CodeLocation> CodeLocation for &'a T {
167 fn loc(&self) -> Loc {
168 (**self).loc()
169 }
170}
171
172impl<'a, T: ?Sized + CodeLocation> CodeLocation for &'a mut T {
173 fn loc(&self) -> Loc {
174 (**self).loc()
175 }
176}
177
178impl<'a, T: ?Sized + ToOwned + CodeLocation> CodeLocation for Cow<'a, T> {
179 fn loc(&self) -> Loc {
180 (**self).loc()
181 }
182}
183
184impl<T: ?Sized + CodeLocation> CodeLocation for Box<T> {
185 fn loc(&self) -> Loc {
186 (**self).loc()
187 }
188}
189
190impl<T: ?Sized + CodeLocation> CodeLocation for Rc<T> {
191 fn loc(&self) -> Loc {
192 (**self).loc()
193 }
194}
195
196impl<T: ?Sized + CodeLocation> CodeLocation for Arc<T> {
197 fn loc(&self) -> Loc {
198 (**self).loc()
199 }
200}
201
202macro_rules! impl_for_structs {
203 ($($t:ty),+ $(,)?) => {
204 $(
205 impl CodeLocation for $t {
206 #[inline]
207 fn loc(&self) -> Loc {
208 self.loc
209 }
210 }
211 )+
212 };
213}
214
215impl_for_structs!(
217 pt::Annotation,
218 pt::Base,
219 pt::ContractDefinition,
220 pt::EnumDefinition,
221 pt::ErrorDefinition,
222 pt::ErrorParameter,
223 pt::EventDefinition,
224 pt::EventParameter,
225 pt::FunctionDefinition,
226 pt::HexLiteral,
227 pt::Identifier,
228 pt::IdentifierPath,
229 pt::NamedArgument,
230 pt::Parameter,
231 pt::StringLiteral,
232 pt::StructDefinition,
233 pt::TypeDefinition,
234 pt::Using,
235 pt::UsingFunction,
236 pt::VariableDeclaration,
237 pt::VariableDefinition,
238 pt::YulBlock,
239 pt::YulFor,
240 pt::YulFunctionCall,
241 pt::YulFunctionDefinition,
242 pt::YulSwitch,
243 pt::YulTypedIdentifier,
244);
245
246macro_rules! impl_for_enums {
247 ($(
248 $t:ty: match $s:ident {
249 $($m:tt)*
250 }
251 )+) => {
252 $(
253 impl CodeLocation for $t {
254 fn loc(&$s) -> Loc {
255 match *$s {
256 $($m)*
257 }
258 }
259 }
260 )+
261 };
262}
263
264impl_for_enums! {
266 pt::CatchClause: match self {
267 Self::Simple(l, ..)
268 | Self::Named(l, ..) => l,
269 }
270
271 pt::Comment: match self {
272 Self::Line(l, ..)
273 | Self::Block(l, ..)
274 | Self::DocLine(l, ..)
275 | Self::DocBlock(l, ..) => l,
276 }
277
278 pt::ContractPart: match self {
279 Self::StructDefinition(ref l, ..) => l.loc(),
280 Self::EventDefinition(ref l, ..) => l.loc(),
281 Self::EnumDefinition(ref l, ..) => l.loc(),
282 Self::ErrorDefinition(ref l, ..) => l.loc(),
283 Self::VariableDefinition(ref l, ..) => l.loc(),
284 Self::FunctionDefinition(ref l, ..) => l.loc(),
285 Self::TypeDefinition(ref l, ..) => l.loc(),
286 Self::Annotation(ref l, ..) => l.loc(),
287 Self::Using(ref l, ..) => l.loc(),
288 Self::StraySemicolon(l, ..) => l,
289 }
290
291 pt::ContractTy: match self {
292 Self::Abstract(l, ..)
293 | Self::Contract(l, ..)
294 | Self::Library(l, ..)
295 | Self::Interface(l, ..) => l,
296 }
297
298 pt::Expression: match self {
299 Self::StringLiteral(ref l, ..) => l.loc_opt().unwrap(),
301 Self::HexLiteral(ref l, ..) => l.loc_opt().unwrap(),
302 Self::Variable(ref l, ..) => l.loc(),
303 Self::PostIncrement(l, ..)
304 | Self::PostDecrement(l, ..)
305 | Self::New(l, ..)
306 | Self::Parenthesis(l, ..)
307 | Self::ArraySubscript(l, ..)
308 | Self::ArraySlice(l, ..)
309 | Self::MemberAccess(l, ..)
310 | Self::FunctionCall(l, ..)
311 | Self::FunctionCallBlock(l, ..)
312 | Self::NamedFunctionCall(l, ..)
313 | Self::Not(l, ..)
314 | Self::BitwiseNot(l, ..)
315 | Self::Delete(l, ..)
316 | Self::PreIncrement(l, ..)
317 | Self::PreDecrement(l, ..)
318 | Self::UnaryPlus(l, ..)
319 | Self::Negate(l, ..)
320 | Self::Power(l, ..)
321 | Self::Multiply(l, ..)
322 | Self::Divide(l, ..)
323 | Self::Modulo(l, ..)
324 | Self::Add(l, ..)
325 | Self::Subtract(l, ..)
326 | Self::ShiftLeft(l, ..)
327 | Self::ShiftRight(l, ..)
328 | Self::BitwiseAnd(l, ..)
329 | Self::BitwiseXor(l, ..)
330 | Self::BitwiseOr(l, ..)
331 | Self::Less(l, ..)
332 | Self::More(l, ..)
333 | Self::LessEqual(l, ..)
334 | Self::MoreEqual(l, ..)
335 | Self::Equal(l, ..)
336 | Self::NotEqual(l, ..)
337 | Self::And(l, ..)
338 | Self::Or(l, ..)
339 | Self::ConditionalOperator(l, ..)
340 | Self::Assign(l, ..)
341 | Self::AssignOr(l, ..)
342 | Self::AssignAnd(l, ..)
343 | Self::AssignXor(l, ..)
344 | Self::AssignShiftLeft(l, ..)
345 | Self::AssignShiftRight(l, ..)
346 | Self::AssignAdd(l, ..)
347 | Self::AssignSubtract(l, ..)
348 | Self::AssignMultiply(l, ..)
349 | Self::AssignDivide(l, ..)
350 | Self::AssignModulo(l, ..)
351 | Self::BoolLiteral(l, ..)
352 | Self::NumberLiteral(l, ..)
353 | Self::RationalNumberLiteral(l, ..)
354 | Self::HexNumberLiteral(l, ..)
355 | Self::ArrayLiteral(l, ..)
356 | Self::List(l, ..)
357 | Self::Type(l, ..)
358 | Self::AddressLiteral(l, ..) => l,
359 }
360
361 pt::FunctionAttribute: match self {
362 Self::Mutability(ref l) => l.loc(),
363 Self::Visibility(ref l) => l.loc_opt().unwrap_or_default(),
364 Self::Virtual(l, ..)
365 | Self::Immutable(l, ..)
366 | Self::Override(l, ..,)
367 | Self::BaseOrModifier(l, ..)
368 | Self::Error(l, ..) => l,
369 }
370
371 pt::Import: match self {
372 Self::GlobalSymbol(.., l)
373 | Self::Plain(.., l)
374 | Self::Rename(.., l) => l,
375 }
376
377 pt::Mutability: match self {
378 Self::Constant(l, ..)
379 | Self::Payable(l, ..)
380 | Self::Pure(l, ..)
381 | Self::View(l, ..) => l,
382 }
383
384 pt::SourceUnitPart: match self {
385 Self::ImportDirective(ref l, ..) => l.loc(),
386 Self::ContractDefinition(ref l, ..) => l.loc(),
387 Self::EnumDefinition(ref l, ..) => l.loc(),
388 Self::StructDefinition(ref l, ..) => l.loc(),
389 Self::EventDefinition(ref l, ..) => l.loc(),
390 Self::ErrorDefinition(ref l, ..) => l.loc(),
391 Self::FunctionDefinition(ref l, ..) => l.loc(),
392 Self::VariableDefinition(ref l, ..) => l.loc(),
393 Self::TypeDefinition(ref l, ..) => l.loc(),
394 Self::Annotation(ref l, ..) => l.loc(),
395 Self::Using(ref l, ..) => l.loc(),
396 Self::PragmaDirective(ref l, ..) => l.loc(),
397 Self::StraySemicolon(l, ..) => l,
398 }
399
400 pt::Statement: match self {
401 Self::Block { loc: l, .. }
402 | Self::Assembly { loc: l, .. }
403 | Self::Args(l, ..)
404 | Self::If(l, ..)
405 | Self::While(l, ..)
406 | Self::Expression(l, ..)
407 | Self::VariableDefinition(l, ..)
408 | Self::For(l, ..)
409 | Self::DoWhile(l, ..)
410 | Self::Continue(l, ..)
411 | Self::Break(l, ..)
412 | Self::Return(l, ..)
413 | Self::Revert(l, ..)
414 | Self::RevertNamedArgs(l, ..)
415 | Self::Emit(l, ..)
416 | Self::Try(l, ..)
417 | Self::Error(l, ..) => l,
418 }
419
420 pt::StorageLocation: match self {
421 Self::Calldata(l, ..)
422 | Self::Memory(l, ..)
423 | Self::Storage(l, ..) => l,
424 }
425
426 pt::UsingList: match self {
427 Self::Library(ref l, ..) => l.loc(),
428 Self::Functions(ref l, ..) => l.loc_opt().unwrap_or_default(),
429 Self::Error => panic!("an error occurred"),
430 }
431
432 pt::VariableAttribute: match self {
433 Self::Visibility(ref l, ..) => l.loc_opt().unwrap_or_default(),
434 Self::Constant(l, ..)
435 | Self::Immutable(l, ..)
436 | Self::Override(l, ..) => l,
437 }
438
439 pt::YulExpression: match self {
440 Self::HexStringLiteral(ref l, ..) => l.loc(),
441 Self::StringLiteral(ref l, ..) => l.loc(),
442 Self::Variable(ref l, ..) => l.loc(),
443 Self::FunctionCall(ref l, ..) => l.loc(),
444 Self::BoolLiteral(l, ..)
445 | Self::NumberLiteral(l, ..)
446 | Self::HexNumberLiteral(l, ..)
447 | Self::SuffixAccess(l, ..) => l,
448 }
449
450 pt::YulStatement: match self {
451 Self::Block(ref l, ..) => l.loc(),
452 Self::FunctionDefinition(ref l, ..) => l.loc(),
453 Self::FunctionCall(ref l, ..) => l.loc(),
454 Self::For(ref l, ..) => l.loc(),
455 Self::Switch(ref l, ..) => l.loc(),
456 Self::Assign(l, ..)
457 | Self::VariableDeclaration(l, ..)
458 | Self::If(l, ..)
459 | Self::Leave(l, ..)
460 | Self::Break(l, ..)
461 | Self::Continue(l, ..)
462 | Self::Error(l, ..) => l,
463 }
464
465 pt::YulSwitchOptions: match self {
466 Self::Case(l, ..)
467 | Self::Default(l, ..) => l,
468 }
469
470 pt::PragmaDirective: match self {
471 Self::Identifier(l, ..)
472 | Self::StringLiteral(l, ..)
473 | Self::Version(l, ..) => l,
474 }
475
476 LexicalError: match self {
478 Self::EndOfFileInComment(l)
479 | Self::EndOfFileInString(l)
480 | Self::EndofFileInHex(l)
481 | Self::MissingNumber(l)
482 | Self::InvalidCharacterInHexLiteral(l, _)
483 | Self::UnrecognisedToken(l, _)
484 | Self::ExpectedFrom(l, _)
485 | Self::MissingExponent(l) => l,
486 }
487}