コード例 #1
0
        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);
            }
        }
コード例 #2
0
		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);
			}
		}
コード例 #3
0
        /// <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));
        }
コード例 #4
0
 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);
 }
コード例 #5
0
		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));
		}
コード例 #6
0
        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);
        }
コード例 #7
0
		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;
		}
コード例 #8
0
		/// <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);
		}
コード例 #9
0
		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 });
				}
			}
		}
コード例 #10
0
		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 ());
			});
		}
コード例 #11
0
        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
                    });
                }
            }
        }
コード例 #12
0
        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);
            }));
        }
コード例 #13
0
		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));
		}
コード例 #14
0
		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));
		}
コード例 #15
0
		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));
		}