private void PushLoop(ILoopStatement node) { #if DEBUG node.BreakLabel = Ast.Label("break" + _labelId++); node.ContinueLabel = Ast.Label("continue" + _labelId++); #else node.BreakLabel = Ast.Label("break"); node.ContinueLabel = Ast.Label("continue"); #endif _loops.Add(node); }
/// <summary> /// Is node available to move outside the loop /// </summary> public static bool IsAvailableToMoveFromLoop([NotNull] ITreeNode toMove, [NotNull] ILoopStatement loop) { toMove.GetPsiServices().Locks.AssertReadAccessAllowed(); var sourceFile = toMove.GetSourceFile(); if (sourceFile == null) { return(false); } var loopStartOffset = loop.GetTreeStartOffset().Offset; return(IsAvailableToMoveInner(toMove, declaredElement => declaredElement.GetDeclarationsIn(sourceFile) .FirstOrDefault(declaration => declaration.GetSourceFile() == sourceFile)?.GetTreeStartOffset() .Offset < loopStartOffset )); }
public virtual void VisitLoopStatement(ILoopStatement s) { }
public sealed override void Initialize(AnalysisContext context) { context.RegisterOperationAction( (operationContext) => { ILoopStatement loop = (ILoopStatement)operationContext.Operation; if (loop.LoopKind == LoopKind.For) { IForLoopStatement forLoop = (IForLoopStatement)loop; IExpression forCondition = forLoop.Condition; if (forCondition.Kind == OperationKind.BinaryOperatorExpression) { IBinaryOperatorExpression condition = (IBinaryOperatorExpression)forCondition; IExpression conditionLeft = condition.Left; IExpression conditionRight = condition.Right; if (conditionRight.ConstantValue != null && conditionRight.ResultType.SpecialType == SpecialType.System_Int32 && conditionLeft.Kind == OperationKind.LocalReferenceExpression) { // Test is known to be a comparison of a local against a constant. int testValue = (int)conditionRight.ConstantValue; ILocalSymbol testVariable = ((ILocalReferenceExpression)conditionLeft).Local; if (forLoop.Before.Length == 1) { IStatement setup = forLoop.Before[0]; if (setup.Kind == OperationKind.ExpressionStatement && ((IExpressionStatement)setup).Expression.Kind == OperationKind.AssignmentExpression) { IAssignmentExpression setupAssignment = (IAssignmentExpression)((IExpressionStatement)setup).Expression; if (setupAssignment.Target.Kind == OperationKind.LocalReferenceExpression && ((ILocalReferenceExpression)setupAssignment.Target).Local == testVariable && setupAssignment.Value.ConstantValue != null && setupAssignment.Value.ResultType.SpecialType == SpecialType.System_Int32) { // Setup is known to be an assignment of a constant to the local used in the test. int initialValue = (int)setupAssignment.Value.ConstantValue; if (forLoop.AtLoopBottom.Length == 1) { IStatement advance = forLoop.AtLoopBottom[0]; if (advance.Kind == OperationKind.ExpressionStatement) { IExpression advanceExpression = ((IExpressionStatement)advance).Expression; IExpression advanceIncrement = null; BinaryOperationKind advanceOperationCode = BinaryOperationKind.None; if (advanceExpression.Kind == OperationKind.AssignmentExpression) { IAssignmentExpression advanceAssignment = (IAssignmentExpression)advanceExpression; if (advanceAssignment.Target.Kind == OperationKind.LocalReferenceExpression && ((ILocalReferenceExpression)advanceAssignment.Target).Local == testVariable && advanceAssignment.Value.Kind == OperationKind.BinaryOperatorExpression && advanceAssignment.Value.ResultType.SpecialType == SpecialType.System_Int32) { // Advance is known to be an assignment of a binary operation to the local used in the test. IBinaryOperatorExpression advanceOperation = (IBinaryOperatorExpression)advanceAssignment.Value; if (!advanceOperation.UsesOperatorMethod && advanceOperation.Left.Kind == OperationKind.LocalReferenceExpression && ((ILocalReferenceExpression)advanceOperation.Left).Local == testVariable && advanceOperation.Right.ConstantValue != null && advanceOperation.Right.ResultType.SpecialType == SpecialType.System_Int32) { // Advance binary operation is known to involve a reference to the local used in the test and a constant. advanceIncrement = advanceOperation.Right; advanceOperationCode = advanceOperation.BinaryKind; } } } else if (advanceExpression.Kind == OperationKind.CompoundAssignmentExpression || advanceExpression.Kind == OperationKind.IncrementExpression) { ICompoundAssignmentExpression advanceAssignment = (ICompoundAssignmentExpression)advanceExpression; if (advanceAssignment.Target.Kind == OperationKind.LocalReferenceExpression && ((ILocalReferenceExpression)advanceAssignment.Target).Local == testVariable && advanceAssignment.Value.ConstantValue != null && advanceAssignment.Value.ResultType.SpecialType == SpecialType.System_Int32) { // Advance binary operation is known to involve a reference to the local used in the test and a constant. advanceIncrement = advanceAssignment.Value; advanceOperationCode = advanceAssignment.BinaryKind; } } if (advanceIncrement != null) { int incrementValue = (int)advanceIncrement.ConstantValue; if (advanceOperationCode == BinaryOperationKind.IntegerSubtract) { advanceOperationCode = BinaryOperationKind.IntegerAdd; incrementValue = -incrementValue; } if (advanceOperationCode == BinaryOperationKind.IntegerAdd && incrementValue != 0 && (condition.BinaryKind == BinaryOperationKind.IntegerLessThan || condition.BinaryKind == BinaryOperationKind.IntegerLessThanOrEqual || condition.BinaryKind == BinaryOperationKind.IntegerNotEquals || condition.BinaryKind == BinaryOperationKind.IntegerGreaterThan || condition.BinaryKind == BinaryOperationKind.IntegerGreaterThanOrEqual)) { int iterationCount = (testValue - initialValue) / incrementValue; if (iterationCount >= 1000000) { Report(operationContext, forLoop.Syntax, BigForDescriptor); } } } } } } } } } } } }, OperationKind.LoopStatement); }
public MoveFromLoopAction([NotNull] ICSharpExpression toMove, [NotNull] ILoopStatement loopStatement, [CanBeNull] string variableName = null) { myToMove = toMove; myLoopStatement = loopStatement; myVariableName = variableName; }
private void PushLoop(ILoopStatement node) { node.BreakLabel = Ast.Label("break"); node.ContinueLabel = Ast.Label("continue"); _loops.Add(node); }