AbstractNode GenerateAstToInsert(string variableName) { var block = new BlockStatement(); block.AddChild(new ExpressionStatement(new IdentifierExpression(caretMarker))); return new IfElseStatement( new BinaryOperatorExpression(new IdentifierExpression(variableName), BinaryOperatorType.InEquality, new PrimitiveExpression(null)), block); }
protected override IEnumerable<string> GenerateCode (INRefactoryASTProvider astProvider, string indent, List<IBaseMember> includedMembers) { // Genereate Equals MethodDeclaration methodDeclaration = new MethodDeclaration (); methodDeclaration.Name = "Equals"; methodDeclaration.TypeReference = DomReturnType.Bool.ConvertToTypeReference (); methodDeclaration.Modifier = ICSharpCode.NRefactory.Ast.Modifiers.Public | ICSharpCode.NRefactory.Ast.Modifiers.Override; methodDeclaration.Body = new BlockStatement (); methodDeclaration.Parameters.Add (new ParameterDeclarationExpression (DomReturnType.Object.ConvertToTypeReference (), "obj")); IdentifierExpression paramId = new IdentifierExpression ("obj"); IfElseStatement ifStatement = new IfElseStatement (null); ifStatement.Condition = new BinaryOperatorExpression (paramId, BinaryOperatorType.Equality, new PrimitiveExpression (null)); ifStatement.TrueStatement.Add (new ReturnStatement (new PrimitiveExpression (false))); methodDeclaration.Body.AddChild (ifStatement); ifStatement = new IfElseStatement (null); List<Expression> arguments = new List<Expression> (); arguments.Add (new ThisReferenceExpression ()); arguments.Add (paramId); ifStatement.Condition = new InvocationExpression (new IdentifierExpression ("ReferenceEquals"), arguments); ifStatement.TrueStatement.Add (new ReturnStatement (new PrimitiveExpression (true))); methodDeclaration.Body.AddChild (ifStatement); ifStatement = new IfElseStatement (null); ifStatement.Condition = new BinaryOperatorExpression (new InvocationExpression (new MemberReferenceExpression (paramId, "GetType")), BinaryOperatorType.InEquality, new TypeOfExpression (new TypeReference (Options.EnclosingType.Name))); ifStatement.TrueStatement.Add (new ReturnStatement (new PrimitiveExpression (false))); methodDeclaration.Body.AddChild (ifStatement); LocalVariableDeclaration varDecl = new LocalVariableDeclaration (new DomReturnType (Options.EnclosingType).ConvertToTypeReference ()); varDecl.Variables.Add (new VariableDeclaration ("other", new CastExpression (varDecl.TypeReference, paramId, CastType.Cast))); methodDeclaration.Body.AddChild (varDecl); IdentifierExpression otherId = new IdentifierExpression ("other"); Expression binOp = null; foreach (IMember member in includedMembers) { Expression right = new BinaryOperatorExpression (new IdentifierExpression (member.Name), BinaryOperatorType.Equality, new MemberReferenceExpression (otherId, member.Name)); if (binOp == null) { binOp = right; } else { binOp = new BinaryOperatorExpression (binOp, BinaryOperatorType.LogicalAnd, right); } } methodDeclaration.Body.AddChild (new ReturnStatement (binOp)); yield return astProvider.OutputNode (this.Options.Dom, methodDeclaration, indent); methodDeclaration = new MethodDeclaration (); methodDeclaration.Name = "GetHashCode"; methodDeclaration.TypeReference = DomReturnType.Int32.ConvertToTypeReference (); methodDeclaration.Modifier = ICSharpCode.NRefactory.Ast.Modifiers.Public | ICSharpCode.NRefactory.Ast.Modifiers.Override; methodDeclaration.Body = new BlockStatement (); binOp = null; foreach (IMember member in includedMembers) { Expression right; right = new InvocationExpression (new MemberReferenceExpression (new IdentifierExpression (member.Name), "GetHashCode")); IType type = Options.Dom.SearchType (Options.Document.ParsedDocument.CompilationUnit, member, member.ReturnType); if (type != null && type.ClassType != MonoDevelop.Projects.Dom.ClassType.Struct&& type.ClassType != MonoDevelop.Projects.Dom.ClassType.Enum) right = new ParenthesizedExpression (new ConditionalExpression (new BinaryOperatorExpression (new IdentifierExpression (member.Name), BinaryOperatorType.InEquality, new PrimitiveExpression (null)), right, new PrimitiveExpression (0))); if (binOp == null) { binOp = right; } else { binOp = new BinaryOperatorExpression (binOp, BinaryOperatorType.ExclusiveOr, right); } } BlockStatement uncheckedBlock = new BlockStatement (); uncheckedBlock.AddChild (new ReturnStatement (binOp)); methodDeclaration.Body.AddChild (new UncheckedStatement (uncheckedBlock)); yield return astProvider.OutputNode (this.Options.Dom, methodDeclaration, indent); }
public override object VisitForeachStatement(ForeachStatement foreachStatement, object data) { base.VisitForeachStatement(foreachStatement, data); if (resolver.CompilationUnit == null) return null; if (foreachStatement.TypeReference.IsNull) { ResolveResult rr = resolver.ResolveIdentifier(foreachStatement.VariableName, foreachStatement.StartLocation, ExpressionContext.Default); if (rr != null && rr.ResolvedType != null) { BlockStatement blockStatement = foreachStatement.EmbeddedStatement as BlockStatement; if (blockStatement == null) { blockStatement = new BlockStatement(); blockStatement.AddChild(foreachStatement.EmbeddedStatement); foreachStatement.EmbeddedStatement = blockStatement; } string newVariableName = foreachStatement.VariableName + "_loopVariable"; ExpressionStatement st = new ExpressionStatement( new AssignmentExpression( new IdentifierExpression(foreachStatement.VariableName), AssignmentOperatorType.Assign, new IdentifierExpression(newVariableName))); blockStatement.Children.Insert(0, st); st.Parent = blockStatement; foreachStatement.VariableName = newVariableName; foreachStatement.TypeReference = ConvertType(rr.ResolvedType); } } return null; }
protected override string GenerateCode(LanguageProperties language, IClass currentClass) { IDocumentLine line = editor.Document.GetLineForOffset(anchor.Offset); string indent = DocumentUtilitites.GetWhitespaceAfter(editor.Document, line.Offset); List<PropertyOrFieldWrapper> filtered = parameterList .Where(p => p.IsSelected) .OrderBy(p => p.Index) .ToList(); BlockStatement block = new BlockStatement(); foreach (PropertyOrFieldWrapper w in filtered) { if (w.AddCheckForNull) { // true = reference, null = generic or unknown if (w.Type.IsReferenceType != false) block.AddChild( new IfElseStatement( new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.Equality, new PrimitiveExpression(null)), new ThrowStatement(new ObjectCreateExpression(new TypeReference("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) ) ); else block.AddChild( new IfElseStatement( new UnaryOperatorExpression(new MemberReferenceExpression(new IdentifierExpression(w.MemberName), "HasValue"), UnaryOperatorType.Not), new ThrowStatement(new ObjectCreateExpression(new TypeReference("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) ) ); } if (w.AddRangeCheck) { block.AddChild( new IfElseStatement( new BinaryOperatorExpression( new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.LessThan, new IdentifierExpression("lower")), BinaryOperatorType.LogicalOr, new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.GreaterThan, new IdentifierExpression("upper")) ), new ThrowStatement( new ObjectCreateExpression( new TypeReference("ArgumentOutOfRangeException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"'), new IdentifierExpression(w.ParameterName), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Concat, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Concat, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Concat, new IdentifierExpression("upper")))) } ) ) ) ); } } foreach (PropertyOrFieldWrapper w in filtered) block.AddChild(new ExpressionStatement(new AssignmentExpression(new MemberReferenceExpression(new ThisReferenceExpression(), w.MemberName), AssignmentOperatorType.Assign, new IdentifierExpression(w.ParameterName)))); AnchorElement parameterListElement = context.ActiveElements .OfType<AnchorElement>() .FirstOrDefault(item => item.Name.Equals("parameterList", StringComparison.OrdinalIgnoreCase)); if (parameterListElement != null) { StringBuilder pList = new StringBuilder(); var parameters = filtered .Select(p => new ParameterDeclarationExpression(ConvertType(p.Type), p.ParameterName)) .ToList(); for (int i = 0; i < parameters.Count; i++) { if (i > 0) pList.Append(", "); pList.Append(language.CodeGenerator.GenerateCode(parameters[i], "")); } parameterListElement.Text = pList.ToString(); } StringBuilder builder = new StringBuilder(); foreach (var element in block.Children.OfType<AbstractNode>()) { builder.Append(language.CodeGenerator.GenerateCode(element, indent)); } return builder.ToString().Trim(); }
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) { List<Change> result = new List<Change> (); MemberResolveResult resolveResult = options.ResolveResult as MemberResolveResult; IProperty property = resolveResult.ResolvedMember as IProperty; TextEditorData data = options.GetTextEditorData (); INRefactoryASTProvider astProvider = options.GetASTProvider (); backingStoreName = GetBackingStoreName (property); FieldDeclaration backingStore = new FieldDeclaration (null); backingStore.TypeReference = options.Document.CompilationUnit.ShortenTypeName (property.ReturnType, property.Location).ConvertToTypeReference (); backingStore.Fields.Add (new VariableDeclaration (backingStoreName)); DocumentLocation location = property.Location.ToDocumentLocation (data.Document); location.Column = 0; refactoringStartOffset = data.Document.LocationToOffset (location); result.Add (new TextReplaceChange () { FileName = options.Document.FileName, Offset = refactoringStartOffset, InsertedText = astProvider.OutputNode (options.Dom, backingStore, options.GetIndent (property)) }); if (property.HasGet) { int startOffset = data.Document.LocationToOffset (property.GetRegion.Start.ToDocumentLocation (data.Document)); int endOffset = data.Document.LocationToOffset (property.GetRegion.End.ToDocumentLocation (data.Document)); BlockStatement getBlock = new BlockStatement (); getBlock.AddChild (new ReturnStatement (new IdentifierExpression (backingStoreName))); string text = astProvider.OutputNode (options.Dom, new PropertyGetRegion (getBlock, null), options.GetIndent (property) + "\t").Trim (); result.Add (new TextReplaceChange () { FileName = options.Document.FileName, Offset = startOffset, RemovedChars = endOffset - startOffset, InsertedText = text }); } if (property.HasSet) { int startOffset = data.Document.LocationToOffset (property.SetRegion.Start.ToDocumentLocation (data.Document)); int endOffset = data.Document.LocationToOffset (property.SetRegion.End.ToDocumentLocation (data.Document)); BlockStatement setBlock = new BlockStatement (); setBlock.AddChild (new ExpressionStatement (new AssignmentExpression (new IdentifierExpression (backingStoreName), AssignmentOperatorType.Assign, new IdentifierExpression ("value")))); string text = astProvider.OutputNode (options.Dom, new PropertySetRegion (setBlock, null), options.GetIndent (property) + "\t").Trim (); result.Add (new TextReplaceChange () { FileName = options.Document.FileName, Offset = startOffset, RemovedChars = endOffset - startOffset, InsertedText = text }); } return result; }
void AddToBlock(VariableDeclaration hashCodeVar, MethodDeclaration getHashCodeMethod, bool usePrimeMultiplication, BlockStatement hashCalculationBlock, ref int fieldIndex, IProperty property) { Expression expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(property.Name), "GetHashCode")); if (usePrimeMultiplication) { int prime = largePrimes[fieldIndex++ % largePrimes.Length]; expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr)); } else { expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.ExclusiveOr, expr); } if (IsValueType(property.ReturnType)) { hashCalculationBlock.AddChild(new ExpressionStatement(expr)); } else { hashCalculationBlock.AddChild(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(property.Name), BinaryOperatorType.ReferenceInequality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr))); } }
protected override IEnumerable<ICSharpCode.NRefactory.Ast.INode> GenerateCode (List<IBaseMember> includedMembers) { foreach (IMember member in includedMembers) { ICSharpCode.NRefactory.Ast.Modifiers modifier = (((ICSharpCode.NRefactory.Ast.Modifiers)member.Modifiers) & ~(ICSharpCode.NRefactory.Ast.Modifiers.Abstract | ICSharpCode.NRefactory.Ast.Modifiers.Virtual)); bool isInterfaceMember = member.DeclaringType.ClassType == MonoDevelop.Projects.Dom.ClassType.Interface; if (!isInterfaceMember) modifier |= ICSharpCode.NRefactory.Ast.Modifiers.Override; if (isInterfaceMember) modifier |= ICSharpCode.NRefactory.Ast.Modifiers.Public; MemberReferenceExpression baseReference = new MemberReferenceExpression (new BaseReferenceExpression (), member.Name); if (member is IMethod) { IMethod method = (IMethod)member; MethodDeclaration methodDeclaration = new MethodDeclaration () { Name = method.Name, TypeReference = member.ReturnType.ConvertToTypeReference (), Modifier = modifier, Body = new BlockStatement () }; List<Expression> arguments = new List<Expression> (); foreach (IParameter parameter in method.Parameters) { methodDeclaration.Parameters.Add (new ParameterDeclarationExpression (Options.ShortenTypeName (parameter.ReturnType.ConvertToTypeReference ()), parameter.Name, GetModifier (parameter))); arguments.Add (new DirectionExpression (GetDirection (parameter), new IdentifierExpression (parameter.Name))); } if (isInterfaceMember) { methodDeclaration.Body.AddChild (throwNotImplemented); } else { InvocationExpression baseInvocation = new InvocationExpression (baseReference, arguments); if (method.ReturnType.FullName == "System.Void") { methodDeclaration.Body.AddChild (new ExpressionStatement (baseInvocation)); } else { methodDeclaration.Body.AddChild (new ReturnStatement (baseInvocation)); } } yield return methodDeclaration; } if (member is IProperty) { IProperty property = (IProperty)member; PropertyDeclaration propertyDeclaration = new PropertyDeclaration (modifier, null, member.Name, null); propertyDeclaration.TypeReference = Options.ShortenTypeName (member.ReturnType.ConvertToTypeReference ()); if (property.HasGet) { BlockStatement block = new BlockStatement (); block.AddChild (isInterfaceMember ? throwNotImplemented : new ReturnStatement (baseReference)); propertyDeclaration.GetRegion = new PropertyGetRegion (block, null); } if (property.HasSet) { BlockStatement block = new BlockStatement (); block.AddChild (isInterfaceMember ? throwNotImplemented : new ExpressionStatement (new AssignmentExpression (baseReference, AssignmentOperatorType.Assign, new IdentifierExpression ("value")))); propertyDeclaration.SetRegion = new PropertySetRegion (block, null); } yield return propertyDeclaration; } } }