public FilterMethodToBeDecompiled(MethodDefinition method, CatchClause catchClause, DecompilationContext context, BlockStatement block)
 {
     this.Method = method;
     this.CatchClause = catchClause;
     this.Context = context;
     this.Block = block;
 }
 public FilterMethodToBeDecompiled(MethodDefinition method, Telerik.JustDecompiler.Ast.Statements.CatchClause catchClause, DecompilationContext context, BlockStatement block)
 {
     base();
     this.set_Method(method);
     this.set_CatchClause(catchClause);
     this.set_Context(context);
     this.set_Block(block);
     return;
 }
 public RebuildCatchClausesFilterStep()
 {
     this.currentCatchClause = null;
     this.variablesUsedOutsideFilters = new HashSet<VariableDefinition>();
     this.catchClausesUsedVariablesMap = new Dictionary<CatchClause, HashSet<VariableDefinition>>();
     this.catchClausesUsedParametersMap = new Dictionary<CatchClause, HashSet<ParameterDefinition>>();
     this.catchClausesVariablesToParametersMap = new Dictionary<CatchClause, Dictionary<VariableDefinition, ParameterDefinition>>();
     this.methodsToBeDecompiled = new List<FilterMethodToBeDecompiled>();
 }
 private void SetParentToThis(CatchClause catchClause)
 {
     if (catchClause.Body != null)
     {
         catchClause.Body.Parent = this;
     }
     if (catchClause.Filter != null)
     {
         catchClause.Filter.Parent = this;
     }
 }
        public override ICodeNode VisitCatchClause(CatchClause node)
        {
            // If we have a catch clause with filter, we need aggressive inlining (only for TernaryConditionPattern) of the filter block, because our pattern matching relies on this.
            if (node.Filter != null)
            {
                this.isInFilter = true;
                node.Filter = (Statement)Visit(node.Filter);
                this.isInFilter = false;

                node.Body = (BlockStatement)Visit(node.Body);

                return node;
            }

            return base.VisitCatchClause(node);
        }
        public override ICodeNode VisitCatchClause(CatchClause node)
        {
            // We first visit the body and the filter
            node.Body = (BlockStatement)base.Visit(node.Body);

            if (node.Filter == null || !(node.Filter is BlockStatement))
            {
                return node;
            }

            currentCatchClause = node;
            node.Filter = (Statement)base.Visit(node.Filter);
            currentCatchClause = null;

            VariableDeclarationExpression variableDeclaration;
            Expression filterExpression;
            bool matchSucceed = CatchClausesFilterPattern.TryMatch(node.Filter as BlockStatement, out variableDeclaration, out filterExpression);
            if (!matchSucceed)
            {
                if (variableDeclaration == null || variableDeclaration.ExpressionType.FullName == Constants.Object ||
                    !CatchClausesFilterPattern.TryMatchMethodStructure(node.Filter as BlockStatement))
                {
                    throw new NotSupportedException("Unsupported structure of filter clause.");
                }

                CreateMethod(node, variableDeclaration, out filterExpression);
            }

            this.context.MethodContext.VariablesToNotDeclare.Add(variableDeclaration.Variable);

            node.Variable = variableDeclaration;
            node.Type = variableDeclaration.ExpressionType;
            node.Filter = new ExpressionStatement(filterExpression);

            return node;
        }
 private void SetParentToThis(CatchClause catchClause)
 {
     if (catchClause.Body != null)
     {
         catchClause.Body.Parent = this;
     }
     if (catchClause.Filter != null)
     {
         catchClause.Filter.Parent = this;
     }
 }
 public void AddToCatchClauses(CatchClause catchClause)
 {
     SetParentToThis(catchClause);
     CatchClauses.Add(catchClause);
 }
        public override void VisitCatchClause(CatchClause node)
        {
            WriteKeyword(KeyWordWriter.Catch);

            if (node.Type.FullName != Constants.Object)
            {
                WriteSpace();

				if (node.Variable != null)
				{
					loopStates.Push(StatementState.Catch);
					Visit(node.Variable);
					loopStates.Pop();
				}
				else
				{
					WriteReferenceAndNamespaceIfInCollision(node.Type);
				}
            }

            if (node.Filter != null)
            {
                WriteSpace();
                WriteKeyword(KeyWordWriter.When);
                WriteSpace();
                Visit((node.Filter as ExpressionStatement).Expression);
            }

            WriteLine();
            Visit(node.Body);
        }
        public override void VisitCatchClause(CatchClause node)
        {
            WriteKeyword(KeyWordWriter.Catch);

            if (node.Type.FullName != Constants.Object)
            {
                WriteSpace();
                WriteSpecialBetweenParenthesis(() =>
                                               {
                                                   if (node.Variable != null)
                                                       Visit(node.Variable);
                                                   else
                                                       WriteReferenceAndNamespaceIfInCollision(node.Type);
                                               });
            }

            if (node.Filter != null)
            {
                WriteSpace();
                WriteKeyword(KeyWordWriter.When);
                WriteSpace();
                WriteSpecialBetweenParenthesis((node.Filter as ExpressionStatement).Expression);
            }

            WriteLine();
            Visit(node.Body);
        }
        private void AddVariablesToNotDeclare(DecompilationContext context, CatchClause currentCatch)
        {
            foreach (VariableDefinition variable in context.MethodContext.Variables)
            {
                if (variablesUsedOutsideFilters.Contains(variable))
                {
                    context.MethodContext.VariablesToNotDeclare.Add(variable);
                }

                foreach (KeyValuePair<CatchClause, HashSet<VariableDefinition>> map in catchClausesUsedVariablesMap)
                {
                    if (map.Key.Equals(currentCatch))
                    {
                        continue;
                    }

                    if (map.Value.Contains(variable))
                    {
                        context.MethodContext.VariablesToNotDeclare.Add(variable);
                    }
                }
            }
        }
        private List<Expression> AddAllParameters(CatchClause catchClause, MethodDefinition method, VariableDeclarationExpression variable)
        {
            List<Expression> methodInvocationArguments = new List<Expression>();

            method.Parameters.Add(CreateParameter(Constants.JustDecompileGeneratedException, variable.Variable.VariableType));
            methodInvocationArguments.Add(new UnaryExpression(UnaryOperator.AddressReference, new VariableReferenceExpression(variable.Variable, null), null));

            if (this.catchClausesUsedVariablesMap.ContainsKey(catchClause))
            {
                foreach (VariableDefinition variableDefinition in this.catchClausesUsedVariablesMap[catchClause])
                {
                    if (variablesUsedOutsideFilters.Contains(variableDefinition) && variableDefinition != variable.Variable)
                    {
                        // If parameter's name is null, it will be ranamed in RenameVariables step.
                        string parameterName = context.MethodContext.VariablesToRename.Contains(variableDefinition) ? null : variableDefinition.Name;
                        ParameterDefinition parameter = CreateParameter(parameterName, variableDefinition.VariableType);
                        if (parameterName == null)
                        {
                            if (!catchClausesVariablesToParametersMap.ContainsKey(catchClause))
                            {
                                catchClausesVariablesToParametersMap.Add(catchClause, new Dictionary<VariableDefinition, ParameterDefinition>());
                            }

                            catchClausesVariablesToParametersMap[catchClause].Add(variableDefinition, parameter);
                        }
                        
                        method.Parameters.Add(parameter);
                        methodInvocationArguments.Add(new UnaryExpression(UnaryOperator.AddressReference, new VariableReferenceExpression(variableDefinition, null), null));
                    }
                }
            }

            if (this.catchClausesUsedParametersMap.ContainsKey(catchClause))
            {
                foreach (ParameterDefinition parameterDefinition in this.catchClausesUsedParametersMap[catchClause])
                {
                    method.Parameters.Add(CreateParameter(parameterDefinition.Name, parameterDefinition.ParameterType));
                    methodInvocationArguments.Add(new UnaryExpression(UnaryOperator.AddressReference, new ArgumentReferenceExpression(parameterDefinition, null), null));
                }
            }
            
            return methodInvocationArguments;
        }
 /// <summary>
 /// This method fixes all variables names that reffer to nameless parameter.
 /// </summary>
 private void FixVariablesNames(DecompilationContext innerContext, CatchClause currentCatch)
 {
     if (catchClausesVariablesToParametersMap.ContainsKey(currentCatch))
     {
         foreach (KeyValuePair<VariableDefinition, ParameterDefinition> pair in catchClausesVariablesToParametersMap[currentCatch])
         {
             innerContext.MethodContext.VariableDefinitionToNameMap[pair.Key] = innerContext.MethodContext.ParameterDefinitionToNameMap[pair.Value];
         }
     }
 }
        private void CreateMethod(CatchClause catchClause, VariableDeclarationExpression variable, out Expression methodInvocationExpression)
        {
            methodInvocationExpression = null;

            BlockStatement filter = catchClause.Filter as BlockStatement;

            // Fixes the variable definition in the first statement.
            ExpressionStatement firstStatement = filter.Statements.First() as ExpressionStatement;
            BinaryExpression assignment = firstStatement.Expression as BinaryExpression;
            SafeCastExpression safeCast = assignment.Right as SafeCastExpression;
            VariableReferenceExpression variableReference = safeCast.Expression as VariableReferenceExpression;
            variableReference.Variable = variable.Variable;

            // Replace the variable reference in the last statement with return statement.
            ExpressionStatement lastStatement = filter.Statements.Last() as ExpressionStatement;
            lastStatement.Expression = new ReturnExpression(lastStatement.Expression, lastStatement.Expression.MappedInstructions);

            int methodNumber = this.context.TypeContext.GeneratedFilterMethods.Count + this.methodsToBeDecompiled.Count;
            string methodName = string.Format(Constants.JustDecompileGeneratedFilterPattern, methodNumber);
            MethodDefinition method = new MethodDefinition(methodName, Mono.Cecil.MethodAttributes.Private, this.context.MethodContext.Method.Module.TypeSystem.Boolean);
            method.Body = new MethodBody(method);
            // Practically no chance for duplicates, because of decrementing the MaxRID
            method.MetadataToken = new MetadataToken(TokenType.Method, MaxRID - (uint)methodNumber);
            method.IsStatic = this.context.MethodContext.Method.IsStatic;
            method.HasThis = !method.IsStatic;
            method.DeclaringType = context.MethodContext.Method.DeclaringType;
            method.SemanticsAttributes = MethodSemanticsAttributes.None;
            method.IsJustDecompileGenerated = true;

            DecompilationContext newContext = new DecompilationContext(CloneAndReplaceMethodBody(this.context.MethodContext, method.Body), this.context.TypeContext);

            VariableDefinition variableDefinition = variableReference.Variable.Resolve();
            if (!newContext.MethodContext.VariableDefinitionToNameMap.ContainsKey(variableDefinition))
            {
                newContext.MethodContext.VariableDefinitionToNameMap[variableDefinition] = Constants.JustDecompileGeneratedException;
            }
            else
            {
                newContext.MethodContext.VariableDefinitionToNameMap.Add(variableDefinition, Constants.JustDecompileGeneratedException);
            }

            newContext.MethodContext.VariablesToNotDeclare.Add(variable.Variable);

            methodsToBeDecompiled.Add(new FilterMethodToBeDecompiled(method, catchClause, newContext, catchClause.Filter as BlockStatement));

            List<Expression> parameters = AddAllParameters(catchClause, method, variable);
            methodInvocationExpression = CreateMethodInvocation(method, parameters);
        }
 public virtual void VisitCatchClause(CatchClause node)
 {
     Visit(node.Body);
     Visit(node.Variable);
     Visit(node.Filter);
 }
 public void AddToCatchClauses(CatchClause catchClause)
 {
     SetParentToThis(catchClause);
     CatchClauses.Add(catchClause);
 }