| // |
| // Copyright (c) 2010-2023 Antmicro |
| // |
| // This file is licensed under the MIT License. |
| // Full license text is available in 'licenses/MIT.txt'. |
| // |
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using Antmicro.Renode.Logging; |
| |
| namespace Antmicro.Renode.PlatformDescription.Syntax |
| { |
| public static class SyntaxTreeHelpers |
| { |
| public static bool ScanFor(object objectToScan, IWithPosition objectToFind) |
| { |
| var found = false; |
| VisitSyntaxTree<IWithPosition>(objectToScan, x => |
| { |
| found |= objectToFind.Equals(x); |
| }); |
| return found; |
| } |
| |
| public static void VisitSyntaxTree<TValue>(object root, Action<TValue> visitorAction) where TValue : class |
| { |
| VisitSyntaxTreeInner<TValue>(root, visitorAction, null); |
| } |
| |
| public static void VisitSyntaxTree<TValue>(object root, Action<TValue> visitorAction, Func<object, bool, bool> filter) where TValue : class |
| { |
| VisitSyntaxTreeInner(root, visitorAction, filter); |
| } |
| |
| private static void VisitSyntaxTreeInner<TValue>(object objectToVisit, Action<TValue> visitorAction, Func<object, bool, bool> filter) where TValue : class |
| { |
| var objectAsValue = objectToVisit as TValue; |
| if(objectAsValue != null) |
| { |
| visitorAction(objectAsValue); |
| } |
| |
| var objectIsEntry = objectToVisit.GetType() == typeof(Antmicro.Renode.PlatformDescription.Syntax.Entry); |
| |
| var objectAsVisitable = objectToVisit as IVisitable; |
| if(objectAsVisitable != null) |
| { |
| foreach(var element in objectAsVisitable.Visit()) |
| { |
| if(element != null && ApplyFilter(element, objectIsEntry, filter)) |
| { |
| VisitSyntaxTreeInner(element, visitorAction, filter); |
| } |
| } |
| return; |
| } |
| |
| var objectType = objectToVisit.GetType(); |
| var publicProperties = objectType.GetProperties(); |
| foreach(var property in publicProperties.Where(x => x.CanRead)) |
| { |
| var propertyValue = property.GetGetMethod().Invoke(objectToVisit, new object[0]); |
| if(propertyValue != null) |
| { |
| var typeOfValue = propertyValue.GetType(); |
| if(typeOfValue.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>) && |
| x.GetGenericArguments()[0].Namespace.StartsWith(OurNamespace, StringComparison.InvariantCulture))) |
| { |
| foreach(var element in ((System.Collections.IEnumerable)propertyValue)) |
| { |
| if(ApplyFilter(element, objectIsEntry, filter)) |
| { |
| VisitSyntaxTreeInner(element, visitorAction, filter); |
| } |
| } |
| } |
| else if(typeOfValue.Namespace.StartsWith(OurNamespace, StringComparison.InvariantCulture)) |
| { |
| if(ApplyFilter(propertyValue, objectIsEntry, filter)) |
| { |
| VisitSyntaxTreeInner(propertyValue, visitorAction, filter); |
| } |
| } |
| } |
| } |
| } |
| |
| private static bool ApplyFilter(object obj, bool isEntryChild, Func<object, bool, bool> filter) |
| { |
| return filter == null ? true : filter(obj, isEntryChild); |
| } |
| |
| private static readonly string OurNamespace = typeof(SyntaxTreeHelpers).Namespace; |
| } |
| } |