/// <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
            {
                XmlNode valueNode = CreateNode(xmlNode, "value");
                valueNode.InnerText = valueText;
                xmlNode.AppendChild(valueNode);
                declarationHeader.Update();
            }
        }
        /// <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>
        /// 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>
        /// Inserts a returns element to the element if its missing.
        /// </summary>
        /// <param name="memberDeclaration">
        /// The <see cref="ITypeMemberDeclaration"/> to check and fix.
        /// </param>
        /// <param name="returnType">
        /// The text to insert as the return type.
        /// </param>
        public void InsertReturnsElement(ITypeMemberDeclaration memberDeclaration, string returnType)
        {
            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 <see cref=\"{0}\"/>.", returnType.SubstringBefore('{'));
            }

            if (declarationHeader.HasReturns)
            {
                if (string.IsNullOrEmpty(returnsXmlNode.InnerText.Trim()))
                {
                    returnsXmlNode.InnerXml = valueText;
                    declarationHeader.Update();
                }
            }
            else
            {
                XmlNode valueNode = CreateNode(xmlNode, "returns");
                valueNode.InnerXml = valueText;
                xmlNode.AppendChild(valueNode);
                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>
        /// Inserts a missing summary element.
        /// </summary>
        /// <param name="declaration">
        /// The <see cref="IDeclaration"/> to get comment from.
        /// </param>
        /// <returns>
        /// True if the element was inserted.
        /// </returns>
        public bool InsertMissingSummaryElement(IDeclaration declaration)
        {
            bool returnValue = false;
            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

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

            string summaryText = string.Empty;
            IContextBoundSettingsStore settingsStore = PsiSourceFileExtensions.GetSettingsStore(null, declaration.GetSolution());
            if (settingsStore.GetValue((StyleCopOptionsSettingsKey key) => key.InsertTextIntoDocumentation))
            {
                string text;
                if (declaration is IInterfaceDeclaration)
                {
                    text = declaration.DeclaredName.Substring(1) + " interface";
                }
                else
                {
                    text = Utils.ConvertTextToSentence(declaration.DeclaredName).ToLower();
                }

                summaryText = string.Format("The {0}.", text);
            }

            summaryText = Utils.UpdateTextWithToDoPrefixIfRequired(summaryText, settingsStore);

            XmlNode summaryXmlNode = declarationHeader.SummaryXmlNode;

            if (declarationHeader.HasSummary)
            {
                if (declarationHeader.HasEmptySummary)
                {
                    summaryXmlNode.InnerText = summaryText;
                    declarationHeader.Update();
                    returnValue = true;
                }
            }
            else
            {
                XmlNode newChild = CreateNode(declarationHeader.XmlNode, "summary");
                newChild.InnerText = summaryText;
                declarationHeader.XmlNode.InsertBefore(newChild, declarationHeader.XmlNode.FirstChild);
                declarationHeader.Update();
                returnValue = true;
            }

            return returnValue;
        }
        /// <summary>
        /// Formats a summary element.
        /// </summary>
        /// <param name="declaration">
        /// The <see cref="IDeclaration"/> to format the text for.
        /// </param>
        public void FormatSummaryElement(IDeclaration declaration)
        {
            DeclarationHeader declarationHeader = new DeclarationHeader(declaration);

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

            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>
        /// 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, CachedCodeStrings.HeaderSummaryForDestructor, destructorDescriptionText);

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

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

                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 ? CachedCodeStrings.StructText : CachedCodeStrings.ClassText;
            string textWeShouldStartWith;

            if (constructorDeclaration.IsStatic)
            {
                textWeShouldStartWith = string.Format(
                    CultureInfo.InvariantCulture, CachedCodeStrings.HeaderSummaryForStaticConstructor, constructorDeclaration.DeclaredName, structOrClass);
            }
            else if (constructorDeclaration.GetAccessRights() == AccessRights.PRIVATE && constructorParameterCount == 0)
            {
                textWeShouldStartWith = string.Format(
                    CultureInfo.InvariantCulture, CachedCodeStrings.HeaderSummaryForPrivateInstanceConstructor, constructorDeclaration.DeclaredName, structOrClass);
            }
            else
            {
                string constructorDescriptionText = Utils.CreateConstructorDescriptionText(constructorDeclaration, true);
                textWeShouldStartWith = string.Format(
                    CultureInfo.InvariantCulture, CachedCodeStrings.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();
            }
        }