[#60671] CreationDriver: Accept alternative parameter names specified in NameAlias attributes
diff --git a/src/Renode/PlatformDescription/CreationDriver.cs b/src/Renode/PlatformDescription/CreationDriver.cs index 833ef94..4e5900f 100644 --- a/src/Renode/PlatformDescription/CreationDriver.cs +++ b/src/Renode/PlatformDescription/CreationDriver.cs
@@ -663,14 +663,14 @@ for(var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; - var attribute = attributes.SingleOrDefault(x => x.Name == parameter.Name); + var attribute = attributes.SingleOrDefault(x => ParameterNameMatches(x.Name, parameter, silent: true)); if(attribute == null) { FillDefaultParameter(ref parameterValues[i], parameter); continue; } - if(TryConvertSimpleValue(parameter.ParameterType, attribute.Value, out parameterValues[i]).ResultType == ConversionResultType.ConversionSuccessful) + if(TryConvertSimpleValue(parameter.ParameterType, attribute.Value, out parameterValues[i], silent: true).ResultType == ConversionResultType.ConversionSuccessful) { continue; } @@ -1282,7 +1282,7 @@ return ConversionResult.Success; } - private ConversionResult TryConvertSimpleValue(Type expectedType, Value value, out object result) + private ConversionResult TryConvertSimpleValue(Type expectedType, Value value, out object result, bool silent = false) { result = null; @@ -1329,16 +1329,27 @@ { return new ConversionResult(ConversionResultType.ConversionUnsuccesful, ParsingError.TypeMismatch, string.Format(TypeMismatchMessage, expectedType)); } - var namespaceAndType = expectedType.Namespace.Split('.').Concat(new[] { expectedType.Name }); - var givenReversedTypeAndNamespace = enumValue.TypeAndReversedNamespace; - // zip compares elements of the namespace from the end one by one and looks for the first difference - var error = givenReversedTypeAndNamespace.Zip(namespaceAndType.Reverse(), (first, second) => first != second ? Tuple.Create(first, second) : null).FirstOrDefault(x => x != null); - if(error != null) + // Compare types first as enum's type may use an alias + if(!TypeNameMatches(enumValue.TypeName, expectedType, silent)) { return new ConversionResult(ConversionResultType.ConversionUnsuccesful, ParsingError.EnumMismatch, - $"Enum namespace or type mismatch, expected '{error.Item2}' instead of '{error.Item1}'."); + $"Enum type mismatch, expected '{expectedType.Name}' instead of '{enumValue.TypeName}'."); } + + var expectedNamespace = expectedType.Namespace.Split('.'); + var givenNamespace = enumValue.ReversedNamespace; + + // Compare namespaces + foreach(var names in givenNamespace.Zip(expectedNamespace.Reverse(), (first, second) => Tuple.Create(first, second))) + { + if(names.Item1 != names.Item2) + { + return new ConversionResult(ConversionResultType.ConversionUnsuccesful, ParsingError.EnumMismatch, + $"Enum namespace mismatch, expected '{names.Item2}' instead of '{names.Item1}'."); + } + } + if(!SmartParser.Instance.TryParse(enumValue.Value, expectedType, out result)) { return new ConversionResult(ConversionResultType.ConversionUnsuccesful, ParsingError.EnumMismatch, @@ -1407,7 +1418,7 @@ foreach(var argument in ctor.GetParameters()) { - var correspondingAttribute = attributes.SingleOrDefault(x => x.Name == argument.Name); + var correspondingAttribute = attributes.SingleOrDefault(x => ParameterNameMatches(x.Name, argument)); if(correspondingAttribute == null) { object defaultValue = null; @@ -1529,6 +1540,36 @@ return false; } + private bool ParameterNameMatches(string given, ParameterInfo info, bool silent = false) + { + return NameOrAliasMatches(given, info.Name, "parameter", info.GetCustomAttribute<NameAliasAttribute>(), silent); + } + + private bool TypeNameMatches(string given, Type type, bool silent = false) + { + return NameOrAliasMatches(given, type.Name, "type", type.GetCustomAttribute<NameAliasAttribute>(), silent); + } + + private bool NameOrAliasMatches(string given, string name, string typeClass, NameAliasAttribute alias, bool silent = false) + { + if(given == name) + { + return true; + } + + if(alias != null && alias.Name == given) + { + if(!silent && alias.WarnOnUsage) + { + Logger.Log(LogLevel.Warning, "Using alias '{0}' for {1} '{2}'", alias.Name, typeClass, name); + } + + return true; + } + + return false; + } + private void HandleInternalError(IWithPosition failingObject = null, [CallerMemberName] string callingMethod = "", [CallerFilePath] string callingFilePath = "",
diff --git a/src/Renode/PlatformDescription/Syntax/EnumValue.cs b/src/Renode/PlatformDescription/Syntax/EnumValue.cs index 1e4b97d..348c6d7 100644 --- a/src/Renode/PlatformDescription/Syntax/EnumValue.cs +++ b/src/Renode/PlatformDescription/Syntax/EnumValue.cs
@@ -1,5 +1,5 @@ // -// Copyright (c) 2010-2018 Antmicro +// Copyright (c) 2010-2024 Antmicro // // This file is licensed under the MIT License. // Full license text is available in 'licenses/MIT.txt'. @@ -22,7 +22,8 @@ nameSpaceAndType.Push(element); } Value = nameSpaceAndType.Pop(); - TypeAndReversedNamespace = nameSpaceAndType; + TypeName = nameSpaceAndType.Pop(); + ReversedNamespace = nameSpaceAndType; } public override string ToString() @@ -32,10 +33,11 @@ public string ToShortString() { - return TypeAndReversedNamespace.Reverse().Concat(new[] { Value }).Aggregate((x, y) => x + '.' + y); + return ReversedNamespace.Reverse().Concat(new[] { TypeName, Value }).Aggregate((x, y) => x + '.' + y); } - public IEnumerable<string> TypeAndReversedNamespace { get; private set; } + public IEnumerable<string> ReversedNamespace { get; private set; } public string Value { get; private set; } + public string TypeName { get; } } }