public ExtractMethodParameters CreateParameters(RefactoringOptions options)
        {
            var buffer = options.Document.Editor;

            if (!buffer.IsSomethingSelected)
            {
                return(null);
            }

            ParsedDocument doc = options.ParseDocument();

            if (doc == null || doc.CompilationUnit == null)
            {
                return(null);
            }

            IMember member = doc.CompilationUnit.GetMemberAt(buffer.Caret.Line, buffer.Caret.Column);

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

            ExtractMethodParameters param = new ExtractMethodParameters()
            {
                DeclaringMember = member,
                Location        = new DomLocation(buffer.Caret.Line, buffer.Caret.Column)
            };

            Analyze(options, param, true);
            return(param);
        }
Example #2
0
        public ExtractMethodParameters CreateParameters(RefactoringOptions options)
        {
            var buffer = options.Document.TextEditor;

            if (buffer.SelectionStartPosition - buffer.SelectionEndPosition == 0)
            {
                return(null);
            }

            ParsedDocument doc = options.ParseDocument();

            if (doc == null || doc.CompilationUnit == null)
            {
                return(null);
            }

            int line, column;

            buffer.GetLineColumnFromPosition(buffer.CursorPosition, out line, out column);
            IMember member = doc.CompilationUnit.GetMemberAt(line, column);

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

            ExtractMethodParameters param = new ExtractMethodParameters()
            {
                DeclaringMember = member,
                Location        = new DomLocation(line, column)
            };

            Analyze(options, param, true);
            return(param);
        }
        public override void Run(RefactoringOptions options)
        {
            ExtractMethodParameters param = CreateParameters(options);

            if (param == null)
            {
                return;
            }
            if (!Analyze(options, param, false))
            {
                MessageService.ShowError(GettextCatalog.GetString("Invalid selection for method extraction."));
                return;
            }
            MessageService.ShowCustomDialog(new ExtractMethodDialog(options, this, param));
        }
        static DomMethod GenerateMethodStub(RefactoringOptions options, ExtractMethodParameters param)
        {
            DomMethod result = new DomMethod();

            result.Name       = param.Name;
            result.ReturnType = param.ExpressionType ?? DomReturnType.Void;
            result.Modifiers  = param.Modifiers;
            if (!param.ReferencesMember)
            {
                result.Modifiers |= Modifiers.Static;
            }

            if (param.Parameters == null)
            {
                return(result);
            }
            foreach (var p in param.Parameters)
            {
                if (param.OneChangedVariable && p.UsedAfterCutRegion && !p.UsedInCutRegion)
                {
                    continue;
                }
                var newParameter = new DomParameter();
                newParameter.Name       = p.Name;
                newParameter.ReturnType = p.ReturnType;

                if (!param.OneChangedVariable)
                {
                    if (!p.IsDefinedInsideCutRegion && p.IsChangedInsideCutRegion)
                    {
                        newParameter.ParameterModifiers = p.UsedBeforeCutRegion ? ParameterModifiers.Ref : ParameterModifiers.Out;
                    }
                }
                result.Add(newParameter);
            }
            return(result);
        }
		public ExtractMethodParameters CreateParameters (RefactoringOptions options)
		{
			var buffer = options.Document.TextEditor;
			
			if (buffer.SelectionStartPosition - buffer.SelectionEndPosition == 0)
				return null;

			ParsedDocument doc = options.ParseDocument ();
			if (doc == null || doc.CompilationUnit == null)
				return null;

			int line, column;
			buffer.GetLineColumnFromPosition (buffer.CursorPosition, out line, out column);
			IMember member = doc.CompilationUnit.GetMemberAt (line, column);
			if (member == null)
				return null;
			
			ExtractMethodParameters param = new ExtractMethodParameters () {
				DeclaringMember = member,
				Location = new DomLocation (line, column)
			};
			Analyze (options, param, true);
			return param;
		}
		static string GenerateMethodDeclaration (RefactoringOptions options, ExtractMethodParameters param)
		{
			StringBuilder methodText = new StringBuilder ();
			string indent = options.GetIndent (param.DeclaringMember);
			if (param.InsertionPoint != null) {
				switch (param.InsertionPoint.LineBefore) {
				case NewLineInsertion.Eol:
					methodText.AppendLine ();
					break;
				case NewLineInsertion.BlankLine:
					methodText.Append (indent);
					methodText.AppendLine ();
					break;
				}
			} else {
				methodText.AppendLine ();
				methodText.Append (indent);
				methodText.AppendLine ();
			}
			var codeGenerator = new CSharpCodeGenerator () {
				UseSpaceIndent = options.Document.Editor.Options.TabsToSpaces,
				EolMarker = options.Document.Editor.EolMarker,
				TabSize = options.Document.Editor.Options.TabSize
			};
			
			var newMethod = GenerateMethodStub (options, param);
			IType callingType = null;
			var cu = options.Document.CompilationUnit;
			if (cu != null)
				callingType = newMethod.DeclaringType = options.Document.CompilationUnit.GetTypeAt (options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column);
				
			var createdMethod = codeGenerator.CreateMemberImplementation (callingType, newMethod, false);

			if (param.GenerateComment && DocGenerator.Instance != null)
				methodText.AppendLine (DocGenerator.Instance.GenerateDocumentation (newMethod, indent + "/// "));
			string code = createdMethod.Code;
			int idx1 = code.LastIndexOf ("throw");
			int idx2 = code.LastIndexOf (";");
			methodText.Append (code.Substring (0, idx1));

			if (param.Nodes != null && (param.Nodes.Count == 1 && param.Nodes[0].NodeType == NodeType.Expression)) {
				methodText.Append ("return ");
				methodText.Append (param.Text.Trim ());
				methodText.Append (";");
			} else {
				StringBuilder text = new StringBuilder ();
				if (param.OneChangedVariable) {
					var par = param.Variables.First (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion);
					if (!par.UsedInCutRegion) {
						
						text.Append (new CSharpAmbience ().GetString (par.ReturnType, OutputFlags.ClassBrowserEntries));
						text.Append (" ");
						text.Append (par.Name);
						text.AppendLine (";");
					}
				}
				text.Append (param.Text);
				if (param.OneChangedVariable) {
					text.AppendLine ();
					text.Append ("return ");
					text.Append (param.Variables.First (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion).Name);
					text.Append (";");
				}
				methodText.Append (AddIndent (text.ToString (), indent + "\t"));
			}

			methodText.Append (code.Substring (idx2 + 1));
			if (param.InsertionPoint != null) {
				switch (param.InsertionPoint.LineAfter) {
				case NewLineInsertion.Eol:
					methodText.AppendLine ();
					break;
				case NewLineInsertion.BlankLine:
					methodText.AppendLine ();
					methodText.Append (indent);
					methodText.AppendLine ();
					break;
				case NewLineInsertion.None:
					methodText.AppendLine ();
					break;
				}
			} else {
				methodText.AppendLine ();
				methodText.Append (indent);
				methodText.AppendLine ();
			}
			return methodText.ToString ();
		}
		static DomMethod GenerateMethodStub (RefactoringOptions options, ExtractMethodParameters param)
		{
			DomMethod result = new DomMethod ();
			result.Name = param.Name;
			result.ReturnType = param.ExpressionType ?? DomReturnType.Void;
			result.Modifiers = param.Modifiers;
			if (!param.ReferencesMember)
				result.Modifiers |= MonoDevelop.Projects.Dom.Modifiers.Static;
			
			if (param.Parameters == null)
				return result;
			foreach (var p in param.Parameters) {
				if (param.OneChangedVariable && p.UsedAfterCutRegion && !p.UsedInCutRegion)
					continue;
				var newParameter = new DomParameter ();
				newParameter.Name = p.Name;
				newParameter.ReturnType = p.ReturnType;
				
				if (!param.OneChangedVariable) {
					if (!p.IsDefinedInsideCutRegion && p.IsChangedInsideCutRegion) {
						newParameter.ParameterModifiers = p.UsedBeforeCutRegion ? ParameterModifiers.Ref : ParameterModifiers.Out;
					}
				}
				result.Add (newParameter);
			}
			return result;
		}
		static string GenerateMethodCall (RefactoringOptions options, ExtractMethodParameters param)
		{
//			var data = options.GetTextEditorData ();
			StringBuilder sb = new StringBuilder ();
			
	/*		LineSegment line = data.Document.GetLine (Math.Max (0, data.Document.OffsetToLineNumber (data.SelectionRange.Offset) - 1));
			if (param.VariablesToGenerate != null && param.VariablesToGenerate.Count > 0) {
				string indent = options.GetWhitespaces (line.Offset);
				sb.Append (Environment.NewLine + indent);
				foreach (VariableDescriptor var in param.VariablesToGenerate) {
					var returnType = options.ShortenTypeName (var.ReturnType);
					sb.Append (returnType.ToInvariantString ());
					sb.Append (" ");
					sb.Append (var.Name);
					sb.AppendLine (";");
					sb.Append (indent);
				}
			}*/
			if (param.OneChangedVariable) {
				var resultVariable = param.Variables.First (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion);
				if (resultVariable.IsDefinedInsideCutRegion) {
					var s = resultVariable.Declaration.Type.StartLocation;
					var e = resultVariable.Declaration.Type.EndLocation;
					sb.Append (options.Document.Editor.GetTextBetween (s.Line, s.Column, e.Line, e.Column) + " ");
				}
				
				sb.Append (resultVariable.Name);
				sb.Append (" = ");
			}
			sb.Append (param.Name);
			sb.Append (" "); // TODO: respect formatting
			sb.Append ("(");
			bool first = true;
			foreach (VariableDescriptor var in param.Parameters) {
				if (param.OneChangedVariable && var.UsedAfterCutRegion && !var.UsedInCutRegion)
					continue;
				if (first) {
					first = false;
				} else {
					sb.Append (", "); // TODO: respect formatting
				}
				if (!param.OneChangedVariable) {
					if (!var.IsDefinedInsideCutRegion && var.IsChangedInsideCutRegion) {
						sb.Append (var.UsedBeforeCutRegion ? "ref " : "out ");
					}
				}
				sb.Append (var.Name);
			}
			sb.Append (")");
			if (param.Nodes != null && (param.Nodes.Count > 1 || param.Nodes.Count == 1 && param.Nodes[0].NodeType != NodeType.Expression)) 
				sb.Append (";");
			return sb.ToString ();
		}
		bool Analyze (RefactoringOptions options, ExtractMethodParameters param, bool fillParameter)
		{
			var data = options.GetTextEditorData ();
			var parser = new CSharpParser ();
			var unit = parser.Parse (data);
			var resolver = options.GetResolver ();
			if (unit == null)
				return false;
			var selectionRange = data.SelectionRange;
			var startOffset = selectionRange.Offset;
			while (startOffset + 1 < data.Length && char.IsWhiteSpace (data.GetCharAt (startOffset + 1)))
				startOffset++;
			var endOffset = selectionRange.EndOffset;
			while (startOffset < endOffset && endOffset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (endOffset - 1)))
				endOffset--;
			if (startOffset >= endOffset)
				return false;
			
			var endLocation = data.OffsetToLocation (endOffset);
			var startLocation = data.OffsetToLocation (startOffset);
			param.StartOffset = startOffset;
			param.EndOffset = endOffset;
			param.Nodes = new List<AstNode> (unit.GetNodesBetween (startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column));
			string text = options.Document.Editor.GetTextBetween (startLocation, endLocation);
			
			param.Text = RemoveIndent (text, GetIndent (data.GetTextBetween (data.GetLine (startLocation.Line).Offset, data.GetLine (endLocation.Line).EndOffset))).TrimEnd ('\n', '\r');
			VariableLookupVisitor visitor = new VariableLookupVisitor (resolver, param.Location);
			visitor.MemberLocation = param.DeclaringMember.Location;
			visitor.CutRegion = new DomRegion (startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column);
			if (fillParameter) {
				unit.AcceptVisitor (visitor, null);
				if (param.Nodes != null && (param.Nodes.Count == 1 && param.Nodes [0].NodeType == NodeType.Expression)) {
					ResolveResult resolveResult = resolver.Resolve (new ExpressionResult ("(" + text + ")"), param.Location);
					if (resolveResult != null && resolveResult.ResolvedType != null)
						param.ExpressionType = resolveResult.ResolvedType;
				}
				
				foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefinedInsideCutRegion && (v.UsedInCutRegion || v.IsChangedInsideCutRegion || v.UsedAfterCutRegion && v.IsDefinedInsideCutRegion))) {
					param.Parameters.Add (varDescr);
				}
			
				param.Variables = new List<VariableDescriptor> (visitor.Variables.Values);
				param.ReferencesMember = visitor.ReferencesMember;
				
				param.OneChangedVariable = param.Variables.Count (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion) == 1;
				if (param.OneChangedVariable)
					param.ExpressionType = param.Variables.First (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion).ReturnType;
				/*
					foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefined && param.Variables.Contains (v))) {
					if (param.Parameters.Contains (varDescr))
						continue;
					if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
						continue;
					param.Parameters.Add (varDescr);
				}
				
				
				param.ChangedVariables = new HashSet<string> (visitor.Variables.Values.Where (v => v.GetsChanged).Select (v => v.Name));
				*/
				// analyze the variables outside of the selected text
				IMember member = param.DeclaringMember;
			
				int bodyStartOffset = data.Document.LocationToOffset (member.BodyRegion.Start.Line, member.BodyRegion.Start.Column);
				int bodyEndOffset = data.Document.LocationToOffset (member.BodyRegion.End.Line, member.BodyRegion.End.Column);
				if (startOffset < bodyStartOffset || bodyEndOffset < endOffset)
					return false;
				text = data.Document.GetTextBetween (bodyStartOffset, startOffset) + data.Document.GetTextBetween (endOffset, bodyEndOffset);
				//				ICSharpCode.OldNRefactory.Ast.INode parsedNode = provider.ParseText (text);
				//				visitor = new VariableLookupVisitor (resolver, param.Location);
				//				visitor.CutRegion = new DomRegion (data.MainSelection.MinLine, data.MainSelection.MaxLine);
				//				visitor.MemberLocation = new Location (param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
				//				if (parsedNode != null)
				//					parsedNode.AcceptVisitor (visitor, null);
				
				
				/*	
				param.VariablesOutside = new Dictionary<string, VariableDescriptor> ();
				foreach (var pair in visitor.Variables) {
					if (startLocation < pair.Value.Location || endLocation >= pair.Value.Location) {
						param.VariablesOutside.Add (pair.Key, pair.Value);
					}
				}
				param.OutsideVariableList = new List<VariableDescriptor> ();
				foreach (var v in visitor.VariableList) {
					if (startLocation < v.Location || endLocation >= v.Location)
						param.OutsideVariableList.Add (v);
				}
				
				param.ChangedVariablesUsedOutside = new List<VariableDescriptor> (param.Variables.Where (v => v.GetsChanged && param.VariablesOutside.ContainsKey (v.Name)));
				param.OneChangedVariable = param.Nodes.Count == 1 && param.Nodes[0] is BlockStatement;
				if (param.OneChangedVariable) 
					param.OneChangedVariable = param.ChangedVariablesUsedOutside.Count == 1;
				
				param.VariablesToGenerate = new List<VariableDescriptor> (param.ChangedVariablesUsedOutside.Where (v => v.IsDefined));
				foreach (VariableDescriptor var in param.VariablesToGenerate) {
					param.Parameters.Add (var);
				}
				if (param.OneChangedVariable) {
					param.VariablesToDefine = new List<VariableDescriptor> (param.Parameters.Where (var => !var.InitialValueUsed));
					param.VariablesToDefine.ForEach (var => param.Parameters.Remove (var));
				} else {
					param.VariablesToDefine = new List<VariableDescriptor> ();
				}*/
			}
			
			return true;
		}
        public override List <Change> PerformChanges(RefactoringOptions options, object prop)
        {
            List <Change>           result = new List <Change> ();
            ExtractMethodParameters param  = (ExtractMethodParameters)prop;
            var data = options.GetTextEditorData();
            //	IResolver resolver = options.GetResolver ();

            TextReplaceChange replacement = new TextReplaceChange();

            replacement.Description        = string.Format(GettextCatalog.GetString("Substitute selected statement(s) with call to {0}"), param.Name);
            replacement.FileName           = options.Document.FileName;
            replacement.Offset             = param.StartOffset;
            replacement.RemovedChars       = param.EndOffset - param.StartOffset;
            replacement.MoveCaretToReplace = true;
            replacement.InsertedText       = GenerateMethodCall(options, param);
            result.Add(replacement);

            TextReplaceChange insertNewMethod = new TextReplaceChange();

            insertNewMethod.FileName    = options.Document.FileName;
            insertNewMethod.Description = string.Format(GettextCatalog.GetString("Create new method {0} from selected statement(s)"), param.Name);
            var insertionPoint = param.InsertionPoint;

            if (insertionPoint == null)
            {
                var points = CodeGenerationService.GetInsertionPoints(options.Document, param.DeclaringMember.DeclaringType);
                insertionPoint = points.LastOrDefault(p => p.Location.Line < param.DeclaringMember.Location.Line);
                if (insertionPoint == null)
                {
                    insertionPoint = points.FirstOrDefault();
                }
            }

            insertNewMethod.RemovedChars = 0;             //insertionPoint.LineBefore == NewLineInsertion.Eol ? 0 : insertionPoint.Location.Column - 1;
            insertNewMethod.Offset       = data.Document.LocationToOffset(insertionPoint.Location) - insertNewMethod.RemovedChars;
            insertNewMethod.InsertedText = GenerateMethodDeclaration(options, param);
            result.Add(insertNewMethod);

            /*
             *
             * ExtractMethodAstTransformer transformer = new ExtractMethodAstTransformer (param.VariablesToGenerate);
             * node.AcceptVisitor (transformer, null);
             * if (!param.OneChangedVariable && node is Expression) {
             *      ResolveResult resolveResult = resolver.Resolve (new ExpressionResult ("(" + provider.OutputNode (options.Dom, node) + ")"), new DomLocation (options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column));
             *      if (resolveResult.ResolvedType != null)
             *              returnType = options.ShortenTypeName (resolveResult.ResolvedType).ConvertToTypeReference ();
             * }
             *
             * MethodDeclaration methodDecl = new MethodDeclaration ();
             * methodDecl.Name = param.Name;
             * methodDecl.Modifier = param.Modifiers;
             * methodDecl.TypeReference = returnType;
             *
             *
             * if (node is BlockStatement) {
             *      methodDecl.Body = new BlockStatement ();
             *      methodDecl.Body.AddChild (new EmptyStatement ());
             *      if (param.OneChangedVariable)
             *              methodDecl.Body.AddChild (new ReturnStatement (new IdentifierExpression (param.ChangedVariables.First ())));
             * } else if (node is Expression) {
             *      methodDecl.Body = new BlockStatement ();
             *      methodDecl.Body.AddChild (new ReturnStatement (node as Expression));
             * }
             *
             * foreach (VariableDescriptor var in param.VariablesToDefine) {
             *      BlockStatement block = methodDecl.Body;
             *      LocalVariableDeclaration varDecl = new LocalVariableDeclaration (options.ShortenTypeName (var.ReturnType).ConvertToTypeReference ());
             *      varDecl.Variables.Add (new VariableDeclaration (var.Name));
             *      block.Children.Insert (0, varDecl);
             * }
             *
             *
             *
             * string indent = options.GetIndent (param.DeclaringMember);
             * StringBuilder methodText = new StringBuilder ();
             * switch (param.InsertionPoint.LineBefore) {
             * case NewLineInsertion.Eol:
             *      methodText.AppendLine ();
             *      break;
             * case NewLineInsertion.BlankLine:
             *      methodText.Append (indent);
             *      methodText.AppendLine ();
             *      break;
             * }
             * if (param.GenerateComment) {
             *      methodText.Append (indent);
             *      methodText.AppendLine ("/// <summary>");
             *      methodText.Append (indent);
             *      methodText.AppendLine ("/// TODO: write a comment.");
             *      methodText.Append (indent);
             *      methodText.AppendLine ("/// </summary>");
             *      Ambience ambience = AmbienceService.GetAmbienceForFile (options.Document.FileName);
             *      foreach (ParameterDeclarationExpression pde in methodDecl.Parameters) {
             *              methodText.Append (indent);
             *              methodText.Append ("/// <param name=\"");
             *              methodText.Append (pde.ParameterName);
             *              methodText.Append ("\"> A ");
             *              methodText.Append (ambience.GetString (pde.TypeReference.ConvertToReturnType (), OutputFlags.IncludeGenerics | OutputFlags.UseFullName));
             *              methodText.Append (" </param>");
             *              methodText.AppendLine ();
             *      }
             *      if (methodDecl.TypeReference.Type != "System.Void") {
             *              methodText.Append (indent);
             *              methodText.AppendLine ("/// <returns>");
             *              methodText.Append (indent);
             *              methodText.Append ("/// A ");
             *              methodText.AppendLine (ambience.GetString (methodDecl.TypeReference.ConvertToReturnType (), OutputFlags.IncludeGenerics | OutputFlags.UseFullName));
             *              methodText.Append (indent);
             *              methodText.AppendLine ("/// </returns>");
             *      }
             * }
             *
             * methodText.Append (indent);
             *
             * if (node is BlockStatement) {
             *      string text = provider.OutputNode (options.Dom, methodDecl, indent).Trim ();
             *      int emptyStatementMarker = text.LastIndexOf (';');
             *      if (param.OneChangedVariable)
             *              emptyStatementMarker = text.LastIndexOf (';', emptyStatementMarker - 1);
             *      StringBuilder sb = new StringBuilder ();
             *      sb.Append (text.Substring (0, emptyStatementMarker));
             *      sb.Append (AddIndent (param.Text, indent + "\t"));
             *      sb.Append (text.Substring (emptyStatementMarker + 1));
             *
             *      methodText.Append (sb.ToString ());
             * } else {
             *      methodText.Append (provider.OutputNode (options.Dom, methodDecl, options.GetIndent (param.DeclaringMember)).Trim ());
             * }
             *
             */
            return(result);
        }
Example #11
0
        ICSharpCode.NRefactory.Ast.INode Analyze(RefactoringOptions options, ExtractMethodParameters param, bool fillParameter)
        {
            IResolver resolver = options.GetResolver();
            INRefactoryASTProvider provider = options.GetASTProvider();

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

            string text = options.Document.TextEditor.GetText(options.Document.TextEditor.SelectionStartPosition, options.Document.TextEditor.SelectionEndPosition);

            TextEditorData data = options.GetTextEditorData();
            var            cu   = provider.ParseFile(data.Document.GetTextAt(0, data.SelectionRange.Offset) + "MethodCall ();" + data.Document.GetTextAt(data.SelectionRange.EndOffset, data.Document.Length - data.SelectionRange.EndOffset));

            if (cu == null || provider.LastErrors.Count > 0)
            {
                cu = provider.ParseFile(data.Document.GetTextAt(0, data.SelectionRange.Offset) + "MethodCall ()" + data.Document.GetTextAt(data.SelectionRange.EndOffset, data.Document.Length - data.SelectionRange.EndOffset));
            }

            if (cu == null || provider.LastErrors.Count > 0)
            {
                return(null);
            }

            param.Text = RemoveIndent(text, GetIndent(text)).TrimEnd('\n', '\r');

            ICSharpCode.NRefactory.Ast.INode result = provider.ParseText(text);
            if (cu == null || provider.LastErrors.Count > 0)
            {
                return(null);
            }

            VariableLookupVisitor visitor = new VariableLookupVisitor(resolver, param.Location);

            visitor.MemberLocation = new Location(param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
            if (fillParameter)
            {
                if (result != null)
                {
                    result.AcceptVisitor(visitor, null);
                }
                if (result is Expression)
                {
                    ResolveResult resolveResult = resolver.Resolve(new ExpressionResult(text), param.Location);
                    if (resolveResult != null)
                    {
                        param.ExpressionType = resolveResult.ResolvedType;
                    }
                }

                var startLocation = data.Document.OffsetToLocation(data.SelectionRange.Offset);
                var endLocation   = data.Document.OffsetToLocation(data.SelectionRange.EndOffset);
//				Console.WriteLine ("startLocation={0}, endLocation={1}", startLocation, endLocation);

                foreach (VariableDescriptor varDescr in visitor.VariableList.Where(v => !v.IsDefined && v.InitialValueUsed))
                {
                    if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
                    {
                        continue;
                    }
//					Console.WriteLine (varDescr.Location);
//					Console.WriteLine (startLocation <= varDescr.Location);
//					Console.WriteLine (varDescr.Location < endLocation);
                    param.Parameters.Add(varDescr);
                }
                param.Variables = new List <VariableDescriptor> (visitor.Variables.Values);
                foreach (VariableDescriptor varDescr in visitor.VariableList.Where(v => !v.IsDefined && param.Variables.Contains(v)))
                {
                    if (param.Parameters.Contains(varDescr))
                    {
                        continue;
                    }
                    if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
                    {
                        continue;
                    }
                    param.Parameters.Add(varDescr);
                }

                param.ReferencesMember = visitor.ReferencesMember;
                param.ChangedVariables = new HashSet <string> (visitor.Variables.Values.Where(v => v.GetsChanged).Select(v => v.Name));

                // analyze the variables outside of the selected text
                IMember member = param.DeclaringMember;

                int startOffset = data.Document.LocationToOffset(member.BodyRegion.Start.Line, member.BodyRegion.Start.Column);
                int endOffset   = data.Document.LocationToOffset(member.BodyRegion.End.Line, member.BodyRegion.End.Column);
                if (data.SelectionRange.Offset < startOffset || endOffset < data.SelectionRange.EndOffset)
                {
                    return(null);
                }
                text = data.Document.GetTextBetween(startOffset, data.SelectionRange.Offset) + data.Document.GetTextBetween(data.SelectionRange.EndOffset, endOffset);
                ICSharpCode.NRefactory.Ast.INode parsedNode = provider.ParseText(text);
                visitor                = new VariableLookupVisitor(resolver, param.Location);
                visitor.CutRegion      = new DomRegion(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                visitor.MemberLocation = new Location(param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
                if (parsedNode != null)
                {
                    parsedNode.AcceptVisitor(visitor, null);
                }


                param.VariablesOutside = new Dictionary <string, VariableDescriptor> ();
                foreach (var pair in visitor.Variables)
                {
                    if (startLocation < pair.Value.Location || endLocation >= pair.Value.Location)
                    {
                        param.VariablesOutside.Add(pair.Key, pair.Value);
                    }
                }
                param.OutsideVariableList = new List <VariableDescriptor> ();
                foreach (var v in visitor.VariableList)
                {
                    if (startLocation < v.Location || endLocation >= v.Location)
                    {
                        param.OutsideVariableList.Add(v);
                    }
                }



                param.ChangedVariablesUsedOutside = new List <VariableDescriptor> (param.Variables.Where(v => v.GetsChanged && param.VariablesOutside.ContainsKey(v.Name)));
                param.OneChangedVariable          = result is BlockStatement;
                if (param.OneChangedVariable)
                {
                    param.OneChangedVariable = param.ChangedVariablesUsedOutside.Count == 1;
                }

                param.VariablesToGenerate = new List <VariableDescriptor> (param.ChangedVariablesUsedOutside.Where(v => v.IsDefined));
                foreach (VariableDescriptor var in param.VariablesToGenerate)
                {
                    param.Parameters.Add(var);
                }
                if (param.OneChangedVariable)
                {
                    param.VariablesToDefine = new List <VariableDescriptor> (param.Parameters.Where(var => !var.InitialValueUsed));
                    param.VariablesToDefine.ForEach(var => param.Parameters.Remove(var));
                }
                else
                {
                    param.VariablesToDefine = new List <VariableDescriptor> ();
                }
            }
            return(result);
        }
        static string GenerateMethodCall(RefactoringOptions options, ExtractMethodParameters param)
        {
//			var data = options.GetTextEditorData ();
            StringBuilder sb = new StringBuilder();

            /*		LineSegment line = data.Document.GetLine (Math.Max (0, data.Document.OffsetToLineNumber (data.SelectionRange.Offset) - 1));
             *              if (param.VariablesToGenerate != null && param.VariablesToGenerate.Count > 0) {
             *                      string indent = options.GetWhitespaces (line.Offset);
             *                      sb.Append (Environment.NewLine + indent);
             *                      foreach (VariableDescriptor var in param.VariablesToGenerate) {
             *                              var returnType = options.ShortenTypeName (var.ReturnType);
             *                              sb.Append (returnType.ToInvariantString ());
             *                              sb.Append (" ");
             *                              sb.Append (var.Name);
             *                              sb.AppendLine (";");
             *                              sb.Append (indent);
             *                      }
             *              }*/
            if (param.OneChangedVariable)
            {
                var resultVariable = param.Variables.First(p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion);
                if (resultVariable.IsDefinedInsideCutRegion)
                {
                    var s = resultVariable.Declaration.Type.StartLocation;
                    var e = resultVariable.Declaration.Type.EndLocation;
                    sb.Append(options.Document.Editor.GetTextBetween(s.Line, s.Column, e.Line, e.Column) + " ");
                }

                sb.Append(resultVariable.Name);
                sb.Append(" = ");
            }
            sb.Append(param.Name);
            sb.Append(" ");              // TODO: respect formatting
            sb.Append("(");
            bool first = true;

            foreach (VariableDescriptor var in param.Parameters)
            {
                if (param.OneChangedVariable && var.UsedAfterCutRegion && !var.UsedInCutRegion)
                {
                    continue;
                }
                if (first)
                {
                    first = false;
                }
                else
                {
                    sb.Append(", ");                      // TODO: respect formatting
                }
                if (!param.OneChangedVariable)
                {
                    if (!var.IsDefinedInsideCutRegion && var.IsChangedInsideCutRegion)
                    {
                        sb.Append(var.UsedBeforeCutRegion ? "ref " : "out ");
                    }
                }
                sb.Append(var.Name);
            }
            sb.Append(")");
            if (param.Nodes != null && (param.Nodes.Count > 1 || param.Nodes.Count == 1 && param.Nodes[0].NodeType != NodeType.Expression))
            {
                sb.Append(";");
            }
            return(sb.ToString());
        }
        bool Analyze(RefactoringOptions options, ExtractMethodParameters param, bool fillParameter)
        {
            var data     = options.GetTextEditorData();
            var parser   = new CSharpParser();
            var unit     = parser.Parse(data);
            var resolver = options.GetResolver();

            if (unit == null)
            {
                return(false);
            }
            var selectionRange = data.SelectionRange;
            var startOffset    = selectionRange.Offset;

            while (startOffset + 1 < data.Length && char.IsWhiteSpace(data.GetCharAt(startOffset + 1)))
            {
                startOffset++;
            }
            var endOffset = selectionRange.EndOffset;

            while (startOffset < endOffset && endOffset - 1 > 0 && char.IsWhiteSpace(data.GetCharAt(endOffset - 1)))
            {
                endOffset--;
            }
            if (startOffset >= endOffset)
            {
                return(false);
            }

            var endLocation   = data.OffsetToLocation(endOffset);
            var startLocation = data.OffsetToLocation(startOffset);

            param.StartOffset = startOffset;
            param.EndOffset   = endOffset;
            param.Nodes       = new List <AstNode> (unit.GetNodesBetween(startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column));

            string text = options.Document.Editor.GetTextBetween(startLocation, endLocation);

            param.Text = RemoveIndent(text, GetIndent(data.GetTextBetween(data.GetLine(startLocation.Line).Offset, data.GetLine(endLocation.Line).EndOffset))).TrimEnd('\n', '\r');
            VariableLookupVisitor visitor = new VariableLookupVisitor(resolver, param.Location);

            visitor.MemberLocation = param.DeclaringMember.Location;
            visitor.CutRegion      = new DomRegion(startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column);
            if (fillParameter)
            {
                unit.AcceptVisitor(visitor, null);
                if (param.Nodes != null && (param.Nodes.Count == 1 && param.Nodes [0].NodeType == NodeType.Expression))
                {
                    ResolveResult resolveResult = resolver.Resolve(new ExpressionResult("(" + text + ")"), param.Location);
                    if (resolveResult != null && resolveResult.ResolvedType != null)
                    {
                        param.ExpressionType = resolveResult.ResolvedType;
                    }
                }

                foreach (VariableDescriptor varDescr in visitor.VariableList.Where(v => !v.IsDefinedInsideCutRegion && (v.UsedInCutRegion || v.IsChangedInsideCutRegion || v.UsedAfterCutRegion && v.IsDefinedInsideCutRegion)))
                {
                    param.Parameters.Add(varDescr);
                }

                param.Variables        = new List <VariableDescriptor> (visitor.Variables.Values);
                param.ReferencesMember = visitor.ReferencesMember;

                param.OneChangedVariable = param.Variables.Count(p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion) == 1;
                if (param.OneChangedVariable)
                {
                    param.ExpressionType = param.Variables.First(p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion).ReturnType;
                }

                /*
                 *      foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefined && param.Variables.Contains (v))) {
                 *      if (param.Parameters.Contains (varDescr))
                 *              continue;
                 *      if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
                 *              continue;
                 *      param.Parameters.Add (varDescr);
                 * }
                 *
                 *
                 * param.ChangedVariables = new HashSet<string> (visitor.Variables.Values.Where (v => v.GetsChanged).Select (v => v.Name));
                 */
                // analyze the variables outside of the selected text
                IMember member = param.DeclaringMember;

                int bodyStartOffset = data.Document.LocationToOffset(member.BodyRegion.Start.Line, member.BodyRegion.Start.Column);
                int bodyEndOffset   = data.Document.LocationToOffset(member.BodyRegion.End.Line, member.BodyRegion.End.Column);
                if (startOffset < bodyStartOffset || bodyEndOffset < endOffset)
                {
                    return(false);
                }
                text = data.Document.GetTextBetween(bodyStartOffset, startOffset) + data.Document.GetTextBetween(endOffset, bodyEndOffset);
                //				ICSharpCode.NRefactory.Ast.INode parsedNode = provider.ParseText (text);
                //				visitor = new VariableLookupVisitor (resolver, param.Location);
                //				visitor.CutRegion = new DomRegion (data.MainSelection.MinLine, data.MainSelection.MaxLine);
                //				visitor.MemberLocation = new Location (param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
                //				if (parsedNode != null)
                //					parsedNode.AcceptVisitor (visitor, null);


                /*
                 * param.VariablesOutside = new Dictionary<string, VariableDescriptor> ();
                 * foreach (var pair in visitor.Variables) {
                 *      if (startLocation < pair.Value.Location || endLocation >= pair.Value.Location) {
                 *              param.VariablesOutside.Add (pair.Key, pair.Value);
                 *      }
                 * }
                 * param.OutsideVariableList = new List<VariableDescriptor> ();
                 * foreach (var v in visitor.VariableList) {
                 *      if (startLocation < v.Location || endLocation >= v.Location)
                 *              param.OutsideVariableList.Add (v);
                 * }
                 *
                 * param.ChangedVariablesUsedOutside = new List<VariableDescriptor> (param.Variables.Where (v => v.GetsChanged && param.VariablesOutside.ContainsKey (v.Name)));
                 * param.OneChangedVariable = param.Nodes.Count == 1 && param.Nodes[0] is BlockStatement;
                 * if (param.OneChangedVariable)
                 *      param.OneChangedVariable = param.ChangedVariablesUsedOutside.Count == 1;
                 *
                 * param.VariablesToGenerate = new List<VariableDescriptor> (param.ChangedVariablesUsedOutside.Where (v => v.IsDefined));
                 * foreach (VariableDescriptor var in param.VariablesToGenerate) {
                 *      param.Parameters.Add (var);
                 * }
                 * if (param.OneChangedVariable) {
                 *      param.VariablesToDefine = new List<VariableDescriptor> (param.Parameters.Where (var => !var.InitialValueUsed));
                 *      param.VariablesToDefine.ForEach (var => param.Parameters.Remove (var));
                 * } else {
                 *      param.VariablesToDefine = new List<VariableDescriptor> ();
                 * }*/
            }

            return(true);
        }
Example #14
0
        public override List <Change> PerformChanges(RefactoringOptions options, object prop)
        {
            List <Change>           result   = new List <Change> ();
            ExtractMethodParameters param    = (ExtractMethodParameters)prop;
            TextEditorData          data     = options.GetTextEditorData();
            INRefactoryASTProvider  provider = options.GetASTProvider();
            IResolver resolver = options.GetResolver();

            ICSharpCode.NRefactory.Ast.INode node = Analyze(options, param, false);
            if (param.VariablesToGenerate.Count > 0)
            {
                TextReplaceChange varGen = new TextReplaceChange();
                varGen.Description = GettextCatalog.GetString("Generate some temporary variables");
                varGen.FileName    = options.Document.FileName;
                LineSegment line = data.Document.GetLine(Math.Max(0, data.Document.OffsetToLineNumber(data.SelectionRange.Offset) - 1));
                varGen.Offset       = line.Offset + line.EditableLength;
                varGen.InsertedText = Environment.NewLine + options.GetWhitespaces(line.Offset);
                foreach (VariableDescriptor var in param.VariablesToGenerate)
                {
                    TypeReference tr = options.ShortenTypeName(var.ReturnType).ConvertToTypeReference();
                    varGen.InsertedText += provider.OutputNode(options.Dom, new LocalVariableDeclaration(new VariableDeclaration(var.Name, null, tr))).Trim();
                }
                result.Add(varGen);
            }
            InvocationExpression invocation = new InvocationExpression(new IdentifierExpression(param.Name));

            foreach (VariableDescriptor var in param.Parameters)
            {
                if (!param.OneChangedVariable && param.ChangedVariables.Contains(var.Name))
                {
                    FieldDirection     fieldDirection = FieldDirection.Ref;
                    VariableDescriptor outsideVar     = null;
                    if (param.VariablesOutside.TryGetValue(var.Name, out outsideVar) && (var.GetsAssigned || param.VariablesToGenerate.Where(v => v.Name == var.Name).Any()))
                    {
                        if (!outsideVar.GetsAssigned)
                        {
                            fieldDirection = FieldDirection.Out;
                        }
                    }
                    invocation.Arguments.Add(new DirectionExpression(fieldDirection, new IdentifierExpression(var.Name)));
                }
                else
                {
                    invocation.Arguments.Add(new IdentifierExpression(var.Name));
                }
            }
            //	string mimeType = DesktopService.GetMimeTypeForUri (options.Document.FileName);
            TypeReference returnType = new TypeReference("System.Void", true);

            ICSharpCode.NRefactory.Ast.INode outputNode;
            if (param.OneChangedVariable)
            {
                string name = param.ChangedVariables.First();
                returnType = options.ShortenTypeName(param.Variables.Find(v => v.Name == name).ReturnType).ConvertToTypeReference();
                if (param.OutsideVariableList.Any(v => v.Name == name && !v.IsDefined))
                {
                    LocalVariableDeclaration varDecl = new LocalVariableDeclaration(returnType);
                    varDecl.Variables.Add(new VariableDeclaration(name, invocation));
                    outputNode = varDecl;
                }
                else
                {
                    outputNode = new ExpressionStatement(new AssignmentExpression(new IdentifierExpression(name), ICSharpCode.NRefactory.Ast.AssignmentOperatorType.Assign, invocation));
                }
            }
            else
            {
                outputNode = node is BlockStatement ? (ICSharpCode.NRefactory.Ast.INode) new ExpressionStatement(invocation) : invocation;
            }
            TextReplaceChange replacement = new TextReplaceChange();

            replacement.Description        = string.Format(GettextCatalog.GetString("Substitute selected statement(s) with call to {0}"), param.Name);
            replacement.FileName           = options.Document.FileName;
            replacement.Offset             = options.Document.TextEditor.SelectionStartPosition;
            replacement.RemovedChars       = options.Document.TextEditor.SelectionEndPosition - options.Document.TextEditor.SelectionStartPosition;
            replacement.MoveCaretToReplace = true;

            LineSegment line1 = data.Document.GetLineByOffset(options.Document.TextEditor.SelectionEndPosition);

            if (options.Document.TextEditor.SelectionEndPosition == line1.Offset)
            {
                if (line1.Offset > 0)
                {
                    LineSegment line2 = data.Document.GetLineByOffset(line1.Offset - 1);
                    replacement.RemovedChars -= line2.DelimiterLength;
                }
            }

            replacement.InsertedText = options.GetWhitespaces(options.Document.TextEditor.SelectionStartPosition) + provider.OutputNode(options.Dom, outputNode).Trim();

            result.Add(replacement);

            TextReplaceChange insertNewMethod = new TextReplaceChange();

            insertNewMethod.FileName     = options.Document.FileName;
            insertNewMethod.Description  = string.Format(GettextCatalog.GetString("Create new method {0} from selected statement(s)"), param.Name);
            insertNewMethod.RemovedChars = param.InsertionPoint.LineBefore == NewLineInsertion.Eol ? 0 : param.InsertionPoint.Location.Column;
            insertNewMethod.Offset       = data.Document.LocationToOffset(param.InsertionPoint.Location) - insertNewMethod.RemovedChars;

            ExtractMethodAstTransformer transformer = new ExtractMethodAstTransformer(param.VariablesToGenerate);

            node.AcceptVisitor(transformer, null);
            if (!param.OneChangedVariable && node is Expression)
            {
                ResolveResult resolveResult = resolver.Resolve(new ExpressionResult("(" + provider.OutputNode(options.Dom, node) + ")"), new DomLocation(options.Document.TextEditor.CursorLine, options.Document.TextEditor.CursorColumn));
                if (resolveResult.ResolvedType != null)
                {
                    returnType = options.ShortenTypeName(resolveResult.ResolvedType).ConvertToTypeReference();
                }
            }

            MethodDeclaration methodDecl = new MethodDeclaration();

            methodDecl.Name          = param.Name;
            methodDecl.Modifier      = param.Modifiers;
            methodDecl.TypeReference = returnType;

            if (!param.ReferencesMember)
            {
                methodDecl.Modifier |= ICSharpCode.NRefactory.Ast.Modifiers.Static;
            }
            if (node is BlockStatement)
            {
                methodDecl.Body = new BlockStatement();
                methodDecl.Body.AddChild(new EmptyStatement());
                if (param.OneChangedVariable)
                {
                    methodDecl.Body.AddChild(new ReturnStatement(new IdentifierExpression(param.ChangedVariables.First())));
                }
            }
            else if (node is Expression)
            {
                methodDecl.Body = new BlockStatement();
                methodDecl.Body.AddChild(new ReturnStatement(node as Expression));
            }

            foreach (VariableDescriptor var in param.VariablesToDefine)
            {
                BlockStatement           block   = methodDecl.Body;
                LocalVariableDeclaration varDecl = new LocalVariableDeclaration(options.ShortenTypeName(var.ReturnType).ConvertToTypeReference());
                varDecl.Variables.Add(new VariableDeclaration(var.Name));
                block.Children.Insert(0, varDecl);
            }

            foreach (VariableDescriptor var in param.Parameters)
            {
                TypeReference typeReference        = options.ShortenTypeName(var.ReturnType).ConvertToTypeReference();
                ParameterDeclarationExpression pde = new ParameterDeclarationExpression(typeReference, var.Name);
                if (!param.OneChangedVariable)
                {
                    if (param.ChangedVariables.Contains(var.Name))
                    {
                        pde.ParamModifier = ICSharpCode.NRefactory.Ast.ParameterModifiers.Ref;
                    }
                    if (param.VariablesToGenerate.Where(v => v.Name == var.Name).Any())
                    {
                        pde.ParamModifier = ICSharpCode.NRefactory.Ast.ParameterModifiers.Out;
                    }
                    VariableDescriptor outsideVar = null;
                    if (var.GetsAssigned && param.VariablesOutside.TryGetValue(var.Name, out outsideVar))
                    {
                        if (!outsideVar.GetsAssigned)
                        {
                            pde.ParamModifier = ICSharpCode.NRefactory.Ast.ParameterModifiers.Out;
                        }
                    }
                }

                methodDecl.Parameters.Add(pde);
            }

            string        indent     = options.GetIndent(param.DeclaringMember);
            StringBuilder methodText = new StringBuilder();

            switch (param.InsertionPoint.LineBefore)
            {
            case NewLineInsertion.Eol:
                methodText.AppendLine();
                break;

            case NewLineInsertion.BlankLine:
                methodText.Append(indent);
                methodText.AppendLine();
                break;
            }
            if (param.GenerateComment)
            {
                methodText.Append(indent);
                methodText.AppendLine("/// <summary>");
                methodText.Append(indent);
                methodText.AppendLine("/// TODO: write a comment.");
                methodText.Append(indent);
                methodText.AppendLine("/// </summary>");
                Ambience ambience = AmbienceService.GetAmbienceForFile(options.Document.FileName);
                foreach (ParameterDeclarationExpression pde in methodDecl.Parameters)
                {
                    methodText.Append(indent);
                    methodText.Append("/// <param name=\"");
                    methodText.Append(pde.ParameterName);
                    methodText.Append("\"> A ");
                    methodText.Append(ambience.GetString(pde.TypeReference.ConvertToReturnType(), OutputFlags.IncludeGenerics | OutputFlags.UseFullName));
                    methodText.Append(" </param>");
                    methodText.AppendLine();
                }
                if (methodDecl.TypeReference.Type != "System.Void")
                {
                    methodText.Append(indent);
                    methodText.AppendLine("/// <returns>");
                    methodText.Append(indent);
                    methodText.Append("/// A ");
                    methodText.AppendLine(ambience.GetString(methodDecl.TypeReference.ConvertToReturnType(), OutputFlags.IncludeGenerics | OutputFlags.UseFullName));
                    methodText.Append(indent);
                    methodText.AppendLine("/// </returns>");
                }
            }

            methodText.Append(indent);

            if (node is BlockStatement)
            {
                string text = provider.OutputNode(options.Dom, methodDecl, indent).Trim();
                int    emptyStatementMarker = text.LastIndexOf(';');
                if (param.OneChangedVariable)
                {
                    emptyStatementMarker = text.LastIndexOf(';', emptyStatementMarker - 1);
                }
                StringBuilder sb = new StringBuilder();
                sb.Append(text.Substring(0, emptyStatementMarker));
                sb.Append(AddIndent(param.Text, indent + "\t"));
                sb.Append(text.Substring(emptyStatementMarker + 1));

                methodText.Append(sb.ToString());
            }
            else
            {
                methodText.Append(provider.OutputNode(options.Dom, methodDecl, options.GetIndent(param.DeclaringMember)).Trim());
            }

            switch (param.InsertionPoint.LineAfter)
            {
            case NewLineInsertion.Eol:
                methodText.AppendLine();
                break;

            case NewLineInsertion.BlankLine:
                methodText.AppendLine();
                methodText.AppendLine();
                methodText.Append(indent);
                break;
            }
            insertNewMethod.InsertedText = methodText.ToString();
            result.Add(insertNewMethod);

            return(result);
        }
		ICSharpCode.NRefactory.Ast.INode Analyze (RefactoringOptions options, ExtractMethodParameters param, bool fillParameter)
		{
			IResolver resolver = options.GetResolver ();
			INRefactoryASTProvider provider = options.GetASTProvider ();
			if (resolver == null || provider == null)
				return null;

			string text = options.Document.Editor.GetTextAt (options.Document.Editor.SelectionRange);
			
			TextEditorData data = options.GetTextEditorData ();
			var cu = provider.ParseFile (data.Document.GetTextAt (0, data.SelectionRange.Offset) + "MethodCall ();" + data.Document.GetTextAt (data.SelectionRange.EndOffset, data.Document.Length - data.SelectionRange.EndOffset));
			
			if (cu == null || provider.LastErrors.Count > 0) 
				cu = provider.ParseFile (data.Document.GetTextAt (0, data.SelectionRange.Offset) + "MethodCall ()" + data.Document.GetTextAt (data.SelectionRange.EndOffset, data.Document.Length - data.SelectionRange.EndOffset));
			
			if (cu == null || provider.LastErrors.Count > 0) 
				return null;
			
			param.Text = RemoveIndent (text, GetIndent (text)).TrimEnd ('\n', '\r');
			
			ICSharpCode.NRefactory.Ast.INode result = provider.ParseText (text);
			if (cu == null || provider.LastErrors.Count > 0) {
				return null;
			}
			
			VariableLookupVisitor visitor = new VariableLookupVisitor (resolver, param.Location);
			visitor.MemberLocation = new Location (param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
			if (fillParameter) {
				if (result != null)
					result.AcceptVisitor (visitor, null);
				if (result is Expression) {
					ResolveResult resolveResult = resolver.Resolve (new ExpressionResult (text), param.Location);
					if (resolveResult != null)
						param.ExpressionType = resolveResult.ResolvedType;
				}
				
				var startLocation = data.Document.OffsetToLocation (data.SelectionRange.Offset);
				var endLocation = data.Document.OffsetToLocation (data.SelectionRange.EndOffset);
//				Console.WriteLine ("startLocation={0}, endLocation={1}", startLocation, endLocation);
				
				foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefined && v.InitialValueUsed)) {
					if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
						continue;
//					Console.WriteLine (varDescr.Location);
//					Console.WriteLine (startLocation <= varDescr.Location);
//					Console.WriteLine (varDescr.Location < endLocation);
					param.Parameters.Add (varDescr);
				}
				param.Variables = new List<VariableDescriptor> (visitor.Variables.Values);
				foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefined && param.Variables.Contains (v))) {
					if (param.Parameters.Contains (varDescr))
						continue;
					if (startLocation <= varDescr.Location && varDescr.Location < endLocation)
						continue;
					param.Parameters.Add (varDescr);
				}
				
				param.ReferencesMember = visitor.ReferencesMember;
				param.ChangedVariables = new HashSet<string> (visitor.Variables.Values.Where (v => v.GetsChanged).Select (v => v.Name));
				
				// analyze the variables outside of the selected text
				IMember member = param.DeclaringMember;
			
				int startOffset = data.Document.LocationToOffset (member.BodyRegion.Start.Line, member.BodyRegion.Start.Column);
				int endOffset = data.Document.LocationToOffset (member.BodyRegion.End.Line, member.BodyRegion.End.Column);
				if (data.SelectionRange.Offset < startOffset || endOffset < data.SelectionRange.EndOffset)
					return null;
				text = data.Document.GetTextBetween (startOffset, data.SelectionRange.Offset) + data.Document.GetTextBetween (data.SelectionRange.EndOffset, endOffset);
				ICSharpCode.NRefactory.Ast.INode parsedNode = provider.ParseText (text);
				visitor = new VariableLookupVisitor (resolver, param.Location);
				visitor.CutRegion = new DomRegion (data.MainSelection.MinLine, data.MainSelection.MaxLine);
				visitor.MemberLocation = new Location (param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line);
				if (parsedNode != null)
					parsedNode.AcceptVisitor (visitor, null);
				
				
				param.VariablesOutside = new Dictionary<string, VariableDescriptor> ();
				foreach (var pair in visitor.Variables) {
					if (startLocation < pair.Value.Location || endLocation >= pair.Value.Location) {
						param.VariablesOutside.Add (pair.Key, pair.Value);
					}
				}
				param.OutsideVariableList = new List<VariableDescriptor> ();
				foreach (var v in visitor.VariableList) {
					if (startLocation < v.Location || endLocation >= v.Location)
						param.OutsideVariableList.Add (v);
				}
				
				
				
				param.ChangedVariablesUsedOutside = new List<VariableDescriptor> (param.Variables.Where (v => v.GetsChanged && param.VariablesOutside.ContainsKey (v.Name)));
				param.OneChangedVariable = result is BlockStatement;
				if (param.OneChangedVariable) 
					param.OneChangedVariable = param.ChangedVariablesUsedOutside.Count == 1;
				
				param.VariablesToGenerate = new List<VariableDescriptor> (param.ChangedVariablesUsedOutside.Where (v => v.IsDefined));
				foreach (VariableDescriptor var in param.VariablesToGenerate) {
					param.Parameters.Add (var);
				}
				if (param.OneChangedVariable) {
					param.VariablesToDefine = new List<VariableDescriptor> (param.Parameters.Where (var => !var.InitialValueUsed));
					param.VariablesToDefine.ForEach (var => param.Parameters.Remove (var));
				} else {
					param.VariablesToDefine = new List<VariableDescriptor> ();
				}
			}
			return result;
		}
		public ExtractMethodParameters CreateParameters (RefactoringOptions options)
		{
			var buffer = options.Document.Editor;
			
			if (!buffer.IsSomethingSelected)
				return null;

			ParsedDocument doc = options.ParseDocument ();
			if (doc == null || doc.CompilationUnit == null)
				return null;

			IMember member = doc.CompilationUnit.GetMemberAt (buffer.Caret.Line, buffer.Caret.Column);
			if (member == null)
				return null;
			
			ExtractMethodParameters param = new ExtractMethodParameters () {
				DeclaringMember = member,
				Location = new DomLocation (buffer.Caret.Line, buffer.Caret.Column)
			};
			Analyze (options, param, true);
			return param;
		}
        static string GenerateMethodDeclaration(RefactoringOptions options, ExtractMethodParameters param)
        {
            StringBuilder methodText = new StringBuilder();
            string        indent     = options.GetIndent(param.DeclaringMember);

            if (param.InsertionPoint != null)
            {
                switch (param.InsertionPoint.LineBefore)
                {
                case NewLineInsertion.Eol:
                    methodText.AppendLine();
                    break;

                case NewLineInsertion.BlankLine:
                    methodText.Append(indent);
                    methodText.AppendLine();
                    break;
                }
            }
            else
            {
                methodText.AppendLine();
                methodText.Append(indent);
                methodText.AppendLine();
            }
            var codeGenerator = new CSharpCodeGenerator()
            {
                UseSpaceIndent = options.Document.Editor.Options.TabsToSpaces,
                EolMarker      = options.Document.Editor.EolMarker,
                TabSize        = options.Document.Editor.Options.TabSize
            };

            var   newMethod   = GenerateMethodStub(options, param);
            IType callingType = null;
            var   cu          = options.Document.CompilationUnit;

            if (cu != null)
            {
                callingType = newMethod.DeclaringType = options.Document.CompilationUnit.GetTypeAt(options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column);
            }

            var createdMethod = codeGenerator.CreateMemberImplementation(callingType, newMethod, false);

            if (param.GenerateComment && DocGenerator.Instance != null)
            {
                methodText.AppendLine(DocGenerator.Instance.GenerateDocumentation(newMethod, indent + "/// "));
            }
            string code = createdMethod.Code;
            int    idx1 = code.LastIndexOf("throw");
            int    idx2 = code.LastIndexOf(";");

            methodText.Append(code.Substring(0, idx1));

            if (param.Nodes != null && (param.Nodes.Count == 1 && param.Nodes[0].NodeType == NodeType.Expression))
            {
                methodText.Append("return ");
                methodText.Append(param.Text.Trim());
                methodText.Append(";");
            }
            else
            {
                StringBuilder text = new StringBuilder();
                if (param.OneChangedVariable)
                {
                    var par = param.Variables.First(p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion);
                    if (!par.UsedInCutRegion)
                    {
                        text.Append(new CSharpAmbience().GetString(par.ReturnType, OutputFlags.ClassBrowserEntries));
                        text.Append(" ");
                        text.Append(par.Name);
                        text.AppendLine(";");
                    }
                }
                text.Append(param.Text);
                if (param.OneChangedVariable)
                {
                    text.AppendLine();
                    text.Append("return ");
                    text.Append(param.Variables.First(p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion).Name);
                    text.Append(";");
                }
                methodText.Append(AddIndent(text.ToString(), indent + "\t"));
            }

            methodText.Append(code.Substring(idx2 + 1));
            if (param.InsertionPoint != null)
            {
                switch (param.InsertionPoint.LineAfter)
                {
                case NewLineInsertion.Eol:
                    methodText.AppendLine();
                    break;

                case NewLineInsertion.BlankLine:
                    methodText.AppendLine();
                    methodText.Append(indent);
                    methodText.AppendLine();
                    break;

                case NewLineInsertion.None:
                    methodText.AppendLine();
                    break;
                }
            }
            else
            {
                methodText.AppendLine();
                methodText.Append(indent);
                methodText.AppendLine();
            }
            return(methodText.ToString());
        }