/// <summary>
        /// Checks a class comments block for parameters.
        /// </summary>
        /// <param name="typeDeclaration">
        /// The <see cref="ITypeDeclaration"/> to check.
        /// </param>
        /// <param name="options">
        /// <see cref="OrderingOptions"/>Current options that we can reference.
        /// </param>
        private void CheckClassDeclarationForParams(ITypeDeclaration typeDeclaration, DocumentationOptions options)
        {
            Param.RequireNotNull(typeDeclaration, "typeDeclaration");
            Param.RequireNotNull(options, "options");

            bool insertMissingParamTagOption = options.SA1611ElementParametersMustBeDocumented;

            if (insertMissingParamTagOption)
            {
                if (typeDeclaration.DeclaredElement != null)
                {
                    if (typeDeclaration.DeclaredElement.TypeParameters.Count > 0)
                    {
                        this.InsertMissingTypeParamElement(typeDeclaration);
                    }
                }
            }
        }
        /// <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>
        /// Execute comments processing for declarations.
        /// </summary>
        /// <param name="options">
        /// The <see cref="OrderingOptions"/> to use.
        /// </param>
        /// <param name="file">
        /// The <see cref="ICSharpFile"/> to use.
        /// </param>
        public void Execute(DocumentationOptions options, ICSharpFile file)
        {
            StyleCopTrace.In(options, file);

            Param.RequireNotNull(options, "options");
            Param.RequireNotNull(file, "file");

            foreach (ICSharpNamespaceDeclaration namespaceDeclaration in file.NamespaceDeclarations)
            {
                this.ProcessCSharpTypeDeclarations(options, file, namespaceDeclaration.TypeDeclarations);
            }

            this.ProcessCSharpTypeDeclarations(options, file, file.TypeDeclarations);

            bool fixSingleLineCommentsOption = options.SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes;

            if (fixSingleLineCommentsOption)
            {
                this.SwapDocCommentsToSingleLineComments(file.FirstChild);
            }

            this.UpdateFileHeader(options, file);
            StyleCopTrace.Out();
        }
        /// <summary>
        /// Inserts any missing items from the file header.
        /// Also formats the existing header ensuring that the top and bottom line start with 2 slashes and a space and that a newline follows the header.
        /// </summary>
        /// <param name="options">
        /// The options.
        /// </param>
        /// <param name="file">
        /// The file to update.
        /// </param>
        private void UpdateFileHeader(DocumentationOptions options, ICSharpFile file)
        {
            // The idea here is to load the existing header into our FileHeader object
            // The FileHeader object will ensure that the format of the header is correct even if we're not changing its contents
            // Thus we'll swap it out if its changed at the end.
            string fileName = file.GetSourceFile().ToProjectFile().Location.Name;
            UpdateFileHeaderStyle updateFileHeaderOption = options.SA1633SA1641UpdateFileHeader;

            if (updateFileHeaderOption == UpdateFileHeaderStyle.Ignore)
            {
                return;
            }

            DocumentationRulesConfiguration docConfig = this.GetDocumentationRulesConfig(file);
            string summaryText = Utils.GetSummaryText(file);
            FileHeader fileHeader = new FileHeader(file) { InsertSummary = options.SA1639FileHeaderMustHaveSummary };

            switch (updateFileHeaderOption)
            {
                case UpdateFileHeaderStyle.ReplaceCopyrightElement:
                    fileHeader.FileName = fileName;
                    fileHeader.CompanyName = docConfig.CompanyName;
                    fileHeader.CopyrightText = docConfig.Copyright;
                    fileHeader.Summary = string.IsNullOrEmpty(fileHeader.Summary) ? summaryText : fileHeader.Summary;
                    break;

                case UpdateFileHeaderStyle.ReplaceAll:
                    fileHeader.FileName = fileName;
                    fileHeader.CompanyName = docConfig.CompanyName;
                    fileHeader.CopyrightText = docConfig.Copyright;
                    fileHeader.Summary = summaryText;
                    break;

                case UpdateFileHeaderStyle.InsertMissing:
                    fileHeader.FileName = string.IsNullOrEmpty(fileHeader.FileName) ? fileName : fileHeader.FileName;
                    fileHeader.CompanyName = string.IsNullOrEmpty(fileHeader.CompanyName) ? docConfig.CompanyName : fileHeader.CompanyName;
                    fileHeader.CopyrightText = string.IsNullOrEmpty(fileHeader.CopyrightText) ? docConfig.Copyright : fileHeader.CopyrightText;
                    fileHeader.Summary = string.IsNullOrEmpty(fileHeader.Summary) ? summaryText : fileHeader.Summary;
                    break;
            }

            fileHeader.Update();
        }
        /// <summary>
        /// Process nested declarations.
        /// </summary>
        /// <param name="options">
        /// <see cref="OrderingOptions"/>Current options that we can reference.
        /// </param>
        /// <param name="file">
        /// The <see cref="ICSharpFile"/> to use.
        /// </param>
        /// <param name="typeDeclarations">
        /// The type <see cref="ICSharpTypeDeclaration"/> to check.
        /// </param>
        private void ProcessNestedTypeDeclarations(DocumentationOptions options, ICSharpFile file, IEnumerable<ITypeDeclaration> typeDeclarations)
        {
            Param.RequireNotNull(options, "options");
            Param.RequireNotNull(file, "file");
            Param.RequireNotNull(typeDeclarations, "typeDeclarations");

            foreach (ITypeDeclaration typeDeclaration in typeDeclarations)
            {
                this.CheckDeclarationDocumentation(file, typeDeclaration, options);

                this.CheckClassDeclarationForParams(typeDeclaration, options);

                foreach (ITypeMemberDeclaration memberDeclaration in typeDeclaration.MemberDeclarations)
                {
                    this.CheckDeclarationDocumentation(file, memberDeclaration, options);
                }

                this.ProcessNestedTypeDeclarations(options, file, typeDeclaration.NestedTypeDeclarations);
            }
        }
        /// <summary>
        /// Checks method comment blocks.
        /// </summary>
        /// <param name="methodDeclaration">
        /// The method <see cref="IDeclaration"/> to check.
        /// </param>
        /// <param name="options">
        /// <see cref="OrderingOptions"/>Current options that we can reference.
        /// </param>
        private void CheckMethodDeclarationDocumentation(IMethodDeclaration methodDeclaration, DocumentationOptions options)
        {
            Param.RequireNotNull(options, "options");

            if (methodDeclaration == null)
            {
                return;
            }

            bool insertMissingParamTagOption = options.SA1611ElementParametersMustBeDocumented;
            bool insertMissingReturnTagOption = options.SA1615ElementReturnValueMustBeDocumented;
            bool removeReturnTagOnVoidElementsOption = options.SA1617VoidReturnValueMustNotBeDocumented;

            if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(methodDeclaration, StyleCopRules.SA1611))
            {
                if (methodDeclaration.ParameterDeclarations.Count > 0)
                {
                    this.InsertMissingParamElement(methodDeclaration);
                }
            }

            DeclaredTypeFromCLRName declaredTypeFromCLRName = methodDeclaration.GetReturnType() as DeclaredTypeFromCLRName;

            if (removeReturnTagOnVoidElementsOption && !Utils.IsRuleSuppressed(methodDeclaration, StyleCopRules.SA1617))
            {
                // Remove the <returns> if the return type is void
                if (declaredTypeFromCLRName != null && declaredTypeFromCLRName.GetClrName().FullName == "System.Void")
                {
                    this.RemoveReturnsElement(methodDeclaration);
                }
            }

            if (insertMissingReturnTagOption && !Utils.IsRuleSuppressed(methodDeclaration, StyleCopRules.SA1615))
            {
                // Insert the <returns> if the return type is not void and it was missing
                if (declaredTypeFromCLRName != null && declaredTypeFromCLRName.GetClrName().FullName != "System.Void")
                {
                    this.InsertReturnsElement(methodDeclaration);
                }
            }
        }
        /// <summary>
        /// Get default setting for given profile type.
        /// </summary>
        /// <param name="profile">
        /// The code cleanup profile to use.
        /// </param>
        /// <param name="profileType">
        /// Determine if it is a full or reformat <see cref="CodeCleanup.DefaultProfileType"/>.
        /// </param>
        public void SetDefaultSetting(CodeCleanupProfile profile, CodeCleanup.DefaultProfileType profileType)
        {
            // Default option are set in the constructors.
            OrderingOptions orderingOptions = new OrderingOptions();
            profile.SetSetting(OrderingDescriptor, orderingOptions);

            LayoutOptions layoutOptions = new LayoutOptions();
            profile.SetSetting(LayoutDescriptor, layoutOptions);

            DocumentationOptions documentationOptions = new DocumentationOptions();
            profile.SetSetting(DocumentationDescriptor, documentationOptions);

            SpacingOptions spacingOptions = new SpacingOptions();
            profile.SetSetting(SpacingDescriptor, spacingOptions);

            ReadabilityOptions readabilityOptions = new ReadabilityOptions();
            profile.SetSetting(ReadabilityDescriptor, readabilityOptions);

            MaintainabilityOptions maintainabilityOptions = new MaintainabilityOptions();
            profile.SetSetting(MaintainabilityDescriptor, maintainabilityOptions);
        }