review(Driver.TwinCAT.Cli): clean parse errors + FlushLogging() in finally
Re-review at 7286d320. -008 (Low): ParseValue maps FormatException/OverflowException to a
clean CommandException (was raw stack trace) + tests. -009: FlushLogging() in all 5 commands'
finally blocks (parity with AbCip.Cli).
This commit is contained in:
@@ -63,33 +63,54 @@ public sealed class WriteCommand : TwinCATTagCommandBase
|
||||
finally
|
||||
{
|
||||
await driver.ShutdownAsync(CancellationToken.None);
|
||||
FlushLogging();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Parse <c>--value</c> per <see cref="TwinCATDataType"/>, invariant culture.</summary>
|
||||
/// <summary>
|
||||
/// Parse <c>--value</c> per <see cref="TwinCATDataType"/>, invariant culture. Wraps
|
||||
/// <see cref="FormatException"/> and <see cref="OverflowException"/> in a
|
||||
/// <see cref="CliFx.Exceptions.CommandException"/> so the operator sees a clean one-line
|
||||
/// error instead of a raw stack trace (Driver.TwinCAT.Cli-008).
|
||||
/// </summary>
|
||||
/// <param name="raw">The raw string value to parse.</param>
|
||||
/// <param name="type">The target TwinCAT data type.</param>
|
||||
internal static object ParseValue(string raw, TwinCATDataType type) => type switch
|
||||
internal static object ParseValue(string raw, TwinCATDataType type)
|
||||
{
|
||||
TwinCATDataType.Bool => ParseBool(raw),
|
||||
TwinCATDataType.SInt => sbyte.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.USInt => byte.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.Int => short.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.UInt => ushort.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.DInt => int.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.UDInt => uint.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.LInt => long.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.ULInt => ulong.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.Real => float.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.LReal => double.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.String or TwinCATDataType.WString => raw,
|
||||
// IEC 61131-3 time/date types are stored as UDINT on the wire — accept a numeric raw
|
||||
// value + let the caller handle the encoding semantics.
|
||||
TwinCATDataType.Time or TwinCATDataType.Date
|
||||
or TwinCATDataType.DateTime or TwinCATDataType.TimeOfDay
|
||||
=> uint.Parse(raw, CultureInfo.InvariantCulture),
|
||||
_ => throw new CliFx.Exceptions.CommandException($"Unsupported DataType '{type}' for write."),
|
||||
};
|
||||
try
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
TwinCATDataType.Bool => ParseBool(raw),
|
||||
TwinCATDataType.SInt => sbyte.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.USInt => byte.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.Int => short.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.UInt => ushort.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.DInt => int.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.UDInt => uint.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.LInt => long.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.ULInt => ulong.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.Real => float.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.LReal => double.Parse(raw, CultureInfo.InvariantCulture),
|
||||
TwinCATDataType.String or TwinCATDataType.WString => raw,
|
||||
// IEC 61131-3 time/date types are stored as UDINT on the wire — accept a numeric raw
|
||||
// value + let the caller handle the encoding semantics.
|
||||
TwinCATDataType.Time or TwinCATDataType.Date
|
||||
or TwinCATDataType.DateTime or TwinCATDataType.TimeOfDay
|
||||
=> uint.Parse(raw, CultureInfo.InvariantCulture),
|
||||
_ => throw new CliFx.Exceptions.CommandException($"Unsupported DataType '{type}' for write."),
|
||||
};
|
||||
}
|
||||
catch (CliFx.Exceptions.CommandException)
|
||||
{
|
||||
throw; // already a clean user-facing error (Bool parse, Structure, unsupported type)
|
||||
}
|
||||
catch (Exception ex) when (ex is FormatException or OverflowException)
|
||||
{
|
||||
throw new CliFx.Exceptions.CommandException(
|
||||
$"Cannot parse '{raw}' as {type}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ParseBool(string raw) => raw.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user