Skip to content

Commit 5f8922f

Browse files
committed
Reorganize and combine some rules.
Fill in missing cases in tests.
1 parent d4fe364 commit 5f8922f

19 files changed

+601
-896
lines changed

src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,36 +1844,30 @@
18441844
<value>Constant is expected for the parameter</value>
18451845
</data>
18461846
<data name="ConstantExpectedUsageDescription" xml:space="preserve">
1847-
<value>The parameter expects a constant for best performance.</value>
1847+
<value>The parameter expects a constant for optimal performance.</value>
18481848
</data>
1849-
<data name="ConstantExpectedInvalidTypeMessage" xml:space="preserve">
1850-
<value>The '{0}' parameter cannot have be annotated with ConstantExpected.</value>
1849+
<data name="ConstantExpectedNotSupportedMessage" xml:space="preserve">
1850+
<value>The '{0}' parameter is not supported for ConstantExpectedAttribute.</value>
18511851
</data>
18521852
<data name="ConstantExpectedIncompatibleConstantTypeMessage" xml:space="preserve">
1853-
<value>The '{0}' condition does not match parameter type of '{1}'.</value>
1854-
</data>
1855-
<data name="ConstantExpectedIncompatibleConstantMinMaxMessage" xml:space="preserve">
1856-
<value>The Min/Max condition can only be null for '{0}' types.</value>
1853+
<value>The '{0}' value is not compatible with parameter type of '{1}'.</value>
18571854
</data>
18581855
<data name="ConstantExpectedInvalidBoundsMessage" xml:space="preserve">
1859-
<value>The '{0}' condition does not fit within the parameter value bounds of '{1}' to '{2}'.</value>
1856+
<value>The '{0}' value does not fit within the parameter value bounds of '{1}' to '{2}'.</value>
18601857
</data>
18611858
<data name="ConstantExpectedInvertedRangeMessage" xml:space="preserve">
1862-
<value>The Min and Max conditions are inverted.</value>
1859+
<value>The Min and Max value are inverted.</value>
18631860
</data>
18641861
<data name="ConstantExpectedOutOfBoundsMessage" xml:space="preserve">
1865-
<value>The constant does not fit within the parameter value bounds of '{0}' to '{1}'.</value>
1862+
<value>The constant does not fit within the value bounds of '{0}' to '{1}'.</value>
18661863
</data>
1867-
<data name="ConstantExpectedNotConstantMessage" xml:space="preserve">
1868-
<value>The argument should be a constant.</value>
1864+
<data name="ConstantExpectedInvalidMessage" xml:space="preserve">
1865+
<value>The constant is not of the same '{0}' type as the parameter</value>
18691866
</data>
1870-
<data name="ConstantExpectedAttributeOutOfBoundsMessage" xml:space="preserve">
1871-
<value>The ConstantExpectedAttribute does not fit within the parameter value bounds of '{0}' to '{1}'.</value>
1867+
<data name="ConstantExpectedNotConstantMessage" xml:space="preserve">
1868+
<value>The argument should be a constant for optimal performance.</value>
18721869
</data>
18731870
<data name="ConstantExpectedAttributExpectedMessage" xml:space="preserve">
18741871
<value>The ConstantExpectedAttribute expected for the parameter due to the interface/base method.</value>
18751872
</data>
1876-
<data name="ConstantExpectedAttributeNotSameTypeMessage" xml:space="preserve">
1877-
<value>The ConstantExpectedAttribute does not have the same '{0}' type as the ConstantExpectedAttribute in the invoked method parameter.</value>
1878-
</data>
18791873
</root>

src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Performance/ConstantExpectedAnalyzer.UnmanagedHelper.cs

Lines changed: 29 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,32 @@ static UnmanagedHelper()
2121
{
2222
if (typeof(T) == typeof(long))
2323
{
24-
var helper = new UnmanagedHelper<long>.TransformHelper(TryConvertInt64, TryTransformInt64);
24+
var helper = new UnmanagedHelper<long>.TransformHelper(TryTransformInt64);
2525
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
2626
}
2727
else if (typeof(T) == typeof(ulong))
2828
{
29-
var helper = new UnmanagedHelper<ulong>.TransformHelper(TryConvertUInt64, TryTransformUInt64);
29+
var helper = new UnmanagedHelper<ulong>.TransformHelper(TryTransformUInt64);
3030
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
3131
}
3232
else if (typeof(T) == typeof(float))
3333
{
34-
var helper = new UnmanagedHelper<float>.TransformHelper(TryConvertSingle, TryTransformSingle);
34+
var helper = new UnmanagedHelper<float>.TransformHelper(TryTransformSingle);
3535
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
3636
}
3737
else if (typeof(T) == typeof(double))
3838
{
39-
var helper = new UnmanagedHelper<double>.TransformHelper(TryConvertDouble, TryTransformDouble);
39+
var helper = new UnmanagedHelper<double>.TransformHelper(TryTransformDouble);
4040
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
4141
}
4242
else if (typeof(T) == typeof(char))
4343
{
44-
var helper = new UnmanagedHelper<char>.TransformHelper(TryConvertChar, TryTransformChar);
44+
var helper = new UnmanagedHelper<char>.TransformHelper(TryTransformChar);
4545
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
4646
}
4747
else if (typeof(T) == typeof(bool))
4848
{
49-
var helper = new UnmanagedHelper<bool>.TransformHelper(TryConvertBoolean, TryTransformBoolean);
49+
var helper = new UnmanagedHelper<bool>.TransformHelper(TryTransformBoolean);
5050
_instance = new ConstantExpectedParameterFactory((TransformHelper)(object)helper);
5151
}
5252
}
@@ -57,15 +57,12 @@ public static bool Validate(IParameterSymbol parameterSymbol, AttributeData attr
5757
=> Instance.Validate(parameterSymbol, attributeData, typeMin, typeMax, diagnosticHelper, out diagnostics);
5858

5959
public delegate bool TryTransform(object constant, out T value, out bool isInvalid);
60-
public delegate bool TryConvert(object? constant, out T value);
6160
public sealed class TransformHelper
6261
{
6362
private readonly TryTransform _tryTransform;
64-
private readonly TryConvert _convert;
6563

66-
public TransformHelper(TryConvert convert, TryTransform tryTransform)
64+
public TransformHelper(TryTransform tryTransform)
6765
{
68-
_convert = convert;
6966
_tryTransform = tryTransform;
7067
}
7168

@@ -105,7 +102,7 @@ public bool TryTransformMax(object constant, out T value, ref ErrorKind errorFla
105102
}
106103
return false;
107104
}
108-
public bool TryConvert(object? val, out T value) => _convert(val, out value);
105+
public bool TryConvert(object val, out T value) => _tryTransform(val, out value, out _);
109106
}
110107

111108
public sealed class ConstantExpectedParameterFactory
@@ -136,7 +133,7 @@ public bool TryCreate(IParameterSymbol parameterSymbol, AttributeData attributeD
136133
return false;
137134
}
138135

139-
parameter = new UnmanagedConstantExpectedParameter(parameterSymbol, attributeData.ApplicationSyntaxReference.GetSyntax(), minValue, maxValue, _helper);
136+
parameter = new UnmanagedConstantExpectedParameter(parameterSymbol, minValue, maxValue, _helper);
140137
return true;
141138
}
142139

@@ -179,7 +176,7 @@ private bool IsValidMinMax(AttributeData attributeData, T typeMin, T typeMax, ou
179176
public sealed class UnmanagedConstantExpectedParameter : ConstantExpectedParameter
180177
{
181178
private readonly TransformHelper _helper;
182-
public UnmanagedConstantExpectedParameter(IParameterSymbol parameter, SyntaxNode attributeSyntax, T min, T max, TransformHelper helper) : base(parameter, attributeSyntax)
179+
public UnmanagedConstantExpectedParameter(IParameterSymbol parameter, T min, T max, TransformHelper helper) : base(parameter)
183180
{
184181
Min = min;
185182
Max = max;
@@ -189,12 +186,12 @@ public UnmanagedConstantExpectedParameter(IParameterSymbol parameter, SyntaxNode
189186
public T Min { get; }
190187
public T Max { get; }
191188

192-
public override bool ValidateParameterIsWithinRange(ConstantExpectedParameter subsetCandidate, [NotNullWhen(false)] out Diagnostic? validationDiagnostics)
189+
public override bool ValidateParameterIsWithinRange(ConstantExpectedParameter subsetCandidate, IArgumentOperation argument, [NotNullWhen(false)] out Diagnostic? validationDiagnostics)
193190
{
194191
if (Parameter.Type.SpecialType != subsetCandidate.Parameter.Type.SpecialType ||
195192
subsetCandidate is not UnmanagedConstantExpectedParameter subsetCandidateTParameter)
196193
{
197-
validationDiagnostics = Diagnostic.Create(AttributeNotSameTypeRule, subsetCandidate.AttributeSyntax.GetLocation(), Parameter.Type.ToDisplayString());
194+
validationDiagnostics = Diagnostic.Create(CA1861.ConstantInvalidConstantRule, argument.Syntax.GetLocation(), Parameter.Type.ToDisplayString());
198195
return false;
199196
}
200197

@@ -204,22 +201,23 @@ public override bool ValidateParameterIsWithinRange(ConstantExpectedParameter su
204201
validationDiagnostics = null;
205202
return true;
206203
}
207-
validationDiagnostics = Diagnostic.Create(AttributeOutOfBoundsRule, subsetCandidateTParameter.AttributeSyntax.GetLocation(), Min.ToString(), Max.ToString());
204+
validationDiagnostics = Diagnostic.Create(CA1861.ConstantOutOfBoundsRule, argument.Syntax.GetLocation(), Min.ToString(), Max.ToString());
208205
return false;
209206
}
210207

211208
public override bool ValidateValue(IArgumentOperation argument, object? constant, [NotNullWhen(false)] out Diagnostic? validationDiagnostics)
212209
{
213-
if (_helper.TryConvert(constant, out T value))
210+
if (constant is not null && _helper.TryConvert(constant, out T value))
214211
{
215212
if (!_helper.IsLessThan(value, Min) && !_helper.IsLessThan(Max, value))
216213
{
217214
validationDiagnostics = null;
218215
return true;
219216
}
217+
validationDiagnostics = argument.CreateDiagnostic(CA1861.ConstantOutOfBoundsRule, Min.ToString(), Max.ToString());
218+
return false;
220219
}
221-
222-
validationDiagnostics = argument.CreateDiagnostic(ConstantOutOfBoundsRule, Min.ToString(), Max.ToString());
220+
validationDiagnostics = argument.CreateDiagnostic(CA1861.ConstantInvalidConstantRule, Parameter.Type.ToDisplayString());
223221
return false;
224222
}
225223
}
@@ -262,17 +260,6 @@ private static bool TryConvertUnsignedInteger(object constant, out ulong integer
262260
return true;
263261
}
264262

265-
private static bool TryConvertInt64(object? constant, out long value)
266-
{
267-
if (constant is not null)
268-
{
269-
value = Convert.ToInt64(constant);
270-
return true;
271-
}
272-
value = default;
273-
return false;
274-
}
275-
276263
private static bool TryTransformInt64(object constant, out long value, out bool isInvalid)
277264
{
278265
bool isValidSigned = TryConvertSignedInteger(constant, out value);
@@ -287,16 +274,6 @@ private static bool TryTransformInt64(object constant, out long value, out bool
287274
}
288275
return isValidSigned;
289276
}
290-
private static bool TryConvertUInt64(object? constant, out ulong value)
291-
{
292-
if (constant is not null)
293-
{
294-
value = Convert.ToUInt64(constant);
295-
return true;
296-
}
297-
value = default;
298-
return false;
299-
}
300277
private static bool TryTransformUInt64(object constant, out ulong value, out bool isInvalid)
301278
{
302279
bool isValidUnsigned = TryConvertUnsignedInteger(constant, out value);
@@ -318,31 +295,17 @@ private static bool TryTransformChar(object constant, out char value, out bool i
318295
{
319296
if (constant is string or bool)
320297
{
321-
value = default;
322-
isInvalid = true;
323-
return false;
298+
return Invalid(out value, out isInvalid);
324299
}
325300
value = Convert.ToChar(constant);
326301
}
327302
catch
328303
{
329-
value = default;
330-
isInvalid = true;
331-
return false;
304+
return Invalid(out value, out isInvalid);
332305
}
333306
isInvalid = false;
334307
return true;
335308
}
336-
private static bool TryConvertChar(object? constant, out char value)
337-
{
338-
if (constant is not null)
339-
{
340-
value = Convert.ToChar(constant);
341-
return true;
342-
}
343-
value = default;
344-
return false;
345-
}
346309

347310
private static bool TryTransformBoolean(object constant, out bool value, out bool isInvalid)
348311
{
@@ -352,83 +315,35 @@ private static bool TryTransformBoolean(object constant, out bool value, out boo
352315
isInvalid = false;
353316
return true;
354317
}
355-
isInvalid = true;
356-
value = default;
357-
return false;
358-
}
359-
private static bool TryConvertBoolean(object? constant, out bool value)
360-
{
361-
if (constant is not null)
362-
{
363-
value = (bool)constant;
364-
return true;
365-
}
366-
value = default;
367-
return false;
318+
return Invalid(out value, out isInvalid);
368319
}
369320

370321
private static bool TryTransformSingle(object constant, out float value, out bool isInvalid)
371322
{
372-
try
373-
{
374-
if (constant is string or bool)
375-
{
376-
value = default;
377-
isInvalid = true;
378-
return false;
379-
}
380-
value = Convert.ToSingle(constant);
381-
}
382-
catch
323+
if (constant is string or bool)
383324
{
384-
value = default;
385-
isInvalid = true;
386-
return false;
325+
return Invalid(out value, out isInvalid);
387326
}
327+
value = Convert.ToSingle(constant);
388328
isInvalid = false;
389329
return true;
390330
}
391331

392-
private static bool TryConvertSingle(object? constant, out float value)
393-
{
394-
if (constant is not null)
395-
{
396-
value = Convert.ToSingle(constant);
397-
return true;
398-
}
399-
value = default;
400-
return false;
401-
}
402-
403332
private static bool TryTransformDouble(object constant, out double value, out bool isInvalid)
404333
{
405-
try
334+
if (constant is string or bool)
406335
{
407-
if (constant is string or bool)
408-
{
409-
value = default;
410-
isInvalid = true;
411-
return false;
412-
}
413-
value = Convert.ToDouble(constant);
414-
}
415-
catch
416-
{
417-
value = default;
418-
isInvalid = true;
419-
return false;
336+
return Invalid(out value, out isInvalid);
420337
}
338+
value = Convert.ToDouble(constant);
421339
isInvalid = false;
422340
return true;
423341
}
424-
private static bool TryConvertDouble(object? constant, out double value)
342+
343+
private static bool Invalid<T>(out T value, out bool isInvalid) where T : unmanaged
425344
{
426-
if (constant is not null)
427-
{
428-
value = Convert.ToDouble(constant);
429-
return true;
430-
}
431345
value = default;
346+
isInvalid = true;
432347
return false;
433348
}
434349
}

0 commit comments

Comments
 (0)