示例#1
0
        public override object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data)
        {
            if (searchedMember is LocalVariable)
            {
                LocalVariable searchedVariable          = (LocalVariable)searchedMember;
                ICSharpCode.NRefactory.Ast.INode parent = localVariableDeclaration.Parent;
                while (parent != null && !(parent is MemberNode) && !(parent is ParametrizedNode))
                {
                    parent = parent.Parent;
                }

                if (parent != null &&
                    localVariableDeclaration.StartLocation.Line == searchedVariable.Location.Line &&
                    localVariableDeclaration.StartLocation.Column == searchedVariable.Location.Column &&
                    parent.StartLocation.Line == searchedVariable.DeclaringMember.Location.Line &&
                    parent.StartLocation.Column == searchedVariable.DeclaringMember.Location.Column)
                {
                    foreach (VariableDeclaration decl in localVariableDeclaration.Variables)
                    {
                        if (decl.Name == searchedMemberName)
                        {
                            AddUniqueReference(decl.StartLocation.Y, decl.StartLocation.X, searchedMemberName);
                        }
                    }
                }
            }
            return(base.VisitLocalVariableDeclaration(localVariableDeclaration, data));
        }
示例#2
0
        public override List <Change> PerformChanges(RefactoringOptions options, object prop)
        {
            IResolver              resolver = options.GetResolver();
            List <Change>          result   = new List <Change> ();
            INRefactoryASTProvider provider = options.GetASTProvider();

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

            TypeDeclaration newType = new TypeDeclaration(ICSharpCode.NRefactory.Ast.Modifiers.None, null);

            newType.Name = createExpression.CreateType.Type;
            newType.Type = GetNewTypeType();

            ConstructorDeclaration constructor = new ConstructorDeclaration(newType.Name, ICSharpCode.NRefactory.Ast.Modifiers.Public, null, null);

            constructor.Body = new BlockStatement();
            int i = 0;

            foreach (Expression expression in createExpression.Parameters)
            {
                i++;
                string output = provider.OutputNode(options.Dom, expression);
                string parameterName;
                if (Char.IsLetter(output[0]) || output[0] == '_')
                {
                    parameterName = output;
                }
                else
                {
                    parameterName = "par" + i;
                }

                ResolveResult resolveResult2 = resolver.Resolve(new ExpressionResult(output), options.ResolveResult.ResolvedExpression.Region.Start);
                TypeReference typeReference  = new TypeReference(resolveResult2.ResolvedType.ToInvariantString());
                typeReference.IsKeyword = true;
                ParameterDeclarationExpression pde = new ParameterDeclarationExpression(typeReference, parameterName);
                constructor.Parameters.Add(pde);
            }
            ICSharpCode.NRefactory.Ast.INode node = newType;
            IType curType = options.Document.CompilationUnit.GetTypeAt(options.Document.Editor.Caret.Line, options.Document.Editor.Caret.Column);

            if (curType != null && !string.IsNullOrEmpty(curType.Namespace))
            {
                NamespaceDeclaration namespaceDeclaration = new NamespaceDeclaration(curType.Namespace);
                namespaceDeclaration.Children.Add(newType);
                node = namespaceDeclaration;
            }
            newType.Children.Add(constructor);
            string fileName = GetName(Path.Combine(Path.GetDirectoryName(options.Document.FileName), newType.Name + Path.GetExtension(options.Document.FileName)));
            string header   = options.Dom.Project is DotNetProject?StandardHeaderService.GetHeader(options.Dom.Project, fileName, true) + Environment.NewLine : "";

            CreateFileChange createFile = new CreateFileChange(fileName, header + provider.OutputNode(options.Dom, node));

            result.Add(createFile);
            result.Add(new OpenFileChange(fileName));
            return(result);
        }
示例#3
0
            internal static void EvaluateComplexityMetrics(ICSharpCode.NRefactory.Ast.INode method, MethodProperties props)
            {
                props.CyclometricComplexity = 1;
                props.LOCReal           = 0;
                props.NumberOfVariables = 0;

                cls = props.ParentClass;

                ASTVisitor ctxAstVisitor = new ASTVisitor();

                if (method is MethodDeclaration)
                {
                    foreach (var statement in ((MethodDeclaration)method).Body.Children)
                    {
                        ctxAstVisitor.VisitStatement(statement, props);
                    }
                }
                else if (method is ConstructorDeclaration)
                {
                    foreach (var statement in ((ConstructorDeclaration)method).Body.Children)
                    {
                        ctxAstVisitor.VisitStatement(statement, props);
                    }
                }
                cls.CyclometricComplexity += props.CyclometricComplexity;
            }
        bool DoCaseCompletion(SharpDevelopTextAreaControl editor)
        {
            ICSharpCode.TextEditor.Caret caret = editor.ActiveTextAreaControl.Caret;
            NRefactoryResolver           r     = new NRefactoryResolver(LanguageProperties.CSharp);

            if (r.Initialize(ParserService.GetParseInformation(editor.FileName), caret.Line + 1, caret.Column + 1))
            {
                AST.INode currentMember = r.ParseCurrentMember(editor.Text);
                if (currentMember != null)
                {
                    CaseCompletionSwitchFinder ccsf = new CaseCompletionSwitchFinder(caret.Line + 1, caret.Column + 1);
                    currentMember.AcceptVisitor(ccsf, null);
                    if (ccsf.bestStatement != null)
                    {
                        r.RunLookupTableVisitor(currentMember);
                        ResolveResult rr = r.ResolveInternal(ccsf.bestStatement.SwitchExpression, ExpressionContext.Default);
                        if (rr != null && rr.ResolvedType != null)
                        {
                            return(ProvideContextCompletion(editor, rr.ResolvedType, ' '));
                        }
                    }
                }
            }
            return(false);
        }
        bool IsSearchedNode(ICSharpCode.NRefactory.Ast.INode node)
        {
            if (node == null || node.StartLocation.IsEmpty)
            {
                return(false);
            }
            foreach (var tuple in searchedMembers)
            {
                var searchedMember         = tuple.Item1;
                var searchedMemberFile     = tuple.Item3;
                var searchedMemberLocation = tuple.Item4;

                if (searchedMember is CompoundType)
                {
                    foreach (IType part in ((CompoundType)searchedMember).Parts)
                    {
                        if (fileName == part.CompilationUnit.FileName &&
                            node.StartLocation.Line == part.Location.Line
//						&& node.StartLocation.Column == part.Location.Column
                            )
                        {
                            return(true);
                        }
                    }
                }

                return((string.IsNullOrEmpty(searchedMemberFile) || fileName == searchedMemberFile) &&
                       node.StartLocation.Line == searchedMemberLocation.Line
//					&& node.StartLocation.Column == this.searchedMemberLocation.Column
                       );
            }
            return(false);
        }
示例#6
0
 void CheckNode(ICSharpCode.NRefactory.Ast.INode node)
 {
     if (IsSearchedNode(node))
     {
         int line, column;
         if (SearchText(searchedMemberName, node.StartLocation.Line, node.StartLocation.Column, out line, out column))
         {
             AddUniqueReference(line, column, searchedMemberName);
         }
     }
 }
 public override bool IsValid(RefactoringOptions options)
 {
     if (!(options.SelectedItem is LocalVariable))
     {
         //				Console.WriteLine ("!!! Item is not LocalVariable");
         return(false);
     }
     ICSharpCode.NRefactory.Ast.INode result = GetMemberBodyNode(options);
     if (result == null)
     {
         return(false);
     }
     return(true);
 }
示例#8
0
 private void VisitStatement(ICSharpCode.NRefactory.Ast.INode statement, MethodProperties meth)
 {
     try{
         if (statement is BlockStatement)
         {
             VisitStatement((BlockStatement)statement, meth);
         }
         else if (statement is IfElseStatement)
         {
             VisitStatement((IfElseStatement)statement, meth);
         }
         else if (statement is ElseIfSection)
         {
             VisitStatement((ElseIfSection)statement, meth);
         }
         else if (statement is ForeachStatement)
         {
             VisitStatement((ForeachStatement)statement, meth);
         }
         else if (statement is ForStatement)
         {
             VisitStatement((ForStatement)statement, meth);
         }
         else if (statement is ForNextStatement)
         {
             VisitStatement((ForNextStatement)statement, meth);
         }
         else if (statement is DoLoopStatement)
         {
             VisitStatement((DoLoopStatement)statement, meth);
         }
         else if (statement is SwitchStatement)
         {
             VisitStatement((SwitchStatement)statement, meth);
         }
         else if (statement is LocalVariableDeclaration)
         {
             VisitStatement((LocalVariableDeclaration)statement, meth);
         }
         else if (statement is ExpressionStatement)
         {
             VisitStatement((ExpressionStatement)statement, meth);
         }
     }catch (Exception ex) {
         Console.WriteLine(ex.ToString());
     }
     //See other potential types to exploit
 }
示例#9
0
        public MethodProperties(IMethod m)
        {
            mthd          = m;
            mthdAst       = null;
            ParameterList = new List <string> (0);
            foreach (var param in m.Parameters)
            {
                ParameterList.Add(param.ReturnType.FullName);
            }

            AfferentCoupling = 0;
            EfferentCoupling = 0;
            FilePath         = "";
            this.FullName    = mthd.FullName;
            this.StartLine   = mthd.BodyRegion.Start.Line;
            this.EndLine     = mthd.BodyRegion.End.Line;
        }
示例#10
0
 private static void ProcessNode(MetricsContext ctx, ICSharpCode.NRefactory.Ast.INode node)
 {
     if (node is UsingStatement)
     {
         //TODO do something (something to do with afferent and efferent coupling of namespaces)
     }
     else if (node is NamespaceDeclaration)
     {
         try {
             PrefixName.Push(((NamespaceDeclaration)node).Name);
             LOCEvaluate.EvaluateNamespaceLOC(ctx, (NamespaceDeclaration)node);
             PrefixName.Pop();
         } catch (Exception e) {
         }
     }
     else if (node is TypeDeclaration)
     {
         LOCEvaluate.EvaluateTypeLOC(ctx, null, (TypeDeclaration)node, node.StartLocation.Line);
     }
 }
        protected override void BeginVisit(ICSharpCode.NRefactory.Ast.INode node)
        {
            StatementWithEmbeddedStatement embedded = node as StatementWithEmbeddedStatement;

            if (embedded != null)
            {
                if (ContainsLocation(embedded.EmbeddedStatement))
                {
                    statementStack.Push(embedded);
                }
            }
            // if ... else ... is a special case
            if (node is IfElseStatement)
            {
                IfElseStatement ifElse = (IfElseStatement)node;
                if (ifElse.TrueStatement.Count > 0 && ContainsLocation(ifElse.TrueStatement[0]) || ifElse.FalseStatement.Count > 0 && ContainsLocation(ifElse.FalseStatement[0]))
                {
                    statementStack.Push(ifElse);
                }
            }
        }
        public override List <Change> PerformChanges(RefactoringOptions options, object properties)
        {
            ICSharpCode.NRefactory.Ast.INode memberNode = GetMemberBodyNode(options);
            List <Change> changes = new List <Change> ();

            if (memberNode == null)
            {
                return(null);
            }
            try {
                //				Console.WriteLine ("AcceptVisitor");
                //				Console.WriteLine ("Start: " + memberNode.StartLocation.ToString () + " - End: " + memberNode.EndLocation.ToString ());
                memberNode.AcceptVisitor(new IntegrateTemporaryVariableVisitor(), new IntegrateTemporaryVariableVisitorOptions(changes, options));
                //				Console.WriteLine ("AcceptVisitor done");
            } catch (IntegrateTemporaryVariableException e) {
                //				Console.WriteLine ("Exception catched");
                MessageService.ShowError("Could not perform integration : ", e.Message);
                return(new List <Change>());
            }
//			Console.WriteLine ("Changes calculated");
            return(changes);
        }
示例#13
0
        public MethodProperties(ICSharpCode.NRefactory.Ast.INode m, ClassProperties prop)
        {
            mthd          = null;
            ParameterList = new List <string> (0);
            if (m is MethodDeclaration)
            {
                mthdAst = (MethodDeclaration)m;
                VisitMethodMember((MethodDeclaration)m, prop);
                this.FullName = prop.FullName + "." + ((MethodDeclaration)m).Name.Substring(((MethodDeclaration)m).Name.LastIndexOf(".") + 1);
            }
            else if (m is ConstructorDeclaration)
            {
                mthdAst = (ConstructorDeclaration)m;
                VisitConstructorMember((ConstructorDeclaration)m, prop);
                this.FullName = prop.FullName + "." + ((ConstructorDeclaration)m).Name.Substring(((ConstructorDeclaration)m).Name.LastIndexOf(".") + 1);
            }

            AfferentCoupling = 0;
            EfferentCoupling = 0;
            FilePath         = "";
            this.ParentClass = prop;
            this.StartLine   = mthdAst.StartLocation.Line;
            this.EndLine     = mthdAst.EndLocation.Line;
        }
		public MethodProperties (IMethod m)
		{ 
			mthd = m;
			mthdAst = null;
			ParameterList = new List<string> (0);
			foreach(var param in m.Parameters) {
				ParameterList.Add(param.ReturnType.FullName);
			}
			
			AfferentCoupling=0;
			EfferentCoupling=0;
			FilePath="";
			this.FullName = mthd.FullName;
			this.StartLine = mthd.BodyRegion.Start.Line;
			this.EndLine = mthd.BodyRegion.End.Line;
		}
示例#15
0
        private static void ProcessMethod(MetricsContext ctx, ICSharpCode.NRefactory.Ast.INode method, IProperties parentClass)
        {
            if (method == null)
            {
                return;
            }

            StringBuilder methodName = new StringBuilder("");

            string[] PrefixArray = PrefixName.ToArray();
            for (int i = 0; i < PrefixArray.Length; i++)
            {
                methodName.Append(PrefixArray[PrefixArray.Length - i - 1] + ".");
            }
            List <string> methodParameterList = new List <string>(0);

            if (method is MethodDeclaration)
            {
                methodName.Append(((MethodDeclaration)method).Name);
                foreach (ParameterDeclarationExpression pde in ((MethodDeclaration)method).Parameters)
                {
                    string type = pde.TypeReference.Type;
                    if (type.Contains("."))
                    {
                        type = type.Substring(type.LastIndexOf(".") + 1);
                    }
                    methodParameterList.Add(type);
                }
            }
            else if (method is ConstructorDeclaration)
            {
                methodName.Append(((ConstructorDeclaration)method).Name);
                foreach (ParameterDeclarationExpression pde in ((ConstructorDeclaration)method).Parameters)
                {
                    string type = pde.TypeReference.Type;
                    if (type.Contains("."))
                    {
                        type = type.Substring(type.LastIndexOf(".") + 1);
                    }
                    methodParameterList.Add(type);
                }
            }

            StringBuilder MethodKey = new StringBuilder();

            MethodKey.Append(methodName.ToString() + " ");
            foreach (string paramName in methodParameterList)
            {
                MethodKey.Append(paramName + " ");
            }
            try{
                if (parentClass is ClassProperties)
                {
                    if (!(parentClass as ClassProperties).Methods.ContainsKey(MethodKey.ToString()))
                    {
                        if (method is MethodDeclaration)
                        {
                            (parentClass as ClassProperties).Methods.Add(MethodKey.ToString(), new MethodProperties((MethodDeclaration)method, parentClass as ClassProperties));
                        }
                        else if (method is ConstructorDeclaration)
                        {
                            (parentClass as ClassProperties).Methods.Add(MethodKey.ToString(), new MethodProperties((ConstructorDeclaration)method, parentClass as ClassProperties));
                        }
                    }
                    var currentMethodReference = (parentClass as ClassProperties).Methods[MethodKey.ToString()];
                    //Calculate all metrics here
                    ASTVisitor.EvaluateComplexityMetrics(method, currentMethodReference);
                    LOCEvaluate.EvaluateMethodLOC(currentMethodReference, FileText, FileDoc);
                    currentMethodReference.FilePath = File.FilePath;
                }
            } catch (NullReferenceException ex) {
                LoggingService.LogError("Error in '" + methodName.ToString() + "'", ex);
                Console.WriteLine(MethodKey.ToString() + " hoo");
            }
        }
示例#16
0
        // could work to extend selection to set of adjacent statements separated by blank lines
        Selection ExtendSelection(ITextEditor editor, CompilationUnit parsedCU, IList <ISpecial> commentsBlankLines, out INode selectedResultNode, Type[] interestingNodeTypes)
        {
            selectedResultNode = null;

            var selectionStart = editor.Document.OffsetToPosition(editor.SelectionStart);
            var selectionEnd   = editor.Document.OffsetToPosition(editor.SelectionStart + editor.SelectionLength);

            Ast.INode currentNode = parsedCU.Children.Select(
                n => EditorContext.FindInnermostNodeContainingSelection(n, selectionStart, selectionEnd)).Where(n => n != null).FirstOrDefault();
            if (currentNode == null)
            {
                return(null);
            }
            if (!IsNodeTypeInteresting(currentNode, interestingNodeTypes))
            {
                // ignore uninteresting nodes in the AST
                currentNode = GetInterestingParent(currentNode, interestingNodeTypes);
            }
            if (currentNode == null)
            {
                return(null);
            }
            selectedResultNode = currentNode;

            // whole node already selected -> expand selection
            if (currentNode.StartLocation == selectionStart && currentNode.EndLocation == selectionEnd)
            {
                bool extendToComments = false;
                if (IsNodeTypeInteresting(currentNode, interestingNodeTypes))
                {
                    // if interesting node already selected, we can try to also add comments
                    var selectionExtendedToComments = ExtendSelectionToComments(editor.Document, selectionStart, selectionEnd, commentsBlankLines);
                    if (selectionExtendedToComments != null)
                    {
                        // Can be extended to comments -> extend
                        selectionStart   = selectionExtendedToComments.Start;
                        selectionEnd     = selectionExtendedToComments.End;
                        extendToComments = true;
                    }
                }
                if (!extendToComments)
                {
                    var parent = GetInterestingParent(currentNode, interestingNodeTypes);
                    // it can happen that parent region exactly matches child region - in this case we need to advance even to the next parent
                    // bc otherwise the selection would never move
                    while (parent != null && parent.StartLocation == selectionStart && parent.EndLocation == selectionEnd)
                    {
                        parent = GetInterestingParent(parent, interestingNodeTypes);
                    }
                    if (parent == null)
                    {
                        return(new Selection {
                            Start = selectionStart, End = selectionEnd
                        });
                    }
                    // Select the parent
                    var extendedSelectionStart = parent.StartLocation;
                    var extendedLocationEnd    = parent.EndLocation;
                    selectedResultNode = parent;

                    // if the extended selection would contain blank lines, extend the selection only to the blank lines/comments on both sides (use siblings)
                    //   if the selection contains blank lines or comments on both sides, dont do this
                    var blankLines = commentsBlankLines.Where(s => s is BlankLine).Cast <BlankLine>().ToList();
                    //if (SelectionContainsBlankLines(extendedSelectionStart, extendedLocationEnd, blankLines)) {
                    if (false)                       // blank line separators - implement later

                    {
                    }
                    else
                    {
                        selectionStart = extendedSelectionStart;
                        selectionEnd   = extendedLocationEnd;
                    }
                }
            }
            else
            {
                // select current node
                selectionStart     = currentNode.StartLocation;
                selectionEnd       = currentNode.EndLocation;
                selectedResultNode = currentNode;
            }
            return(new Selection {
                Start = selectionStart, End = selectionEnd
            });
        }
		public MethodProperties (ICSharpCode.NRefactory.Ast.INode m, ClassProperties prop)
		{
			mthd=null;
			ParameterList = new List<string> (0);
			if(m is MethodDeclaration) {
				mthdAst = (MethodDeclaration)m;
				VisitMethodMember((MethodDeclaration)m, prop);
				this.FullName = prop.FullName + "." + ((MethodDeclaration)m).Name.Substring(((MethodDeclaration)m).Name.LastIndexOf(".")+1);
			} else if(m is ConstructorDeclaration) {
				mthdAst = (ConstructorDeclaration)m;
				VisitConstructorMember((ConstructorDeclaration)m, prop);
				this.FullName = prop.FullName + "." + ((ConstructorDeclaration)m).Name.Substring(((ConstructorDeclaration)m).Name.LastIndexOf(".")+1);
			}
			
			AfferentCoupling=0;
			EfferentCoupling=0;
			FilePath="";
			this.ParentClass = prop;
			this.StartLine = mthdAst.StartLocation.Line;
			this.EndLine = mthdAst.EndLocation.Line;

		}
示例#18
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);
        }
示例#19
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);
        }