void Run(AstNode node, DefiniteAssignmentAnalysis daa) { BlockStatement block = node as BlockStatement; if (block != null) { var variables = block.Statements.TakeWhile(stmt => stmt is VariableDeclarationStatement) .Cast <VariableDeclarationStatement>().ToList(); if (variables.Count > 0) { // remove old variable declarations: foreach (VariableDeclarationStatement varDecl in variables) { Debug.Assert(varDecl.Variables.Single().Initializer.IsNull); varDecl.Remove(); } if (daa == null) { // If possible, reuse the DefiniteAssignmentAnalysis that was created for the parent block daa = new DefiniteAssignmentAnalysis(block, cancellationToken); } foreach (VariableDeclarationStatement varDecl in variables) { string variableName = varDecl.Variables.Single().Name; bool allowPassIntoLoops = varDecl.Variables.Single().Annotation <DelegateConstruction.CapturedVariableAnnotation>() == null; DeclareVariableInBlock(daa, block, varDecl.Type, variableName, allowPassIntoLoops); } } } for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { Run(child, daa); } }
void Run(AstNode node, DefiniteAssignmentAnalysis daa) { BlockStatement block = node as BlockStatement; if (block != null) { var variables = block.Statements.TakeWhile(stmt => stmt is VariableDeclarationStatement) .Cast<VariableDeclarationStatement>().ToList(); if (variables.Count > 0) { // remove old variable declarations: foreach (VariableDeclarationStatement varDecl in variables) { Debug.Assert(varDecl.Variables.Single().Initializer.IsNull); varDecl.Remove(); } if (daa == null) { // If possible, reuse the DefiniteAssignmentAnalysis that was created for the parent block daa = new DefiniteAssignmentAnalysis(block, cancellationToken); } foreach (VariableDeclarationStatement varDecl in variables) { string variableName = varDecl.Variables.Single().Name; bool allowPassIntoLoops = varDecl.Variables.Single().Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null; DeclareVariableInBlock(daa, block, varDecl.Type, variableName, allowPassIntoLoops); } } } for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { Run(child, daa); } }
/// <summary> /// Finds the declaration point for the variable within the specified block. /// </summary> /// <param name="daa"> /// Definite assignment analysis, must be prepared for 'block' or one of its parents. /// </param> /// <param name="varDecl">The variable to declare</param> /// <param name="block">The block in which the variable should be declared</param> /// <param name="declarationPoint"> /// Output parameter: the first statement within 'block' where the variable needs to be declared. /// </param> /// <returns> /// Returns whether it is possible to move the variable declaration into sub-blocks. /// </returns> public static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, VariableDeclarationStatement varDecl, BlockStatement block, out Statement declarationPoint) { string variableName = varDecl.Variables.Single().Name; bool allowPassIntoLoops = varDecl.Variables.Single().Annotation <DelegateConstruction.CapturedVariableAnnotation>() == null; return(FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint)); }
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); }
public void TryFinally() { BlockStatement block = new BlockStatement { new TryCatchStatement { TryBlock = new BlockStatement { new GotoStatement("LABEL"), new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(1)) }, CatchClauses = { new CatchClause { Body = new BlockStatement { new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(3)) } } }, FinallyBlock = new BlockStatement { new AssignmentExpression(new IdentifierExpression("j"), new PrimitiveExpression(5)) } }, new LabelStatement { Label = "LABEL" }, new EmptyStatement() }; TryCatchStatement tryCatchStatement = (TryCatchStatement)block.Statements.First(); Statement stmt1 = tryCatchStatement.TryBlock.Statements.ElementAt(1); Statement stmt3 = tryCatchStatement.CatchClauses.Single().Body.Statements.Single(); Statement stmt5 = tryCatchStatement.FinallyBlock.Statements.Single(); LabelStatement label = (LabelStatement)block.Statements.ElementAt(1); DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(block, CecilLoaderTests.Mscorlib); da.Analyze("i"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement)); Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1)); Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt3)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt5)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(label)); da.Analyze("j"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement)); Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1)); Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt3)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt5)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(label)); }
bool CanMoveVariableDeclarationIntoStatement(VariableDeclarationStatement varDecl, Statement targetStatement, out Statement declarationPoint) { Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); // Find all blocks between targetStatement and varDecl.Parent List <BlockStatement> blocks = targetStatement.Ancestors.TakeWhile(block => block != varDecl.Parent).OfType <BlockStatement>().ToList(); blocks.Add((BlockStatement)varDecl.Parent); // also handle the varDecl.Parent block itself blocks.Reverse(); // go from parent blocks to child blocks DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(blocks[0], context.CancellationToken); declarationPoint = null; foreach (BlockStatement block in blocks) { if (!DeclareVariables.FindDeclarationPoint(daa, varDecl, block, out declarationPoint)) { 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; }
/// <summary> /// Finds the declaration point for the variable within the specified block. /// </summary> /// <param name="daa"> /// Definite assignment analysis, must be prepared for 'block' or one of its parents. /// </param> /// <param name="varDecl">The variable to declare</param> /// <param name="block">The block in which the variable should be declared</param> /// <param name="declarationPoint"> /// Output parameter: the first statement within 'block' where the variable needs to be declared. /// </param> /// <returns> /// Returns whether it is possible to move the variable declaration into sub-blocks. /// </returns> public static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, VariableDeclarationStatement varDecl, BlockStatement block, out Statement declarationPoint) { string variableName = varDecl.Variables.Single().Name; bool allowPassIntoLoops = varDecl.Variables.Single().Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null; return FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint); }
void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, bool allowPassIntoLoops) { // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block Statement declarationPoint = null; // Check whether we can move down the variable into the sub-blocks bool canMoveVariableIntoSubBlocks = FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint); if (declarationPoint == null) { // The variable isn't used at all return; } if (canMoveVariableIntoSubBlocks) { // Declare the variable within the sub-blocks foreach (Statement stmt in block.Statements) { ForStatement forStmt = stmt as ForStatement; if (forStmt != null && forStmt.Initializers.Count == 1) { // handle the special case of moving a variable into the for initializer if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName)) continue; } UsingStatement usingStmt = stmt as UsingStatement; if (usingStmt != null && usingStmt.ResourceAcquisition is AssignmentExpression) { // handle the special case of moving a variable into a using statement if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName)) continue; } foreach (AstNode child in stmt.Children) { BlockStatement subBlock = child as BlockStatement; if (subBlock != null) { DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops); } else if (HasNestedBlocks(child)) { foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) { DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops); } } } } } else { // Try converting an assignment expression into a VariableDeclarationStatement if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) { // Declare the variable in front of declarationPoint variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, InsertionPoint = declarationPoint }); } } }
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 ()); }); }
void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, bool allowPassIntoLoops) { // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block Statement declarationPoint = null; // Check whether we can move down the variable into the sub-blocks bool canMoveVariableIntoSubBlocks = FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint); if (declarationPoint == null) { // The variable isn't used at all return; } if (canMoveVariableIntoSubBlocks) { // Declare the variable within the sub-blocks foreach (Statement stmt in block.Statements) { ForStatement forStmt = stmt as ForStatement; if (forStmt != null && forStmt.Initializers.Count == 1) { // handle the special case of moving a variable into the for initializer if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName)) { continue; } } UsingStatement usingStmt = stmt as UsingStatement; if (usingStmt != null && usingStmt.ResourceAcquisition is AssignmentExpression) { // handle the special case of moving a variable into a using statement if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName)) { continue; } } foreach (AstNode child in stmt.Children) { BlockStatement subBlock = child as BlockStatement; if (subBlock != null) { DeclareVariableInBlock(daa, subBlock, type, variableName, allowPassIntoLoops); } else if (HasNestedBlocks(child)) { foreach (BlockStatement nestedSubBlock in child.Children.OfType <BlockStatement>()) { DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, allowPassIntoLoops); } } } } } else { // Try converting an assignment expression into a VariableDeclarationStatement if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) { // Declare the variable in front of declarationPoint variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, InsertionPoint = declarationPoint }); } } }
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); })); }
public void ConditionalAnd() { IfElseStatement ifStmt = new IfElseStatement { Condition = new BinaryOperatorExpression { Left = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.GreaterThan, new PrimitiveExpression(0)), Operator = BinaryOperatorType.ConditionalAnd, Right = new BinaryOperatorExpression { Left = new ParenthesizedExpression { Expression = new AssignmentExpression { Left = new IdentifierExpression("i"), Operator = AssignmentOperatorType.Assign, Right = new IdentifierExpression("y") } }, Operator = BinaryOperatorType.GreaterThanOrEqual, Right = new PrimitiveExpression(0) } }, TrueStatement = new BlockStatement(), FalseStatement = new BlockStatement() }; DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib); da.Analyze("i"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.TrueStatement)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt.FalseStatement)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt)); }
public void ForLoop() { ForStatement loop = new ForStatement { Initializers = { new ExpressionStatement( new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)) ) }, Condition = new BinaryOperatorExpression(new IdentifierExpression("i"), BinaryOperatorType.LessThan, new PrimitiveExpression(1000)), Iterators = { new ExpressionStatement( new AssignmentExpression { Left = new IdentifierExpression("i"), Operator = AssignmentOperatorType.Add, Right = new IdentifierExpression("j") } ) }, EmbeddedStatement = new ExpressionStatement( new AssignmentExpression(new IdentifierExpression("j"), new IdentifierExpression("i")) )}; DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); da.Analyze("i"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single())); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Initializers.Single())); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBeforeLoopCondition(loop)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single())); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single())); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop)); da.Analyze("j"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single())); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop.Initializers.Single())); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBeforeLoopCondition(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single())); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single())); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop)); }
public void WhileTrue() { WhileStatement loop = new WhileStatement { Condition = new PrimitiveExpression(true), EmbeddedStatement = new BlockStatement { new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)), new BreakStatement() } }; DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); da.Analyze("i"); Assert.AreEqual(0, da.UnassignedVariableUses.Count); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(loop.EmbeddedStatement)); Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop)); }