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