[#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; }
}
}