using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text.RegularExpressions; using DynamicExpresso.Exceptions; using DynamicExpresso.Parsing; namespace DynamicExpresso { internal class ParserArguments { private readonly Dictionary _declaredParameters; private readonly HashSet _usedParameters = new HashSet(); private readonly HashSet _usedTypes = new HashSet(); private readonly HashSet _usedIdentifiers = new HashSet(); public ParserArguments( string expressionText, ParserSettings settings, Type expressionReturnType, IEnumerable declaredParameters ) { ExpressionText = expressionText; ExpressionReturnType = expressionReturnType; Settings = settings; _declaredParameters = new Dictionary(settings.KeyComparer); foreach (var pe in declaredParameters) { try { _declaredParameters.Add(pe.Name, pe); } catch (ArgumentException) { throw new DuplicateParameterException(pe.Name); } } } public ParserSettings Settings { get; private set; } public string ExpressionText { get; private set; } public Type ExpressionReturnType { get; private set; } public IEnumerable DeclaredParameters { get { return _declaredParameters.Values; } } public IEnumerable UsedParameters { get { return _usedParameters; } } public IEnumerable UsedTypes { get { return _usedTypes; } } public IEnumerable UsedIdentifiers { get { return _usedIdentifiers; } } public bool TryGetKnownType(string name, out Type type) { if (Settings.KnownTypes.TryGetValue(name, out var reference)) { _usedTypes.Add(reference); type = reference.Type; return true; } type = null; return false; } /// /// Returns true if the known types contain a generic type definition with the given name + any arity (e.g. name`1). /// internal bool HasKnownGenericTypeDefinition(string name) { var regex = new Regex("^" + name + "`\\d+$"); return Settings.KnownTypes.Values.Any(refType => regex.IsMatch(refType.Name) && refType.Type.IsGenericTypeDefinition); } public bool TryGetIdentifier(string name, out Expression expression) { if (Settings.Identifiers.TryGetValue(name, out var identifier)) { _usedIdentifiers.Add(identifier); expression = identifier.Expression; return true; } expression = null; return false; } /// /// Get the parameter and mark is as used. /// public bool TryGetParameters(string name, out ParameterExpression expression) { if (_declaredParameters.TryGetValue(name, out var parameter)) { _usedParameters.Add(parameter); expression = parameter.Expression; return true; } expression = null; return false; } public IEnumerable GetExtensionMethods(string methodName) { var comparer = Settings.KeyComparer; return Settings.ExtensionMethods.Where(p => comparer.Equals(p.Name, methodName)); } } }