public override bool IsValid(RefactoringOptions options) { IResolver resolver = options.GetResolver(); INRefactoryASTProvider provider = options.GetASTProvider(); if (resolver == null || provider == null) { return(false); } TextEditorData data = options.GetTextEditorData(); if (data == null) { return(false); } if (data.IsSomethingSelected) { ExpressionResult expressionResult = new ExpressionResult(data.SelectedText.Trim()); if (expressionResult.Expression.Contains(" ") || expressionResult.Expression.Contains("\t")) { expressionResult.Expression = "(" + expressionResult.Expression + ")"; } var endPoint = data.MainSelection.Anchor < data.MainSelection.Lead ? data.MainSelection.Lead : data.MainSelection.Anchor; options.ResolveResult = resolver.Resolve(expressionResult, new DomLocation(endPoint.Line, endPoint.Column)); if (options.ResolveResult == null) { return(false); } if (options.ResolveResult.CallingMember == null || !options.ResolveResult.CallingMember.BodyRegion.Contains(endPoint.Line, endPoint.Column)) { return(false); } return(true); } LineSegment lineSegment = data.Document.GetLine(data.Caret.Line); string line = data.Document.GetTextAt(lineSegment); Expression expression = provider.ParseExpression(line); BlockStatement block = provider.ParseText(line) as BlockStatement; if (expression == null || (block != null && block.Children [0] is LocalVariableDeclaration)) { return(false); } options.ResolveResult = resolver.Resolve(new ExpressionResult(line), new DomLocation(options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column)); return(options.ResolveResult.ResolvedType != null && !string.IsNullOrEmpty(options.ResolveResult.ResolvedType.FullName) && options.ResolveResult.ResolvedType.FullName != DomReturnType.Void.FullName); }
public override bool IsValid(RefactoringOptions options) { TextEditorData data = options.GetTextEditorData(); LineSegment line = data.Document.GetLine(data.Caret.Line); if (!data.IsSomethingSelected && line != null) { Stack <Span> stack = line.StartSpan != null ? new Stack <Span> (line.StartSpan) : new Stack <Span> (); Mono.TextEditor.Highlighting.SyntaxModeService.ScanSpans(data.Document, data.Document.SyntaxMode, data.Document.SyntaxMode, stack, line.Offset, data.Caret.Offset); foreach (Span span in stack) { if (span.Color == "string.single" || span.Color == "string.double") { return(options.Document.CompilationUnit.GetMemberAt(data.Caret.Line, data.Caret.Column) != null); } } } INRefactoryASTProvider provider = options.GetASTProvider(); if (provider == null) { return(false); } string expressionText = null; if (options.ResolveResult != null && options.ResolveResult.ResolvedExpression != null) { expressionText = options.ResolveResult.ResolvedExpression.Expression; } if (string.IsNullOrEmpty(expressionText)) { int start, end; expressionText = SearchNumber(data, out start, out end); } Expression expression = provider.ParseExpression(expressionText); return(expression is PrimitiveExpression); }
public override List <Change> PerformChanges(RefactoringOptions options, object properties) { TextEditorData data = options.GetTextEditorData(); int start, end; MonoDevelop.Refactoring.IntroduceConstant.IntroduceConstantRefactoring.SearchString(data, '"', out start, out end); LineSegment line = data.Document.GetLineByOffset(start); int closingTagLength = 1; // length of the closing " if (end > line.Offset + line.EditableLength) // assume missing closing tag { end = line.Offset + line.EditableLength; closingTagLength = 0; } INRefactoryASTProvider provider = options.GetASTProvider(); List <Expression> args = new List <Expression> (); IExpressionFinder expressionFinder = options.GetParser().CreateExpressionFinder(options.Dom); int expressionStart = start - 1; while (expressionStart > 0) { if (data.Document.GetCharAt(expressionStart) == '(') { expressionStart--; break; } expressionStart--; } // Add parameter to existing string.format call ExpressionResult expressionResult = expressionFinder.FindFullExpression(options.Document.TextEditor.Text, expressionStart); InvocationExpression formatCall = null; if (expressionResult != null) { InvocationExpression possibleFormatCall = provider.ParseExpression(expressionResult.Expression) as InvocationExpression; if (possibleFormatCall != null && possibleFormatCall.TargetObject is MemberReferenceExpression && ((MemberReferenceExpression)possibleFormatCall.TargetObject).MemberName == "Format") { PrimitiveExpression expr = possibleFormatCall.Arguments[0] as PrimitiveExpression; if (expr != null) { string str = data.Document.GetTextBetween(start + 1, data.SelectionRange.Offset) + "{" + (possibleFormatCall.Arguments.Count - 1) + "}" + data.Document.GetTextBetween(data.SelectionRange.EndOffset, end); expr.Value = str; expr.StringValue = '"' + str + '"'; possibleFormatCall.Arguments.Add(new PrimitiveExpression(data.Document.GetTextAt(data.SelectionRange))); formatCall = possibleFormatCall; start = data.Document.LocationToOffset(expressionResult.Region.Start.Line - 1, expressionResult.Region.Start.Column - 1); end = data.Document.LocationToOffset(expressionResult.Region.End.Line - 1, expressionResult.Region.End.Column - 1) - 1; } } } // insert new format call if (formatCall == null) { string formattedString = UnescapeString(data.Document.GetTextBetween(start + 1, data.SelectionRange.Offset) + "{0}" + data.Document.GetTextBetween(data.SelectionRange.EndOffset, end)); args.Add(new PrimitiveExpression(formattedString)); args.Add(new PrimitiveExpression(data.Document.GetTextAt(data.SelectionRange))); TypeReference typeRef = new TypeReference("System.String"); typeRef.IsKeyword = true; MemberReferenceExpression stringFormat = new MemberReferenceExpression(new TypeReferenceExpression(typeRef), "Format"); formatCall = new InvocationExpression(stringFormat, args); } List <Change> changes = new List <Change> (); TextReplaceChange change = new TextReplaceChange(); change.FileName = options.Document.FileName; change.Offset = start; change.RemovedChars = end - start + closingTagLength; change.InsertedText = provider.OutputNode(options.Dom, formatCall); change.MoveCaretToReplace = true; changes.Add(change); return(changes); }
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); }
public override List <Change> PerformChanges(RefactoringOptions options, object properties) { List <Change> result = new List <Change> (); Parameters param = properties as Parameters; if (param == null) { return(result); } TextEditorData data = options.GetTextEditorData(); IResolver resolver = options.GetResolver(); IMember curMember = options.Document.CompilationUnit.GetMemberAt(data.Caret.Line, data.Caret.Column); ResolveResult resolveResult = options.ResolveResult; int start = 0; int end = 0; if (resolveResult == null) { LineSegment line = data.Document.GetLine(data.Caret.Line); if (line != null) { Stack <Span> stack = line.StartSpan != null ? new Stack <Span> (line.StartSpan) : new Stack <Span> (); Mono.TextEditor.Highlighting.SyntaxModeService.ScanSpans(data.Document, data.Document.SyntaxMode, data.Document.SyntaxMode, stack, line.Offset, data.Caret.Offset); foreach (Span span in stack) { if (span.Color == "string.single" || span.Color == "string.double") { resolveResult = resolver.Resolve(new ExpressionResult(SearchString(data, span.Color == "string.single" ? '\'' : '"', out start, out end)), DomLocation.Empty); end++; } } } if (end == 0) { resolveResult = resolver.Resolve(new ExpressionResult(SearchNumber(data, out start, out end)), DomLocation.Empty); } } else { start = data.Document.LocationToOffset(resolveResult.ResolvedExpression.Region.Start.Line - 1, resolveResult.ResolvedExpression.Region.Start.Column - 1); end = data.Document.LocationToOffset(resolveResult.ResolvedExpression.Region.End.Line - 1, resolveResult.ResolvedExpression.Region.End.Column - 1); } if (start == 0 && end == 0) { return(result); } INRefactoryASTProvider provider = options.GetASTProvider(); FieldDeclaration fieldDeclaration = new FieldDeclaration(null); VariableDeclaration varDecl = new VariableDeclaration(param.Name); varDecl.Initializer = provider.ParseExpression(resolveResult.ResolvedExpression.Expression); fieldDeclaration.Fields.Add(varDecl); fieldDeclaration.Modifier = param.Modifiers; fieldDeclaration.Modifier |= ICSharpCode.NRefactory.Ast.Modifiers.Const; fieldDeclaration.TypeReference = resolveResult.ResolvedType.ConvertToTypeReference(); fieldDeclaration.TypeReference.IsKeyword = true; TextReplaceChange insertConstant = new TextReplaceChange(); insertConstant.FileName = options.Document.FileName; insertConstant.Description = string.Format(GettextCatalog.GetString("Generate constant '{0}'"), param.Name); insertConstant.Offset = data.Document.LocationToOffset(curMember.Location.Line - 1, 0); insertConstant.InsertedText = provider.OutputNode(options.Dom, fieldDeclaration, options.GetIndent(curMember)) + Environment.NewLine; result.Add(insertConstant); TextReplaceChange replaceConstant = new TextReplaceChange(); replaceConstant.FileName = options.Document.FileName; replaceConstant.Description = string.Format(GettextCatalog.GetString("Replace expression with constant '{0}'"), param.Name); replaceConstant.Offset = start; replaceConstant.RemovedChars = end - start; replaceConstant.InsertedText = param.Name; result.Add(replaceConstant); 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(); 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); }