private static void OrderPropertyIndexerAndEventDeclarations(ICSharpFile file, AnalyzerSettings analyzerSettings) { bool propertyAccessorsMustFollowOrder = analyzerSettings.IsRuleEnabled("PropertyAccessorsMustFollowOrder"); bool eventAccessorsMustFollowOrder = analyzerSettings.IsRuleEnabled("EventAccessorsMustFollowOrder"); foreach (ICSharpNamespaceDeclaration namespaceDeclaration in file.NamespaceDeclarations) { ProcessTypeDeclarations(namespaceDeclaration.TypeDeclarations, propertyAccessorsMustFollowOrder, eventAccessorsMustFollowOrder); } ProcessTypeDeclarations(file.TypeDeclarations, propertyAccessorsMustFollowOrder, eventAccessorsMustFollowOrder); }
/// <summary> /// Executes the cleanup rules. /// </summary> /// <param name="file"> /// The file to process. /// </param> /// <param name="settings"> /// The merged settings for the given file /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file); var analyzerSettings = new AnalyzerSettings(settings, typeof(CSharp.ReadabilityRules).FullName); if (analyzerSettings.IsRuleEnabled("DoNotPlaceRegionsWithinElements")) { DoNotPlaceRegionsWithinElements(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("BlockStatementsMustNotContainEmbeddedComments")) { BlockStatementsMustNotContainEmbeddedComments(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("BlockStatementsMustNotContainEmbeddedRegions")) { BlockStatementsMustNotContainEmbeddedRegions(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CodeMustNotContainEmptyStatements")) { CodeMustNotContainEmptyStatements(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CodeMustNotContainEmptyRegions")) { CodeMustNotContainEmptyRegions(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("UseStringEmptyForEmptyStrings")) { ReplaceEmptyStringsWithStringDotEmpty(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("UseBuiltInTypeAlias")) { SwapToBuiltInTypeAlias(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CommentsMustContainText")) { RemoveEmptyComments(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("DoNotPrefixCallsWithBaseUnlessLocalImplementationExists")) { DoNotPrefixCallsWithBaseUnlessLocalImplementationExists(file.FirstChild); } StyleCopTrace.Out(); }
/// <summary> /// The Execute method. /// </summary> /// <param name="file"> /// The file to fix /// </param> /// <param name="settings"> /// The settings to use in the fix. /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file, settings); var analyzerSettings = new AnalyzerSettings(settings, typeof(CSharp.MaintainabilityRules).FullName); if (analyzerSettings.IsRuleEnabled("StatementMustNotUseUnnecessaryParenthesis")) { RemoveUnnecessaryParenthesisFromStatements(file.FirstChild); } StyleCopTrace.Out(); }
/// <summary> /// The Execute method. /// </summary> /// <param name="file"> /// The file to fix. /// </param> /// <param name="settings"> /// The settings to use. /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file, settings); var analyzerSettings = new AnalyzerSettings(settings, "StyleCop.CSharp.LayoutRules"); if (analyzerSettings.IsRuleEnabled("SingleLineCommentMustBeProceededByBlankLine")) { CommentsMustBePreceededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("SingleLineCommentsMustNotBeFollowedByBlankLine")) { CommentsMustNotBeFollowedByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ClosingCurlyBracketMustBeFollowedByBlankLine")) { ClosingCurlyBracketMustBeFollowedByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("WhileDoFooterMustNotBePrecededByBlankLine")) { WhileDoFooterMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ChainedStatementBlocksMustNotBePrecededByBlankLine")) { ChainedStatementBlocksMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("OpeningCurlyBracketsMustNotBePrecededByBlankLine")) { OpeningCurlyBracketsMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ElementDocumentationHeaderMustBePrecededByBlankLine")) { ElementDocumentationHeadersMustBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CurlyBracketsForMultiLineStatementsMustNotShareLine")) { CurlyBracketsForMultiLineStatementsMustNotShareLine(file.FirstChild); } StyleCopTrace.Out(); }
/// <summary> /// Orders the files usings statements. /// </summary> /// <param name="file"> /// The file to process. /// </param> /// <param name="analyzerSettings"> /// The settings for the analyzer. /// </param> private static void OrderUsings(ICSharpFile file, AnalyzerSettings analyzerSettings) { bool organiseUsings = analyzerSettings.IsRuleEnabled("UsingDirectivesMustBeOrderedAlphabeticallyByNamespace"); // TODO: Does this have a related setting? // It used to be a code cleanup setting, but doesn't seem to have a related StyleCop setting. // If there's no StyleCop setting (and therefore rule) we shouldn't do anything bool expandUsings = true; // Exit if both options are to ignore if (!organiseUsings && !expandUsings) { return; } foreach (ICSharpNamespaceDeclaration namespaceDeclaration in file.NamespaceDeclarations) { ProcessImports(namespaceDeclaration.Imports, organiseUsings, expandUsings, namespaceDeclaration); } ProcessImports(file.Imports, organiseUsings, expandUsings, file); }
/// <summary> /// Implement the Execute method. /// </summary> /// <param name="file"> /// The file to use. /// </param> /// <param name="settings"> /// The settings to use. /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file, settings); var analyzerSettings = new AnalyzerSettings(settings, "StyleCop.CSharp.SpacingRules"); if (analyzerSettings.IsRuleEnabled("CodeMustNotContainMultipleWhitespaceInARow")) { CodeMustNotContainMultipleWhitespaceInARow(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CommasMustBeSpacedCorrectly")) { CommasMustBeSpacedCorrectly(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("SingleLineCommentsMustBeginWithSingleSpace")) { SingleLineCommentsMustBeginWithSingleSpace(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("PreprocessorKeywordsMustNotBePrecededBySpace")) { PreprocessorKeywordsMustNotBePrecededBySpace(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("NegativeSignsMustBeSpacedCorrectly")) { NegativeAndPositiveSignsMustBeSpacedCorrectly(file.FirstChild, CSharpTokenType.MINUS); } if (analyzerSettings.IsRuleEnabled("PositiveSignsMustBeSpacedCorrectly")) { NegativeAndPositiveSignsMustBeSpacedCorrectly(file.FirstChild, CSharpTokenType.PLUS); } StyleCopTrace.Out(); }
/// <summary> /// Implement the Execute method. /// </summary> /// <param name="file"> /// The file to use. /// </param> /// <param name="settings"> /// The settings to use. /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file, settings); var analyzerSettings = new AnalyzerSettings(settings, typeof(CSharp.SpacingRules).FullName); if (analyzerSettings.IsRuleEnabled("CodeMustNotContainMultipleWhitespaceInARow")) { CodeMustNotContainMultipleWhitespaceInARow(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CommasMustBeSpacedCorrectly")) { CommasMustBeSpacedCorrectly(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("SingleLineCommentsMustBeginWithSingleSpace")) { SingleLineCommentsMustBeginWithSingleSpace(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("PreprocessorKeywordsMustNotBePrecededBySpace")) { PreprocessorKeywordsMustNotBePrecededBySpace(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("NegativeSignsMustBeSpacedCorrectly")) { NegativeAndPositiveSignsMustBeSpacedCorrectly(file.FirstChild, CSharpTokenType.MINUS); } if (analyzerSettings.IsRuleEnabled("PositiveSignsMustBeSpacedCorrectly")) { NegativeAndPositiveSignsMustBeSpacedCorrectly(file.FirstChild, CSharpTokenType.PLUS); } StyleCopTrace.Out(); }
/// <summary> /// The Execute method. /// </summary> /// <param name="file"> /// The file to fix. /// </param> /// <param name="settings"> /// The settings to use. /// </param> public static void ExecuteAll(ICSharpFile file, Settings settings) { StyleCopTrace.In(file, settings); var analyzerSettings = new AnalyzerSettings(settings, typeof(CSharp.LayoutRules).FullName); if (analyzerSettings.IsRuleEnabled("SingleLineCommentMustBeProceededByBlankLine")) { CommentsMustBePreceededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("SingleLineCommentsMustNotBeFollowedByBlankLine")) { CommentsMustNotBeFollowedByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ClosingCurlyBracketMustBeFollowedByBlankLine")) { ClosingCurlyBracketMustBeFollowedByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("WhileDoFooterMustNotBePrecededByBlankLine")) { WhileDoFooterMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ChainedStatementBlocksMustNotBePrecededByBlankLine")) { ChainedStatementBlocksMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("OpeningCurlyBracketsMustNotBePrecededByBlankLine")) { OpeningCurlyBracketsMustNotBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("ElementDocumentationHeaderMustBePrecededByBlankLine")) { ElementDocumentationHeadersMustBePrecededByBlankLine(file.FirstChild); } if (analyzerSettings.IsRuleEnabled("CurlyBracketsForMultiLineStatementsMustNotShareLine")) { CurlyBracketsForMultiLineStatementsMustNotShareLine(file.FirstChild); } StyleCopTrace.Out(); }
/// <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>s /// <param name="options"> /// <see cref="AnalyzerSettings"/>Current options that we can reference. /// </param> public static void CheckDeclarationDocumentation(ICSharpFile file, IDeclaration declaration, AnalyzerSettings options) { Param.RequireNotNull(file, "file"); Param.RequireNotNull(declaration, "declaration"); Param.Ignore(options); bool insertMissingElementDocOption = options.IsRuleEnabled("ElementsMustBeDocumented"); bool documentationTextMustBeginWithACapitalLetter = options.IsRuleEnabled("DocumentationTextMustBeginWithACapitalLetter"); bool documentationTextMustEndWithAPeriod = options.IsRuleEnabled("DocumentationTextMustEndWithAPeriod"); bool elementDocumentationMustHaveSummary = options.IsRuleEnabled("ElementDocumentationMustHaveSummary"); bool constructorSummaryDocBeginsWithStandardText = options.IsRuleEnabled("ConstructorSummaryDocumentationMustBeginWithStandardText"); bool destructorSummaryDocBeginsWithStandardText = options.IsRuleEnabled("DestructorSummaryDocumentationMustBeginWithStandardText"); bool propertyDocumentationMustHaveValueDocumented = options.IsRuleEnabled("PropertyDocumentationMustHaveValue"); bool insertMissingParamTagOption = options.IsRuleEnabled("ElementParametersMustBeDocumented"); bool genericTypeParametersMustBeDocumented = options.IsRuleEnabled("GenericTypeParametersMustBeDocumented"); DeclarationHeader declarationHeader = new DeclarationHeader(declaration); bool formatSummary = false; if (insertMissingElementDocOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1600) && declarationHeader.IsMissing) { formatSummary = InsertMissingDeclarationHeader(file, declaration); } if (elementDocumentationMustHaveSummary && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1604) && !declarationHeader.HasSummary) { formatSummary = formatSummary | InsertMissingSummaryElement(declaration); } if (formatSummary) { FormatSummaryElement(declaration); } if (declaration is IConstructorDeclaration) { if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1611)) { IConstructorDeclaration constructorDeclaration = declaration as IConstructorDeclaration; if (constructorDeclaration.ParameterDeclarations.Count > 0) { InsertMissingParamElement(constructorDeclaration); } } if (constructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1642)) { EnsureConstructorSummaryDocBeginsWithStandardText(declaration as IConstructorDeclaration); } } Lifetimes.Using( lifetime => { DocumentationRulesConfiguration docConfig = GetDocumentationRulesConfig(lifetime, 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)) { EnsureDocumentationTextIsUppercase(declaration); } ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("DocumentationTextMustEndWithAPeriod"); if (documentationTextMustEndWithAPeriod && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1629)) { EnsureDocumentationTextEndsWithAPeriod(declaration); } if (declaration is IDestructorDeclaration) { if (destructorSummaryDocBeginsWithStandardText && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1643)) { EnsureDestructorSummaryDocBeginsWithStandardText(declaration as IDestructorDeclaration); } } if (declaration is IMethodDeclaration || declaration is IIndexerDeclaration) { CheckMethodAndIndexerDeclarationDocumentation(declaration as IParametersOwnerDeclaration, options); } if (declaration is IPropertyDeclaration) { ruleIsEnabled = docConfig.GetStyleCopRuleEnabled("PropertyDocumentationMustHaveValue"); if (propertyDocumentationMustHaveValueDocumented && ruleIsEnabled && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1609)) { InsertValueElement(declaration as IPropertyDeclaration); } } if (declaration is ITypeParametersOwner && (genericTypeParametersMustBeDocumented && !Utils.IsRuleSuppressed(declaration, StyleCopRules.SA1618))) { InsertMissingTypeParamElement(declaration); } }); }
/// <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="file"> /// The file to update. /// </param> /// <param name="analyzerSettings"> /// The analyzer Settings. /// </param> private static void UpdateFileHeader(ICSharpFile file, AnalyzerSettings analyzerSettings) { // 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; // TODO: How do we handle updating the file header? // From the main options page? // Actually, looks like ReplaceCopyrightElement is the best option. It fixes the filename, // the company name and the copyright, and it'll update the summary, if it isn't already set. UpdateFileHeaderStyle updateFileHeaderOption = UpdateFileHeaderStyle.ReplaceCopyrightElement; if (updateFileHeaderOption == UpdateFileHeaderStyle.Ignore) { return; } Lifetimes.Using( lifetime => { DocumentationRulesConfiguration docConfig = GetDocumentationRulesConfig(lifetime, file); string summaryText = Utils.GetSummaryText(file); FileHeader fileHeader = new FileHeader(file) { InsertSummary = analyzerSettings.IsRuleEnabled("FileHeaderMustHaveSummary") }; 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> /// Checks method comment blocks. /// </summary> /// <param name="methodDeclaration"> /// The method <see cref="IDeclaration"/> to check. /// </param> /// <param name="options"> /// The options. /// </param> private static void CheckMethodAndIndexerDeclarationDocumentation(IParametersOwnerDeclaration methodDeclaration, AnalyzerSettings options) { Param.Ignore(options); if (methodDeclaration == null) { return; } bool insertMissingParamTagOption = options.IsRuleEnabled("ElementParametersMustBeDocumented"); bool insertMissingReturnTagOption = options.IsRuleEnabled("ElementReturnValueMustBeDocumented"); bool removeReturnTagOnVoidElementsOption = options.IsRuleEnabled("VoidReturnValueMustNotBeDocumented"); if (insertMissingParamTagOption && !Utils.IsRuleSuppressed(methodDeclaration, StyleCopRules.SA1611)) { if (methodDeclaration.ParameterDeclarations.Count > 0) { 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") { 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) { 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="analyzerSettings"> /// The <see cref="AnalyzerSettings"/> for the current analyzer. /// </param> private static void CheckClassDeclarationForParams(ITypeDeclaration typeDeclaration, AnalyzerSettings analyzerSettings) { Param.RequireNotNull(typeDeclaration, "typeDeclaration"); Param.RequireNotNull(analyzerSettings, "analyzerSettings"); if (analyzerSettings.IsRuleEnabled("ElementParametersMustBeDocumented")) { if (typeDeclaration.DeclaredElement != null) { if (typeDeclaration.DeclaredElement.TypeParameters.Count > 0) { InsertMissingTypeParamElement(typeDeclaration); } } } }