Esempio n. 1
0
        public static List <IVariable> Analyze(RefactoringContext context, Expression expression)
        {
            var visitor = new VariableLookupVisitor(context);

            expression.AcceptVisitor(visitor);
            return(visitor.UsedVariables);
        }
Esempio n. 2
0
        public static List <IVariable> Analyze(RefactoringContext context, List <AstNode> statements)
        {
            var visitor = new VariableLookupVisitor(context);

            statements.ForEach(stmt => stmt.AcceptVisitor(visitor));
            return(visitor.UsedVariables);
        }
Esempio n. 3
0
        static bool ContainsLocalReferences(RefactoringContext context, AstNode expr, AstNode body)
        {
            var visitor = new ExtractMethod.VariableLookupVisitor(context);

            body.AcceptVisitor(visitor);
            return(visitor.UsedVariables.Any(variable => !expr.Contains(variable.Region.Begin)));
        }
Esempio n. 4
0
        CodeAction CreateFromExpression(RefactoringContext context, Expression expression)
        {
            var resolveResult = context.Resolve(expression);

            if (resolveResult.IsError)
            {
                return(null);
            }

            return(new CodeAction(context.TranslateString("Extract method"), script => {
                string methodName = "NewMethod";
                var method = new MethodDeclaration {
                    ReturnType = context.CreateShortType(resolveResult.Type),
                    Name = methodName,
                    Body = new BlockStatement {
                        new ReturnStatement(expression.Clone())
                    }
                };
                if (!StaticVisitor.UsesNotStaticMember(context, expression))
                {
                    method.Modifiers |= Modifiers.Static;
                }

                var usedVariables = VariableLookupVisitor.Analyze(context, expression);

                var inExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);

                usedVariables.Sort((l, r) => l.Region.Begin.CompareTo(r.Region.Begin));
                var target = new IdentifierExpression(methodName);
                var invocation = new InvocationExpression(target);
                foreach (var variable in usedVariables)
                {
                    Expression argumentExpression = new IdentifierExpression(variable.Name);

                    var mod = ParameterModifier.None;
                    if (inExtractedRegion.GetStatus(variable) == VariableState.Changed)
                    {
                        mod = ParameterModifier.Ref;
                        argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
                    }

                    method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(variable.Type), variable.Name, mod));
                    invocation.Arguments.Add(argumentExpression);
                }

                script
                .InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method)
                .ContinueScript(delegate {
                    script.Replace(expression, invocation);
                    script.Link(target, method.NameToken);
                });
            }, expression));
        }
Esempio n. 5
0
        CodeAction CreateFromStatements(RefactoringContext context, List <AstNode> statements)
        {
            if (!(statements [0].Parent is Statement))
            {
                return(null);
            }

            return(new CodeAction(context.TranslateString("Extract method"), script => {
                string methodName = "NewMethod";
                var method = new MethodDeclaration()
                {
                    ReturnType = new PrimitiveType("void"),
                    Name = methodName,
                    Body = new BlockStatement()
                };
                bool usesNonStaticMember = false;
                foreach (var node in statements)
                {
                    usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
                    if (node is Statement)
                    {
                        method.Body.Add((Statement)node.Clone());
                    }
                    else
                    {
                        method.Body.AddChildUnsafe(node.Clone(), node.Role);
                    }
                }
                if (!usesNonStaticMember)
                {
                    method.Modifiers |= Modifiers.Static;
                }

                var target = new IdentifierExpression(methodName);
                var invocation = new InvocationExpression(target);

                var usedVariables = VariableLookupVisitor.Analyze(context, statements);

                var inExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                var lastStatement = statements [statements.Count - 1];

                var stmt = statements [0].GetParent <BlockStatement>();
                while (stmt.GetParent <BlockStatement> () != null)
                {
                    stmt = stmt.GetParent <BlockStatement>();
                }

                inExtractedRegion.SetAnalyzedRange(statements [0], lastStatement);
                stmt.AcceptVisitor(inExtractedRegion);

                var beforeExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                beforeExtractedRegion.SetAnalyzedRange(statements [0].Parent, statements [0], true, false);
                stmt.AcceptVisitor(beforeExtractedRegion);

                var afterExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                afterExtractedRegion.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);
                stmt.AcceptVisitor(afterExtractedRegion);
                usedVariables.Sort((l, r) => l.Region.Begin.CompareTo(r.Region.Begin));

                IVariable generatedReturnVariable = null;
                foreach (var variable in usedVariables)
                {
                    if ((variable is IParameter) || beforeExtractedRegion.Has(variable) || !afterExtractedRegion.Has(variable))
                    {
                        continue;
                    }
                    generatedReturnVariable = variable;
                    method.ReturnType = context.CreateShortType(variable.Type);
                    method.Body.Add(new ReturnStatement(new IdentifierExpression(variable.Name)));
                    break;
                }

                int parameterOutCount = 0;
                foreach (var variable in usedVariables)
                {
                    if (!(variable is IParameter) && !beforeExtractedRegion.Has(variable) && !afterExtractedRegion.Has(variable))
                    {
                        continue;
                    }
                    if (variable == generatedReturnVariable)
                    {
                        continue;
                    }
                    Expression argumentExpression = new IdentifierExpression(variable.Name);

                    ParameterModifier mod = ParameterModifier.None;
                    if (inExtractedRegion.GetStatus(variable) == VariableState.Changed)
                    {
                        if (beforeExtractedRegion.GetStatus(variable) == VariableState.None)
                        {
                            mod = ParameterModifier.Out;
                            argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
                            parameterOutCount++;
                        }
                        else
                        {
                            mod = ParameterModifier.Ref;
                            argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
                        }
                    }

                    method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(variable.Type), variable.Name, mod));
                    invocation.Arguments.Add(argumentExpression);
                }

                ParameterDeclaration parameterToTransform = null;
                bool transformParameterToReturn = method.ReturnType is PrimitiveType &&
                                                  ((PrimitiveType)method.ReturnType).Keyword == "void" &&
                                                  parameterOutCount == 1;
                if (transformParameterToReturn)
                {
                    parameterToTransform = method.Parameters.First(p => p.ParameterModifier == ParameterModifier.Out);
                    parameterToTransform.Remove();
                    var argumentExpression = invocation.Arguments.OfType <DirectionExpression>().First(a => a.FieldDirection == FieldDirection.Out);
                    argumentExpression.Remove();
                    method.ReturnType = parameterToTransform.Type.Clone();
                    var argumentDecl = new VariableDeclarationStatement(parameterToTransform.Type.Clone(), parameterToTransform.Name);
                    method.Body.InsertChildBefore(method.Body.First(), argumentDecl, BlockStatement.StatementRole);
                    method.Body.Add(new ReturnStatement(new IdentifierExpression(parameterToTransform.Name)));
                }

                script
                .InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method)
                .ContinueScript(delegate {
                    foreach (var node in statements.Skip(1))
                    {
                        if (node is NewLineNode)
                        {
                            continue;
                        }
                        script.Remove(node);
                    }
                    foreach (var variable in usedVariables)
                    {
                        if ((variable is IParameter) || beforeExtractedRegion.Has(variable) || !afterExtractedRegion.Has(variable))
                        {
                            continue;
                        }
                        if (variable == generatedReturnVariable)
                        {
                            continue;
                        }
                        script.InsertBefore(statements [0], new VariableDeclarationStatement(context.CreateShortType(variable.Type), variable.Name));
                    }
                    Statement invocationStatement;

                    if (generatedReturnVariable != null)
                    {
                        invocationStatement = new VariableDeclarationStatement(new SimpleType("var"), generatedReturnVariable.Name, invocation);
                    }
                    else if (transformParameterToReturn)
                    {
                        invocationStatement = new AssignmentExpression(new IdentifierExpression(parameterToTransform.Name), invocation);
                    }
                    else
                    {
                        invocationStatement = invocation;
                    }

                    script.Replace(statements [0], invocationStatement);


                    script.Link(target, method.NameToken);
                });
            }, statements.First().StartLocation, statements.Last().EndLocation));
        }
 public static List<IVariable> Analyze(RefactoringContext context, List<AstNode> statements)
 {
     var visitor = new VariableLookupVisitor(context);
     statements.ForEach(stmt => stmt.AcceptVisitor(visitor));
     return visitor.UsedVariables;
 }
 public static List<IVariable> Analyze(RefactoringContext context, Expression expression)
 {
     var visitor = new VariableLookupVisitor(context);
     expression.AcceptVisitor(visitor);
     return visitor.UsedVariables;
 }
		CodeAction CreateFromStatements(RefactoringContext context, List<Statement> statements)
		{
			if (!(statements [0].Parent is Statement))
				return null;
			
			return new CodeAction(context.TranslateString("Extract method"), script => {
				string methodName = "NewMethod";
				var method = new MethodDeclaration() {
					ReturnType = new PrimitiveType("void"),
					Name = methodName,
					Body = new BlockStatement()
				};
				bool usesNonStaticMember = false;
				foreach (Statement node in statements) {
					usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
					method.Body.Add(node.Clone());
				}
				if (!usesNonStaticMember)
					method.Modifiers |= Modifiers.Static;
				
				var target = new IdentifierExpression(methodName);
				var invocation = new InvocationExpression(target);
				
				var usedVariables = VariableLookupVisitor.Analyze(context, statements);
				
				var extractedCodeAnalysis = new DefiniteAssignmentAnalysis(
					(Statement)statements [0].Parent,
					context.Resolver,
					context.CancellationToken);
				var lastStatement = statements [statements.Count - 1];
				extractedCodeAnalysis.SetAnalyzedRange(statements [0], lastStatement);
				var statusAfterMethod = new List<Tuple<IVariable, DefiniteAssignmentStatus>>();
				
				foreach (var variable in usedVariables) {
					extractedCodeAnalysis.Analyze(
						variable.Name,
						DefiniteAssignmentStatus.PotentiallyAssigned,
						context.CancellationToken);
					statusAfterMethod.Add(Tuple.Create(variable, extractedCodeAnalysis.GetStatusAfter(lastStatement)));
				}
				var stmt = statements [0].GetParent<BlockStatement>();
				while (stmt.GetParent<BlockStatement> () != null) {
					stmt = stmt.GetParent<BlockStatement>();
				}
				
				var wholeCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
				var statusBeforeMethod = new Dictionary<IVariable, DefiniteAssignmentStatus>();
				foreach (var variable in usedVariables) {
					wholeCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
					statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
				}
				
				var afterCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
				var statusAtEnd = new Dictionary<IVariable, DefiniteAssignmentStatus>();
				afterCodeAnalysis.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);
				
				foreach (var variable in usedVariables) {
					afterCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
					statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
				}
				var beforeVisitor = new VariableLookupVisitor(context);
				beforeVisitor.SetAnalyzedRange(stmt, statements [0], true, false);
				stmt.AcceptVisitor(beforeVisitor);
				var afterVisitor = new VariableLookupVisitor(context);
				afterVisitor.SetAnalyzedRange(lastStatement, stmt, false, true);
				stmt.AcceptVisitor(afterVisitor);
				
				foreach (var status in statusAfterMethod) {
					if (!beforeVisitor.UsedVariables.Contains(status.Item1) && !afterVisitor.UsedVariables.Contains(status.Item1))
						continue;
					Expression argumentExpression = new IdentifierExpression(status.Item1.Name); 
					
					ParameterModifier mod;
					switch (status.Item2) {
						case DefiniteAssignmentStatus.AssignedAfterTrueExpression:
						case DefiniteAssignmentStatus.AssignedAfterFalseExpression:
						case DefiniteAssignmentStatus.PotentiallyAssigned:
							mod = ParameterModifier.Ref;
							argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
							break;
						case DefiniteAssignmentStatus.DefinitelyAssigned:
							if (statusBeforeMethod [status.Item1] != DefiniteAssignmentStatus.PotentiallyAssigned)
								goto case DefiniteAssignmentStatus.PotentiallyAssigned;
							mod = ParameterModifier.Out;
							argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
							break;
							//						case DefiniteAssignmentStatus.Unassigned:
						default:
							mod = ParameterModifier.None;
							break;
					}
					method.Parameters.Add(
						new ParameterDeclaration(context.CreateShortType(status.Item1.Type), status.Item1.Name, mod));
					invocation.Arguments.Add(argumentExpression);
				}
				var task = script.InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method);
				task.ContinueWith (delegate {
					foreach (var node in statements.Skip (1)) {
						script.Remove(node);
					}
					script.Replace(statements [0], new ExpressionStatement(invocation));
					script.Link(target, method.NameToken);
				}, TaskScheduler.FromCurrentSynchronizationContext ());
			});
		}
 static bool ContainsLocalReferences(RefactoringContext context, AstNode expr, AstNode body)
 {
     var visitor = new ExtractMethod.VariableLookupVisitor (context);
     body.AcceptVisitor (visitor);
     return visitor.UsedVariables.Any (variable => !expr.Contains (variable.Region.Begin));
 }
        CodeAction CreateFromStatements(RefactoringContext context, List <Statement> statements)
        {
            if (!(statements [0].Parent is Statement))
            {
                return(null);
            }

            return(new CodeAction(context.TranslateString("Extract method"), script => {
                string methodName = "NewMethod";
                var method = new MethodDeclaration()
                {
                    ReturnType = new PrimitiveType("void"),
                    Name = methodName,
                    Body = new BlockStatement()
                };
                bool usesNonStaticMember = false;
                foreach (Statement node in statements)
                {
                    usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
                    method.Body.Add(node.Clone());
                }
                if (!usesNonStaticMember)
                {
                    method.Modifiers |= Modifiers.Static;
                }

                var target = new IdentifierExpression(methodName);
                var invocation = new InvocationExpression(target);

                var usedVariables = VariableLookupVisitor.Analyze(context, statements);

                var extractedCodeAnalysis = new DefiniteAssignmentAnalysis((Statement)statements [0].Parent, context.Resolver, context.CancellationToken);
                var lastStatement = statements [statements.Count - 1];
                extractedCodeAnalysis.SetAnalyzedRange(statements [0], lastStatement);
                var statusAfterMethod = new List <Tuple <IVariable, DefiniteAssignmentStatus> >();

                foreach (var variable in usedVariables)
                {
                    extractedCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
                    statusAfterMethod.Add(Tuple.Create(variable, extractedCodeAnalysis.GetStatusAfter(lastStatement)));
                }
                var stmt = statements [0].GetParent <BlockStatement>();
                while (stmt.GetParent <BlockStatement> () != null)
                {
                    stmt = stmt.GetParent <BlockStatement>();
                }

                var wholeCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
                var statusBeforeMethod = new Dictionary <IVariable, DefiniteAssignmentStatus>();
                foreach (var variable in usedVariables)
                {
                    wholeCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
                    statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
                }

                var afterCodeAnalysis = new DefiniteAssignmentAnalysis(stmt, context.Resolver, context.CancellationToken);
                var statusAtEnd = new Dictionary <IVariable, DefiniteAssignmentStatus>();
                afterCodeAnalysis.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);

                foreach (var variable in usedVariables)
                {
                    afterCodeAnalysis.Analyze(variable.Name, DefiniteAssignmentStatus.PotentiallyAssigned, context.CancellationToken);
                    statusBeforeMethod [variable] = extractedCodeAnalysis.GetStatusBefore(statements [0]);
                }
                var beforeVisitor = new VariableLookupVisitor(context);
                beforeVisitor.SetAnalyzedRange(stmt, statements [0], true, false);
                stmt.AcceptVisitor(beforeVisitor);
                var afterVisitor = new VariableLookupVisitor(context);
                afterVisitor.SetAnalyzedRange(lastStatement, stmt, false, true);
                stmt.AcceptVisitor(afterVisitor);

                foreach (var status in statusAfterMethod)
                {
                    if (!beforeVisitor.UsedVariables.Contains(status.Item1) && !afterVisitor.UsedVariables.Contains(status.Item1))
                    {
                        continue;
                    }
                    Expression argumentExpression = new IdentifierExpression(status.Item1.Name);

                    ParameterModifier mod;
                    switch (status.Item2)
                    {
                    case DefiniteAssignmentStatus.AssignedAfterTrueExpression:
                    case DefiniteAssignmentStatus.AssignedAfterFalseExpression:
                    case DefiniteAssignmentStatus.PotentiallyAssigned:
                        mod = ParameterModifier.Ref;
                        argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
                        break;

                    case DefiniteAssignmentStatus.DefinitelyAssigned:
                        if (statusBeforeMethod [status.Item1] != DefiniteAssignmentStatus.PotentiallyAssigned)
                        {
                            goto case DefiniteAssignmentStatus.PotentiallyAssigned;
                        }
                        mod = ParameterModifier.Out;
                        argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
                        break;

//						case DefiniteAssignmentStatus.Unassigned:
                    default:
                        mod = ParameterModifier.None;
                        break;
                    }
                    method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(status.Item1.Type), status.Item1.Name, mod));
                    invocation.Arguments.Add(argumentExpression);
                }

                foreach (var node in statements.Skip(1))
                {
                    script.Remove(node);
                }
                script.Replace(statements [0], new ExpressionStatement(invocation));
                script.InsertWithCursor(context.TranslateString("Extract method"), method, Script.InsertPosition.Before);
                //script.Link(target, method.NameToken);
            }));
        }
        CodeAction CreateFromStatements(RefactoringContext context, List <Statement> statements)
        {
            if (!(statements [0].Parent is Statement))
            {
                return(null);
            }

            return(new CodeAction(context.TranslateString("Extract method"), script =>
            {
                string methodName = "NewMethod";
                var method = new MethodDeclaration()
                {
                    ReturnType = new PrimitiveType("void"),
                    Name = methodName,
                    Body = new BlockStatement()
                };
                bool usesNonStaticMember = false;
                foreach (Statement node in statements)
                {
                    usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
                    method.Body.Add(node.Clone());
                }
                if (!usesNonStaticMember)
                {
                    method.Modifiers |= Modifiers.Static;
                }

                var target = new IdentifierExpression(methodName);
                var invocation = new InvocationExpression(target);

                var usedVariables = VariableLookupVisitor.Analyze(context, statements);

                var inExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                var lastStatement = statements [statements.Count - 1];

                var stmt = statements [0].GetParent <BlockStatement>();
                while (stmt.GetParent <BlockStatement> () != null)
                {
                    stmt = stmt.GetParent <BlockStatement>();
                }

                inExtractedRegion.SetAnalyzedRange(statements [0], lastStatement);
                stmt.AcceptVisitor(inExtractedRegion);

                var beforeExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                beforeExtractedRegion.SetAnalyzedRange(statements [0].Parent, statements [0], true, false);
                stmt.AcceptVisitor(beforeExtractedRegion);

                var afterExtractedRegion = new VariableUsageAnalyzation(context, usedVariables);
                afterExtractedRegion.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);
                stmt.AcceptVisitor(afterExtractedRegion);
                usedVariables.Sort((l, r) => l.Region.Begin.CompareTo(r.Region.Begin));

                IVariable generatedReturnVariable = null;
                foreach (var variable in usedVariables)
                {
                    if ((variable is IParameter) || beforeExtractedRegion.Has(variable) || !afterExtractedRegion.Has(variable))
                    {
                        continue;
                    }
                    generatedReturnVariable = variable;
                    method.ReturnType = context.CreateShortType(variable.Type);
                    method.Body.Add(new ReturnStatement(new IdentifierExpression(variable.Name)));
                    break;
                }

                foreach (var variable in usedVariables)
                {
                    if (!(variable is IParameter) && !beforeExtractedRegion.Has(variable) && !afterExtractedRegion.Has(variable))
                    {
                        continue;
                    }
                    if (variable == generatedReturnVariable)
                    {
                        continue;
                    }
                    Expression argumentExpression = new IdentifierExpression(variable.Name);

                    ParameterModifier mod = ParameterModifier.None;
                    if (inExtractedRegion.GetStatus(variable) == VariableState.Changed)
                    {
                        if (beforeExtractedRegion.GetStatus(variable) == VariableState.None)
                        {
                            mod = ParameterModifier.Out;
                            argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
                        }
                        else
                        {
                            mod = ParameterModifier.Ref;
                            argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
                        }
                    }

                    method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(variable.Type), variable.Name, mod));
                    invocation.Arguments.Add(argumentExpression);
                }
                var task = script.InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method);
                Action <Task> replaceStatements = delegate {
                    foreach (var node in statements.Skip(1))
                    {
                        script.Remove(node);
                    }
                    foreach (var variable in usedVariables)
                    {
                        if ((variable is IParameter) || beforeExtractedRegion.Has(variable) || !afterExtractedRegion.Has(variable))
                        {
                            continue;
                        }
                        if (variable == generatedReturnVariable)
                        {
                            continue;
                        }
                        script.InsertBefore(statements [0], new VariableDeclarationStatement(context.CreateShortType(variable.Type), variable.Name));
                    }
                    AstNode invocationStatement;

                    if (generatedReturnVariable != null)
                    {
                        invocationStatement = new VariableDeclarationStatement(new SimpleType("var"), generatedReturnVariable.Name, invocation);
                    }
                    else
                    {
                        invocationStatement = new ExpressionStatement(invocation);
                    }
                    script.Replace(statements [0], invocationStatement);


                    script.Link(target, method.NameToken);
                };

                if (task.IsCompleted)
                {
                    replaceStatements(null);
                }
                else
                {
                    task.ContinueWith(replaceStatements, TaskScheduler.FromCurrentSynchronizationContext());
                }
            }));
        }