/// <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); }