/// <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; }
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; }
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); }
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; }