/// <summary> /// Processes the given expression. /// </summary> /// <param name="expression"> /// The expression to process. /// </param> /// <param name="element"> /// The parent element. /// </param> /// <param name="validPrefixes"> /// The list of acceptable Hungarian-type prefixes. /// </param> private void ProcessExpression(Expression expression, CsElement element, Dictionary <string, string> validPrefixes) { Param.AssertNotNull(expression, "expression"); Param.AssertNotNull(element, "element"); Param.AssertNotNull(validPrefixes, "validPrefixes"); // Check the type of the expression. if (expression.ExpressionType == ExpressionType.AnonymousMethod) { AnonymousMethodExpression anonymousMethod = (AnonymousMethodExpression)expression; // Check the anonymous method's variables. if (anonymousMethod.Variables != null) { foreach (Variable variable in anonymousMethod.Variables) { this.CheckMethodVariablePrefix(variable, element, validPrefixes); } // Check the statements under the anonymous method. foreach (Statement statement in anonymousMethod.ChildStatements) { this.ProcessStatement(statement, element, validPrefixes); } } } // Check the child expressions under this expression. foreach (Expression childExpression in expression.ChildExpressions) { this.ProcessExpression(childExpression, element, validPrefixes); } }
/// <summary> /// Checks the given list of expressions. /// </summary> /// <param name="element"> /// The element containing the expressions. /// </param> /// <param name="expressions"> /// The list of expressions. /// </param> private void CheckStatementFormattingRulesForExpressions(CsElement element, ICollection <Expression> expressions) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(expressions, "expressions"); foreach (Expression expression in expressions) { if (expression.ExpressionType == ExpressionType.AnonymousMethod) { // Check the statements within this anonymous method expression. AnonymousMethodExpression anonymousMethod = expression as AnonymousMethodExpression; this.CheckStatementFormattingRulesForStatements(element, anonymousMethod.ChildStatements); } else { // Check the child expressions under this expression. this.CheckStatementFormattingRulesForExpressions(element, expression.ChildExpressions); } } }
/// <summary> /// Checks that parenthesis are used correctly within an anonymous method. /// </summary> /// <param name="element"> /// The parent element. /// </param> /// <param name="expression"> /// The expression to check. /// </param> private void CheckAnonymousMethodParenthesis(CsElement element, AnonymousMethodExpression expression) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(expression, "expression"); if (expression.Parameters == null || expression.Parameters.Count == 0) { // Check for parenthesis. for (Node<CsToken> tokenNode = expression.Tokens.First; tokenNode != expression.Tokens.Last; tokenNode = tokenNode.Next) { if (tokenNode.Value.CsTokenType == CsTokenType.OpenCurlyBracket) { break; } if (tokenNode.Value.CsTokenType == CsTokenType.OpenParenthesis) { // If we're inside a MethodInvocation and the method being called is a method on our class // with at least 2 signatures then the parens are required. if (expression.Parent is MethodInvocationExpression) { MethodInvocationExpression parentExpression = expression.Parent as MethodInvocationExpression; CsToken classMemberName = Utils.ExtractBaseClassMemberName(parentExpression, parentExpression.Tokens.First); if (classMemberName == null) { break; } ClassBase classBase = Utils.GetClassBase(element); Dictionary<string, List<CsElement>> allClassMembers = Utils.CollectClassMembers(classBase); ICollection<CsElement> classMembers = Utils.FindClassMember(classMemberName.Text, classBase, allClassMembers, false); if (classMembers != null && classMembers.Count > 1) { break; } } this.AddViolation(element, tokenNode.Value.LineNumber, Rules.RemoveDelegateParenthesisWhenPossible); break; } } } }
/// <summary> /// Reads an anonymous method from the code. /// </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 expression. /// </returns> private AnonymousMethodExpression GetAnonymousMethodExpression(Reference<ICodePart> parentReference, bool unsafeCode) { Param.AssertNotNull(parentReference, "parentReference"); Param.Ignore(unsafeCode); Reference<ICodePart> expressionReference = new Reference<ICodePart>(); // Create the anonymous method object now. AnonymousMethodExpression anonymousMethod = new AnonymousMethodExpression(); Node<CsToken> previousTokenNode = this.tokens.Last; // First symbol could be 'async' for asynchronous delegates. Symbol nextSymbol = this.symbols.Peek(1); if (nextSymbol.SymbolType == SymbolType.Other && nextSymbol.Text == "async") { this.tokens.Add(this.GetToken(CsTokenType.Async, SymbolType.Other, expressionReference)); anonymousMethod.Async = true; } // Get the delegate keyword. this.tokens.Add(this.GetToken(CsTokenType.Delegate, SymbolType.Delegate, parentReference, expressionReference)); // Check whether the next symbol is an opening parenthesis. Symbol symbol = this.GetNextSymbol(expressionReference); ICollection<Parameter> parameters = null; if (symbol.SymbolType == SymbolType.OpenParenthesis) { parameters = this.ParseAnonymousMethodParameterList(expressionReference, unsafeCode); } // The next symbol must be an opening curly bracket. Bracket openingBracket = this.GetBracketToken(CsTokenType.OpenCurlyBracket, SymbolType.OpenCurlyBracket, expressionReference); Node<CsToken> openingBracketNode = this.tokens.InsertLast(openingBracket); // Read the child statements. Node<CsToken> closingBracketNode = this.ParseStatementScope(anonymousMethod, expressionReference, unsafeCode); if (closingBracketNode == null) { // If we failed to get a closing bracket back, then there is a syntax // error in the document since there is an opening bracket with no matching // closing bracket. throw this.CreateSyntaxException(); } openingBracket.MatchingBracketNode = closingBracketNode; ((Bracket)closingBracketNode.Value).MatchingBracketNode = openingBracketNode; // Create the token list for the anonymous method expression. Node<CsToken> firstNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; anonymousMethod.Tokens = new CsTokenList(this.tokens, firstNode, this.tokens.Last); // Get the item's argument list if necessary. if (parameters != null && parameters.Count > 0) { anonymousMethod.AddParameters(parameters); } // Add a variable for each of the parameters. if (anonymousMethod.Parameters != null && anonymousMethod.Parameters.Count > 0) { // Add a variable for each of the parameters. foreach (Parameter parameter in anonymousMethod.Parameters) { anonymousMethod.Variables.Add( new Variable(parameter.Type, parameter.Name, VariableModifiers.None, parameter.Location, expressionReference, parameter.Generated)); } } // Return the expression. expressionReference.Target = anonymousMethod; return anonymousMethod; }
/// <summary> /// The save. /// </summary> /// <param name="anonymousMethodExpression"> /// The anonymous method expression. /// </param> private void Save(AnonymousMethodExpression anonymousMethodExpression) { this.cppWriter.Write("[=]"); this.Save(anonymousMethodExpression.Parameters, this.cppWriter, SavingOptions.None /* SavingOptions.ApplyReference */); this.Save(anonymousMethodExpression, SaveICodeUnit.NoNewLine); this.SetMarkBeginOfBlock(); }