示例#1
0
        /// <summary>
        /// Checks to make sure that the slashes in in the Xml header are followed by a space.
        /// </summary>
        /// <param name="header">The Xml header token.</param>
        private void CheckXmlHeaderComment(ElementHeader header)
        {
            Param.AssertNotNull(header, "header");

            for (ElementHeaderLine item = header.FindFirstDescendent<ElementHeaderLine>(); item != null; item = item.FindNextDescendentOf<ElementHeaderLine>(header))
            {
                if (item.Text.Length > 3)
                {
                    if (item.Text[3] != ' ' &&
                        item.Text[3] != '\t' &&
                        item.Text[3] != '/' &&
                        item.Text[2] != '\n' &&
                        item.Text[2] != '\r')
                    {
                        // The header line does not start with any spaces.
                        this.AddViolation(item.FindParentElement(), item.LineNumber, Rules.DocumentationLinesMustBeginWithSingleSpace);
                    }
                    else if (item.Text.Length > 4 && (item.Text[4] == ' ' || item.Text[4] == '\t'))
                    {
                        // The header line starts with more than one space. This is only allowed when the 
                        // header line is not the first or last line in the header.
                        bool error = true;
                        for (LexicalElement previous = item.FindPreviousLexicalElement(); previous != null; previous = previous.FindPreviousLexicalElement())
                        {
                            if (previous.Is(CommentType.ElementHeaderLine))
                            {
                                for (LexicalElement next = item.FindNextLexicalElement(); next != null; next = next.FindNextLexicalElement())
                                {
                                    if (next.Is(CommentType.ElementHeaderLine))
                                    {
                                        error = false;
                                        break;
                                    }
                                }

                                break;
                            }
                        }

                        if (error)
                        {
                            this.AddViolation(item.FindParentElement(), item.LineNumber, Rules.DocumentationLinesMustBeginWithSingleSpace);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Loads the header text for the element into a document and returns it.
        /// </summary>
        /// <param name="element">The element containing the header.</param>
        /// <param name="header">The header to load.</param>
        /// <param name="lineNumber">The line number that the header begins on.</param>
        /// <param name="rawDocs">Returns the docs with whitepace and newlines left in place.</param>
        /// <param name="formattedDocs">Returns the docs with newlines filtered out.</param>
        private void LoadHeaderIntoDocuments(Element element, ElementHeader header, int lineNumber, out XmlDocument rawDocs, out XmlDocument formattedDocs)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(header, "header");
            Param.AssertGreaterThanZero(lineNumber, "lineNumber");

            rawDocs = new XmlDocument();
            formattedDocs = new XmlDocument();

            try
            {
                string correctxml = "<root>" + header.HeaderXml + "</root>";
                formattedDocs.LoadXml(correctxml);

                correctxml = "<root>" + header.HeaderXmlWithNewlines + "</root>";
                rawDocs.LoadXml(correctxml);
            }
            catch (XmlException xmlex)
            {
                this.AddViolation(element, lineNumber, Rules.DocumentationMustContainValidXml, xmlex.Message);
                rawDocs = formattedDocs = null;
            }
        }
        /// <summary>
        /// Checks the documentation header to see whether it contains any blank lines.
        /// </summary>
        /// <param name="element">The element containing the header.</param>
        /// <param name="header">The documentation header.</param>
        private void CheckForBlankLinesInDocumentationHeader(Element element, ElementHeader header)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(header, "header");

            if (!element.Generated)
            {
                int blankLineCount = 0;
                int insideCodeElementCount = 0;

                for (CodeUnit item = header.FindFirstChild(); item != null; item = item.FindNextSibling())
                {
                    if (item.Is(LexicalElementType.EndOfLine))
                    {
                        ++blankLineCount;

                        if (blankLineCount > 1)
                        {
                            this.AddViolation(element, item.LineNumber, Rules.DocumentationHeadersMustNotContainBlankLines);
                            break;
                        }
                    }
                    else if (item.Is(CommentType.ElementHeaderLine))
                    {
                        ElementHeaderLine headerLine = (ElementHeaderLine)item;
                        insideCodeElementCount += XmlHeaderLineCodeElementCount(headerLine);

                        if (headerLine == header.Children.First || headerLine == header.Children.Last)
                        {
                            if (IsXmlHeaderLineEmpty(headerLine) && insideCodeElementCount == 0)
                            {
                                this.AddViolation(element, headerLine.LineNumber, Rules.DocumentationHeadersMustNotContainBlankLines);
                                break;
                            }
                        }
                        else if (!IsXmlHeaderLineEmpty(headerLine) || insideCodeElementCount > 0)
                        {
                            blankLineCount = 0;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Parses the contents of the header for validity.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="header">The header.</param>
        /// <param name="lineNumber">The line number that the header element begins on.</param>
        /// <param name="partialElement">Indicates whether the element has the partial attribute.</param>
        private void ParseHeader(Element element, ElementHeader header, int lineNumber, bool partialElement)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(header, "header");
            Param.AssertGreaterThanZero(lineNumber, "lineNumber");
            Param.Ignore(partialElement);

            // Load this into an xml document.
            XmlDocument rawDocs = null;
            XmlDocument formattedDocs = null;

            this.LoadHeaderIntoDocuments(element, header, lineNumber, out rawDocs, out formattedDocs);

            if (rawDocs != null && formattedDocs != null)
            {
                // Check whether the method has an <inheritdoc> tag at the root. If so, discontinue checking the contents of the header, 
                // but verify that the class actually inherits from a base class. Otherwise this tag is not allowed.
                if (rawDocs.SelectSingleNode("root/inheritdoc") != null)
                {
                    this.CheckInheritDocRules(element);
                }
                else
                {
                    // Insert any documentation present in 'include' tags.
                    if (this.InsertIncludedDocumentation(element, Path.GetDirectoryName(element.Document.Path), formattedDocs))
                    {
                        this.CheckForBlankLinesInDocumentationHeader(element, header);
                        this.CheckHeaderSummary(element, lineNumber, partialElement, formattedDocs);

                        // Check element parameters and return types.
                        if (element.ElementType == ElementType.Method)
                        {
                            Method item = element as Method;
                            this.CheckHeaderParams(element, item.ParameterList, formattedDocs);
                            this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Constructor)
                        {
                            Constructor item = element as Constructor;
                            this.CheckHeaderParams(element, item.ParameterList, formattedDocs);
                            this.CheckConstructorSummaryText(item, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Delegate)
                        {
                            StyleCop.CSharp.CodeModel.Delegate item = element as StyleCop.CSharp.CodeModel.Delegate;
                            this.CheckHeaderParams(element, item.ParameterList, formattedDocs);
                            this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Indexer)
                        {
                            Indexer item = element as Indexer;
                            this.CheckHeaderParams(element, item.ParameterList, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Property)
                        {
                            // Check value tags on properties.
                            this.CheckPropertyValueTag(element, formattedDocs);

                            // Check that the property summary starts with the correct text.
                            this.CheckPropertySummaryFormatting(element as Property, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Destructor)
                        {
                            this.CheckDestructorSummaryText((Destructor)element, formattedDocs);
                        }

                        // Check for repeating comments on all element types which can contain params or typeparams.
                        if (element.ElementType == ElementType.Method ||
                            element.ElementType == ElementType.Constructor ||
                            element.ElementType == ElementType.Delegate ||
                            element.ElementType == ElementType.Indexer ||
                            element.ElementType == ElementType.Class ||
                            element.ElementType == ElementType.Struct ||
                            element.ElementType == ElementType.Interface)
                        {
                            this.CheckForRepeatingComments(element, formattedDocs);
                        }

                        // Check generic type parameters.
                        if (element.ElementType == ElementType.Class ||
                            element.ElementType == ElementType.Method ||
                            element.ElementType == ElementType.Delegate ||
                            element.ElementType == ElementType.Interface ||
                            element.ElementType == ElementType.Struct)
                        {
                            this.CheckGenericTypeParams(element, formattedDocs);
                        }
                    }
                }
            }
        }