Sdk
ExpressionUtility.cs
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using GitHub.DistributedTask.Logging;
namespace GitHub.DistributedTask.Expressions2.Sdk
{
[EditorBrowsable(EditorBrowsableState.Never)]
internal static clast ExpressionUtility
{
internal static Object ConvertToCanonicalValue(
Object val,
out ValueKind kind,
out Object raw)
{
raw = null;
if (Object.ReferenceEquals(val, null))
{
kind = ValueKind.Null;
return null;
}
else if (val is Boolean)
{
kind = ValueKind.Boolean;
return val;
}
else if (val is Double)
{
kind = ValueKind.Number;
return val;
}
else if (val is String)
{
kind = ValueKind.String;
return val;
}
else if (val is INull n)
{
kind = ValueKind.Null;
raw = val;
return null;
}
else if (val is IBoolean boolean)
{
kind = ValueKind.Boolean;
raw = val;
return boolean.GetBoolean();
}
else if (val is INumber number)
{
kind = ValueKind.Number;
raw = val;
return number.GetNumber();
}
else if (val is IString str)
{
kind = ValueKind.String;
raw = val;
return str.GetString();
}
else if (val is IReadOnlyObject)
{
kind = ValueKind.Object;
return val;
}
else if (val is IReadOnlyArray)
{
kind = ValueKind.Array;
return val;
}
else if (!val.GetType().GetTypeInfo().IsClast)
{
if (val is Decimal || val is Byte || val is SByte || val is Int16 || val is UInt16 || val is Int32 || val is UInt32 || val is Int64 || val is UInt64 || val is Single)
{
kind = ValueKind.Number;
return Convert.ToDouble(val);
}
else if (val is Enum)
{
var strVal = String.Format(CultureInfo.InvariantCulture, "{0:G}", val);
if (Double.TryParse(strVal, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out Double doubleValue))
{
kind = ValueKind.Number;
return doubleValue;
}
kind = ValueKind.String;
return strVal;
}
}
kind = ValueKind.Object;
return val;
}
internal static String FormatValue(
ISecretMasker secretMasker,
EvaluationResult evaluationResult)
{
return FormatValue(secretMasker, evaluationResult.Value, evaluationResult.Kind);
}
internal static String FormatValue(
ISecretMasker secretMasker,
Object value,
ValueKind kind)
{
switch (kind)
{
case ValueKind.Null:
return ExpressionConstants.Null;
case ValueKind.Boolean:
return ((Boolean)value) ? ExpressionConstants.True : ExpressionConstants.False;
case ValueKind.Number:
var strNumber = ((Double)value).ToString(ExpressionConstants.NumberFormat, CultureInfo.InvariantCulture);
return secretMasker != null ? secretMasker.MaskSecrets(strNumber) : strNumber;
case ValueKind.String:
// Mask secrets before string-escaping.
var strValue = secretMasker != null ? secretMasker.MaskSecrets(value as String) : value as String;
return $"'{StringEscape(strValue)}'";
case ValueKind.Array:
case ValueKind.Object:
return kind.ToString();
default: // Should never reach here.
throw new NotSupportedException($"Unable to convert to realized expression. Unexpected value kind: {kind}");
}
}
internal static bool IsLegalKeyword(String str)
{
if (String.IsNullOrEmpty(str))
{
return false;
}
var first = str[0];
if ((first >= 'a' && first = 'A' && first = 'a' && c = 'A' && c = '0' && c 2 &&
str[1] == 'x' &&
str.Skip(2).All(x => (x >= '0' && x = 'a' && x = 'A' && x 2 &&
str[1] == 'o' &&
str.Skip(2).All(x => x >= '0' && x