static bool VariableExists(VariableLookupVisitor visitor, string name)
 {
     foreach (var descriptor in visitor.Variables.Values)
     {
         if (descriptor.Name == name)
         {
             return(true);
         }
     }
     return(false);
 }
 static string CreateVariableName(MonoDevelop.Projects.Dom.IReturnType returnType, VariableLookupVisitor visitor)
 {
     string[] possibleNames = GetPossibleName(returnType);
     foreach (string name in possibleNames)
     {
         if (!VariableExists(visitor, name))
         {
             return(name);
         }
     }
     foreach (string name in possibleNames)
     {
         for (int i = 1; i < 99; i++)
         {
             if (!VariableExists(visitor, name + i.ToString()))
             {
                 return(name + i.ToString());
             }
         }
     }
     return("a" + returnType.Name);
 }
        public override List <Change> PerformChanges(RefactoringOptions options, object prop)
        {
            varCount       = 0;
            selectionStart = selectionEnd = -1;

            List <Change>          result   = new List <Change> ();
            IResolver              resolver = options.GetResolver();
            INRefactoryASTProvider provider = options.GetASTProvider();
            TextEditorData         data     = options.GetTextEditorData();

            if (resolver == null || provider == null || data == null)
            {
                return(result);
            }

            DocumentLocation endPoint;

            if (data.IsSomethingSelected)
            {
                endPoint = data.MainSelection.Anchor < data.MainSelection.Lead ? data.MainSelection.Lead : data.MainSelection.Anchor;
            }
            else
            {
                endPoint = data.Caret.Location;
            }
            ResolveResult resolveResult;
            LineSegment   lineSegment;
            var           unit = provider.ParseFile(data.Document.Text);

            if (unit == null)
            {
                LoggingService.LogError("Declare local error: parese file == null");
                return(result);
            }
            var visitor = new VariableLookupVisitor(resolver, new DomLocation(endPoint.Line, endPoint.Column));

            if (options.ResolveResult == null)
            {
                LoggingService.LogError("Declare local error: resolve result == null");
                return(result);
            }
            IMember callingMember = options.ResolveResult.CallingMember;

            if (callingMember != null)
            {
                visitor.MemberLocation = new AstLocation(callingMember.Location.Column, callingMember.Location.Line);
            }
            unit.AcceptVisitor(visitor, null);

            ExpressionResult expressionResult = new ExpressionResult(data.SelectedText.Trim());

            if (expressionResult.Expression.Contains(" ") || expressionResult.Expression.Contains("\t"))
            {
                expressionResult.Expression = "(" + expressionResult.Expression + ")";
            }
            resolveResult = resolver.Resolve(expressionResult, new DomLocation(endPoint.Line, endPoint.Column));
            if (resolveResult == null)
            {
                return(result);
            }
            IReturnType resolvedType = GetResolvedType(options, resolveResult);

            AstType returnType;

            if (resolveResult.ResolvedType == null || string.IsNullOrEmpty(resolveResult.ResolvedType.Name))
            {
                returnType = new SimpleType("var");
            }
            else
            {
                returnType = options.ShortenTypeName(resolvedType).ConvertToTypeReference();
            }

            varName = CreateVariableName(resolvedType, visitor);
            options.ParseMember(resolveResult.CallingMember);

            // insert local variable declaration
            TextReplaceChange insert = new TextReplaceChange();

            insert.FileName    = options.Document.FileName;
            insert.Description = GettextCatalog.GetString("Insert variable declaration");

            var varDecl = new VariableDeclarationStatement(returnType, varName, provider.ParseExpression(data.SelectedText));

            var node = unit.GetNodeAt(endPoint.Line, endPoint.Column);

            var containing = node.Parent;

            while (!(containing.Parent is BlockStatement))
            {
                containing = containing.Parent;
            }

            if (containing is BlockStatement)
            {
                lineSegment = data.Document.GetLine(data.Caret.Line);
            }
            else
            {
                lineSegment = data.Document.GetLine(containing.StartLocation.Line);
            }
            insert.Offset       = lineSegment.Offset;
            insert.InsertedText = options.GetWhitespaces(lineSegment.Offset) + provider.OutputNode(options.Dom, varDecl);
            var insertOffset = insert.Offset + options.GetWhitespaces(lineSegment.Offset).Length + provider.OutputNode(options.Dom, varDecl.Type).Length + " ".Length;

            offsets.Add(insertOffset);
            result.Add(insert);
            varCount++;

            // replace main selection
            TextReplaceChange replace = new TextReplaceChange();

            replace.FileName     = options.Document.FileName;
            replace.Offset       = data.SelectionRange.Offset;
            replace.RemovedChars = data.SelectionRange.Length;
            replace.InsertedText = varName;
            result.Add(replace);
            int delta = insert.InsertedText.Length - insert.RemovedChars;

            offsets.Add(replace.Offset + delta);
            Console.WriteLine(replace.Offset);
            delta += varName.Length - replace.RemovedChars;
            varCount++;
            selectionStart = insert.Offset;

            if (replaceAll)
            {
                matches.Sort((x, y) => x.StartLocation.CompareTo(y.StartLocation));
                foreach (var match in matches)
                {
                    replace          = new TextReplaceChange();
                    replace.FileName = options.Document.FileName;
                    int start = data.LocationToOffset(match.StartLocation.Line, match.StartLocation.Column);
                    int end   = data.LocationToOffset(match.EndLocation.Line, match.EndLocation.Column);

                    replace.Offset       = start;
                    replace.RemovedChars = end - start;
                    replace.InsertedText = varName;
                    result.Add(replace);
                    offsets.Add(start + delta);
                    delta += varName.Length - replace.RemovedChars;
                }
            }
            return(result);
        }