예제 #1
0
            public override void VisitVariableDeclarationStatement(VariableDeclarationStatement varDecl)
            {
                base.VisitVariableDeclarationStatement(varDecl);
                if (varDecl.Modifiers.HasFlag(Modifiers.Const) || varDecl.Role == ForStatement.InitializerRole)
                {
                    return;
                }
                if (varDecl.Variables.Count() > 1)
                {
                    return;
                }
                if (varDecl.Variables.Any(v => !(ctx.Resolve(v.Initializer) is ConstantResolveResult)))
                {
                    return;
                }
                var containingBlock = varDecl.GetParent <BlockStatement> ();

                if (containingBlock == null)
                {
                    return;
                }

                var returnTypeRR = ctx.Resolve(varDecl.Type);

                if (returnTypeRR.Type.IsReferenceType.HasValue && returnTypeRR.Type.IsReferenceType.Value)
                {
                    return;
                }

                var vr = ctx.Resolve(varDecl.Variables.First()) as LocalResolveResult;

                if (vr == null)
                {
                    return;
                }
                var assignmentAnalysis = new VariableUsageAnalyzation(ctx);

                containingBlock.AcceptVisitor(assignmentAnalysis);

                if (assignmentAnalysis.GetStatus(vr.Variable) == VariableState.Changed)
                {
                    return;
                }
                AddIssue(
                    varDecl.Variables.First().NameToken,
                    ctx.TranslateString("Convert to constant"),
                    ctx.TranslateString("To const"),
                    script => {
                    var constVarDecl        = (VariableDeclarationStatement)varDecl.Clone();
                    constVarDecl.Modifiers |= Modifiers.Const;
                    script.Replace(varDecl, constVarDecl);
                }
                    );
            }
		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);
				}

				var task = script.InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method);

				Action<Task> replaceStatements = delegate {
					script.Replace(expression, invocation);
					script.Link(target, method.NameToken);
				};

				if (task.IsCompleted) {
					replaceStatements (null);
				} else {
					task.ContinueWith (replaceStatements, TaskScheduler.FromCurrentSynchronizationContext ());
				}
			});
		}
 public override void VisitBlockStatement(BlockStatement blockStatement)
 {
     base.VisitBlockStatement(blockStatement);
     if (blockStatement.Parent is EntityDeclaration || blockStatement.Parent is Accessor)
     {
         var assignmentAnalysis = new VariableUsageAnalyzation(ctx);
         var newVars            = new List <Tuple <VariableInitializer, IVariable> >();
         blockStatement.AcceptVisitor(assignmentAnalysis);
         foreach (var variable in fieldStack.Pop())
         {
             if (assignmentAnalysis.GetStatus(variable.Item2) == VariableState.Changed)
             {
                 continue;
             }
             newVars.Add(variable);
         }
         fieldStack.Push(newVars);
     }
 }
            public override void VisitVariableDeclarationStatement(VariableDeclarationStatement varDecl)
            {
                base.VisitVariableDeclarationStatement(varDecl);
                if (varDecl.Modifiers.HasFlag(Modifiers.Const) || varDecl.Role == ForStatement.InitializerRole)
                {
                    return;
                }
                if (varDecl.Variables.Count() > 1)
                {
                    return;
                }
                if (varDecl.Variables.Any(v => !ctx.Resolve(v.Initializer).IsCompileTimeConstant))
                {
                    return;
                }
                var containingBlock = varDecl.GetParent <BlockStatement> ();

                if (containingBlock == null)
                {
                    return;
                }

                var returnTypeRR = ctx.Resolve(varDecl.Type);

                if (!IsValidConstType(returnTypeRR.Type))
                {
                    return;
                }

                var variable = varDecl.Variables.First();
                var vr       = ctx.Resolve(variable) as LocalResolveResult;

                if (vr == null)
                {
                    return;
                }

                if (ctx.Resolve(variable.Initializer).ConstantValue == null)
                {
                    return;
                }

                var assignmentAnalysis = new VariableUsageAnalyzation(ctx);

                containingBlock.AcceptVisitor(assignmentAnalysis);

                if (assignmentAnalysis.GetStatus(vr.Variable) == VariableState.Changed)
                {
                    return;
                }
                AddIssue(new CodeIssue(
                             variable.NameToken,
                             ctx.TranslateString("Convert to constant"),
                             ctx.TranslateString("To const"),
                             script => {
                    var constVarDecl        = (VariableDeclarationStatement)varDecl.Clone();
                    constVarDecl.Modifiers |= Modifiers.Const;
                    if (varDecl.Type.IsVar())
                    {
                        var builder       = ctx.CreateTypeSystemAstBuilder(varDecl);
                        constVarDecl.Type = builder.ConvertType(ctx.Resolve(varDecl.Type).Type);
                    }
                    script.Replace(varDecl, constVarDecl);
                }
                             ));
            }
		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;
				}

				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 ());
				}
			});
		}