/// <summary>
        /// Initializes a new instance of the FinallyStatement class.
        /// </summary>
        /// <param name="tokens">The list of tokens that form the statement.</param>
        /// <param name="tryStatement">The try-statement that this finally-statement is embedded to.</param>
        /// <param name="embeddedStatement">The statement embedded within the finally-statement.</param>
        internal FinallyStatement(CsTokenList tokens, TryStatement tryStatement, BlockStatement embeddedStatement)
            : base(StatementType.Finally, tokens)
        {
            Param.AssertNotNull(tokens, "tokens");
            Param.AssertNotNull(tryStatement, "tryStatement");
            Param.AssertNotNull(embeddedStatement, "embeddedStatement");

            this.tryStatement = tryStatement;
            this.embeddedStatement = embeddedStatement;

            this.AddStatement(embeddedStatement);
        }
        /// <summary>
        /// Looks for a catch-statement, and if it is found, parses and returns it.
        /// </summary>
        /// <param name="tryStatement">The parent try statement.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the statement.</returns>
        private CatchStatement GetAttachedCatchStatement(TryStatement tryStatement, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(tryStatement, "tryStatement");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            CatchStatement catchStatement = null;

            // Look for a catch keyword.
            Symbol symbol = this.GetNextSymbol(parentReference);
            if (symbol.SymbolType == SymbolType.Catch)
            {
                var statementReference = new Reference<ICodePart>();

                // Move up to the catch keyword and add it.
                CsToken firstToken = this.GetToken(CsTokenType.Catch, SymbolType.Catch, statementReference);
                Node<CsToken> firstTokenNode = this.tokens.InsertLast(firstToken);

                Expression catchExpression = null;

                // Get the opening parenthesis, if there is one.
                symbol = this.GetNextSymbol(statementReference);
                if (symbol.SymbolType == SymbolType.OpenParenthesis)
                {
                    Bracket openParenthesis = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis, statementReference);
                    Node<CsToken> openParenthesisNode = this.tokens.InsertLast(openParenthesis);

                    // Get the type, if there is one.
                    symbol = this.GetNextSymbol(statementReference);
                    if (symbol.SymbolType == SymbolType.Other)
                    {
                        catchExpression = this.GetNextExpression(ExpressionPrecedence.None, statementReference, unsafeCode, true, true);
                    }

                    // Get the closing parenthesis.
                    Bracket closeParenthesis = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis, statementReference);
                    Node<CsToken> closeParenthesisNode = this.tokens.InsertLast(closeParenthesis);

                    openParenthesis.MatchingBracketNode = closeParenthesisNode;
                    closeParenthesis.MatchingBracketNode = openParenthesisNode;
                }

                // Get the embedded statement. This must be a block statement.
                BlockStatement childStatement = this.GetNextStatement(statementReference, unsafeCode) as BlockStatement;
                if (childStatement == null)
                {
                    throw new SyntaxException(this.document.SourceCode, firstToken.LineNumber);
                }

                // Create the token list for the statement.
                CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);

                // Create the catch statement.
                catchStatement = new CatchStatement(partialTokens, tryStatement, catchExpression, childStatement);
                ((IWriteableCodeUnit)catchStatement).SetParent(tryStatement);
                statementReference.Target = catchStatement;

                if (catchStatement.ClassType != null && catchStatement.Identifier != null)
                {
                    // Add the variable.
                    Variable variable = new Variable(
                        catchStatement.ClassType,
                        catchStatement.Identifier.Text,
                        VariableModifiers.None,
                        CodeLocation.Join(catchStatement.ClassType.Location, catchStatement.Identifier.Location),
                        statementReference,
                        catchStatement.ClassType.Generated);

                    // If there is already a variable in this scope with the same name, ignore this one.
                    if (!catchStatement.Variables.Contains(catchStatement.Identifier.Text))
                    {
                        catchStatement.Variables.Add(variable);
                    }
                }
            }

            return catchStatement;
        }
        /// <summary>
        /// Looks for a finally-statement, and if it is found, parses and returns it.
        /// </summary>
        /// <param name="tryStatement">The parent try statement.</param>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the statement.</returns>
        private FinallyStatement GetAttachedFinallyStatement(TryStatement tryStatement, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(tryStatement, "tryStatement");
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            FinallyStatement finallyStatement = null;

            // Look for a finally keyword.
            Symbol symbol = this.GetNextSymbol(parentReference);
            if (symbol.SymbolType == SymbolType.Finally)
            {
                var statementReference = new Reference<ICodePart>();

                // Move up to the finally keyword and add it.
                CsToken firstToken = this.GetToken(CsTokenType.Finally, SymbolType.Finally, statementReference);
                Node<CsToken> firstTokenNode = this.tokens.InsertLast(firstToken);

                // Get the embedded statement. This must be a block statement.
                BlockStatement childStatement = this.GetNextStatement(statementReference, unsafeCode) as BlockStatement;
                if (childStatement == null)
                {
                    throw new SyntaxException(this.document.SourceCode, firstToken.LineNumber);
                }

                // Create the token list for the statement.
                CsTokenList partialTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);

                // Create and return the finally statement.
                finallyStatement = new FinallyStatement(partialTokens, tryStatement, childStatement);
                ((IWriteableCodeUnit)finallyStatement).SetParent(tryStatement);
                statementReference.Target = finallyStatement;
            }

            return finallyStatement;
        }
        /// <summary>
        /// Reads the next try-statement from the file and returns it.
        /// </summary>
        /// <param name="parentReference">The parent code unit.</param>
        /// <param name="unsafeCode">Indicates whether the code being parsed resides in an unsafe code block.</param>
        /// <returns>Returns the statement.</returns>
        private TryStatement ParseTryStatement(Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(parentReference, "parentReference");
            Param.Ignore(unsafeCode);

            var statementReference = new Reference<ICodePart>();

            // Move past the try keyword.
            CsToken firstToken = this.GetToken(CsTokenType.Try, SymbolType.Try, parentReference, statementReference);
            Node<CsToken> firstTokenNode = this.tokens.InsertLast(firstToken);

            // Get the embedded statement. It must be a block statement.
            BlockStatement childStatement = this.GetNextStatement(statementReference, unsafeCode) as BlockStatement;
            if (childStatement == null)
            {
                throw this.CreateSyntaxException();
            }

            // Create the try-statement now.
            TryStatement statement = new TryStatement(childStatement);

            // Get the attached catch statements, if any.
            List<CatchStatement> catchStatements = new List<CatchStatement>();
            while (true)
            {
                CatchStatement catchStatement = this.GetAttachedCatchStatement(statement, statementReference, unsafeCode);
                if (catchStatement == null)
                {
                    break;
                }

                catchStatements.Add(catchStatement);
            }

            // Get the attached finally statement, if any.
            FinallyStatement finallyStatement = this.GetAttachedFinallyStatement(statement, statementReference, unsafeCode);

            // Create the full token list for the try-statement and add it.
            statement.Tokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);

            // Add the catch and finally statements to the try statement.
            statement.CatchStatements = catchStatements.ToArray();
            statement.FinallyStatement = finallyStatement;

            // Return the statement.
            statementReference.Target = statement;
            return statement;
        }
Example #5
0
 private TryStatement ParseTryStatement(bool unsafeCode)
 {
     CsToken item = this.GetToken(CsTokenType.Try, SymbolType.Try);
     Microsoft.StyleCop.Node<CsToken> firstItemNode = this.tokens.InsertLast(item);
     BlockStatement nextStatement = this.GetNextStatement(unsafeCode) as BlockStatement;
     if (nextStatement == null)
     {
         throw this.CreateSyntaxException();
     }
     TryStatement tryStatement = new TryStatement(nextStatement);
     List<CatchStatement> list = new List<CatchStatement>();
     while (true)
     {
         CatchStatement attachedCatchStatement = this.GetAttachedCatchStatement(tryStatement, unsafeCode);
         if (attachedCatchStatement == null)
         {
             break;
         }
         list.Add(attachedCatchStatement);
     }
     FinallyStatement attachedFinallyStatement = this.GetAttachedFinallyStatement(tryStatement, unsafeCode);
     tryStatement.Tokens = new CsTokenList(this.tokens, firstItemNode, this.tokens.Last);
     tryStatement.CatchStatements = list.ToArray();
     tryStatement.FinallyStatement = attachedFinallyStatement;
     return tryStatement;
 }
Example #6
0
 private FinallyStatement GetAttachedFinallyStatement(TryStatement tryStatement, bool unsafeCode)
 {
     FinallyStatement statement = null;
     if (this.GetNextSymbol().SymbolType != SymbolType.Finally)
     {
         return statement;
     }
     CsToken item = this.GetToken(CsTokenType.Finally, SymbolType.Finally);
     Microsoft.StyleCop.Node<CsToken> firstItemNode = this.tokens.InsertLast(item);
     BlockStatement nextStatement = this.GetNextStatement(unsafeCode) as BlockStatement;
     if (nextStatement == null)
     {
         throw new SyntaxException(this.document.SourceCode, item.LineNumber);
     }
     return new FinallyStatement(new CsTokenList(this.tokens, firstItemNode, this.tokens.Last), tryStatement, nextStatement);
 }
Example #7
0
 private CatchStatement GetAttachedCatchStatement(TryStatement tryStatement, bool unsafeCode)
 {
     CatchStatement statement = null;
     if (this.GetNextSymbol().SymbolType == SymbolType.Catch)
     {
         CsToken item = this.GetToken(CsTokenType.Catch, SymbolType.Catch);
         Microsoft.StyleCop.Node<CsToken> firstItemNode = this.tokens.InsertLast(item);
         Expression classExpression = null;
         if (this.GetNextSymbol().SymbolType == SymbolType.OpenParenthesis)
         {
             Bracket bracketToken = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis);
             Microsoft.StyleCop.Node<CsToken> node2 = this.tokens.InsertLast(bracketToken);
             if (this.GetNextSymbol().SymbolType == SymbolType.Other)
             {
                 classExpression = this.GetNextExpression(ExpressionPrecedence.None, unsafeCode, true, true);
             }
             Bracket bracket2 = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis);
             Microsoft.StyleCop.Node<CsToken> node3 = this.tokens.InsertLast(bracket2);
             bracketToken.MatchingBracketNode = node3;
             bracket2.MatchingBracketNode = node2;
         }
         BlockStatement nextStatement = this.GetNextStatement(unsafeCode) as BlockStatement;
         if (nextStatement == null)
         {
             throw new SyntaxException(this.document.SourceCode, item.LineNumber);
         }
         CsTokenList tokens = new CsTokenList(this.tokens, firstItemNode, this.tokens.Last);
         statement = new CatchStatement(tokens, tryStatement, classExpression, nextStatement);
         if ((statement.ClassType != null) && !string.IsNullOrEmpty(statement.Identifier))
         {
             Variable variable = new Variable(statement.ClassType, statement.Identifier, VariableModifiers.None, statement.ClassType.Location.StartPoint, statement.ClassType.Generated);
             if (!statement.Variables.Contains(statement.Identifier))
             {
                 statement.Variables.Add(variable);
             }
         }
     }
     return statement;
 }
 private static bool IsUnnecessaryTryStatement(TryStatement tryStatement)
 {
     return (IsEmptyParentOfBlockStatement(tryStatement) || (((tryStatement.CatchStatements == null) || (tryStatement.CatchStatements.Count == 0)) && ((tryStatement.FinallyStatement == null) || IsEmptyParentOfBlockStatement(tryStatement.FinallyStatement))));
 }
        /// <summary>
        /// Checks the given try statement to make sure that it is needed.
        /// </summary>
        /// <param name="tryStatement">The try statement to check.</param>
        /// <returns>Returns true if the try statement is not needed, false otherwise.</returns>
        private static bool IsUnnecessaryTryStatement(TryStatement tryStatement)
        {
            Param.AssertNotNull(tryStatement, "tryStatement");

            // If the body of the try-statement is empty, it is not needed.
            if (IsEmptyParentOfBlockStatement(tryStatement))
            {
                // If the try-statement contains a non-empty finally or a non-empty catch statement, then it is allowed to be empty.
                // This is because an empty try-statement can be used to create a critical execution region and the finally or catch areas
                // will run even in the case of a ThreadAbortException.
                if (tryStatement.FinallyStatement != null && !IsEmptyParentOfBlockStatement(tryStatement.FinallyStatement))
                {
                    return false;
                }

                if (tryStatement.CatchStatements != null && tryStatement.CatchStatements.Count > 0)
                {
                    foreach (CatchStatement catchStatement in tryStatement.CatchStatements)
                    {
                        if (!IsEmptyParentOfBlockStatement(catchStatement))
                        {
                            return false;
                        }
                    }
                }

                return true;
            }
            else
            {
                // If the try-statement does not contain any catch statements or finally statements, it is not needed.
                if (tryStatement.CatchStatements == null || tryStatement.CatchStatements.Count == 0)
                {
                    if (tryStatement.FinallyStatement == null || IsEmptyParentOfBlockStatement(tryStatement.FinallyStatement))
                    {
                        return true;
                    }
                }
            }

            return false;
        }