/// <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> public void CheckDeclarationDocumentation(ICSharpFile file, IDeclaration declaration, DocumentationOptions options) { Param.RequireNotNull(file, "file"); Param.RequireNotNull(declaration, "declaration"); Param.Ignore(options); bool insertMissingElementDocOption = true; bool documentationTextMustBeginWithACapitalLetter = true; bool documentationTextMustEndWithAPeriod = true; bool elementDocumentationMustHaveSummary = true; bool constructorSummaryDocBeginsWithStandardText = true; bool destructorSummaryDocBeginsWithStandardText = true; bool propertyDocumentationMustHaveValueDocumented = true; bool insertMissingParamTagOption = true; bool genericTypeParametersMustBeDocumented = true; if (options != null) { insertMissingElementDocOption = options.SA1600ElementsMustBeDocumented; documentationTextMustBeginWithACapitalLetter = options.SA1628DocumentationTextMustBeginWithACapitalLetter; documentationTextMustEndWithAPeriod = options.SA1629DocumentationTextMustEndWithAPeriod; elementDocumentationMustHaveSummary = options.SA1604ElementDocumentationMustHaveSummary; constructorSummaryDocBeginsWithStandardText = options.SA1642ConstructorSummaryDocumentationMustBeginWithStandardText; destructorSummaryDocBeginsWithStandardText = options.SA1643DestructorSummaryDocumentationMustBeginWithStandardText; propertyDocumentationMustHaveValueDocumented = options.SA1609PropertyDocumentationMustHaveValue; insertMissingParamTagOption = options.SA1611ElementParametersMustBeDocumented; genericTypeParametersMustBeDocumented = options.SA1618GenericTypeParametersMustBeDocumented; } DeclarationHeader declarationHeader = new DeclarationHeader(declaration); bool formatSummary = false; if (insertMissingElementDocOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1600) && declarationHeader.IsMissing) { formatSummary = this.InsertMissingDeclarationHeader(file, declaration); } if (elementDocumentationMustHaveSummary && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1604) && !declarationHeader.HasSummary) { formatSummary = formatSummary | this.InsertMissingSummaryElement(declaration); } if (formatSummary) { this.FormatSummaryElement(declaration); } if (declaration is IConstructorDeclaration) { if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1611)) { IConstructorDeclaration constructorDeclaration = declaration as IConstructorDeclaration; if (constructorDeclaration.ParameterDeclarations.Count > 0) { this.InsertMissingParamElement(constructorDeclaration); } } if (constructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1642)) { this.EnsureConstructorSummaryDocBeginsWithStandardText(declaration as IConstructorDeclaration); } } 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 (declaration is IDestructorDeclaration) { if (destructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1643)) { this.EnsureDestructorSummaryDocBeginsWithStandardText(declaration as IDestructorDeclaration); } } if (declaration is IMethodDeclaration || declaration is IIndexerDeclaration) { this.CheckMethodAndIndexerDeclarationDocumentation(declaration as IParametersOwnerDeclaration, options); } if (declaration is IPropertyDeclaration) { ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("PropertyDocumentationMustHaveValue"); if (propertyDocumentationMustHaveValueDocumented && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1609)) { this.InsertValueElement(declaration as IPropertyDeclaration); } } if (declaration is ITypeParametersOwner && (genericTypeParametersMustBeDocumented && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1618))) { this.InsertMissingTypeParamElement(declaration); } }
/// <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); }
/// <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 CheckMethodAndIndexerDeclarationDocumentation(IParametersOwnerDeclaration methodDeclaration, DocumentationOptions options) { Param.Ignore(options); if (methodDeclaration == null) { return; } bool insertMissingParamTagOption = true; bool insertMissingReturnTagOption = true; bool removeReturnTagOnVoidElementsOption = true; if (options != null) { insertMissingParamTagOption = options.SA1611ElementParametersMustBeDocumented; insertMissingReturnTagOption = options.SA1615ElementReturnValueMustBeDocumented; removeReturnTagOnVoidElementsOption = options.SA1617VoidReturnValueMustNotBeDocumented; } if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(methodDeclaration, StyleCopRules.SA1611)) { if (methodDeclaration.ParameterDeclarations.Count > 0) { this.InsertMissingParamElement(methodDeclaration); } } if (methodDeclaration.DeclaredElement == null) { return; } DeclaredTypeFromCLRName declaredTypeFromClrName = methodDeclaration.DeclaredParametersOwner.ReturnType 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 as ITypeMemberDeclaration); } } 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") || declaredTypeFromClrName == null) { this.InsertReturnsElement(methodDeclaration as ITypeMemberDeclaration, Utils.GetXmlPresentableName(methodDeclaration.DeclaredParametersOwner.ReturnType)); } } }
/// <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); } } } }