public IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var identifier = CreateFieldAction.GetCreatePropertyOrFieldNode(context);

            if (identifier == null)
            {
                yield break;
            }
            if (CreateFieldAction.IsInvocationTarget(identifier))
            {
                yield break;
            }

            var propertyName = GetPropertyName(identifier);

            if (propertyName == null)
            {
                yield break;
            }

            var statement = context.GetNode <Statement>();

            if (statement == null)
            {
                yield break;
            }

            if (!(context.Resolve(identifier).IsError))
            {
                yield break;
            }

            var guessedType = CreateFieldAction.GuessAstType(context, identifier);

            if (guessedType == null)
            {
                yield break;
            }
            var state = context.GetResolverStateBefore(identifier);

            if (state.CurrentTypeDefinition == null)
            {
                yield break;
            }

            bool          createInOtherType   = false;
            ResolveResult targetResolveResult = null;

            if (identifier is MemberReferenceExpression)
            {
                targetResolveResult = context.Resolve(((MemberReferenceExpression)identifier).Target);
                if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
                {
                    yield break;
                }
                createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
            }

            bool isStatic = targetResolveResult is TypeResolveResult;

            if (createInOtherType)
            {
                if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
                {
                    yield break;
                }
            }
            else
            {
                if (state.CurrentMember == null)
                {
                    yield break;
                }
                isStatic |= state.CurrentTypeDefinition.IsStatic;
                if (targetResolveResult == null)
                {
                    isStatic |= state.CurrentMember.IsStatic;
                }
            }
            isStatic &= !(identifier is NamedExpression);

            //			var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
//			if (service != null && !service.IsValidName(propertyName, AffectedEntity.Property, Modifiers.Private, isStatic)) {
//				yield break;
//			}

            yield return(new CodeAction(context.TranslateString("Create property"), script => {
                var decl = new PropertyDeclaration()
                {
                    ReturnType = guessedType,
                    Name = propertyName,
                    Getter = new Accessor(),
                    Setter = new Accessor()
                };
                if (isStatic)
                {
                    decl.Modifiers |= Modifiers.Static;
                }

                if (createInOtherType)
                {
                    if (targetResolveResult.Type.Kind == TypeKind.Interface)
                    {
                        decl.Modifiers = Modifiers.None;
                    }
                    else
                    {
                        decl.Modifiers |= Modifiers.Public;
                    }
                    script.InsertWithCursor(
                        context.TranslateString("Create property"),
                        targetResolveResult.Type.GetDefinition(),
                        decl);

                    return;
                }

                script.InsertWithCursor(context.TranslateString("Create property"), Script.InsertPosition.Before, decl);
            }));
        }
        public IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var expr = context.GetNode(n => n is IdentifierExpression || n is MemberReferenceExpression) as Expression;

            if (expr == null)
            {
                yield break;
            }

            if (expr is MemberReferenceExpression && !(((MemberReferenceExpression)expr).Target is ThisReferenceExpression))
            {
                yield break;
            }

            var propertyName = CreatePropertyAction.GetPropertyName(expr);

            if (propertyName == null)
            {
                yield break;
            }

            if (IsInvocationTarget(expr))
            {
                yield break;
            }
            var statement = expr.GetParent <Statement>();

            if (statement == null)
            {
                yield break;
            }
            if (!(context.Resolve(expr).IsError))
            {
                yield break;
            }
            var guessedType = CreateFieldAction.GuessAstType(context, expr);

            if (guessedType == null)
            {
                yield break;
            }
            var state = context.GetResolverStateBefore(expr);

            if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
            {
                yield break;
            }

            bool isStatic = state.CurrentMember.IsStatic | state.CurrentTypeDefinition.IsStatic;

//			var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
//			if (service != null && !service.IsValidName(identifier.Identifier, AffectedEntity.Field, Modifiers.Private, isStatic)) {
//				yield break;
//			}

            yield return(new CodeAction(context.TranslateString("Create field"), script =>
            {
                var decl = new FieldDeclaration()
                {
                    ReturnType = guessedType,
                    Variables = { new VariableInitializer(propertyName) }
                };
                if (isStatic)
                {
                    decl.Modifiers |= Modifiers.Static;
                }
                script.InsertWithCursor(context.TranslateString("Create field"), Script.InsertPosition.Before, decl);
            }));
        }
        public override IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            //TODO: implement variable assignment & ctor param
            var varInit = context.GetNode <VariableInitializer>();

            if (varInit != null)
            {
                var selectedNode = varInit.GetNodeAt(context.Location);
                if (selectedNode != varInit.NameToken)
                {
                    yield break;
                }

                AstType type = varInit.GetPrevNode() as AstType;
                if (type == null)
                {
                    yield break;
                }
                if (varInit.Parent is FieldDeclaration)
                {
                    yield break;
                }
                if (CannotExtractField(context, varInit))
                {
                    yield break;
                }

                yield return(new CodeAction(context.TranslateString("Assign to new field"), s => {
                    var name = varInit.Name;

                    AstType extractedType;
                    if (type.IsVar())
                    {
                        IType resolvedType = context.Resolve(varInit.Initializer).Type;
                        extractedType = context.CreateShortType(resolvedType);
                    }
                    else
                    {
                        extractedType = (AstType)type.Clone();
                    }

                    AstNode entityDeclarationNode = varInit.Parent;
                    while (!(entityDeclarationNode is EntityDeclaration) || (entityDeclarationNode is Accessor))
                    {
                        entityDeclarationNode = entityDeclarationNode.Parent;
                    }
                    var entity = (EntityDeclaration)entityDeclarationNode;
                    bool isStatic = entity.HasModifier(Modifiers.Static);

                    FieldDeclaration field = new FieldDeclaration()
                    {
                        Modifiers = isStatic ? Modifiers.Static : Modifiers.None,
                        ReturnType = extractedType,
                        Variables = { new VariableInitializer(null, name) }
                    };
                    AstNode nodeToRemove = RemoveDeclaration(varInit) ? varInit.Parent : type;
                    s.Remove(nodeToRemove, true);
                    s.InsertWithCursor(context.TranslateString("Insert new field"), Script.InsertPosition.Before, field);
                    s.FormatText(varInit.Parent);
                }, selectedNode));
            }

            var idntf = context.GetNode <Identifier>();

            if (idntf == null)
            {
                yield break;
            }
            var paramDec = idntf.Parent as ParameterDeclaration;

            if (paramDec != null)
            {
                var ctor = paramDec.Parent as ConstructorDeclaration;
                if (ctor == null)
                {
                    yield break;
                }
                MemberReferenceExpression thisField = new MemberReferenceExpression(new ThisReferenceExpression(), idntf.Name, new AstType[] {});
                var assign             = new AssignmentExpression(thisField, AssignmentOperatorType.Assign, new IdentifierExpression(idntf.Name));
                var statement          = new ExpressionStatement(assign);
                var type               = (idntf.GetPrevNode() as AstType).Clone();
                FieldDeclaration field = new FieldDeclaration()
                {
                    ReturnType = type.Clone(),
                    Variables  = { new VariableInitializer(null, idntf.Name) }
                };
                yield return(new CodeAction(context.TranslateString("Assign to new field"), s => {
                    s.InsertWithCursor(context.TranslateString("Insert new field"), Script.InsertPosition.Before, field);
                    s.AddTo(ctor.Body, statement);
                }, paramDec.NameToken));
            }
        }
        protected override CodeAction GetAction(RefactoringContext context, VariableInitializer node)
        {
            if (node.Initializer.IsNull)
            {
                return(null);
            }

            var variableDecl = node.Parent as VariableDeclarationStatement;

            if (variableDecl == null || !(variableDecl.Parent is BlockStatement))
            {
                return(null);
            }

            var type = context.ResolveType(variableDecl.Type);

            if (!IsIDisposable(type))
            {
                return(null);
            }

            var unit = context.RootNode as SyntaxTree;

            if (unit == null)
            {
                return(null);
            }

            var resolveResult = (LocalResolveResult)context.Resolve(node);

            return(new CodeAction(context.TranslateString("put inside 'using'"),
                                  script =>
            {
                var lastReference = GetLastReference(resolveResult.Variable, context, unit);

                var body = new BlockStatement();
                var variableToMoveOutside = new List <VariableDeclarationStatement> ();

                if (lastReference != node)
                {
                    var statements = CollectStatements(variableDecl.NextSibling as Statement,
                                                       lastReference.EndLocation).ToArray();

                    // collect statements to put inside 'using' and variable declaration to move outside 'using'
                    foreach (var statement in statements)
                    {
                        script.Remove(statement);

                        var decl = statement as VariableDeclarationStatement;
                        if (decl == null)
                        {
                            body.Statements.Add(statement.Clone());
                            continue;
                        }

                        var outsideDecl = (VariableDeclarationStatement)decl.Clone();
                        outsideDecl.Variables.Clear();
                        var insideDecl = (VariableDeclarationStatement)outsideDecl.Clone();

                        foreach (var variable in decl.Variables)
                        {
                            var reference = GetLastReference(
                                ((LocalResolveResult)context.Resolve(variable)).Variable, context, unit);
                            if (reference.StartLocation > lastReference.EndLocation)
                            {
                                outsideDecl.Variables.Add((VariableInitializer)variable.Clone());
                            }
                            else
                            {
                                insideDecl.Variables.Add((VariableInitializer)variable.Clone());
                            }
                        }
                        if (outsideDecl.Variables.Count > 0)
                        {
                            variableToMoveOutside.Add(outsideDecl);
                        }
                        if (insideDecl.Variables.Count > 0)
                        {
                            body.Statements.Add(insideDecl);
                        }
                    }
                }

                foreach (var decl in variableToMoveOutside)
                {
                    script.InsertBefore(variableDecl, decl);
                }

                var usingStatement = new UsingStatement
                {
                    ResourceAcquisition = new VariableDeclarationStatement(variableDecl.Type.Clone(), node.Name,
                                                                           node.Initializer.Clone()),
                    EmbeddedStatement = body
                };
                script.Replace(variableDecl, usingStatement);

                if (variableDecl.Variables.Count == 1)
                {
                    return;
                }
                // other variables in the same declaration statement
                var remainingVariables = (VariableDeclarationStatement)variableDecl.Clone();
                remainingVariables.Variables.Remove(
                    remainingVariables.Variables.FirstOrDefault(v => v.Name == node.Name));
                script.InsertBefore(usingStatement, remainingVariables);
            }));
        }
        public void Run(RefactoringContext context)
        {
            VariableInitializer initializer;
            var eventDeclaration = GetEventDeclaration(context, out initializer);
            var type             = context.Resolve(eventDeclaration.ReturnType).Type;

            if (type == null)
            {
                return;
            }
            var invokeMethod = type.GetDelegateInvokeMethod();

            if (invokeMethod == null)
            {
                return;
            }

            bool hasSenderParam           = false;
            IEnumerable <IParameter> pars = invokeMethod.Parameters;

            if (invokeMethod.Parameters.Any())
            {
                var first = invokeMethod.Parameters [0];
                if (first.Name == "sender" /*&& first.Type == "System.Object"*/)
                {
                    hasSenderParam = true;
                    pars           = invokeMethod.Parameters.Skip(1);
                }
            }
            const string handlerName = "handler";

            var arguments = new List <Expression> ();

            if (hasSenderParam)
            {
                arguments.Add(new ThisReferenceExpression());
            }
            foreach (var par in pars)
            {
                arguments.Add(new IdentifierExpression(par.Name));
            }

            var methodDeclaration = new MethodDeclaration()
            {
                Name       = "On" + initializer.Name,
                ReturnType = new PrimitiveType("void"),
                Modifiers  = ICSharpCode.NRefactory.CSharp.Modifiers.Protected | ICSharpCode.NRefactory.CSharp.Modifiers.Virtual,
                Body       = new BlockStatement()
                {
                    new VariableDeclarationStatement(context.CreateShortType(eventDeclaration.ReturnType), handlerName, new MemberReferenceExpression(new ThisReferenceExpression(), initializer.Name)),
                    new IfElseStatement()
                    {
                        Condition     = new BinaryOperatorExpression(new IdentifierExpression(handlerName), BinaryOperatorType.InEquality, new PrimitiveExpression(null)),
                        TrueStatement = new ExpressionStatement(new InvocationExpression(new IdentifierExpression(handlerName), arguments))
                    }
                }
            };

            foreach (var par in pars)
            {
                var typeName = context.CreateShortType(par.Type);
                var decl     = new ParameterDeclaration(typeName, par.Name);
                methodDeclaration.Parameters.Add(decl);
            }

            using (var script = context.StartScript()) {
                script.InsertWithCursor("Create event invocator", methodDeclaration, Script.InsertPosition.After);
            }
        }
        static bool CannotExtractField(RefactoringContext context, VariableInitializer varInit)
        {
            var result = varInit.Parent as VariableDeclarationStatement;

            return(result == null || result.Variables.Count != 1 || ContainsAnonymousType(context.Resolve(varInit.Initializer).Type));
        }
Example #7
0
        public IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var indexer = context.GetNode <IndexerExpression>();

            if (indexer == null)
            {
                yield break;
            }
            if (!(context.Resolve(indexer).IsError))
            {
                yield break;
            }

            var state = context.GetResolverStateBefore(indexer);

            if (state.CurrentTypeDefinition == null)
            {
                yield break;
            }
            var guessedType = CreateFieldAction.GuessAstType(context, indexer);

            bool          createInOtherType   = false;
            ResolveResult targetResolveResult = null;

            targetResolveResult = context.Resolve(indexer.Target);
            createInOtherType   = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());

            bool isStatic;

            if (createInOtherType)
            {
                if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
                {
                    yield break;
                }
                isStatic = targetResolveResult is TypeResolveResult;
                if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
                {
                    yield break;
                }
            }
            else
            {
                isStatic = indexer.Target is IdentifierExpression && state.CurrentMember.IsStatic;
            }

            yield return(new CodeAction(context.TranslateString("Create indexer"), script => {
                var decl = new IndexerDeclaration()
                {
                    ReturnType = guessedType,
                    Getter = new Accessor()
                    {
                        Body = new BlockStatement()
                        {
                            new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
                        }
                    },
                    Setter = new Accessor()
                    {
                        Body = new BlockStatement()
                        {
                            new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
                        }
                    },
                };
                decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, indexer.Arguments));
                if (isStatic)
                {
                    decl.Modifiers |= Modifiers.Static;
                }

                if (createInOtherType)
                {
                    if (targetResolveResult.Type.Kind == TypeKind.Interface)
                    {
                        decl.Getter.Body = null;
                        decl.Setter.Body = null;
                        decl.Modifiers = Modifiers.None;
                    }
                    else
                    {
                        decl.Modifiers |= Modifiers.Public;
                    }

                    script.InsertWithCursor(context.TranslateString("Create indexer"), targetResolveResult.Type.GetDefinition(), decl);
                    return;
                }

                script.InsertWithCursor(context.TranslateString("Create indexer"), Script.InsertPosition.Before, decl);
            }));
        }
Example #8
0
        public override IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var invocationExpression = context.GetNode <InvocationExpression>();

            if (invocationExpression == null)
            {
                yield break;
            }

            var resolveResult = context.Resolve(invocationExpression) as CSharpInvocationResolveResult;

            if (resolveResult == null)
            {
                yield break;
            }

            var method = (IMethod)resolveResult.Member;

            bool[] parameterIsSpecified   = new bool[method.Parameters.Count];
            var    argumentToParameterMap = resolveResult.GetArgumentToParameterMap();

            if (argumentToParameterMap != null)
            {
                foreach (int paramIndex in argumentToParameterMap)
                {
                    parameterIsSpecified[paramIndex] = true;
                }
            }
            else
            {
                for (int i = 0; i < Math.Min(resolveResult.Arguments.Count, parameterIsSpecified.Length); i++)
                {
                    parameterIsSpecified[i] = true;
                }
            }
            var missingParameters = new List <IParameter>();

            for (int i = 0; i < method.Parameters.Count; i++)
            {
                if (!parameterIsSpecified[i] && method.Parameters[i].IsOptional)
                {
                    missingParameters.Add(method.Parameters[i]);
                }
            }

            foreach (var parameterToAdd in missingParameters)
            {
                //Add specific parameter
                yield return(new CodeAction(string.Format(context.TranslateString("Add optional parameter \"{0}\""),
                                                          parameterToAdd.Name),
                                            script => {
                    var newInvocation = (InvocationExpression)invocationExpression.Clone();
                    AddArgument(newInvocation, parameterToAdd, parameterToAdd == missingParameters.First());
                    script.Replace(invocationExpression, newInvocation);
                }, invocationExpression));
            }

            if (missingParameters.Count > 1)
            {
                //Add all parameters at once
                yield return(new CodeAction(context.TranslateString("Add all optional parameters"),
                                            script => {
                    var newInvocation = (InvocationExpression)invocationExpression.Clone();

                    foreach (var parameterToAdd in missingParameters)
                    {
                        //We'll add the remaining parameters, in the order they were declared in the function
                        AddArgument(newInvocation, parameterToAdd, true);
                    }
                    script.Replace(invocationExpression, newInvocation);
                }, invocationExpression));
            }
        }
Example #9
0
        public IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            if (!context.IsSomethingSelected)
            {
                yield break;
            }
            var selected = new List <AstNode>(context.GetSelectedNodes());

            if (selected.Count != 1 || !(selected [0] is Expression))
            {
                yield break;
            }
            var expr    = selected [0] as Expression;
            var visitor = new SearchNodeVisitior(expr);

            var node = context.GetNode <BlockStatement>();

            if (node != null)
            {
                node.AcceptVisitor(visitor);
            }

            yield return(new CodeAction(context.TranslateString("Declare local variable"), script =>
            {
                var resolveResult = context.Resolve(expr);
                var guessedType = resolveResult.Type;
                if (resolveResult is MethodGroupResolveResult)
                {
                    guessedType = GetDelegateType(context, ((MethodGroupResolveResult)resolveResult).Methods.First(), expr);
                }
                var name = CreateMethodDeclarationAction.CreateBaseName(expr, guessedType);
                var type = context.UseExplicitTypes ? context.CreateShortType(guessedType) : new SimpleType("var");
                var varDecl = new VariableDeclarationStatement(type, name, expr.Clone());
                if (expr.Parent is ExpressionStatement)
                {
                    script.Replace(expr.Parent, varDecl);
                    script.Select(varDecl.Variables.First().NameToken);
                }
                else
                {
                    var containing = expr.Parent;
                    while (!(containing.Parent is BlockStatement))
                    {
                        containing = containing.Parent;
                    }

                    script.InsertBefore(containing, varDecl);
                    var identifierExpression = new IdentifierExpression(name);
                    script.Replace(expr, identifierExpression);
                    script.Link(varDecl.Variables.First().NameToken, identifierExpression);
                }
            }));

            if (visitor.Matches.Count > 1)
            {
                yield return(new CodeAction(string.Format(context.TranslateString("Declare local variable (replace '{0}' occurrences)"), visitor.Matches.Count), script =>
                {
                    var resolveResult = context.Resolve(expr);
                    var guessedType = resolveResult.Type;
                    if (resolveResult is MethodGroupResolveResult)
                    {
                        guessedType = GetDelegateType(context, ((MethodGroupResolveResult)resolveResult).Methods.First(), expr);
                    }
                    var linkedNodes = new List <AstNode>();
                    var name = CreateMethodDeclarationAction.CreateBaseName(expr, guessedType);
                    var type = context.UseExplicitTypes ? context.CreateShortType(guessedType) : new SimpleType("var");
                    var varDecl = new VariableDeclarationStatement(type, name, expr.Clone());
                    linkedNodes.Add(varDecl.Variables.First().NameToken);
                    var first = visitor.Matches [0];
                    if (first.Parent is ExpressionStatement)
                    {
                        script.Replace(first.Parent, varDecl);
                    }
                    else
                    {
                        var containing = first.Parent;
                        while (!(containing.Parent is BlockStatement))
                        {
                            containing = containing.Parent;
                        }

                        script.InsertBefore(containing, varDecl);
                        var identifierExpression = new IdentifierExpression(name);
                        linkedNodes.Add(identifierExpression);
                        script.Replace(first, identifierExpression);
                    }
                    for (int i = 1; i < visitor.Matches.Count; i++)
                    {
                        var identifierExpression = new IdentifierExpression(name);
                        linkedNodes.Add(identifierExpression);
                        script.Replace(visitor.Matches [i], identifierExpression);
                    }
                    script.Link(linkedNodes.ToArray());
                }));
            }
        }
        void Initialize(AstNode targetNode)
        {
            var target = context.Resolve(targetNode);

            if (target is LocalResolveResult)
            {
                mainInitializerPath = new InitializerPath(((LocalResolveResult)target).Variable);
            }
            else if (target is MemberResolveResult)
            {
                mainInitializerPath = new InitializerPath(((MemberResolveResult)target).Member);
            }
            else
            {
                throw new ArgumentException("variableInitializer must target a variable or a member.");
            }
        }
Example #11
0
        void Initialize(AstNode targetNode)
        {
            var target = context.Resolve(targetNode);
            var targetInitializerPath = AccessPath.FromResolveResult(target);

            if (targetInitializerPath == null)
            {
                throw new ArgumentException(string.Format("Could not create the main initializer path from resolve result ({0})", target));
            }

            mainAccessPath = targetInitializerPath;
        }
Example #12
0
        bool Initialize(AstNode targetNode)
        {
            var target = context.Resolve(targetNode);
            var targetInitializerPath = AccessPath.FromResolveResult(target);

            if (targetInitializerPath == null)
            {
                return(false);
            }

            mainAccessPath = targetInitializerPath;
            return(true);
        }
        public override IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var switchStatement = context.GetNode <SwitchStatement> ();

            if (switchStatement == null || !switchStatement.SwitchToken.Contains(context.Location))
            {
                yield break;
            }
            var result = context.Resolve(switchStatement.Expression);

            if (result.Type.Kind != TypeKind.Enum)
            {
                yield break;
            }

            if (switchStatement.SwitchSections.Count == 0)
            {
                yield return(new CodeAction(context.TranslateString("Create switch labels"), script => {
                    var type = result.Type;
                    var newSwitch = (SwitchStatement)switchStatement.Clone();

                    var target = context.CreateShortType(result.Type);
                    foreach (var field in type.GetFields())
                    {
                        if (field.IsSynthetic || !field.IsConst)
                        {
                            continue;
                        }
                        newSwitch.SwitchSections.Add(new SwitchSection()
                        {
                            CaseLabels =
                            {
                                new CaseLabel(target.Clone().Member(field.Name))
                            },
                            Statements =
                            {
                                new BreakStatement()
                            }
                        });
                    }

                    newSwitch.SwitchSections.Add(new SwitchSection()
                    {
                        CaseLabels =
                        {
                            new CaseLabel()
                        },
                        Statements =
                        {
                            new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "ArgumentOutOfRangeException")))
                        }
                    });

                    script.Replace(switchStatement, newSwitch);
                }, switchStatement));
            }
            else
            {
                var missingFields = new List <IField>();
                foreach (var field in result.Type.GetFields())
                {
                    if (field.IsSynthetic || !field.IsConst)
                    {
                        continue;
                    }
                    if (!IsHandled(context, switchStatement, field))
                    {
                        missingFields.Add(field);
                    }
                }
                if (missingFields.Count == 0)
                {
                    yield break;
                }
                yield return(new CodeAction(context.TranslateString("Create missing switch labels"), script => {
                    var type = result.Type;
                    //var newSwitch = (SwitchStatement)switchStatement.Clone();
                    var insertNode = (AstNode)switchStatement.SwitchSections.LastOrDefault(s => !s.CaseLabels.Any(label => label.Expression.IsNull)) ?? switchStatement.LBraceToken;

                    var target = context.CreateShortType(result.Type);
                    foreach (var field in missingFields)
                    {
                        script.InsertAfter(insertNode, new SwitchSection()
                        {
                            CaseLabels =
                            {
                                new CaseLabel(target.Clone().Member(field.Name))
                            },
                            Statements =
                            {
                                new BreakStatement()
                            }
                        });
                    }
                }, switchStatement));
            }
        }
        public override IEnumerable <CodeAction> GetActions(RefactoringContext context)
        {
            var invocationExpression = context.GetNode <InvocationExpression>();

            if (invocationExpression == null)
            {
                yield break;
            }

            var resolveResult = context.Resolve(invocationExpression) as InvocationResolveResult;

            if (resolveResult == null)
            {
                yield break;
            }

            var method = (IMethod)resolveResult.Member;

            bool foundOptionalParameter = false;

            foreach (var parameter in method.Parameters)
            {
                if (parameter.IsParams)
                {
                    yield break;
                }

                if (parameter.IsOptional)
                {
                    foundOptionalParameter = true;
                    break;
                }
            }

            if (!foundOptionalParameter)
            {
                yield break;
            }

            //Basic sanity checks done, now see if there are any missing optional arguments
            var missingParameters = new List <IParameter>(method.Parameters);

            if (resolveResult.Arguments.Count != invocationExpression.Arguments.Count)
            {
                //Extension method
                missingParameters.RemoveAt(0);
            }
            foreach (var argument in invocationExpression.Arguments)
            {
                var namedArgument = argument as NamedArgumentExpression;
                if (namedArgument == null)
                {
                    missingParameters.RemoveAt(0);
                }
                else
                {
                    missingParameters.RemoveAll(parameter => parameter.Name == namedArgument.Name);
                }
            }

            foreach (var parameterToAdd in missingParameters)
            {
                //Add specific parameter
                yield return(new CodeAction(string.Format(context.TranslateString("Add optional parameter \"{0}\""),
                                                          parameterToAdd.Name),
                                            script => {
                    var newInvocation = (InvocationExpression)invocationExpression.Clone();
                    AddArgument(newInvocation, parameterToAdd, parameterToAdd == missingParameters.First());
                    script.Replace(invocationExpression, newInvocation);
                }, invocationExpression));
            }

            if (missingParameters.Count > 1)
            {
                //Add all parameters at once
                yield return(new CodeAction(context.TranslateString("Add all optional parameters"),
                                            script => {
                    var newInvocation = (InvocationExpression)invocationExpression.Clone();

                    foreach (var parameterToAdd in missingParameters)
                    {
                        //We'll add the remaining parameters, in the order they were declared in the function
                        AddArgument(newInvocation, parameterToAdd, true);
                    }
                    script.Replace(invocationExpression, newInvocation);
                }, invocationExpression));
            }
        }
        protected override CodeAction GetAction(RefactoringContext context, Expression expression)
        {
            if (expression == null)
            {
                return(null);
            }
            if (expression.Role != Roles.Argument || expression is NamedArgumentExpression)
            {
                return(null);
            }
            if (context.Location != expression.StartLocation)
            {
                return(null);
            }
            var parent = expression.Parent;

            if (!(parent is CSharp.Attribute) && !(parent is IndexerExpression) && !(parent is InvocationExpression))
            {
                return(null);
            }

            var attribute = parent as CSharp.Attribute;

            if (attribute != null)
            {
                var resolvedResult = context.Resolve(attribute) as CSharpInvocationResolveResult;
                if (resolvedResult == null || resolvedResult.IsError)
                {
                    return(null);
                }
                var     arguments = attribute.Arguments;
                IMember member    = resolvedResult.Member;

                int index = 0;
                int temp  = 0;
                List <Expression> nodes = new List <Expression>();
                foreach (var argument in arguments)
                {
                    if (argument.Equals(expression))
                    {
                        nodes = CollectNodes(parent, expression);
                        break;
                    }
                    temp++;
                }
                index = temp;
                if (!nodes.Any())
                {
                    return(null);
                }
                var method = member as IMethod;
                if (method == null || method.Parameters.Count == 0 || method.Parameters.Last().IsParams)
                {
                    return(null);
                }

                var parameterMap = resolvedResult.GetArgumentToParameterMap();
                var parameters   = method.Parameters;
                if (index >= parameterMap.Count)
                {
                    return(null);
                }
                var name = parameters[parameterMap[index]].Name;
                return(new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        int p = index + i;
                        if (p >= parameterMap.Count)
                        {
                            break;
                        }
                        name = parameters[parameterMap[p]].Name;
                        var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
                        script.Replace(arguments.ElementAt(p), namedArgument);
                    }
                },
                                      expression
                                      ));
            }

            var indexerExpression = parent as IndexerExpression;

            if (indexerExpression != null)
            {
                var resolvedResult = context.Resolve(indexerExpression) as CSharpInvocationResolveResult;
                if (resolvedResult == null || resolvedResult.IsError)
                {
                    return(null);
                }
                var     arguments = indexerExpression.Arguments;
                IMember member    = resolvedResult.Member;

                int index = 0;
                int temp  = 0;
                List <Expression> nodes = new List <Expression>();
                foreach (var argument in arguments)
                {
                    if (argument.Equals(expression))
                    {
                        nodes = CollectNodes(parent, expression);
                        break;
                    }
                    temp++;
                }
                index = temp;
                if (!nodes.Any())
                {
                    return(null);
                }
                var property = member as IProperty;
                if (property == null || property.Parameters.Count == 0 || property.Parameters.Last().IsParams)
                {
                    return(null);
                }
                var parameterMap = resolvedResult.GetArgumentToParameterMap();
                var parameters   = property.Parameters;
                if (index >= parameterMap.Count)
                {
                    return(null);
                }
                var name = parameters[parameterMap[index]].Name;
                return(new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        int p = index + i;
                        if (p >= parameterMap.Count)
                        {
                            break;
                        }
                        name = parameters[parameterMap[p]].Name;
                        var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
                        script.Replace(arguments.ElementAt(p), namedArgument);
                    }
                },
                                      expression
                                      ));
            }

            var invocationExpression = parent as InvocationExpression;

            if (invocationExpression != null)
            {
                var resolvedResult = context.Resolve(invocationExpression) as CSharpInvocationResolveResult;
                if (resolvedResult == null || resolvedResult.IsError)
                {
                    return(null);
                }
                var     arguments = invocationExpression.Arguments;
                IMember member    = resolvedResult.Member;

                int index = 0;
                int temp  = 0;
                List <Expression> nodes = new List <Expression>();
                foreach (var argument in arguments)
                {
                    if (argument.Equals(expression))
                    {
                        nodes = CollectNodes(parent, expression);
                        break;
                    }
                    temp++;
                }
                index = temp;
                if (!nodes.Any())
                {
                    return(null);
                }

                var method = member as IMethod;
                if (method == null || method.Parameters.Count == 0 || method.Parameters.Last().IsParams)
                {
                    return(null);
                }

                var parameterMap = (resolvedResult as CSharpInvocationResolveResult).GetArgumentToParameterMap();
                var parameters   = method.Parameters;
                if (index >= parameterMap.Count)
                {
                    return(null);
                }
                var name = parameters[parameterMap[index]].Name;
                return(new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        int p = index + i;
                        if (p >= parameterMap.Count)
                        {
                            break;
                        }
                        name = parameters[parameterMap[p]].Name;
                        var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
                        script.Replace(arguments.ElementAt(p), namedArgument);
                    }
                },
                                      expression
                                      ));
            }
            return(null);
        }