blob: afb36f0c5706d84eca1d2809b85775ca02037f41 [file] [log] [blame]
//
// 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;
}
}