/// <summary> /// Attempts to locate the given element within the collection of possible elements, and the parents and ancestors of those elements. /// </summary> /// <param name="element"> /// The element to match. /// </param> /// <param name="possibleElements"> /// The collection of possible elements to match against. /// </param> /// <returns> /// Returns true if a match is found; otherwise false. /// </returns> private static bool MatchElementWithPossibleElementsTraversingParents(CsElement element, IList <CsElement> possibleElements) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(possibleElements, "possibleElements"); // Loop through each possible element using a for-style loop rather than a foreach, since this // is faster and this method is called very often. for (int i = 0; i < possibleElements.Count; ++i) { CsElement possibleMatch = possibleElements[i]; // Walk through the element and each of its parents to see if any is a match. CsElement item = element; while (item != null) { if (item == possibleMatch) { return(true); } item = item.FindParentElement(); } } return(false); }
/// <summary> /// Checks that using-directives are placed within the namespace element. /// </summary> /// <param name="element"> /// The element to check. /// </param> private void CheckUsingDirectivePlacement(CsElement element) { Param.AssertNotNull(element, "element"); // Only check the positioning of using directives which are not within generated code. if (!element.Generated && element.ElementType == ElementType.UsingDirective) { CsElement parentElement = element.FindParentElement(); if (parentElement != null && parentElement.ElementType != ElementType.Namespace) { // This is acceptable if there is no namespace in the file at all. bool foundNamespace = false; if (parentElement.ElementType == ElementType.Root) { foreach (CsElement child in parentElement.ChildElements) { if (child.ElementType == ElementType.Namespace) { foundNamespace = true; break; } } } // Its also acceptable if there is an assembly attribute too. bool foundAssemblyAttribute = false; if (parentElement.ElementType == ElementType.Root) { foreach (CsElement child in parentElement.ChildElements) { if (child.ElementType == ElementType.AssemblyOrModuleAttribute) { foundAssemblyAttribute = true; break; } } } if (foundNamespace && !foundAssemblyAttribute) { this.AddViolation(element, Rules.UsingDirectivesMustBePlacedWithinNamespace); } } } }
/// <summary> /// Initializes a new instance of the <see cref="CodeWalker{T}"/> class. /// Initializes a new instance of the CodeWalker class. /// </summary> /// <param name="element"> /// The element to walk through. /// </param> /// <param name="elementCallback"> /// Callback executed when an element is visited. /// </param> /// <param name="statementCallback"> /// Callback executed when a statement is visited. /// </param> /// <param name="expressionCallback"> /// Callback executed when an expression is visited. /// </param> /// <param name="queryClauseCallback"> /// Callback executed when a query clause is visited. /// </param> /// <param name="context"> /// The optional visitor context data. /// </param> private CodeWalker( CsElement element, CodeWalkerElementVisitor <T> elementCallback, CodeWalkerStatementVisitor <T> statementCallback, CodeWalkerExpressionVisitor <T> expressionCallback, CodeWalkerQueryClauseVisitor <T> queryClauseCallback, T context) { Param.AssertNotNull(element, "element"); Param.Ignore(elementCallback); Param.Ignore(statementCallback); Param.Ignore(expressionCallback); Param.Ignore(queryClauseCallback); Param.Ignore(context); this.elementCallback = elementCallback; this.statementCallback = statementCallback; this.expressionCallback = expressionCallback; this.queryClauseCallback = queryClauseCallback; this.WalkElement(element, element.FindParentElement(), context); }