bool AnalyzeTargetExpression (RefactoringOptions options, MonoDevelop.CSharp.Ast.CompilationUnit unit) { var data = options.GetTextEditorData (); var target = unit.GetNodeAt (data.Caret.Line, data.Caret.Column); if (target == null) return false; if (target.Parent is MemberReferenceExpression && ((MemberReferenceExpression)target.Parent).GetChildByRole (MemberReferenceExpression.Roles.Identifier) == target) { var memberReference = (MemberReferenceExpression)target.Parent; target = memberReference.Target; var targetResult = options.GetResolver ().Resolve (new ExpressionResult (data.GetTextBetween (target.StartLocation.Line, target.StartLocation.Column, target.EndLocation.Line, target.EndLocation.Column)), resolvePosition); if (targetResult.StaticResolve) modifiers = MonoDevelop.Projects.Dom.Modifiers.Static; declaringType = options.Dom.GetType (targetResult.ResolvedType); methodName = memberReference.MemberName; } else if (target is Identifier) { declaringType = options.ResolveResult.CallingType; methodName = data.GetTextBetween (target.StartLocation.Line, target.StartLocation.Column, target.EndLocation.Line, target.EndLocation.Column); } if (declaringType != null && !HasCompatibleMethod (declaringType, methodName, invocation)) { if (declaringType.HasParts) declaringType = declaringType.Parts.FirstOrDefault (t => t.CompilationUnit.FileName == options.Document.FileName) ?? declaringType; var doc = ProjectDomService.GetParsedDocument (declaringType.SourceProjectDom, declaringType.CompilationUnit.FileName); declaringType = doc.CompilationUnit.GetTypeAt (declaringType.Location) ?? declaringType; return true; } return false; }
bool AnalyzeTargetExpression (RefactoringOptions options, MonoDevelop.CSharp.Dom.CompilationUnit unit) { var data = options.GetTextEditorData (); var target = unit.GetNodeAt (data.Caret.Line, data.Caret.Column); if (target == null) return false; if (target.Parent is MemberReferenceExpression && ((MemberReferenceExpression)target.Parent).Identifier == target) { var memberReference = (MemberReferenceExpression)target.Parent; target = memberReference.Target; var targetResult = options.GetResolver ().Resolve (new ExpressionResult (data.GetTextBetween (target.StartLocation.Line, target.StartLocation.Column, target.EndLocation.Line, target.EndLocation.Column)), resolvePosition); if (targetResult.StaticResolve) modifiers = MonoDevelop.Projects.Dom.Modifiers.Static; declaringType = options.Dom.GetType (targetResult.ResolvedType); methodName = memberReference.Identifier.Name; } else if (target is Identifier) { declaringType = options.ResolveResult.CallingType; methodName = data.GetTextBetween (target.StartLocation.Line, target.StartLocation.Column, target.EndLocation.Line, target.EndLocation.Column); } return declaringType != null && !HasCompatibleMethod (declaringType, methodName, invocation); }
IMethod ConstructMethodFromInvocation (RefactoringOptions options) { var resolver = options.GetResolver (); var data = options.GetTextEditorData (); DomMethod result = new DomMethod (methodName, modifiers, MethodModifier.None, DomLocation.Empty, DomRegion.Empty, returnType); result.DeclaringType = new DomType ("GeneratedType") { ClassType = declaringType.ClassType }; int i = 1; foreach (var curArg in invocation.Arguments) { var argument = curArg; DomParameter arg = new DomParameter (); if (argument is DirectionExpression) { var de = (DirectionExpression)argument; arg.ParameterModifiers = de.FieldDirection == FieldDirection.Out ? ParameterModifiers.Out : ParameterModifiers.Ref; argument = de.Expression; } string argExpression = data.GetTextBetween (argument.StartLocation.Line, argument.StartLocation.Column, argument.EndLocation.Line, argument.EndLocation.Column); var resolveResult = resolver.Resolve (new ExpressionResult (argExpression), resolvePosition); if (argument is MemberReferenceExpression) { arg.Name = ((MemberReferenceExpression)argument).Identifier.Name; } else if (argument is IdentifierExpression) { arg.Name = ((IdentifierExpression)argument).Identifier; int idx = arg.Name.LastIndexOf ('.'); if (idx >= 0) arg.Name = arg.Name.Substring (idx + 1); } else { arg.Name = "par" + i++; } arg.Name = char.ToLower (arg.Name[0]) + arg.Name.Substring (1); if (resolveResult != null) { arg.ReturnType = resolveResult.ResolvedType; } else { arg.ReturnType = DomReturnType.Object; } result.Add (arg); } return result; }
IReturnType GuessReturnType (RefactoringOptions options) { var resolver = options.GetResolver (); var data = options.GetTextEditorData (); DomNode node = invocation; while (node != null) { if (node.Parent is VariableInitializer) { var initializer = (VariableInitializer)node.Parent; var resolveResult = resolver.Resolve (new ExpressionResult (initializer.Name), resolvePosition); return resolveResult.ResolvedType; } if (node.Parent is AssignmentExpression) { var resolveResult = ResolveAssignment (options, (AssignmentExpression)node.Parent); if (resolveResult != null) return resolveResult.ResolvedType; } if (node.Parent is InvocationExpression) { var parentInvocation = (InvocationExpression)node.Parent; int idx = 0; foreach (var arg in parentInvocation.Arguments) { if (arg == node) break; idx++; } var resolveResult = resolver.Resolve (new ExpressionResult (data.GetTextBetween (parentInvocation.StartLocation.Line, parentInvocation.StartLocation.Column, parentInvocation.EndLocation.Line, parentInvocation.EndLocation.Column)), resolvePosition) as MethodResolveResult; if (resolveResult != null) { if (idx < resolveResult.MostLikelyMethod.Parameters.Count) return resolveResult.MostLikelyMethod.Parameters[idx].ReturnType; } return DomReturnType.Object; } node = node.Parent; } return DomReturnType.Void; }
ResolveResult ResolveAssignment (RefactoringOptions options, AssignmentExpression assignment) { var resolver = options.GetResolver (); var data = options.GetTextEditorData (); string expression; if (assignment.Left is IdentifierExpression) { expression = ((IdentifierExpression)assignment.Left).Identifier; } else { var left = assignment.Left; expression = data.GetTextBetween (left.StartLocation.Line, left.StartLocation.Column, left.EndLocation.Line, left.EndLocation.Column); } return resolver.Resolve (new ExpressionResult (expression), resolvePosition); }
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; }