static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, string variableName, bool allowPassIntoLoops, BlockStatement block, out Statement declarationPoint) { // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block declarationPoint = null; foreach (Statement stmt in block.Statements) { if (UsesVariable(stmt, variableName)) { if (declarationPoint == null) { declarationPoint = stmt; } if (!CanMoveVariableUseIntoSubBlock(stmt, variableName, allowPassIntoLoops)) { // If it's not possible to move the variable use into a nested block, // we need to declare the variable in this block return(false); } // If we can move the variable into the sub-block, we need to ensure that the remaining code // does not use the value that was assigned by the first sub-block Statement nextStatement = stmt.GetNextStatement(); if (nextStatement != null) { // Analyze the range from the next statement to the end of the block daa.SetAnalyzedRange(nextStatement, block); daa.Analyze(variableName); if (daa.UnassignedVariableUses.Count > 0) { return(false); } } } } return(true); }
static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, string variableName, bool allowPassIntoLoops, BlockStatement block, out Statement declarationPoint) { // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block declarationPoint = null; foreach (Statement stmt in block.Statements) { if (UsesVariable(stmt, variableName)) { if (declarationPoint == null) declarationPoint = stmt; if (!CanMoveVariableUseIntoSubBlock(stmt, variableName, allowPassIntoLoops)) { // If it's not possible to move the variable use into a nested block, // we need to declare the variable in this block return false; } // If we can move the variable into the sub-block, we need to ensure that the remaining code // does not use the value that was assigned by the first sub-block Statement nextStatement = stmt.GetNextStatement(); if (nextStatement != null) { // Analyze the range from the next statement to the end of the block daa.SetAnalyzedRange(nextStatement, block); daa.Analyze(variableName); if (daa.UnassignedVariableUses.Count > 0) { return false; } } } } return true; }
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 ()); }); }
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); })); }