static CodeAction HandleNegatedCase(BaseRefactoringContext ctx, IfElseStatement ifElseStatement, Match match, out IsExpression isExpression, out int foundCastCount) { foundCastCount = 0; var outerIs = match.Get <Expression>("isExpression").Single(); isExpression = CSharpUtil.GetInnerMostExpression(outerIs) as IsExpression; var obj = CSharpUtil.GetInnerMostExpression(isExpression.Expression); var castToType = isExpression.Type; var cast = new Choice { PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastTo(castToType.Clone())), PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastAs(castToType.Clone())) }; var rr = ctx.Resolve(castToType); if (rr == null || rr.IsError || rr.Type.IsReferenceType == false) { return(null); } var foundCasts = ifElseStatement.GetParent <BlockStatement>().DescendantNodes(n => n.StartLocation >= ifElseStatement.StartLocation && !cast.IsMatch(n)).Where(n => cast.IsMatch(n)).ToList(); foundCastCount = foundCasts.Count; return(new CodeAction(ctx.TranslateString("Use 'as' and check for null"), script => { var varName = ctx.GetNameProposal(CreateMethodDeclarationAction.GuessNameFromType(rr.Type), ifElseStatement.StartLocation); var varDec = new VariableDeclarationStatement(new PrimitiveType("var"), varName, new AsExpression(obj.Clone(), castToType.Clone())); var binaryOperatorIdentifier = new IdentifierExpression(varName); var binaryOperatorExpression = new BinaryOperatorExpression(binaryOperatorIdentifier, BinaryOperatorType.Equality, new NullReferenceExpression()); var linkedNodes = new List <AstNode>(); linkedNodes.Add(varDec.Variables.First().NameToken); linkedNodes.Add(binaryOperatorIdentifier); if (IsEmbeddedStatement(ifElseStatement)) { var block = new BlockStatement(); block.Add(varDec); var newIf = (IfElseStatement)ifElseStatement.Clone(); newIf.Condition = binaryOperatorExpression; foreach (var node in newIf.DescendantNodesAndSelf(n => !cast.IsMatch(n)).Where(n => cast.IsMatch(n))) { var id = new IdentifierExpression(varName); linkedNodes.Add(id); node.ReplaceWith(id); } block.Add(newIf); script.Replace(ifElseStatement, block); } else { script.InsertBefore(ifElseStatement, varDec); script.Replace(ifElseStatement.Condition, binaryOperatorExpression); foreach (var c in foundCasts) { var id = new IdentifierExpression(varName); linkedNodes.Add(id); script.Replace(c, id); } } script.Link(linkedNodes); }, isExpression.IsToken)); }
protected override CodeAction GetAction(RefactoringContext ctx, IfElseStatement ifElseStatement) { var isExpr = ctx.GetNode <IsExpression>(); if (isExpr == null || !isExpr.IsToken.Contains(ctx.Location)) { return(null); } int foundCasts; var action = ScanIfElse(ctx, ifElseStatement, out isExpr, out foundCasts); if (action != null) { return(action); } isExpr = ctx.GetNode <IsExpression>(); var node = isExpr.Parent; while (node is ParenthesizedExpression) { node = node.Parent; } var uOp = node as UnaryOperatorExpression; if (uOp != null && uOp.Operator == UnaryOperatorType.Not) { var rr = ctx.Resolve(isExpr.Type); if (rr == null || rr.IsError || rr.Type.IsReferenceType == false) { return(null); } return(new CodeAction(ctx.TranslateString("Use 'as' and check for null"), script => { var varName = ctx.GetNameProposal(CreateMethodDeclarationAction.GuessNameFromType(rr.Type), ifElseStatement.StartLocation); var varDec = new VariableDeclarationStatement(new PrimitiveType("var"), varName, new AsExpression(isExpr.Expression.Clone(), isExpr.Type.Clone())); var binaryOperatorIdentifier = new IdentifierExpression(varName); var binaryOperatorExpression = new BinaryOperatorExpression(binaryOperatorIdentifier, BinaryOperatorType.Equality, new NullReferenceExpression()); if (IsEmbeddedStatement(ifElseStatement)) { var block = new BlockStatement(); block.Add(varDec); var newIf = (IfElseStatement)ifElseStatement.Clone(); newIf.Condition = binaryOperatorExpression; block.Add(newIf); script.Replace(ifElseStatement, block); } else { script.InsertBefore(ifElseStatement, varDec); script.Replace(uOp, binaryOperatorExpression); } }, isExpr.IsToken)); } var obj = isExpr.Expression; var castToType = isExpr.Type; var cast = new Choice { PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastTo(castToType.Clone())), PatternHelper.OptionalParentheses(PatternHelper.OptionalParentheses(obj.Clone()).CastAs(castToType.Clone())) }; var rr2 = ctx.Resolve(castToType); if (rr2 == null || rr2.IsError || rr2.Type.IsReferenceType == false) { return(null); } var foundCasts2 = isExpr.GetParent <Statement>().DescendantNodesAndSelf(n => !cast.IsMatch(n)).Where(n => isExpr.StartLocation < n.StartLocation && cast.IsMatch(n)).ToList(); return(new CodeAction(ctx.TranslateString("Use 'as' and check for null"), script => { var varName = ctx.GetNameProposal(CreateMethodDeclarationAction.GuessNameFromType(rr2.Type), ifElseStatement.StartLocation); var varDec = new VariableDeclarationStatement(new PrimitiveType("var"), varName, new AsExpression(obj.Clone(), castToType.Clone())); var binaryOperatorIdentifier = new IdentifierExpression(varName); var binaryOperatorExpression = new BinaryOperatorExpression(binaryOperatorIdentifier, BinaryOperatorType.InEquality, new NullReferenceExpression()); var linkedNodes = new List <AstNode>(); linkedNodes.Add(varDec.Variables.First().NameToken); linkedNodes.Add(binaryOperatorIdentifier); if (IsEmbeddedStatement(ifElseStatement)) { var block = new BlockStatement(); block.Add(varDec); var newIf = (IfElseStatement)ifElseStatement.Clone(); newIf.Condition = binaryOperatorExpression; foreach (var node2 in newIf.DescendantNodesAndSelf(n => !cast.IsMatch(n)).Where(n => cast.IsMatch(n))) { var id = new IdentifierExpression(varName); linkedNodes.Add(id); node2.ReplaceWith(id); } block.Add(newIf); script.Replace(ifElseStatement, block); } else { script.InsertBefore(ifElseStatement, varDec); script.Replace(isExpr, binaryOperatorExpression); foreach (var c in foundCasts2) { var id = new IdentifierExpression(varName); linkedNodes.Add(id); script.Replace(c, id); } } script.Link(linkedNodes); }, isExpr.IsToken)); }