/// <summary> /// This strategy uses the names and needs the whole array of base types, not just one type in the base list. /// </summary> /// <param name="baseTypeInfo"></param> private List <BaseTypeReference> DiscriminateByName(IEnumerable <BaseTypeSyntax> simpleBaseTypes) { var baseTypes = new List <BaseTypeReference>(); IEnumerable <SemanticUtilities.BaseTypeInfo> baseTypeInfos = SemanticUtilities.SeparateClassAndInterfacesBasedOnNames(simpleBaseTypes); foreach (var baseTypeInfo in baseTypeInfos) { // Semantic model passed for consistency, but here is actually null switch (baseTypeInfo.Kind) { case Roslyn.TypeKind.Class: baseTypes.Add(this.CreateBaseTypeReferenceHelper(baseTypeInfo.Node, this.SemanticModel, Roslyn.TypeKind.Class)); break; case Roslyn.TypeKind.Interface: baseTypes.Add(this.CreateBaseTypeReferenceHelper(baseTypeInfo.Node, this.SemanticModel, Roslyn.TypeKind.Interface)); break; default: // Not recognized, skip it continue; } } return(baseTypes); }
private static IfRefactoring CreateIfToAssignmentWithWithCoalesceExpression( IfStatementSyntax ifStatement, ExpressionSyntax left, ExpressionSyntax expression1, ExpressionSyntax expression2, NullCheckExpression nullCheck, SemanticModel semanticModel, CancellationToken cancellationToken) { if (nullCheck.Kind == NullCheckKind.EqualsToNull || nullCheck.Kind == NullCheckKind.NotEqualsToNull) { if (IsEquivalent(nullCheck.Expression, expression1)) { return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2)); } } if (expression1.IsKind(SyntaxKind.SimpleMemberAccessExpression) && SemanticUtilities.IsPropertyOfNullableOfT(expression1, "Value", semanticModel, cancellationToken)) { expression1 = ((MemberAccessExpressionSyntax)expression1).Expression; if (IsEquivalent(nullCheck.Expression, expression1)) { return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2)); } } return(null); }
private static IfRefactoring CreateIfToReturnWithCoalesceExpression( IfStatementSyntax ifStatement, ExpressionSyntax expression1, ExpressionSyntax expression2, NullCheckExpression nullCheck, bool isYield, SemanticModel semanticModel, CancellationToken cancellationToken) { if (nullCheck.Kind == NullCheckKind.EqualsToNull || nullCheck.Kind == NullCheckKind.NotEqualsToNull) { if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true)) { return(IfToReturnWithCoalesceExpression.Create(ifStatement, expression1, expression2, isYield)); } } if (expression1.IsKind(SyntaxKind.SimpleMemberAccessExpression) && SemanticUtilities.IsPropertyOfNullableOfT(expression1, "Value", semanticModel, cancellationToken)) { expression1 = ((MemberAccessExpressionSyntax)expression1).Expression; if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true)) { return(IfToReturnWithCoalesceExpression.Create(ifStatement, expression1, expression2, isYield)); } } return(null); }
public static async Task <Document> RefactorAsync( Document document, ConditionalExpressionSyntax conditionalExpressionSyntax, CancellationToken cancellationToken) { ConditionalExpressionInfo conditionalExpression; if (ConditionalExpressionInfo.TryCreate(conditionalExpressionSyntax, out conditionalExpression)) { SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false); NullCheckExpression nullCheck; if (NullCheckExpression.TryCreate(conditionalExpression.Condition, semanticModel, out nullCheck, cancellationToken)) { ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpression.WhenTrue : conditionalExpression.WhenFalse; ExpressionSyntax whenNull = (nullCheck.IsCheckingNull) ? conditionalExpression.WhenTrue : conditionalExpression.WhenFalse; ExpressionSyntax expression = FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull); ExpressionSyntax newNode; if (expression.Parent == whenNotNull && whenNotNull.IsKind(SyntaxKind.SimpleMemberAccessExpression) && SemanticUtilities.IsPropertyOfNullableOfT(whenNotNull, "Value", semanticModel, cancellationToken)) { newNode = expression; } else { newNode = SyntaxFactory.ParseExpression(whenNotNull.ToString().Insert(expression.Span.End - whenNotNull.SpanStart, "?")); } if (!semanticModel.GetTypeSymbol(whenNotNull, cancellationToken).IsReferenceType) { newNode = CSharpFactory.CoalesceExpression(newNode.Parenthesize(), whenNull.Parenthesize()); } newNode = newNode .WithTriviaFrom(conditionalExpressionSyntax) .Parenthesize(); return(await document.ReplaceNodeAsync(conditionalExpressionSyntax, newNode, cancellationToken).ConfigureAwait(false)); } } Debug.Fail(conditionalExpressionSyntax.ToString()); return(document); }
private static bool IsPropertyOfNullableOfT(ExpressionSyntax expression, string name, SemanticModel semanticModel, CancellationToken cancellationToken) { if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true) { var memberAccessExpression = (MemberAccessExpressionSyntax)expression; SimpleNameSyntax simpleName = memberAccessExpression.Name; if (simpleName?.IsKind(SyntaxKind.IdentifierName) == true) { var identifierName = (IdentifierNameSyntax)simpleName; return(string.Equals(identifierName.Identifier.ValueText, name, StringComparison.Ordinal) && SemanticUtilities.IsPropertyOfNullableOfT(expression, name, semanticModel, cancellationToken)); } } return(false); }
public static bool TryCreate( SyntaxNode node, SemanticModel semanticModel, out NullCheckExpression result, CancellationToken cancellationToken = default(CancellationToken)) { if (node != null) { var expression = node as ExpressionSyntax; if (expression != null) { expression = expression.WalkDownParentheses(); SyntaxKind kind = expression.Kind(); switch (kind) { case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: { var binaryExpression = (BinaryExpressionSyntax)expression; ExpressionSyntax left = binaryExpression.Left?.WalkDownParentheses(); ExpressionSyntax right = binaryExpression.Right?.WalkDownParentheses(); return(TryCreate(binaryExpression, kind, left, right, semanticModel, cancellationToken, out result) || TryCreate(binaryExpression, kind, right, left, semanticModel, cancellationToken, out result)); } case SyntaxKind.SimpleMemberAccessExpression: { if (SemanticUtilities.IsPropertyOfNullableOfT(expression, "HasValue", semanticModel, cancellationToken)) { var memberAccessExpression = (MemberAccessExpressionSyntax)expression; result = new NullCheckExpression(expression, memberAccessExpression.Expression, NullCheckKind.HasValue); return(true); } break; } case SyntaxKind.LogicalNotExpression: { var logicalNotExpression = (PrefixUnaryExpressionSyntax)expression; ExpressionSyntax operand = logicalNotExpression.Operand?.WalkDownParentheses(); if (operand?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true && SemanticUtilities.IsPropertyOfNullableOfT(operand, "HasValue", semanticModel, cancellationToken)) { var memberAccessExpression = (MemberAccessExpressionSyntax)operand; result = new NullCheckExpression(expression, memberAccessExpression.Expression, NullCheckKind.NotHasValue); return(true); } break; } } } } result = default(NullCheckExpression); return(false); }
private static bool TryCreate( BinaryExpressionSyntax binaryExpression, SyntaxKind kind, ExpressionSyntax expression1, ExpressionSyntax expression2, SemanticModel semanticModel, CancellationToken cancellationToken, out NullCheckExpression result) { if (expression1 != null && expression2 != null) { switch (expression1.Kind()) { case SyntaxKind.NullLiteralExpression: { result = new NullCheckExpression( binaryExpression, expression2, (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.EqualsToNull : NullCheckKind.NotEqualsToNull); return(true); } case SyntaxKind.TrueLiteralExpression: { if (expression2?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true && SemanticUtilities.IsPropertyOfNullableOfT(expression2, "HasValue", semanticModel, cancellationToken)) { result = new NullCheckExpression( binaryExpression, ((MemberAccessExpressionSyntax)expression2).Expression, (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.HasValue : NullCheckKind.NotHasValue); return(true); } break; } case SyntaxKind.FalseLiteralExpression: { if (expression2?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true && SemanticUtilities.IsPropertyOfNullableOfT(expression2, "HasValue", semanticModel, cancellationToken)) { result = new NullCheckExpression( binaryExpression, ((MemberAccessExpressionSyntax)expression2).Expression, (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.NotHasValue : NullCheckKind.HasValue); return(true); } break; } } } result = default(NullCheckExpression); return(false); }