From 0f5397821f0b126759330786277db43f9c1b1b26 Mon Sep 17 00:00:00 2001 From: James May Date: Mon, 8 Nov 2021 11:52:43 +1100 Subject: [PATCH] New Analyzer: Do not call Enumerable.Cast or Enumerable.OfType ith incompatible types --- .../Core/AnalyzerReleases.Unshipped.md | 1 + .../MicrosoftNetCoreAnalyzersResources.resx | 15 + ...stOrOfTypeWithIncompatibleTypesAnalyzer.cs | 316 ++++++++ .../MicrosoftNetCoreAnalyzersResources.cs.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.de.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.es.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.fr.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.it.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.ja.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.ko.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.pl.xlf | 26 + ...crosoftNetCoreAnalyzersResources.pt-BR.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.ru.xlf | 26 + .../MicrosoftNetCoreAnalyzersResources.tr.xlf | 26 + ...osoftNetCoreAnalyzersResources.zh-Hans.xlf | 26 + ...osoftNetCoreAnalyzersResources.zh-Hant.xlf | 26 + .../Microsoft.CodeAnalysis.NetAnalyzers.md | 18 + .../Microsoft.CodeAnalysis.NetAnalyzers.sarif | 20 + src/NetAnalyzers/RulesMissingDocumentation.md | 1 + ...fTypeWithIncompatibleTypesAnalyzerTests.cs | 723 ++++++++++++++++++ .../DiagnosticCategoryAndIdRanges.txt | 2 +- 21 files changed, 1433 insertions(+), 1 deletion(-) create mode 100644 src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.cs create mode 100644 src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzerTests.cs diff --git a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md index 5d35f49a65..bd3c05cf8a 100644 --- a/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md +++ b/src/NetAnalyzers/Core/AnalyzerReleases.Unshipped.md @@ -6,5 +6,6 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- CA1849 | Performance | Disabled | UseAsyncMethodInAsyncContext, [Documentation](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1849) CA1850 | Performance | Info | PreferHashDataOverComputeHashAnalyzer, [Documentation](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1850) +CA2019 | Reliability | Warning | DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer, [Documentation](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2017) CA5404 | Security | Disabled | DoNotDisableTokenValidationChecks, [Documentation](https://docs.microsoft.com/visualstudio/code-quality/ca5404) CA5405 | Security | Disabled | DoNotAlwaysSkipTokenValidationInDelegates, [Documentation](https://docs.microsoft.com/visualstudio/code-quality/ca5405) diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx index 8d5aa05b65..a0d66d4aab 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx @@ -1089,6 +1089,12 @@ When creating path for '{0} in method {1}' from relative archive item path to extract file and the source is an untrusted zip archive, make sure to sanitize relative archive item path '{2} in method {3}' + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + Do not create tasks without passing a TaskScheduler @@ -1776,6 +1782,15 @@ The 'ModuleInitializer' attribute should not be used in libraries + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + '{0}' synchronously blocks. Await '{1}' instead. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.cs b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.cs new file mode 100644 index 0000000000..6a1da7fa01 --- /dev/null +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.cs @@ -0,0 +1,316 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Linq; +using Analyzer.Utilities; +using Analyzer.Utilities.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +namespace Microsoft.NetCore.Analyzers.Runtime +{ + /// + /// CA2019: Do not call Enumerable.Cast or Enumerable.OfType with incompatible types. + /// + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public sealed class DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer : DiagnosticAnalyzer + { + internal const string RuleId = "CA2019"; + + private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(MicrosoftNetCoreAnalyzersResources.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesTitle), MicrosoftNetCoreAnalyzersResources.ResourceManager, typeof(MicrosoftNetCoreAnalyzersResources)); + private static readonly LocalizableString s_localizableDescription = new LocalizableResourceString(nameof(MicrosoftNetCoreAnalyzersResources.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesDescription), MicrosoftNetCoreAnalyzersResources.ResourceManager, typeof(MicrosoftNetCoreAnalyzersResources)); + + private static readonly LocalizableString s_localizableCastMessage = new LocalizableResourceString(nameof(MicrosoftNetCoreAnalyzersResources.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesMessageCast), MicrosoftNetCoreAnalyzersResources.ResourceManager, typeof(MicrosoftNetCoreAnalyzersResources)); + private static readonly LocalizableString s_localizableOfTypeMessage = new LocalizableResourceString(nameof(MicrosoftNetCoreAnalyzersResources.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesMessageOfType), MicrosoftNetCoreAnalyzersResources.ResourceManager, typeof(MicrosoftNetCoreAnalyzersResources)); + + internal static DiagnosticDescriptor CastRule = DiagnosticDescriptorHelper.Create(RuleId, + s_localizableTitle, + s_localizableCastMessage, + DiagnosticCategory.Reliability, + RuleLevel.BuildWarning, + s_localizableDescription, + isPortedFxCopRule: false, + isDataflowRule: false); + + internal static DiagnosticDescriptor OfTypeRule = DiagnosticDescriptorHelper.Create(RuleId, + s_localizableTitle, + s_localizableOfTypeMessage, + DiagnosticCategory.Reliability, + RuleLevel.BuildWarning, + s_localizableDescription, + isPortedFxCopRule: false, + isDataflowRule: false); + + private static readonly ImmutableArray<(string MethodName, DiagnosticDescriptor Rule)> s_methodMetadataNames = ImmutableArray.Create( + (nameof(Enumerable.Cast), CastRule), + (nameof(Enumerable.OfType), OfTypeRule) + ); + + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(OfTypeRule, CastRule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + context.RegisterCompilationStartAction(context => + { + if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemLinqEnumerable, out var enumerableType)) + { + return; + } + + var methodRuleDictionary = s_methodMetadataNames + .SelectMany(m => enumerableType + .GetMembers(m.MethodName) + .OfType() + .Where(method => method.IsExtensionMethod + && method.TypeParameters.HasExactly(1) + && method.Parameters.HasExactly(1) + && method.Parameters[0].Type.OriginalDefinition.SpecialType + == SpecialType.System_Collections_IEnumerable + ) + .Select(method => (method, m.Rule))) + .ToImmutableDictionary(key => key.method, v => v.Rule, SymbolEqualityComparer.Default); + + if (methodRuleDictionary.IsEmpty) + { + return; + } + + context.RegisterOperationAction(context => + { + var invocation = (IInvocationOperation)context.Operation; + + var targetMethod = (invocation.TargetMethod.ReducedFrom ?? invocation.TargetMethod).OriginalDefinition; + + if (!methodRuleDictionary.TryGetValue(targetMethod, out var rule)) + { + return; + } + + var instanceArg = invocation.GetInstance(); // "this" argument of an extension method + + static ITypeSymbol? GetIEnumerableTParam(ITypeSymbol type) + { + if (type is not INamedTypeSymbol argIEnumerableType + || !argIEnumerableType.TypeArguments.HasExactly(1)) + { + return null; + } + + return argIEnumerableType.TypeArguments[0]; + } + + static ITypeSymbol? FindElementType(IOperation? operation) + { + if (operation is null) + { + return null; + } + + if (operation.Kind == OperationKind.ArrayCreation) + { + return (operation.Type as IArrayTypeSymbol)?.ElementType; + } + + if (operation.Type?.OriginalDefinition?.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T) + { + return GetIEnumerableTParam(operation.Type); + } + + var r = operation?.Type?.AllInterfaces.FirstOrDefault(t => t.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T); + if (r is not null) + { + return GetIEnumerableTParam(r); + } + + if (operation is IParenthesizedOperation parenthesizedOperation) + { + return FindElementType(parenthesizedOperation.Operand); + } + + if (operation is IConversionOperation conversionOperation + && conversionOperation.OperatorMethod is null) // implicit meaning 'not user defined' + { + return FindElementType(conversionOperation.Operand); + } + + return null; + } + + // because the type of the parameter is actually the non-generic IEnumerable, + // we have to reach back through conversion operator(s) to get the element type + var castFrom = FindElementType(instanceArg); + if (castFrom is null) + { + return; + } + + if (!invocation.TargetMethod.TypeArguments.HasExactly(1)) + { + return; + } + + var castTo = invocation.TargetMethod.TypeArguments[0]; + + if (CastWillAlwaysFail(castFrom, castTo)) + { + context.ReportDiagnostic(invocation.CreateDiagnostic(rule, castFrom.ToDisplayString(), castTo.ToDisplayString())); + } + }, OperationKind.Invocation); + }); + + // because this is a warning, we want to be very sure + // this won't catch all problems, but it should never report something + // as a problem in correctly. We don't want another IDE0004 + static bool CastWillAlwaysFail(ITypeSymbol castFrom, ITypeSymbol castTo) + { + if (castFrom.TypeKind == TypeKind.Error + || castTo.TypeKind == TypeKind.Error) + { + return false; + } + + if (castFrom.SpecialType == SpecialType.System_Object + || castTo.SpecialType == SpecialType.System_Object) + { + // some things will actually fail, eg. TypedReference + // but they should be pretty rare + return false; + } + + if (castFrom.Equals(castTo, SymbolEqualityComparer.Default)) + { + return false; + } + + static ITypeSymbol UnwrapNullableValueType(ITypeSymbol typeSymbol) + { + if (typeSymbol.IsValueType + && typeSymbol.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T + && ((INamedTypeSymbol)typeSymbol).TypeArguments[0] is var nullableTypeArgument) + { + return nullableTypeArgument; + } + return typeSymbol; + } + + castFrom = UnwrapNullableValueType(castFrom); + castTo = UnwrapNullableValueType(castTo); + + static bool IsUnconstrainedTypeParameter(ITypeParameterSymbol typeParameterSymbol) + => !typeParameterSymbol.HasValueTypeConstraint + && typeParameterSymbol.ConstraintTypes.IsEmpty; + // because object is a reference type the 'class' reference type constraint + // doesn't actually constrain unless a type is specified too + // not implemented: + // NotNullConstraint + // ConstructorConstraint + // UnmanagedTypeConstraint + // Nullability annotations + + switch (castFrom.OriginalDefinition.TypeKind, castTo.OriginalDefinition.TypeKind) + { + case (TypeKind.TypeParameter, _): + var castFromTypeParam = (ITypeParameterSymbol)castFrom.OriginalDefinition; + if (IsUnconstrainedTypeParameter(castFromTypeParam)) + { + return false; + } + + if (castFromTypeParam.ConstraintTypes.Any(constraintType => CastWillAlwaysFail(constraintType, castTo))) + { + return true; + } + + if (castFromTypeParam.HasValueTypeConstraint + && castTo.TypeKind == TypeKind.Class) + { + return true; + } + return false; + case (_, TypeKind.TypeParameter): + var castToTypeParam = (ITypeParameterSymbol)castTo.OriginalDefinition; + if (IsUnconstrainedTypeParameter(castToTypeParam)) + { + return false; + } + + if (castToTypeParam.ConstraintTypes.Any(constraintType => CastWillAlwaysFail(castFrom, constraintType))) + { + return true; + } + + if (castToTypeParam.HasValueTypeConstraint + && castFrom.TypeKind == TypeKind.Class) + { + return true; + } + return false; + + case (TypeKind.Class, TypeKind.Class): + return !castFrom.DerivesFrom(castTo) + && !castTo.DerivesFrom(castFrom); + + case (TypeKind.Interface, TypeKind.Class): + return castTo.IsSealed && !castTo.AllInterfaces.Contains(castFrom); + case (TypeKind.Class, TypeKind.Interface): + return castFrom.IsSealed && !castFrom.AllInterfaces.Contains(castTo); + + case (TypeKind.Class, TypeKind.Enum): + return castFrom.OriginalDefinition.SpecialType != SpecialType.System_Enum + && castFrom.OriginalDefinition.SpecialType != SpecialType.System_ValueType; + case (TypeKind.Enum, TypeKind.Class): + return castTo.OriginalDefinition.SpecialType != SpecialType.System_Enum + && castTo.OriginalDefinition.SpecialType != SpecialType.System_ValueType; + + case (TypeKind.Struct, TypeKind.Enum) + when castTo.OriginalDefinition is INamedTypeSymbol toEnum: + return !castFrom.Equals(toEnum.EnumUnderlyingType); + case (TypeKind.Enum, TypeKind.Struct) + when castFrom.OriginalDefinition is INamedTypeSymbol fromEnum: + return !fromEnum.EnumUnderlyingType.Equals(castTo); + + case (TypeKind.Enum, TypeKind.Enum) + when castFrom.OriginalDefinition is INamedTypeSymbol fromEnum + && castTo.OriginalDefinition is INamedTypeSymbol toEnum: + return !fromEnum.EnumUnderlyingType.Equals(toEnum.EnumUnderlyingType); + + // this is too conservative + // array variance is not implemented + // - eg. object[] -> class[] + // boxing shouldn't be allowed + // - eg. object[] -> ValueType[] + case (TypeKind.Array, TypeKind.Array) + when castFrom is IArrayTypeSymbol fromArray + && castTo is IArrayTypeSymbol toArray: + return fromArray.Rank != toArray.Rank + || CastWillAlwaysFail(fromArray.ElementType, toArray.ElementType); + + case (TypeKind.Array, TypeKind.Class): + return castTo.OriginalDefinition.SpecialType != SpecialType.System_Array; + case (TypeKind.Class, TypeKind.Array): + return castFrom.OriginalDefinition.SpecialType != SpecialType.System_Array; + + case (TypeKind.Class, TypeKind.Struct): + return castFrom.OriginalDefinition.SpecialType != SpecialType.System_ValueType; + case (TypeKind.Struct, TypeKind.Class): + return castTo.OriginalDefinition.SpecialType != SpecialType.System_ValueType; + + case (_, TypeKind.Enum): + case (TypeKind.Enum, _): + case (_, TypeKind.Struct): + case (TypeKind.Struct, _): + return true; + + case (TypeKind.Interface, TypeKind.Interface): + default: + return false; // we don't *know* it'll fail... + } + } + } + } +} diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf index dc80994265..0215bd89a3 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.cs.xlf @@ -502,6 +502,32 @@ Při deserializaci instance třídy {0} může metoda {1} volat nebezpečnou metodu {2}. Možná volání metod: {3} + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Když konstruktor zavolá virtuální metodu, konstruktor dané instance, která metodu vyvolala, se nemusí spustit. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf index 2f687780a8..122513ad5e 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.de.xlf @@ -502,6 +502,32 @@ Wenn eine Instanz der Klasse "{0}" deserialisiert wird, kann die Methode "{1}" die gefährliche Methode "{2}" aufrufen. Mögliche Methodenaufrufe: {3} + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Wenn ein Konstruktor eine virtuelle Methode aufruft, wurde der Konstruktor für die Instanz, die die Methode aufruft, möglicherweise nicht ausgeführt. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf index 796bdc6015..f3d7c7f628 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.es.xlf @@ -502,6 +502,32 @@ Al deserializar una instancia de la clase {0}, el método {1} puede llamar al método peligroso {2}. Invocaciones de métodos posibles: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Cuando un constructor llama a un método virtual, es posible que no se haya ejecutado el constructor para la instancia que invoca el método. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf index 251817ef26..8af5fa39cd 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.fr.xlf @@ -502,6 +502,32 @@ Quand vous désérialisez une instance de la classe {0}, la méthode {1} peut appeler une méthode dangereuse {2}. Les appels de méthode potentiels sont : {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Quand un constructeur appelle une méthode virtuelle, le constructeur de l'instance qui appelle la méthode n'a peut-être pas été exécuté. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf index 32e5239392..9dcf676f1b 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.it.xlf @@ -502,6 +502,32 @@ Durante la deserializzazione di un'istanza della classe {0} il metodo {1} può chiamare il metodo pericoloso {2}. Le potenziali chiamate al metodo sono: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Quando un costruttore chiama un metodo virtuale, è possibile che il costruttore per l'istanza che richiama il metodo non sia stato eseguito. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf index 7009ff1c2d..75cd8256dc 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ja.xlf @@ -502,6 +502,32 @@ クラス {0} のインスタンスを逆シリアル化すると、メソッド {1} によって危険なメソッド {2} を呼び出されるおそれがあります。考えられるメソッド呼び出し: {3}。 + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. コンストラクターが仮想メソッドを呼び出すときに、メソッドを呼び出すインスタンスのコンストラクターは実行されていない可能性があります。 diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf index 00e6daa4b9..2f9daf2c90 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ko.xlf @@ -502,6 +502,32 @@ {0} 클래스의 인스턴스를 역직렬화할 때 {1} 메서드가 위험한 메서드 {2}을(를) 호출할 수 있습니다. 잠재적인 메서드 호출은 {3}입니다. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. 생성자에서 가상 메서드를 호출하면 메서드를 호출하는 인스턴스에 대한 생성자가 실행되지 않을 수 있습니다. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf index ac5808463f..4d144b7e34 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pl.xlf @@ -502,6 +502,32 @@ Podczas deserializacji wystąpienia klasy {0} metoda {1} może wywołać niebezpieczną metodę {2}. Potencjalne wywołania metod to: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Gdy konstruktor wywołuje metodę wirtualną, konstruktor wystąpienia wywołującego metodę może nie zostać wykonany. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf index 3bf860483d..671f741c4b 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.pt-BR.xlf @@ -502,6 +502,32 @@ Ao desserializar uma instância da classe {0}, o método {1} pode chamar o método perigoso {2}. As possíveis invocações de método são: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Quando um construtor chama um método virtual, o construtor para a instância que invoca o método pode não ter sido executado. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf index fcc7b39172..8b45114e19 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.ru.xlf @@ -502,6 +502,32 @@ При десериализации экземпляра класса {0} метод {1} может вызывать опасный метод {2}. Потенциальные вызовы методов: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Когда конструктор вызывает виртуальный метод, конструктор может не выполняться для экземпляра, вызывающего этот метод. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf index 92c255c2f8..9728955582 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.tr.xlf @@ -502,6 +502,32 @@ {0} sınıfının bir örneği seri durumdan çıkarılırken, {1} metodu tehlikeli {2} metodunu çağırabilir. Olası metot çağırmaları: {3}. + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. Bir oluşturucu tarafından sanal bir yöntem çağrıldığında, yöntemi tetikleyen örneğin oluşturucusu yürütülmemiş olabilir. diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf index c1756ddba4..f70f1e8924 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hans.xlf @@ -502,6 +502,32 @@ 反序列化类 {0} 的实例时,方法 {1} 可调用危险方法 {2}。潜在的方法调用为: {3}。 + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. 构造函数调用虚方法时,可能尚未执行调用该方法的实例的构造函数。 diff --git a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf index 1fa0cbd50f..5a298f4934 100644 --- a/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf +++ b/src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/xlf/MicrosoftNetCoreAnalyzersResources.zh-Hant.xlf @@ -502,6 +502,32 @@ 將類別 {0} 的執行個體還原序列化時,方法 {1} 可以呼叫危險的方法 {2}。潛在的方法引動過程為: {3}。 + + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + Enumerable.Cast<T> and Enumerable.OfType<T> require compatible types to function expectedly. +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast<T> will throw InvalidCastException at runtime on elements of the types specified. +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType<T> will never succeed with elements of types specified, resulting in an empty sequence. +Widening and user defined conversions are not supported with generic types. + + + + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + Type '{0}' is incompatible with type '{1}' and cast attempts will throw InvalidCastException at runtime + + + + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + This call will always result in an empty sequence because type '{0}' is incompatible with type '{1}' + + + + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + Do not call Enumerable.Cast<T> or Enumerable.OfType<T> with incompatible types + + When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed. 當建構函式呼叫虛擬方法時,可能尚未執行叫用方法之執行個體的建構函式。 diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md index cb70695cd5..7af0920841 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.md @@ -1632,6 +1632,24 @@ Number of parameters supplied in the logging message template do not match the n |CodeFix|False| --- +## [CA2019](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2019): Do not call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types + +Enumerable.Cast\ and Enumerable.OfType\ require compatible types to function expectedly. + +The generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast\ will throw InvalidCastException at runtime on elements of the types specified. + +The generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType\ will never succeed with elements of types specified, resulting in an empty sequence. + +Widening and user defined conversions are not supported with generic types. + +|Item|Value| +|-|-| +|Category|Reliability| +|Enabled|True| +|Severity|Warning| +|CodeFix|False| +--- + ## [CA2100](https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2100): Review SQL queries for security vulnerabilities SQL queries that directly use user input can be vulnerable to SQL injection attacks. Review this SQL query for potential vulnerabilities, and consider using a parameterized SQL query. diff --git a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif index 0560a44240..6ba7c527a3 100644 --- a/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif +++ b/src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif @@ -2964,6 +2964,26 @@ ] } }, + "CA2019": { + "id": "CA2019", + "shortDescription": "Do not call Enumerable.Cast or Enumerable.OfType with incompatible types", + "fullDescription": "Enumerable.Cast and Enumerable.OfType require compatible types to function expectedly. \u000aThe generic cast (IL 'unbox.any') used by the sequenced returned by Enumerable.Cast will throw InvalidCastException at runtime on elements of the types specified. \u000aThe generic type check (C# 'is' operator/IL 'isinst') used by Enumerable.OfType will never succeed with elements of types specified, resulting in an empty sequence. \u000aWidening and user defined conversions are not supported with generic types.", + "defaultLevel": "warning", + "helpUri": "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2019", + "properties": { + "category": "Reliability", + "isEnabledByDefault": true, + "typeName": "DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer", + "languages": [ + "C#", + "Visual Basic" + ], + "tags": [ + "Telemetry", + "EnabledRuleInAggressiveMode" + ] + } + }, "CA2100": { "id": "CA2100", "shortDescription": "Review SQL queries for security vulnerabilities", diff --git a/src/NetAnalyzers/RulesMissingDocumentation.md b/src/NetAnalyzers/RulesMissingDocumentation.md index 75e0f77588..30854a9e21 100644 --- a/src/NetAnalyzers/RulesMissingDocumentation.md +++ b/src/NetAnalyzers/RulesMissingDocumentation.md @@ -2,3 +2,4 @@ Rule ID | Missing Help Link | Title | --------|-------------------|-------| +CA2019 | | Do not call Enumerable.Cast\ or Enumerable.OfType\ with incompatible types | diff --git a/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzerTests.cs b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzerTests.cs new file mode 100644 index 0000000000..e4390ffb88 --- /dev/null +++ b/src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzerTests.cs @@ -0,0 +1,723 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Xunit; +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.NetCore.Analyzers.Runtime.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; +using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< + Microsoft.NetCore.Analyzers.Runtime.DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer, + Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>; + +namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests +{ + public class DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzerTests + { + private readonly DiagnosticDescriptor castRule = DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.CastRule; + private readonly DiagnosticDescriptor ofTypeRule = DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.OfTypeRule; + + [Fact] + public async Task OnlyWellKnownIEnumerable() + { + await VerifyCS.VerifyAnalyzerAsync(@" +namespace System.Linq +{ + interface IEnumerable {} + // this 'IEnumerable' isn't 'well known', so the analyzer won't fire + interface IEnumerable : IEnumerable {} + + static class Enumerable + { + public static IEnumerable OfType(this IEnumerable ienum) => null; + } + + class C + { + void M() + { + _ = Enumerable.OfType(default(IEnumerable)); + _ = default(IEnumerable).OfType(); + } + } +} +"); + } + + [Fact()] + public async Task UnrelatedMethodsDontTrigger() + { + await VerifyCS.VerifyAnalyzerAsync(@" +using System.Collections; +using System.Collections.Generic; + +namespace System.Linq +{ + static class Enumerable + { + // missing 'this' + public static IEnumerable Cast(IEnumerable ienum) => null; + // wrong parameter type + public static IEnumerable Cast(this IEnumerable ienum) => null; + // too many parameters + public static IEnumerable Cast(this IEnumerable ienum, object distraction) => null; + // too many type parameters + public static IEnumerable Cast(this IEnumerable ienum) => null; + } + + class C + { + void M() + { + IEnumerable e = default; + _ = Enumerable.Cast(e); + _ = e.Cast(); + _ = e.Cast(null); + _ = e.Cast(); + } + } +} +"); + } + + [Fact] + public async Task NonGenericCasesCSharp() + { + await VerifyCS.VerifyAnalyzerAsync(@" +using System.Linq; +class Fruit {} +class Apple : Fruit {} +class Shoe {} + +interface ICar {} + +interface IPlant {} +interface ITree : IPlant {} +interface IGrass : IPlant {} + +class Plant : IPlant {} +class Tree : ITree {} +sealed class Grass : IGrass {} + +class C +{ + public void M() + { + _ = (new int[0]).OfType(); + _ = {|#10:(new int[0]).OfType()|}; + _ = (new object[0]).OfType(); + + // we don't look through extra casts + _ = (new System.Uri[0] as object[]).OfType(); + _ = ((object[])new System.Uri[0]).OfType(); + + // expression syntax + _ = from string s in new object[0] + select s; + _ = {|#11:from int i in new string[0]|} + select i; + _ = {|#12:Enumerable.Cast(new int[0])|}; + + // interfaces + _ = (new ICar[0]).Cast(); + _ = (new ICar[0]).Cast(); + _ = (new IPlant[0]).Cast(); + _ = (new IPlant[0]).Cast(); + + // classes + _ = (new Fruit[0]).Cast(); // identity + _ = (new Fruit[0]).Cast(); // upcast + _ = {|#40:(new Fruit[0]).Cast()|}; // error + _ = (new Apple[0]).Cast(); // downcast + _ = (new Apple[0]).Cast(); // identity + _ = {|#41:(new Apple[0]).Cast()|}; // error + _ = {|#42:(new Shoe[0]).Cast()|}; // error + _ = {|#43:(new Shoe[0]).Cast()|}; // error + _ = {|#44:(new Shoe[0]).Cast()|}; // error + + // interface to class + _ = (new ICar[0]).Cast(); // subclass of Plant could implement ICar + _ = (new ICar[0]).Cast(); // subclass of Tree could implement ICar + _ = {|#50:(new ICar[0]).Cast()|}; // subclass of Grass could not implement ICar, as Grass is sealed + _ = (new ICar[0]).Cast(); // subclass of Shoe could implement ICar + + _ = (new IPlant[0]).Cast(); + _ = (new IPlant[0]).Cast(); + _ = (new IPlant[0]).Cast(); + _ = (new IPlant[0]).Cast(); + + _ = (new ITree[0]).Cast(); + _ = (new ITree[0]).Cast(); + _ = {|#51:(new ITree[0]).Cast()|}; // subclass of Grass could not implement ICar, as Grass is sealed + _ = (new ITree[0]).Cast(); + + _ = (new IGrass[0]).Cast(); + _ = (new IGrass[0]).Cast(); + _ = (new IGrass[0]).Cast(); + _ = (new IGrass[0]).Cast(); + + // class to interface + _ = (new Plant[0]).Cast(); + _ = (new Tree[0]).Cast(); + _ = {|#52:(new Grass[0]).Cast()|}; // grass doesn't implement ICar, and is sealed so a subclass couldn't either + _ = (new Shoe[0]).Cast(); + + _ = (new Plant[0]).Cast(); + _ = (new Tree[0]).Cast(); + _ = (new Grass[0]).Cast(); + _ = (new Shoe[0]).Cast(); + + _ = (new Plant[0]).Cast(); + _ = (new Tree[0]).Cast(); + _ = {|#53:(new Grass[0]).Cast()|}; + _ = (new Shoe[0]).Cast(); + + _ = (new Plant[0]).Cast(); + _ = (new Tree[0]).Cast(); + _ = (new Grass[0]).Cast(); + _ = (new Shoe[0]).Cast(); + } +} +", + +VerifyCS.Diagnostic(ofTypeRule).WithLocation(10).WithArguments("int", "string"), +VerifyCS.Diagnostic(castRule).WithLocation(11).WithArguments("string", "int"), +VerifyCS.Diagnostic(castRule).WithLocation(12).WithArguments("int", "string"), + +VerifyCS.Diagnostic(castRule).WithLocation(40).WithArguments("Fruit", "Shoe"), +VerifyCS.Diagnostic(castRule).WithLocation(41).WithArguments("Apple", "Shoe"), +VerifyCS.Diagnostic(castRule).WithLocation(42).WithArguments("Shoe", "Fruit"), +VerifyCS.Diagnostic(castRule).WithLocation(43).WithArguments("Shoe", "Apple"), + +VerifyCS.Diagnostic(castRule).WithLocation(50).WithArguments("ICar", "Grass"), +VerifyCS.Diagnostic(castRule).WithLocation(51).WithArguments("ITree", "Grass"), +VerifyCS.Diagnostic(castRule).WithLocation(52).WithArguments("Grass", "ICar"), +VerifyCS.Diagnostic(castRule).WithLocation(53).WithArguments("Grass", "ITree") +); + } + + [Fact] + public async Task ArrayCSharp() + { + Assert.Throws(() + => (new int[][] { new int[] { 1 } }).Cast().ToArray()); + Assert.Throws(() + => (new[] { 1 }).Cast().ToArray()); + + Assert.Throws(() + => (new object[][] { Array.Empty() }).Cast().ToArray()); + + Assert.Throws(() + => (new ValueType[][] { Array.Empty() }).Cast().ToArray()); + + Assert.Throws(() + => (new object[][] { Array.Empty() }).Cast().ToArray()); + + Assert.Throws(() + => (new ValueType[][] { Array.Empty() }).Cast().ToArray()); + + Assert.Throws(() + => (new int[][] { Array.Empty() }).Cast().ToArray()); + + await VerifyCS.VerifyAnalyzerAsync(@" +using System; +using System.Linq; + +class C +{ + void M() + { + Enumerable.OfType(new int[0][]); + Enumerable.OfType(new string[0][]); + Enumerable.OfType(new object[0][]); + + // these should all be errors, but not all implemented + Enumerable.OfType(new object[0][]); + Enumerable.OfType(new object[0][]); + + {|#12:Enumerable.OfType(new int[0][])|}; + {|#13:Enumerable.OfType(new int[0][])|}; + + // multidimensional arrays don't implement IEnumberable + + // IEnumerable != string[,] + {|#20:Enumerable.OfType(new string[0,0])|}; + + // these will throw + {|#21:Enumerable.OfType(new int[0,0])|}; + {|#22:Enumerable.OfType(new int[0,0])|}; + + // arrays of multidimensional arrays are checked, including rank + {|#30:Enumerable.OfType(new string[0][,])|}; + {|#31:Enumerable.OfType(new string[0][])|}; + {|#32:Enumerable.OfType(new int[0][,])|}; + {|#33:Enumerable.OfType(new int[0][])|}; + + // all arrays can be cast to and from System.Array + Enumerable.OfType(Enumerable.Empty()); + + Enumerable.OfType(Enumerable.Empty()); + Enumerable.OfType(Enumerable.Empty()); + Enumerable.OfType(Enumerable.Empty()); + Enumerable.OfType(Enumerable.Empty()); + + Enumerable.OfType(Enumerable.Empty()); + Enumerable.OfType(Enumerable.Empty()); + + // but not non-arrays + {|#41:Enumerable.OfType(Array.Empty())|}; + Enumerable.OfType(Array.Empty()); + {|#42:Enumerable.OfType(Array.Empty())|}; + {|#43:Enumerable.OfType(Array.Empty())|}; + {|#44:Enumerable.OfType(Array.Empty())|}; + + {|#51:Enumerable.OfType(Array.Empty())|}; + Enumerable.OfType(Array.Empty()); + {|#52:Enumerable.OfType(Array.Empty())|}; + {|#53:Enumerable.OfType(Array.Empty())|}; + {|#54:Enumerable.OfType(Array.Empty())|}; + + // this might work + Enumerable.OfType(Enumerable.Empty()); + // this is not allowed, but not implemented yet + Enumerable.OfType(Enumerable.Empty()); + } +}", + // VerifyCS.Diagnostic(ofTypeRule).WithLocation(10).WithArguments("int[]", "object[]"), + // VerifyCS.Diagnostic(ofTypeRule).WithLocation(11).WithArguments("string[]", "object[]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(12).WithArguments("int[]", "string[]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(13).WithArguments("int[]", "string"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(20).WithArguments("string", "string[*,*]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(21).WithArguments("int", "string[]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(22).WithArguments("int", "string[*,*]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(30).WithArguments("string[*,*]", "string[]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(31).WithArguments("string[]", "string[*,*]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(32).WithArguments("int[*,*]", "string[]"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(33).WithArguments("int[]", "string[*,*]"), + + VerifyCS.Diagnostic(ofTypeRule).WithLocation(41).WithArguments("int", "System.Array"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(42).WithArguments("string", "System.Array"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(43).WithArguments("System.ValueType", "System.Array"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(44).WithArguments("System.Enum", "System.Array"), + + VerifyCS.Diagnostic(ofTypeRule).WithLocation(51).WithArguments("System.Array", "int"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(52).WithArguments("System.Array", "string"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(53).WithArguments("System.Array", "System.ValueType"), + VerifyCS.Diagnostic(ofTypeRule).WithLocation(54).WithArguments("System.Array", "System.Enum") + +// VerifyCS.Diagnostic(ofTypeRule).WithLocation(60).WithArguments("ValueType[]", "int[]") +); + } + + [Fact] + public async Task EnumCasesCSharp() + { + Assert.Throws(() => new int[] { 1 }.Cast().ToArray()); + + // this is ok! + _ = new StringComparison[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + _ = new StringComparison[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + _ = new ValueType[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + _ = new Enum[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + _ = new ValueType[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + _ = new Enum[] { StringComparison.OrdinalIgnoreCase }.Cast().ToArray(); + + await VerifyCS.VerifyAnalyzerAsync(@" +using System; +using System.Linq; + +enum ByteEnum : byte {} +enum IntEnum {} +enum IntEnum2 {} +enum UIntEnum : uint {} +enum LongEnum : long {} + +class C +{ + void M() + { + // object is everything + _ = (new object[0]).Cast(); + _ = (new IntEnum[0]).Cast(); + + // base class + _ = (new Enum[0]).Cast(); + _ = (new IntEnum[0]).Cast(); + _ = {|#10:(new int[0]).Cast()|}; + + // value type + _ = Array.Empty().Cast(); + _ = (new IntEnum[0]).Cast(); + _ = (new ValueType[0]).Cast(); + _ = (new Enum[0]).Cast(); + + // Enums with the same underlying type are OK + _ = (new IntEnum[0]).Cast(); + _ = (new IntEnum2[0]).Cast(); + + // to and from the underlying type are ok + _ = (new ByteEnum[0]).Cast(); + _ = (new IntEnum[0]).Cast(); + _ = (new UIntEnum[0]).Cast(); + _ = (new LongEnum[0]).Cast(); + + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + + // enums with different underlying types are not + _ = {|#20:(new IntEnum[0]).Cast()|}; + _ = {|#21:(new IntEnum[0]).Cast()|}; + + _ = {|#22:(new int[0]).Cast()|}; + _ = {|#23:(new int[0]).Cast()|}; + + _ = {|#24:(new IntEnum[0]).Cast()|}; + _ = {|#25:(new int[0]).Cast()|}; + + _ = {|#26:(new ByteEnum[0]).Cast()|}; + _ = {|#27:(new UIntEnum[0]).Cast()|}; + + _ = {|#28:(new ByteEnum[0]).Cast()|}; + _ = {|#29:(new UIntEnum[0]).Cast()|}; + + _ = {|#30:(new LongEnum[0]).Cast()|}; + _ = {|#31:(new LongEnum[0]).Cast()|}; + } +}", + VerifyCS.Diagnostic(castRule).WithLocation(10).WithArguments("int", "System.Enum"), + VerifyCS.Diagnostic(castRule).WithLocation(20).WithArguments("IntEnum", "ByteEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(21).WithArguments("IntEnum", "UIntEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(22).WithArguments("int", "ByteEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(23).WithArguments("int", "UIntEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(24).WithArguments("IntEnum", "LongEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(25).WithArguments("int", "LongEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(26).WithArguments("ByteEnum", "IntEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(27).WithArguments("UIntEnum", "IntEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(28).WithArguments("ByteEnum", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(29).WithArguments("UIntEnum", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(30).WithArguments("LongEnum", "IntEnum"), + VerifyCS.Diagnostic(castRule).WithLocation(31).WithArguments("LongEnum", "int") +); + } + + [Fact] + public async Task NullableValueTypeCasesCSharp() + { + _ = new ValueType[] { StringComparison.OrdinalIgnoreCase, null }.Cast().ToArray(); + + await VerifyCS.VerifyAnalyzerAsync(@" +using System; +using System.Linq; + +enum ByteEnum : byte {} +enum IntEnum {} +enum IntEnum2 {} +enum UIntEnum : uint {} +enum LongEnum : long {} + +class C +{ + void M() + { + // object is everything + _ = (new object[0]).Cast(); + _ = (new IntEnum?[0]).Cast(); + + // base class + _ = (new Enum[0]).Cast(); + _ = (new IntEnum?[0]).Cast(); + _ = {|#10:(new int?[0]).Cast()|}; + _ = {|#11:(new Enum[0]).Cast()|}; + + // value type + _ = (new Enum[0]).Cast(); + _ = Array.Empty().Cast(); + _ = (new IntEnum?[0]).Cast(); + _ = (new ValueType[0]).Cast(); + + // Enums with the same underlying type are OK + _ = (new IntEnum?[0]).Cast(); + _ = (new IntEnum2?[0]).Cast(); + + // to and from the underlying type are ok + _ = (new ByteEnum?[0]).Cast(); + _ = (new IntEnum?[0]).Cast(); + _ = (new UIntEnum?[0]).Cast(); + _ = (new LongEnum?[0]).Cast(); + + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + _ = Enumerable.Empty().Cast(); + + // enums with different underlying types are not + _ = {|#20:(new IntEnum?[0]).Cast()|}; + _ = {|#21:(new IntEnum?[0]).Cast()|}; + + _ = {|#22:(new int?[0]).Cast()|}; + _ = {|#23:(new int?[0]).Cast()|}; + + _ = {|#24:(new IntEnum?[0]).Cast()|}; + _ = {|#25:(new int?[0]).Cast()|}; + + _ = {|#26:(new ByteEnum?[0]).Cast()|}; + _ = {|#27:(new UIntEnum?[0]).Cast()|}; + + _ = {|#28:(new ByteEnum?[0]).Cast()|}; + _ = {|#29:(new UIntEnum?[0]).Cast()|}; + + _ = {|#30:(new LongEnum?[0]).Cast()|}; + _ = {|#31:(new LongEnum?[0]).Cast()|}; + } +}", + VerifyCS.Diagnostic(castRule).WithLocation(10).WithArguments("int?", "System.Enum"), + VerifyCS.Diagnostic(castRule).WithLocation(11).WithArguments("System.Enum", "int?"), + + VerifyCS.Diagnostic(castRule).WithLocation(20).WithArguments("IntEnum?", "ByteEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(21).WithArguments("IntEnum?", "UIntEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(22).WithArguments("int?", "ByteEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(23).WithArguments("int?", "UIntEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(24).WithArguments("IntEnum?", "LongEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(25).WithArguments("int?", "LongEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(26).WithArguments("ByteEnum?", "IntEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(27).WithArguments("UIntEnum?", "IntEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(28).WithArguments("ByteEnum?", "int?"), + VerifyCS.Diagnostic(castRule).WithLocation(29).WithArguments("UIntEnum?", "int?"), + VerifyCS.Diagnostic(castRule).WithLocation(30).WithArguments("LongEnum?", "IntEnum?"), + VerifyCS.Diagnostic(castRule).WithLocation(31).WithArguments("LongEnum?", "int?") +); + } + + [Fact] + public async Task GenericCastsCSharp() + { + await VerifyCS.VerifyAnalyzerAsync(@" +using System.Linq; + +struct Struct : IInterface {} +interface IInterface {} +interface IInterface2 {} + +sealed class S : IInterface {} +sealed class Z : IInterface, IInterface2 {} + +class C : IInterface +{ + void M() + { + (new T[0]).Cast(); // T could be anything + (new int[0]).Cast(); // T could be anything + } + + void MClass() where TClass : class + { + (new TClass[0]).Cast(); // T could be object + (new int[0]).Cast(); // T could be object + } + + void MclassC() where TClassC : C + { + (new TClassC[0]).Cast(); + (new object[0]).Cast(); + + (new TClassC[0]).Cast(); + (new TClassC[0]).Cast(); + + {|#10:(new TClassC[0]).Cast()|}; // C is not string + {|#11:(new string[0]).Cast()|}; // string is not C + + (new C[0]).Cast(); + (new IInterface[0]).Cast(); + + {|#12:(new TClassC[0]).Cast()|}; // error, subclass of C can't be int + {|#13:(new int[0]).Cast()|}; // error, int can't be subclass of C + {|#14:(new TClassC[0]).Cast()|}; // error, subclass of C can't be int + {|#15:(new string[0]).Cast()|}; // error, int can't be subclass of C + } + + void MInterface() where TInterface : IInterface + { + (new TInterface[0]).Cast(); + (new IInterface[0]).Cast(); + + (new TInterface[0]).Cast(); + (new object[0]).Cast(); + + {|#20:(new TInterface[0]).Cast()|}; + {|#21:(new int[0]).Cast()|}; + + {|#22:(new TInterface[0]).Cast()|}; + {|#23:(new string[0]).Cast()|}; + } + + void MInterface2() where TInterface : IInterface, IInterface2 + { + (new TInterface[0]).Cast(); + (new IInterface[0]).Cast(); + + (new TInterface[0]).Cast(); + (new IInterface2[0]).Cast(); + + // does implement both interfaces + (new Z[0]).Cast(); + (new TInterface[0]).Cast(); + + // doesn't implement IInterface2, but a subclass could + (new C[0]).Cast(); + (new TInterface[0]).Cast(); + + // sealed class doesn't implement IInterface2 + {|#30:(new S[0]).Cast()|}; + {|#31:(new TInterface[0]).Cast()|}; + + // struct class doesn't implement IInterface2 + {|#32:(new Struct[0]).Cast()|}; + {|#33:(new TInterface[0]).Cast()|}; + + // ok + (new TInterface[0]).Cast(); + (new object[0]).Cast(); + + {|#34:(new TInterface[0]).Cast()|}; + {|#35:(new int[0]).Cast()|}; + + {|#36:(new TInterface[0]).Cast()|}; + {|#37:(new string[0]).Cast()|}; + } + + void MStructInterface() where TStructInterface : struct, IInterface + { + {|#40:(new TStructInterface[0]).Cast()|}; // error, int doesn't implement I + {|#41:(new int[0]).Cast()|}; // error, I can't be cast to int + } + + void Mstruct() where TStruct : struct + { + (new TStruct[0]).Cast(); // int is a struct + (new TStruct[0]).Cast(); // can always cast to object + {|#50:(new TStruct[0]).Cast()|}; // string is not is a struct + + (new int[0]).Cast(); // int is a struct + (new object[0]).Cast(); // can always cast to object + {|#51:(new string[0]).Cast()|}; // string is not is a struct + } +}", + VerifyCS.Diagnostic(castRule).WithLocation(10).WithArguments("TClassC", "string"), + VerifyCS.Diagnostic(castRule).WithLocation(11).WithArguments("string", "TClassC"), + + VerifyCS.Diagnostic(castRule).WithLocation(12).WithArguments("TClassC", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(13).WithArguments("int", "TClassC"), + VerifyCS.Diagnostic(castRule).WithLocation(14).WithArguments("TClassC", "string"), + VerifyCS.Diagnostic(castRule).WithLocation(15).WithArguments("string", "TClassC"), + + VerifyCS.Diagnostic(castRule).WithLocation(20).WithArguments("TInterface", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(21).WithArguments("int", "TInterface"), + + VerifyCS.Diagnostic(castRule).WithLocation(22).WithArguments("TInterface", "string"), + VerifyCS.Diagnostic(castRule).WithLocation(23).WithArguments("string", "TInterface"), + + VerifyCS.Diagnostic(castRule).WithLocation(30).WithArguments("S", "TInterface"), + VerifyCS.Diagnostic(castRule).WithLocation(31).WithArguments("TInterface", "S"), + VerifyCS.Diagnostic(castRule).WithLocation(32).WithArguments("Struct", "TInterface"), + VerifyCS.Diagnostic(castRule).WithLocation(33).WithArguments("TInterface", "Struct"), + + VerifyCS.Diagnostic(castRule).WithLocation(34).WithArguments("TInterface", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(35).WithArguments("int", "TInterface"), + VerifyCS.Diagnostic(castRule).WithLocation(36).WithArguments("TInterface", "string"), + VerifyCS.Diagnostic(castRule).WithLocation(37).WithArguments("string", "TInterface"), + + VerifyCS.Diagnostic(castRule).WithLocation(40).WithArguments("TStructInterface", "int"), + VerifyCS.Diagnostic(castRule).WithLocation(41).WithArguments("int", "TStructInterface"), + + VerifyCS.Diagnostic(castRule).WithLocation(50).WithArguments("TStruct", "string"), + VerifyCS.Diagnostic(castRule).WithLocation(51).WithArguments("string", "TStruct") +); + } + + [Fact] + public async Task NonGenericCasesVB() + { + var castRule = DoNotCallEnumerableCastOrOfTypeWithIncompatibleTypesAnalyzer.CastRule; + + await VerifyVB.VerifyAnalyzerAsync(@" +Imports System.Linq + +Interface IApple +End Interface + +Public Class Fruit +End Class + +Public Class Orange + Inherits Fruit +End Class + +Class Apple + Inherits Fruit + Implements IApple +End Class + +NotInheritable Class Salad +End Class + +Module M + Sub S + Dim a1 = (New Integer(){}).Cast(Of Object) + Dim a2 = (New Object(){}).Cast(Of String) + Dim a3 = (New Object(){}).Cast(Of Integer) + Dim a4 = {|#11:(New Integer(){}).Cast(Of String)|} + Dim a5 = {|#12:(New String(){}).Cast(Of Integer)|} + + Dim b1 = (New Object(){}).Cast(Of Fruit) + Dim b2 = (New Object(){}).Cast(Of Orange) + Dim b3 = (New Object(){}).Cast(Of IApple) + Dim b4 = (New Object(){}).Cast(Of Apple) + Dim b5 = (New Object(){}).Cast(Of Salad) + + Dim c1 = (New Fruit(){}).Cast(Of Fruit) + Dim c2 = (New Fruit(){}).Cast(Of Orange) + Dim c3 = (New Fruit(){}).Cast(Of IApple) + Dim c4 = (New Fruit(){}).Cast(Of Apple) + Dim c5 = {|#15:(New Fruit(){}).Cast(Of Salad)|} + + Dim d1 = (New Orange(){}).Cast(Of Fruit) + Dim d2 = (New Orange(){}).Cast(Of Orange) + Dim d3 = (New Orange(){}).Cast(Of IApple) ' subclass of Orange could implement IApple + Dim d4 = {|#21:(New Orange(){}).Cast(Of Apple)|} + Dim d5 = {|#22:(New Orange(){}).Cast(Of Salad)|} + + Dim e1 = (New IApple(){}).Cast(Of Fruit) + Dim e2 = (New IApple(){}).Cast(Of Orange) ' subclass of Orange could implement IApple + Dim e3 = (New IApple(){}).Cast(Of IApple) + Dim e4 = (New IApple(){}).Cast(Of Apple) + Dim e5 = {|#30:(New IApple(){}).Cast(Of Salad)|} + + Dim f1 = (New Apple(){}).Cast(Of Fruit) + Dim f2 = {|#40:(New Apple(){}).Cast(Of Orange)|} + Dim f3 = (New Apple(){}).Cast(Of IApple) + Dim f4 = (New Apple(){}).Cast(Of Apple) + Dim f5 = {|#41:(New Apple(){}).Cast(Of Salad)|} + End Sub +End Module +", + VerifyVB.Diagnostic(castRule).WithLocation(11).WithArguments("Integer", "String"), + VerifyVB.Diagnostic(castRule).WithLocation(12).WithArguments("String", "Integer"), + + VerifyVB.Diagnostic(castRule).WithLocation(15).WithArguments("Fruit", "Salad"), + + VerifyVB.Diagnostic(castRule).WithLocation(21).WithArguments("Orange", "Apple"), + VerifyVB.Diagnostic(castRule).WithLocation(22).WithArguments("Orange", "Salad"), + + VerifyVB.Diagnostic(castRule).WithLocation(30).WithArguments("IApple", "Salad"), + + VerifyVB.Diagnostic(castRule).WithLocation(40).WithArguments("Apple", "Orange"), + VerifyVB.Diagnostic(castRule).WithLocation(41).WithArguments("Apple", "Salad") + ); + } + } +} diff --git a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt index a94aba62d9..bd38659444 100644 --- a/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt +++ b/src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt @@ -18,7 +18,7 @@ Usage: CA1801, CA1806, CA1816, CA2200-CA2209, CA2211-CA2258 Naming: CA1700-CA1727 Interoperability: CA1400-CA1419 Maintainability: CA1500-CA1509 -Reliability: CA9998-CA9999, CA2000-CA2018 +Reliability: CA9998-CA9999, CA2000-CA2019 Documentation: CA1200-CA1200 # Microsoft CodeAnalysis API rules