static string CreateVariableName(MonoDevelop.Projects.Dom.IReturnType returnType, MonoDevelop.Refactoring.ExtractMethod.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 (); if (resolver == null || provider == null) return result; TextEditorData data = options.GetTextEditorData (); if (data == null) return result; ResolveResult resolveResult; LineSegment lineSegment; ICSharpCode.NRefactory.Ast.CompilationUnit unit = provider.ParseFile (data.Document.Text); MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor visitor = new MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor (resolver, new DomLocation (data.Caret.Line, data.Caret.Column)); if (options.ResolveResult == null) { LoggingService.LogError ("resolve result == null:" + options.ResolveResult); return result; } IMember callingMember = options.ResolveResult.CallingMember; if (callingMember != null) visitor.MemberLocation = new Location (callingMember.Location.Column, callingMember.Location.Line); unit.AcceptVisitor (visitor, null); if (data.IsSomethingSelected) { 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 (data.Caret.Line, data.Caret.Column)); if (resolveResult == null) return result; IReturnType resolvedType = resolveResult.ResolvedType; if (resolvedType == null || string.IsNullOrEmpty (resolvedType.Name)) resolvedType = DomReturnType.Object; varName = CreateVariableName (resolvedType, visitor); TypeReference returnType; if (resolveResult.ResolvedType == null || string.IsNullOrEmpty (resolveResult.ResolvedType.Name)) { returnType = new TypeReference ("var"); returnType.IsKeyword = true; } else { returnType = options.ShortenTypeName (resolveResult.ResolvedType).ConvertToTypeReference (); } options.ParseMember (resolveResult.CallingMember); TextReplaceChange insert = new TextReplaceChange (); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString ("Insert variable declaration"); LocalVariableDeclaration varDecl = new LocalVariableDeclaration (returnType); varDecl.Variables.Add (new VariableDeclaration (varName, provider.ParseExpression (data.SelectedText))); GetContainingEmbeddedStatementVisitor blockVisitor = new GetContainingEmbeddedStatementVisitor (); blockVisitor.LookupLocation = new Location (data.Caret.Column, data.Caret.Line ); unit.AcceptVisitor (blockVisitor, null); StatementWithEmbeddedStatement containing = blockVisitor.ContainingStatement as StatementWithEmbeddedStatement; if (containing != null && !(containing.EmbeddedStatement is BlockStatement)) { insert.Offset = data.Document.LocationToOffset (containing.StartLocation.Line, containing.StartLocation.Column); lineSegment = data.Document.GetLineByOffset (insert.Offset); insert.RemovedChars = data.Document.LocationToOffset (containing.EndLocation.Line, containing.EndLocation.Column) - insert.Offset; BlockStatement insertedBlock = new BlockStatement (); insertedBlock.AddChild (varDecl); insertedBlock.AddChild (containing.EmbeddedStatement); containing.EmbeddedStatement = insertedBlock; insert.InsertedText = provider.OutputNode (options.Dom, containing, options.GetWhitespaces (lineSegment.Offset)).TrimStart (); int offset, length; if (SearchSubExpression (insert.InsertedText, data.SelectedText, 0, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring (0, offset) + varName + insert.InsertedText.Substring (offset + length); insertOffset = insert.Offset + offset; } } else if (blockVisitor.ContainingStatement is IfElseStatement) { IfElseStatement ifElse = blockVisitor.ContainingStatement as IfElseStatement; insert.Offset = data.Document.LocationToOffset (blockVisitor.ContainingStatement.StartLocation.Line, blockVisitor.ContainingStatement.StartLocation.Column); lineSegment = data.Document.GetLineByOffset (insert.Offset); insert.RemovedChars = data.Document.LocationToOffset (blockVisitor.ContainingStatement.EndLocation.Line, blockVisitor.ContainingStatement.EndLocation.Column) - insert.Offset; BlockStatement insertedBlock = new BlockStatement (); insertedBlock.AddChild (varDecl); if (blockVisitor.ContainsLocation (ifElse.TrueStatement[0])) { insertedBlock.AddChild (ifElse.TrueStatement[0]); ifElse.TrueStatement[0] = insertedBlock; } else { insertedBlock.AddChild (ifElse.FalseStatement[0]); ifElse.FalseStatement[0] = insertedBlock; } insert.InsertedText = provider.OutputNode (options.Dom, blockVisitor.ContainingStatement, options.GetWhitespaces (lineSegment.Offset)); int offset, length; if (SearchSubExpression (insert.InsertedText, provider.OutputNode (options.Dom, insertedBlock), 0, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) if (SearchSubExpression (insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring (0, offset) + varName + insert.InsertedText.Substring (offset + length); insertOffset = insert.Offset + offset; } } else { lineSegment = data.Document.GetLine (data.Caret.Line); insert.Offset = lineSegment.Offset; insert.InsertedText = options.GetWhitespaces (lineSegment.Offset) + provider.OutputNode (options.Dom, varDecl) + Environment.NewLine; insertOffset = insert.Offset + options.GetWhitespaces (lineSegment.Offset).Length + provider.OutputNode (options.Dom, varDecl.TypeReference).Length + " ".Length; 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); replaceOffset = replace.Offset; if (insert.Offset < replaceOffset) replaceOffset += insert.InsertedText.Length - insert.RemovedChars; varCount++; } result.Add (insert); varCount++; selectionStart = insert.Offset; return result; } lineSegment = data.Document.GetLine (data.Caret.Line); string line = data.Document.GetTextAt (lineSegment); Expression expression = provider.ParseExpression (line); if (expression == null) return result; resolveResult = resolver.Resolve (new ExpressionResult (line), new DomLocation (options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column)); if (resolveResult.ResolvedType != null && !string.IsNullOrEmpty (resolveResult.ResolvedType.FullName)) { TextReplaceChange insert = new TextReplaceChange (); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString ("Insert variable declaration"); insert.Offset = lineSegment.Offset + options.GetWhitespaces (lineSegment.Offset).Length; varName = CreateVariableName (resolveResult.ResolvedType, visitor); LocalVariableDeclaration varDecl = new LocalVariableDeclaration (options.ShortenTypeName (resolveResult.ResolvedType).ConvertToTypeReference ()); varDecl.Variables.Add (new VariableDeclaration (varName, expression)); insert.RemovedChars = expression.EndLocation.Column - 1; insert.InsertedText = provider.OutputNode (options.Dom, varDecl); insertOffset = insert.Offset + provider.OutputNode (options.Dom, varDecl.TypeReference).Length + " ".Length; result.Add (insert); varCount++; int idx = 0; while (idx < insert.InsertedText.Length - varName.Length) { if (insert.InsertedText.Substring (idx, varName.Length) == varName && (idx == 0 || insert.InsertedText[idx - 1] == ' ') && (idx == insert.InsertedText.Length - varName.Length - 1 || insert.InsertedText[idx + varName.Length] == ' ')) { selectionStart = insert.Offset + idx; selectionEnd = selectionStart + varName.Length; break; } idx++; } } return result; }
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(); if (resolver == null || provider == null) { return(result); } TextEditorData data = options.GetTextEditorData(); if (data == null) { return(result); } ResolveResult resolveResult; LineSegment lineSegment; ICSharpCode.NRefactory.Ast.CompilationUnit unit = provider.ParseFile(data.Document.Text); MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor visitor = new MonoDevelop.Refactoring.ExtractMethod.VariableLookupVisitor(resolver, new DomLocation(data.Caret.Line, data.Caret.Column)); if (options.ResolveResult == null) { LoggingService.LogError("resolve result == null:" + options.ResolveResult); return(result); } IMember callingMember = options.ResolveResult.CallingMember; if (callingMember != null) { visitor.MemberLocation = new Location(callingMember.Location.Column, callingMember.Location.Line); } unit.AcceptVisitor(visitor, null); if (data.IsSomethingSelected) { 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(data.Caret.Line, data.Caret.Column)); if (resolveResult == null) { return(result); } IReturnType resolvedType = resolveResult.ResolvedType; if (resolvedType == null || string.IsNullOrEmpty(resolvedType.Name)) { resolvedType = DomReturnType.Object; } varName = CreateVariableName(resolvedType, visitor); TypeReference returnType; if (resolveResult.ResolvedType == null || string.IsNullOrEmpty(resolveResult.ResolvedType.Name)) { returnType = new TypeReference("var"); returnType.IsKeyword = true; } else { returnType = options.ShortenTypeName(resolveResult.ResolvedType).ConvertToTypeReference(); } options.ParseMember(resolveResult.CallingMember); TextReplaceChange insert = new TextReplaceChange(); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString("Insert variable declaration"); LocalVariableDeclaration varDecl = new LocalVariableDeclaration(returnType); varDecl.Variables.Add(new VariableDeclaration(varName, provider.ParseExpression(data.SelectedText))); GetContainingEmbeddedStatementVisitor blockVisitor = new GetContainingEmbeddedStatementVisitor(); blockVisitor.LookupLocation = new Location(data.Caret.Column + 1, data.Caret.Line + 1); unit.AcceptVisitor(blockVisitor, null); StatementWithEmbeddedStatement containing = blockVisitor.ContainingStatement as StatementWithEmbeddedStatement; if (containing != null && !(containing.EmbeddedStatement is BlockStatement)) { insert.Offset = data.Document.LocationToOffset(containing.StartLocation.Line - 1, containing.StartLocation.Column - 1); lineSegment = data.Document.GetLineByOffset(insert.Offset); insert.RemovedChars = data.Document.LocationToOffset(containing.EndLocation.Line - 1, containing.EndLocation.Column - 1) - insert.Offset; BlockStatement insertedBlock = new BlockStatement(); insertedBlock.AddChild(varDecl); insertedBlock.AddChild(containing.EmbeddedStatement); containing.EmbeddedStatement = insertedBlock; insert.InsertedText = provider.OutputNode(options.Dom, containing, options.GetWhitespaces(lineSegment.Offset)).TrimStart(); int offset, length; if (SearchSubExpression(insert.InsertedText, data.SelectedText, 0, out offset, out length)) { if (SearchSubExpression(insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring(0, offset) + varName + insert.InsertedText.Substring(offset + length); insertOffset = insert.Offset + offset; } } } else if (blockVisitor.ContainingStatement is IfElseStatement) { IfElseStatement ifElse = blockVisitor.ContainingStatement as IfElseStatement; insert.Offset = data.Document.LocationToOffset(blockVisitor.ContainingStatement.StartLocation.Line - 1, blockVisitor.ContainingStatement.StartLocation.Column - 1); lineSegment = data.Document.GetLineByOffset(insert.Offset); insert.RemovedChars = data.Document.LocationToOffset(blockVisitor.ContainingStatement.EndLocation.Line - 1, blockVisitor.ContainingStatement.EndLocation.Column - 1) - insert.Offset; BlockStatement insertedBlock = new BlockStatement(); insertedBlock.AddChild(varDecl); if (blockVisitor.ContainsLocation(ifElse.TrueStatement[0])) { insertedBlock.AddChild(ifElse.TrueStatement[0]); ifElse.TrueStatement[0] = insertedBlock; } else { insertedBlock.AddChild(ifElse.FalseStatement[0]); ifElse.FalseStatement[0] = insertedBlock; } insert.InsertedText = provider.OutputNode(options.Dom, blockVisitor.ContainingStatement, options.GetWhitespaces(lineSegment.Offset)); int offset, length; if (SearchSubExpression(insert.InsertedText, provider.OutputNode(options.Dom, insertedBlock), 0, out offset, out length)) { if (SearchSubExpression(insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { if (SearchSubExpression(insert.InsertedText, data.SelectedText, offset + 1, out offset, out length)) { insert.InsertedText = insert.InsertedText.Substring(0, offset) + varName + insert.InsertedText.Substring(offset + length); insertOffset = insert.Offset + offset; } } } } else { lineSegment = data.Document.GetLine(data.Caret.Line); insert.Offset = lineSegment.Offset; insert.InsertedText = options.GetWhitespaces(lineSegment.Offset) + provider.OutputNode(options.Dom, varDecl) + Environment.NewLine; insertOffset = insert.Offset + options.GetWhitespaces(lineSegment.Offset).Length + provider.OutputNode(options.Dom, varDecl.TypeReference).Length + " ".Length; 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); replaceOffset = replace.Offset; if (insert.Offset < replaceOffset) { replaceOffset += insert.InsertedText.Length - insert.RemovedChars; } varCount++; } result.Add(insert); varCount++; selectionStart = insert.Offset; return(result); } lineSegment = data.Document.GetLine(data.Caret.Line); string line = data.Document.GetTextAt(lineSegment); Expression expression = provider.ParseExpression(line); if (expression == null) { return(result); } resolveResult = resolver.Resolve(new ExpressionResult(line), new DomLocation(options.Document.TextEditor.CursorLine, options.Document.TextEditor.CursorColumn)); if (resolveResult.ResolvedType != null && !string.IsNullOrEmpty(resolveResult.ResolvedType.FullName)) { TextReplaceChange insert = new TextReplaceChange(); insert.FileName = options.Document.FileName; insert.Description = GettextCatalog.GetString("Insert variable declaration"); insert.Offset = lineSegment.Offset + options.GetWhitespaces(lineSegment.Offset).Length; varName = CreateVariableName(resolveResult.ResolvedType, visitor); LocalVariableDeclaration varDecl = new LocalVariableDeclaration(options.ShortenTypeName(resolveResult.ResolvedType).ConvertToTypeReference()); varDecl.Variables.Add(new VariableDeclaration(varName, expression)); insert.RemovedChars = expression.EndLocation.Column - 1; insert.InsertedText = provider.OutputNode(options.Dom, varDecl); insertOffset = insert.Offset + provider.OutputNode(options.Dom, varDecl.TypeReference).Length + " ".Length; result.Add(insert); varCount++; int idx = 0; while (idx < insert.InsertedText.Length - varName.Length) { if (insert.InsertedText.Substring(idx, varName.Length) == varName && (idx == 0 || insert.InsertedText[idx - 1] == ' ') && (idx == insert.InsertedText.Length - varName.Length - 1 || insert.InsertedText[idx + varName.Length] == ' ')) { selectionStart = insert.Offset + idx; selectionEnd = selectionStart + varName.Length; break; } idx++; } } return(result); }