/// <summary>
        /// Checks declaration comment blocks.
        /// </summary>
        /// <param name="file">
        /// The <see cref="ICSharpFile"/> to use.
        /// </param>
        /// <param name="declaration">
        /// The <see cref="IDeclaration"/> to check.
        /// </param>
        /// <param name="options">
        /// <see cref="OrderingOptions"/>Current options that we can reference.
        /// </param>
        private void CheckDeclarationDocumentation(ICSharpFile file, IDeclaration declaration, DocumentationOptions options)
        {
            Param.RequireNotNull(file, "file");
            Param.RequireNotNull(declaration, "declaration");
            Param.RequireNotNull(options, "options");

            bool insertMissingElementDocOption = options.SA1600ElementsMustBeDocumented;
            bool documentationTextMustBeginWithACapitalLetter = options.SA1628DocumentationTextMustBeginWithACapitalLetter;
            bool documentationTextMustEndWithAPeriod = options.SA1629DocumentationTextMustEndWithAPeriod;
            bool elementDocumentationMustHaveSummary = options.SA1604ElementDocumentationMustHaveSummary;
            bool constructorSummaryDocBeginsWithStandardText = options.SA1642ConstructorSummaryDocumentationMustBeginWithStandardText;
            bool destructorSummaryDocBeginsWithStandardText = options.SA1643DestructorSummaryDocumentationMustBeginWithStandardText;
            bool propertyDocumentationMustHaveValueDocumented = options.SA1609PropertyDocumentationMustHaveValue;
            bool insertMissingParamTagOption = options.SA1611ElementParametersMustBeDocumented;
            bool genericTypeParametersMustBeDocumented = options.SA1618GenericTypeParametersMustBeDocumented;

            if (insertMissingElementDocOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1600))
            {
                DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

                if (declarationHeader.IsMissing
                    || (!declarationHeader.IsInherited && declarationHeader.HasEmptySummary && string.IsNullOrEmpty(declarationHeader.XmlNode.InnerText)))
                {
                    this.InsertMissingDeclarationHeader(file, declaration);
                }
            }

            if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1611))
            {
                if (declaration is IConstructorDeclaration)
                {
                    IConstructorDeclaration constructorDeclaration = declaration as IConstructorDeclaration;

                    if (constructorDeclaration.ParameterDeclarations.Count > 0)
                    {
                        this.InsertMissingParamElement(constructorDeclaration);
                    }
                }
            }

            if (elementDocumentationMustHaveSummary && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1604))
            {
                this.InsertMissingSummaryElement(declaration);
            }

            DocumentationRulesConfiguration docConfig = this.GetDocumentationRulesConfig(file);

            // However it can be on/off depending on the file so we'd have to cache it per file
            bool ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("DocumentationTextMustBeginWithACapitalLetter");

            if (documentationTextMustBeginWithACapitalLetter && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1628))
            {
                this.EnsureDocumentationTextIsUppercase(declaration);
            }

            ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("DocumentationTextMustEndWithAPeriod");

            if (documentationTextMustEndWithAPeriod && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1629))
            {
                this.EnsureDocumentationTextEndsWithAPeriod(declaration);
            }

            if (constructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1642))
            {
                this.EnsureConstructorSummaryDocBeginsWithStandardText(declaration as IConstructorDeclaration);
            }

            if (destructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1643))
            {
                this.EnsureDestructorSummaryDocBeginsWithStandardText(declaration as IDestructorDeclaration);
            }

            if (declaration is IMethodDeclaration)
            {
                this.CheckMethodDeclarationDocumentation(declaration as IMethodDeclaration, options);
            }

            ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("PropertyDocumentationMustHaveValue");

            if (propertyDocumentationMustHaveValueDocumented && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1609))
            {
                if (declaration is IPropertyDeclaration)
                {
                    this.InsertValueElement(declaration as IPropertyDeclaration);
                }
            }

            if (genericTypeParametersMustBeDocumented && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1618))
            {
                this.InsertMissingTypeParamElement(declaration);
            }
        }
        /// <summary>
        /// Removes a return element if it currently has one.
        /// </summary>
        /// <param name="memberDeclaration">
        /// The <see cref="ITypeDeclaration"/> to check and fix.
        /// </param>
        public void RemoveReturnsElement(ITypeMemberDeclaration memberDeclaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(memberDeclaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited || !declarationHeader.HasReturns)
            {
                return;
            }

            declarationHeader.XmlNode.RemoveChild(declarationHeader.ReturnsXmlNode);
            declarationHeader.Update();
        }
        /// <summary>
        /// Ensures that the constructor documentation starts with the standard text summary. 
        /// </summary>
        /// <remarks>
        /// Keeps the existing comment, but prepends the standard text.
        /// </remarks>
        /// <param name="constructorDeclaration">
        /// The destructor <see cref="IDeclaration"/>.
        /// </param>
        public void EnsureConstructorSummaryDocBeginsWithStandardText(IConstructorDeclaration constructorDeclaration)
        {
            if (constructorDeclaration == null)
            {
                return;
            }

            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, constructorDeclaration.GetSolution());
            if (!settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                return;
            }

            DeclarationHeader declarationHeader = new DeclarationHeader(constructorDeclaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited || !declarationHeader.HasSummary)
            {
                return;
            }

            string existingSummaryText = declarationHeader.SummaryXmlNode.InnerXml;

            bool parentIsStruct = Utils.IsContainingTypeAStruct(constructorDeclaration);

            int constructorParameterCount = constructorDeclaration.ParameterDeclarations.Count;

            string xmlComment = Utils.GetTextFromDeclarationHeader(declarationHeader.XmlNode);
            string structOrClass = parentIsStruct ? "struct" : "class";
            string textWeShouldStartWith;

            if (constructorDeclaration.IsStatic)
            {
                textWeShouldStartWith = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForStaticConstructor, constructorDeclaration.DeclaredName, structOrClass);
            }
            else if (constructorDeclaration.GetAccessRights() == AccessRights.PRIVATE && constructorParameterCount == 0)
            {
                textWeShouldStartWith = string.Format(
                    CultureInfo.InvariantCulture, HeaderSummaryForPrivateInstanceConstructor, constructorDeclaration.DeclaredName, structOrClass);
            }
            else
            {
                string constructorDescriptionText = Utils.CreateConstructorDescriptionText(constructorDeclaration, true);
                textWeShouldStartWith = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForInstanceConstructor, constructorDescriptionText, structOrClass);
            }

            if (constructorDeclaration.IsStatic)
            {
                string docStd = string.Format("Initializes the {0} class.", constructorDeclaration.DeclaredName);
                if (xmlComment == docStd)
                {
                    existingSummaryText = string.Empty;
                }
            }

            if (!xmlComment.StartsWith(textWeShouldStartWith, StringComparison.Ordinal))
            {
                string newSummaryText = Utils.CreateSummaryForConstructorDeclaration(constructorDeclaration);

                declarationHeader.SummaryXmlNode.InnerXml = newSummaryText + " " + existingSummaryText;

                declarationHeader.Update();
            }
        }
        /// <summary>
        /// Inserts a returns element to the element if its missing.
        /// </summary>
        /// <param name="memberDeclaration">
        /// The <see cref="ITypeMemberDeclaration"/> to check and fix.
        /// </param>
        public void InsertReturnsElement(ITypeMemberDeclaration memberDeclaration)
        {
            Param.RequireNotNull(memberDeclaration, "memberDeclaration");

            DeclarationHeader declarationHeader = new DeclarationHeader(memberDeclaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            XmlNode xmlNode = declarationHeader.XmlNode;

            XmlNode returnsXmlNode = declarationHeader.ReturnsXmlNode;

            string valueText = string.Empty;
            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, memberDeclaration.GetSolution());
            if (settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                valueText = string.Format("The {0}.", Utils.ConvertTextToSentence(memberDeclaration.DeclaredName).ToLower());
            }

            if (declarationHeader.HasReturns)
            {
                if (string.IsNullOrEmpty(returnsXmlNode.InnerText.Trim()))
                {
                    returnsXmlNode.InnerText = valueText;
                    declarationHeader.Update();
                }
                else
                {
                    return;
                }
            }
            else
            {
                XmlNode valueNode = CreateNode(xmlNode, "returns");
                valueNode.InnerText = valueText;
                xmlNode.AppendChild(valueNode);
                declarationHeader.Update();
            }
        }
        /// <summary>
        /// Inserts a value element to the element if its missing.
        /// </summary>
        /// <param name="propertyDeclaration">
        /// The <see cref="IPropertyDeclaration"/> to check and fix.
        /// </param>
        public void InsertValueElement(IPropertyDeclaration propertyDeclaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(propertyDeclaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            XmlNode xmlNode = declarationHeader.XmlNode;

            string valueText = string.Empty;

            XmlNode valueXmlNode = declarationHeader.ValueXmlNode;

            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, propertyDeclaration.GetSolution());
            if (settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                valueText = string.Format("The {0}.", Utils.ConvertTextToSentence(propertyDeclaration.DeclaredName).ToLower());
            }

            if (declarationHeader.HasValue)
            {
                if (string.IsNullOrEmpty(valueXmlNode.InnerText.Trim()))
                {
                    valueXmlNode.InnerText = valueText;
                    declarationHeader.Update();
                }
                else
                {
                    return;
                }
            }
            else
            {
                XmlNode valueNode = CreateNode(xmlNode, "value");
                valueNode.InnerText = valueText;
                xmlNode.AppendChild(valueNode);
                declarationHeader.Update();
            }
        }
        /// <summary>
        /// Inserts a missing summary element.
        /// </summary>
        /// <param name="declaration">
        /// The <see cref="IDeclaration"/> to get comment from.
        /// </param>
        public void InsertMissingSummaryElement(IDeclaration declaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            string summaryText = string.Empty;
            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, declaration.GetSolution());
            if (settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                summaryText = string.Format("The {0}.", Utils.ConvertTextToSentence(declaration.DeclaredName).ToLower());
            }

            XmlNode summaryXmlNode = declarationHeader.SummaryXmlNode;

            if (declarationHeader.HasSummary)
            {
                if (string.IsNullOrEmpty(summaryXmlNode.InnerText.Trim()))
                {
                    summaryXmlNode.InnerText = summaryText;
                    declarationHeader.Update();
                }
                else
                {
                    return;
                }
            }
            else
            {
                XmlNode newChild = CreateNode(declarationHeader.XmlNode, "summary");
                newChild.InnerText = summaryText;
                declarationHeader.XmlNode.InsertBefore(newChild, declarationHeader.XmlNode.FirstChild);
                declarationHeader.Update();
            }
        }
        /// <summary>
        /// Updates the summary to include all <c>typeparam</c> and remove any extra ones and in the correct order.
        /// </summary>
        /// <param name="declaration">
        /// The <see cref="ITypeDeclaration"/> to check and fix.
        /// </param>
        public void InsertMissingTypeParamElement(IDeclaration declaration)
        {
            ITypeParametersOwner declaredElement = declaration.DeclaredElement as ITypeParametersOwner;

            if (declaredElement == null)
            {
                return;
            }

            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            XmlNode xmlNode = declarationHeader.XmlNode;

            Hashtable ht = new Hashtable();

            foreach (ITypeParameter parameter in declaredElement.TypeParameters)
            {
                ht.Add(parameter.ShortName, null);

                if (declarationHeader.ContainsTypeParameter(parameter.ShortName))
                {
                    continue;
                }

                XmlNode parameterNode = CreateTypeParamNode(xmlNode, parameter.ShortName);

                XmlNodeList paramNodeList = xmlNode.SelectNodes("//typeparam");
                if (paramNodeList != null)
                {
                    XmlNode c = paramNodeList.Count == 0 ? declarationHeader.SummaryXmlNode : paramNodeList.Item(paramNodeList.Count - 1);

                    xmlNode.InsertAfter(parameterNode, c);
                }
            }

            RemoveTypeParamsNotRequired(xmlNode, ht);
            ReorderTypeParams(xmlNode, declaredElement.TypeParameters);
            declarationHeader.Update();
        }
        /// <summary>
        /// Ensures the declaration passed has its comments beginning with a capital letter.
        /// </summary>
        /// <param name="declaration">
        /// The destructor <see cref="IDeclaration"/>.
        /// </param>
        public void EnsureDocumentationTextIsUppercase(IDeclaration declaration)
        {
            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, declaration.GetSolution());
            if (!settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                return;
            }

            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            this.SwapToUpper(declarationHeader.XmlNode);
            declarationHeader.Update();
        }
        /// <summary>
        /// Insert a missing parameter element to the comment.
        /// </summary>
        /// <param name="declaration">
        /// The <see cref="IDeclaration"/> to check and fix.
        /// </param>
        public void InsertMissingParamElement(IDeclaration declaration)
        {
            Param.RequireNotNull(declaration, "declaration");

            IParametersOwnerDeclaration parametersOwnerDeclaration = declaration as IParametersOwnerDeclaration;

            if (parametersOwnerDeclaration == null)
            {
                return;
            }

            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            XmlNode xmlNode = declarationHeader.XmlNode;
            Hashtable ht = new Hashtable();

            IList<IParameterDeclaration> parameters = parametersOwnerDeclaration.ParameterDeclarations;

            if (parameters != null)
            {
                foreach (IParameterDeclaration parameter in parameters)
                {
                    ht.Add(parameter.DeclaredName, null);

                    if (declarationHeader.ContainsParameter(parameter.DeclaredName))
                    {
                        continue;
                    }

                    XmlNodeList paramNodeList = xmlNode.SelectNodes("//param");
                    if (paramNodeList != null)
                    {
                        XmlNode c = paramNodeList.Count == 0 ? declarationHeader.SummaryXmlNode : paramNodeList.Item(paramNodeList.Count - 1);

                        XmlNode parameterNode = CreateParamNode(xmlNode, parameter);

                        xmlNode.InsertAfter(parameterNode, c);
                    }
                }
            }

            RemoveParamsNotRequired(xmlNode, ht);
            ReorderParams(xmlNode, parameters);
            declarationHeader.Update();
        }
        /// <summary>
        /// Ensures the declaration passed has no blank lines unless inside code elements.
        /// </summary>
        /// <param name="declaration">
        /// The destructor <see cref="IDeclaration"/>.
        /// </param>
        public void EnsureDocumentationHasNoBlankLines(IDeclaration declaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited)
            {
                return;
            }

            this.RemoveBlankLines(declarationHeader.XmlNode);
            declarationHeader.Update();
        }
        /// <summary>
        /// Ensures that the destructor documentation starts with the standard text summary. 
        /// </summary>
        /// <remarks>
        /// Keeps the existing comment, but prepends the standard text.
        /// </remarks>
        /// <param name="destructorDeclaration">
        /// The destructor <see cref="IDeclaration"/>.
        /// </param>
        public void EnsureDestructorSummaryDocBeginsWithStandardText(IDestructorDeclaration destructorDeclaration)
        {
            if (destructorDeclaration == null)
            {
                return;
            }

            DeclarationHeader declarationHeader = new DeclarationHeader(destructorDeclaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited || !declarationHeader.HasSummary)
            {
                return;
            }

            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, destructorDeclaration.GetSolution());
            if (!settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                return;
            }

            string destructorDescriptionText = Utils.CreateDestructorDescriptionText(destructorDeclaration, true);

            string xmlComment = Utils.GetTextFromDeclarationHeader(declarationHeader.XmlNode);

            string textWeShouldStartWith = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForDestructor, destructorDescriptionText);

            if (!xmlComment.StartsWith(textWeShouldStartWith, StringComparison.Ordinal))
            {
                string summaryText = Utils.CreateSummaryForDestructorDeclaration(destructorDeclaration);

                declarationHeader.SummaryXmlNode.InnerXml = Environment.NewLine + summaryText;

                declarationHeader.Update();
            }
        }
        /// <summary>
        /// Gets a string of the summary for this destructor.
        /// </summary>
        /// <param name="destructorDeclaration">
        /// The destructor to produce the summary for.
        /// </param>
        /// <returns>
        /// A string of the destructor summary text.
        /// </returns>
        public static string CreateSummaryForDestructorDeclaration(IDestructorDeclaration destructorDeclaration)
        {
            string summaryText = string.Empty;

            DeclarationHeader declarationHeader = new DeclarationHeader(destructorDeclaration);

            if (declarationHeader.IsInherited)
            {
                return declarationHeader.XmlNode.InnerXml;
            }

            if (declarationHeader.HasSummary)
            {
                summaryText = declarationHeader.SummaryXmlNode.InnerXml;
            }

            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, destructorDeclaration.GetSolution());
            if (!settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                return summaryText;
            }

            string destructorDescriptionText = CreateDestructorDescriptionText(destructorDeclaration, true);

            string newXmlText = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForDestructorXml, destructorDescriptionText);

            return newXmlText + " " + summaryText;
        }
        /// <summary>
        /// Creates a new summary string for this constructor.
        /// </summary>
        /// <param name="constructorDeclaration">
        /// The constructor to produce the summary for.
        /// </param>
        /// <returns>
        /// A string of the constructor summary text.
        /// </returns>
        public static string CreateSummaryForConstructorDeclaration(IConstructorDeclaration constructorDeclaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(constructorDeclaration);

            if (declarationHeader.IsInherited)
            {
                return declarationHeader.XmlNode.InnerXml;
            }

            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, constructorDeclaration.GetSolution());
            if (!settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                return string.Empty;
            }

            bool parentIsStruct = IsContainingTypeAStruct(constructorDeclaration);

            string structOrClass = parentIsStruct ? "struct" : "class";

            string xmlWeShouldInsert;

            if (constructorDeclaration.IsStatic)
            {
                xmlWeShouldInsert = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForStaticConstructorXml, constructorDeclaration.DeclaredName, structOrClass);
            }
            else if (constructorDeclaration.GetAccessRights() == AccessRights.PRIVATE && constructorDeclaration.ParameterDeclarations.Count == 0)
            {
                xmlWeShouldInsert = string.Format(
                    CultureInfo.InvariantCulture, HeaderSummaryForPrivateInstanceConstructorXml, constructorDeclaration.DeclaredName, structOrClass);
            }
            else
            {
                string constructorDescriptionText = CreateConstructorDescriptionText(constructorDeclaration, true);

                xmlWeShouldInsert = string.Format(CultureInfo.InvariantCulture, HeaderSummaryForInstanceConstructorXml, constructorDescriptionText, structOrClass);
            }

            return xmlWeShouldInsert;
        }
        /// <summary>
        /// Gets the current summary element for the declaration provided or null if missing.
        /// </summary>
        /// <param name="declaration">
        /// The declaration to get the summary for.
        /// </param>
        /// <returns>
        /// A string of the summary or null.
        /// </returns>
        public static string GetSummaryForDeclaration(IDeclaration declaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

            if (declarationHeader.IsMissing || declarationHeader.IsInherited || !declarationHeader.HasSummary)
            {
                return null;
            }

            return declarationHeader.SummaryXmlNode.InnerXml.Trim();
        }