From eb5067c28c69b546c0bd05a568deedef0944d4c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Oct 2026 11:58:09 +0000 Subject: [PATCH 1/3] Initial plan From d680b9a80e2dbce22365491027269759aaeaae7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Oct 2026 12:01:45 +0000 Subject: [PATCH 2/3] Fix ValidateRange analyzer review findings Co-authored-by: bergmeister <9250262+bergmeister@users.noreply.github.com> --- Rules/AvoidValidateRangeTypeMismatch.cs | 52 ++++++++++++------- .../AvoidValidateRangeTypeMismatch.tests.ps1 | 5 +- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/Rules/AvoidValidateRangeTypeMismatch.cs b/Rules/AvoidValidateRangeTypeMismatch.cs index f288b5ba5..319a865ba 100644 --- a/Rules/AvoidValidateRangeTypeMismatch.cs +++ b/Rules/AvoidValidateRangeTypeMismatch.cs @@ -21,23 +21,23 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules #endif public sealed class AvoidValidateRangeTypeMismatch : IScriptRule { - private static readonly HashSet FloatingPointAndDecimalTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + private static readonly HashSet FloatingPointAndDecimalTypes = new HashSet { - "double", "System.Double", - "single", "float", "System.Single", - "decimal", "System.Decimal" + typeof(double), + typeof(float), + typeof(decimal) }; - private static readonly HashSet IntegralTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + private static readonly HashSet IntegralTypes = new HashSet { - "byte", "System.Byte", - "sbyte", "System.SByte", - "short", "System.Int16", - "ushort", "System.UInt16", - "int", "System.Int32", - "uint", "System.UInt32", - "long", "System.Int64", - "ulong", "System.UInt64" + typeof(byte), + typeof(sbyte), + typeof(short), + typeof(ushort), + typeof(int), + typeof(uint), + typeof(long), + typeof(ulong) }; public IEnumerable AnalyzeScript(Ast ast, string fileName) @@ -51,7 +51,23 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) foreach (ParameterAst parameterAst in parameterAsts) { TypeConstraintAst typeConstraint = parameterAst.Attributes.OfType().FirstOrDefault(); - if (typeConstraint == null || !FloatingPointAndDecimalTypes.Contains(typeConstraint.TypeName.FullName)) + if (typeConstraint == null) + { + continue; + } + + Type parameterType = typeConstraint.TypeName.GetReflectionType(); + if (parameterType == null) + { + continue; + } + + if (parameterType.IsArray) + { + parameterType = parameterType.GetElementType(); + } + + if (!FloatingPointAndDecimalTypes.Contains(parameterType)) { continue; } @@ -60,7 +76,7 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) { if (!IsValidateRangeAttribute(attributeAst) || attributeAst.PositionalArguments.Count < 2 - || !attributeAst.PositionalArguments.Take(2).Any(IsIntegralBoundary)) + || !attributeAst.PositionalArguments.Take(2).All(IsIntegralBoundary)) { continue; } @@ -79,14 +95,12 @@ private static bool IsIntegralBoundary(ExpressionAst expressionAst) { if (expressionAst is ConstantExpressionAst constantExpressionAst) { - return constantExpressionAst.Value != null - && IntegralTypes.Contains(constantExpressionAst.Value.GetType().FullName); + return constantExpressionAst.Value != null && IntegralTypes.Contains(constantExpressionAst.Value.GetType()); } if (expressionAst is ConvertExpressionAst convertExpressionAst) { - return IntegralTypes.Contains(convertExpressionAst.Type.TypeName.FullName) - && IsIntegralBoundary(convertExpressionAst.Child); + return IntegralTypes.Contains(convertExpressionAst.Type.TypeName.GetReflectionType()); } if (expressionAst is UnaryExpressionAst unaryExpressionAst diff --git a/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 b/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 index 0a307a2ee..47b1ea936 100644 --- a/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 +++ b/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 @@ -10,8 +10,10 @@ Describe 'AvoidValidateRangeTypeMismatch' { $scripts = @( 'function Test { param([double][ValidateRange(1, 2)]$Value) }' 'function Test { param([single][ValidateRange(-1, 2)]$Value) }' - 'function Test { param([decimal][ValidateRange(1, 2.0)]$Value) }' + 'function Test { param([double[]][ValidateRange(1, 2)]$Values) }' 'function Test { param([double][System.Management.Automation.ValidateRangeAttribute(1, 2)]$Value) }' + 'function Test { param([double][ValidateRange([int]0.0, [int]100.0)]$Value) }' + 'function Test { param([double][ValidateRange([int32]0.0, [int32]100.0)]$Value) }' ) foreach ($scriptDefinition in $scripts) { @@ -26,6 +28,7 @@ Describe 'AvoidValidateRangeTypeMismatch' { 'function Test { param([double][ValidateRange(1.0, 2.0)]$Value) }' 'function Test { param([single][ValidateRange(1.0, 2.0)]$Value) }' 'function Test { param([decimal][ValidateRange(1.0, 2.0)]$Value) }' + 'function Test { param([double][ValidateRange(1, 2.0)]$Value) }' 'function Test { param([int][ValidateRange(1, 2)]$Value) }' ) From 09de08a12343f62b1c5d796e2cc4ea1e102025b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Oct 2026 12:19:52 +0000 Subject: [PATCH 3/3] Restore decimal range test coverage Co-authored-by: bergmeister <9250262+bergmeister@users.noreply.github.com> --- Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 b/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 index 47b1ea936..bc3915240 100644 --- a/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 +++ b/Tests/Rules/AvoidValidateRangeTypeMismatch.tests.ps1 @@ -10,6 +10,7 @@ Describe 'AvoidValidateRangeTypeMismatch' { $scripts = @( 'function Test { param([double][ValidateRange(1, 2)]$Value) }' 'function Test { param([single][ValidateRange(-1, 2)]$Value) }' + 'function Test { param([decimal][ValidateRange(1, 2)]$Value) }' 'function Test { param([double[]][ValidateRange(1, 2)]$Values) }' 'function Test { param([double][System.Management.Automation.ValidateRangeAttribute(1, 2)]$Value) }' 'function Test { param([double][ValidateRange([int]0.0, [int]100.0)]$Value) }'