提交 5145252b 编写于 作者: M Martin Strecker 提交者: Sam Harwell

Simplify handling of type constraints.

上级 f94eaa9d
......@@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.UseIsNullCheck
internal abstract class AbstractUseIsNullCheckCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public const string Negated = nameof(Negated);
public const string UnconstraintGeneric = nameof(UnconstraintGeneric);
public const string UnconstrainedGeneric = nameof(UnconstrainedGeneric);
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseIsNullCheckDiagnosticId);
......@@ -50,7 +50,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var invocation = diagnostic.AdditionalLocations[0].FindNode(getInnermostNodeForTie: true, cancellationToken: cancellationToken);
var negate = diagnostic.Properties.ContainsKey(Negated);
var isUnconstraintGeneric = diagnostic.Properties.ContainsKey(UnconstraintGeneric);
var isUnconstraintGeneric = diagnostic.Properties.ContainsKey(UnconstrainedGeneric);
var arguments = syntaxFacts.GetArgumentsOfInvocationExpression(invocation);
var argument = syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(arguments[0]))
......
......@@ -15,14 +15,6 @@ internal abstract class AbstractUseIsNullCheckDiagnosticAnalyzer<
where TLanguageKindEnum : struct
{
private enum ConstraintParameterKind
{
NotGeneric,
UnconstraintGeneric,
ReferenceTypeConstraint,
ValueTypeConstraint,
}
protected AbstractUseIsNullCheckDiagnosticAnalyzer(LocalizableString title)
: base(IDEDiagnosticIds.UseIsNullCheckDiagnosticId,
title,
......@@ -121,13 +113,22 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol refe
var properties = ImmutableDictionary<string, string>.Empty;
switch (GetGenericParameterConstraintType(syntaxFacts, semanticModel, arguments[0], arguments[1], cancellationToken))
var genericParameterSymbol = GetGenericParameterSymbol(syntaxFacts, semanticModel, arguments[0], arguments[1], cancellationToken);
if (genericParameterSymbol != null)
{
if (genericParameterSymbol.HasValueTypeConstraint)
{
case ConstraintParameterKind.ValueTypeConstraint:
// 'is null' would generate error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
// '== null' would generate error CS0019: Operator '==' cannot be applied to operands of type 'T' and '<null>'
// 'Is Nothing' would generate error BC30020: 'Is' operator does not accept operands of type 'T'. Operands must be reference or nullable types.
return;
case ConstraintParameterKind.UnconstraintGeneric:
properties = properties.Add(AbstractUseIsNullCheckCodeFixProvider.UnconstraintGeneric, "");
break;
}
if (!genericParameterSymbol.HasReferenceTypeConstraint)
{
// Needs special casing for C#
properties = properties.Add(AbstractUseIsNullCheckCodeFixProvider.UnconstrainedGeneric, "");
}
}
var additionalLocations = ImmutableArray.Create(invocation.GetLocation());
......@@ -145,30 +146,17 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol refe
additionalLocations, properties));
}
private static ConstraintParameterKind GetGenericParameterConstraintType(ISyntaxFactsService syntaxFacts, SemanticModel semanticModel, SyntaxNode node1, SyntaxNode node2, CancellationToken cancellationToken)
private static ITypeParameterSymbol GetGenericParameterSymbol(ISyntaxFactsService syntaxFacts, SemanticModel semanticModel, SyntaxNode node1, SyntaxNode node2, CancellationToken cancellationToken)
{
var valueNode = syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node1)) ? node2 : node1;
var argumentExpression = syntaxFacts.GetExpressionOfArgument(valueNode);
if (argumentExpression != null)
{
var parameterType = semanticModel.GetTypeInfo(argumentExpression, cancellationToken).Type;
if (parameterType is ITypeParameterSymbol typeParameter)
{
if (typeParameter.HasReferenceTypeConstraint)
{
return ConstraintParameterKind.ReferenceTypeConstraint;
}
if (typeParameter.HasValueTypeConstraint)
{
return ConstraintParameterKind.ValueTypeConstraint;
}
return ConstraintParameterKind.UnconstraintGeneric;
}
return parameterType as ITypeParameterSymbol;
}
return ConstraintParameterKind.NotGeneric;
return default;
}
private static bool MatchesPattern(ISyntaxFactsService syntaxFacts, SyntaxNode node1, SyntaxNode node2)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册