From 6485abcea390ee85d436692304deb0a9651fb0bf Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 04:38:06 -0600 Subject: [PATCH 01/47] Implement SA1137 (ElementsShouldHaveTheSameIndentation) --- .../ReadabilityResources.Designer.cs | 27 ++ .../ReadabilityResources.resx | 9 + ...137ElementsShouldHaveTheSameIndentation.cs | 380 ++++++++++++++++++ .../StyleCop.Analyzers.csproj | 1 + 4 files changed, 417 insertions(+) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs index b999bfc69..0a78ff3e0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs @@ -1159,6 +1159,33 @@ internal static string SA1134Title { } } + /// + /// Looks up a localized string similar to Elements at the same level in the syntax tree should have the same indentation.. + /// + internal static string SA1137Description { + get { + return ResourceManager.GetString("SA1137Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elements should have the same indentation. + /// + internal static string SA1137MessageFormat { + get { + return ResourceManager.GetString("SA1137MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elements should have the same indentation. + /// + internal static string SA1137Title { + get { + return ResourceManager.GetString("SA1137Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remove 'this.' prefix. /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx index 1f7a2e197..9d953c8f8 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx @@ -483,6 +483,15 @@ Attributes must not share line + + Elements at the same level in the syntax tree should have the same indentation. + + + Elements should have the same indentation + + + Elements should have the same indentation + Remove 'this.' prefix diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs new file mode 100644 index 000000000..2820d5069 --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -0,0 +1,380 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + +namespace StyleCop.Analyzers.ReadabilityRules +{ + using System; + using System.Collections.Immutable; + using System.Linq; + using Helpers; + using Microsoft.CodeAnalysis; + using Microsoft.CodeAnalysis.CSharp; + using Microsoft.CodeAnalysis.CSharp.Syntax; + using Microsoft.CodeAnalysis.Diagnostics; + + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer + { + public const string ExpectedIndentationKey = "ExpectedIndentation"; + + /// + /// The ID for diagnostics produced by the analyzer. + /// + public const string DiagnosticId = "SA1137"; + private static readonly LocalizableString Title = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Title), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(ReadabilityResources.SA1137MessageFormat), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString Description = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Description), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md"; + + private static readonly DiagnosticDescriptor Descriptor = + new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.DisabledNoTests, Description, HelpLink); + + private static readonly Action CompilationStartAction = HandleCompilationStart; + private static readonly Action CompilationUnitAction = HandleCompilationUnit; + private static readonly Action NamespaceDeclarationAction = HandleNamespaceDeclaration; + private static readonly Action BaseTypeDeclarationAction = HandleBaseTypeDeclaration; + private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; + private static readonly Action EnumDeclarationAction = HandleEnumDeclaration; + private static readonly Action EnumMemberDeclarationAction = HandleEnumMemberDeclaration; + private static readonly Action BaseMethodDeclarationAction = HandleBaseMethodDeclaration; + private static readonly Action MethodDeclarationAction = HandleMethodDeclaration; + private static readonly Action BasePropertyDeclarationAction = HandleBasePropertyDeclaration; + private static readonly Action AccessorListAction = HandleAccessorList; + private static readonly Action AccessorDeclarationAction = HandleAccessorDeclaration; + private static readonly Action VariableDeclarationAction = HandleVariableDeclaration; + private static readonly Action TypeParameterListAction = HandleTypeParameterList; + private static readonly Action TypeParameterAction = HandleTypeParameter; + private static readonly Action ParameterListAction = HandleParameterList; + private static readonly Action ParameterAction = HandleParameter; + private static readonly Action ArgumentListAction = HandleArgumentList; + private static readonly Action AttributeListAction = HandleAttributeList; + private static readonly Action AttributeArgumentListAction = HandleAttributeArgumentList; + private static readonly Action BlockAction = HandleBlock; + private static readonly Action SwitchStatementAction = HandleSwitchStatement; + + /// + public override ImmutableArray SupportedDiagnostics { get; } = + ImmutableArray.Create(Descriptor); + + /// + public override void Initialize(AnalysisContext context) + { + context.RegisterCompilationStartAction(CompilationStartAction); + } + + private static void HandleCompilationStart(CompilationStartAnalysisContext context) + { + context.RegisterSyntaxNodeActionHonorExclusions(CompilationUnitAction, SyntaxKind.CompilationUnit); + context.RegisterSyntaxNodeActionHonorExclusions(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(BaseTypeDeclarationAction, SyntaxKinds.BaseTypeDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(EnumDeclarationAction, SyntaxKind.EnumDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(EnumMemberDeclarationAction, SyntaxKind.EnumMemberDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(BaseMethodDeclarationAction, SyntaxKinds.BaseMethodDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(MethodDeclarationAction, SyntaxKind.MethodDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(BasePropertyDeclarationAction, SyntaxKinds.BasePropertyDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(AccessorListAction, SyntaxKind.AccessorList); + context.RegisterSyntaxNodeActionHonorExclusions(AccessorDeclarationAction, SyntaxKinds.AccessorDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(VariableDeclarationAction, SyntaxKind.VariableDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterListAction, SyntaxKind.TypeParameterList); + context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterAction, SyntaxKind.TypeParameter); + context.RegisterSyntaxNodeActionHonorExclusions(ParameterListAction, SyntaxKind.ParameterList); + context.RegisterSyntaxNodeActionHonorExclusions(ParameterAction, SyntaxKind.Parameter); + context.RegisterSyntaxNodeActionHonorExclusions(ArgumentListAction, SyntaxKind.ArgumentList); + context.RegisterSyntaxNodeActionHonorExclusions(AttributeListAction, SyntaxKind.AttributeList); + context.RegisterSyntaxNodeActionHonorExclusions(AttributeArgumentListAction, SyntaxKind.AttributeArgumentList); + context.RegisterSyntaxNodeActionHonorExclusions(BlockAction, SyntaxKind.Block); + context.RegisterSyntaxNodeActionHonorExclusions(SwitchStatementAction, SyntaxKind.SwitchStatement); + } + + private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context) + { + var compilationUnit = (CompilationUnitSyntax)context.Node; + + var elements = ImmutableList.CreateBuilder(); + + elements.AddRange(compilationUnit.Externs); + elements.AddRange(compilationUnit.Usings); + elements.AddRange(compilationUnit.AttributeLists); + elements.AddRange(compilationUnit.Members); + + CheckElements(context, elements.ToImmutable()); + } + + private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context) + { + var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node; + + var elements = ImmutableList.CreateBuilder(); + + elements.AddRange(namespaceDeclaration.Externs); + elements.AddRange(namespaceDeclaration.Usings); + elements.AddRange(namespaceDeclaration.Members); + + CheckElements(context, elements.ToImmutable()); + } + + private static void HandleBaseTypeDeclaration(SyntaxNodeAnalysisContext context) + { + var baseTypeDeclaration = (BaseTypeDeclarationSyntax)context.Node; + CheckAttributeLists(context, baseTypeDeclaration.AttributeLists, baseTypeDeclaration); + } + + private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context) + { + var typeDeclaration = (TypeDeclarationSyntax)context.Node; + + CheckElements(context, typeDeclaration.Members); + } + + private static void HandleEnumDeclaration(SyntaxNodeAnalysisContext context) + { + var enumDeclaration = (EnumDeclarationSyntax)context.Node; + + CheckElements(context, enumDeclaration.Members); + } + + private static void HandleEnumMemberDeclaration(SyntaxNodeAnalysisContext context) + { + var enumMemberDeclaration = (EnumMemberDeclarationSyntax)context.Node; + + CheckAttributeLists(context, enumMemberDeclaration.AttributeLists, enumMemberDeclaration); + } + + private static void HandleBaseMethodDeclaration(SyntaxNodeAnalysisContext context) + { + var baseMethodDeclaration = (BaseMethodDeclarationSyntax)context.Node; + + CheckAttributeLists(context, baseMethodDeclaration.AttributeLists, baseMethodDeclaration); + } + + private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context) + { + var methodDeclaration = (MethodDeclarationSyntax)context.Node; + + CheckElements(context, methodDeclaration.ConstraintClauses); + } + + private static void HandleBasePropertyDeclaration(SyntaxNodeAnalysisContext context) + { + var basePropertyDeclaration = (BasePropertyDeclarationSyntax)context.Node; + + CheckAttributeLists(context, basePropertyDeclaration.AttributeLists, basePropertyDeclaration); + } + + private static void HandleAccessorList(SyntaxNodeAnalysisContext context) + { + var accessorList = (AccessorListSyntax)context.Node; + + CheckElements(context, accessorList.Accessors); + } + + private static void HandleAccessorDeclaration(SyntaxNodeAnalysisContext context) + { + var accessorDeclaration = (AccessorDeclarationSyntax)context.Node; + + CheckAttributeLists(context, accessorDeclaration.AttributeLists, accessorDeclaration); + } + + private static void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) + { + var variableDeclaration = (VariableDeclarationSyntax)context.Node; + CheckElements(context, variableDeclaration.Variables); + } + + private static void HandleTypeParameterList(SyntaxNodeAnalysisContext context) + { + var typeParameterList = (TypeParameterListSyntax)context.Node; + + CheckElements(context, typeParameterList.Parameters); + } + + private static void HandleTypeParameter(SyntaxNodeAnalysisContext context) + { + var typeParameter = (TypeParameterSyntax)context.Node; + + CheckAttributeLists(context, typeParameter.AttributeLists, typeParameter); + } + + private static void HandleParameterList(SyntaxNodeAnalysisContext context) + { + var parameterList = (ParameterListSyntax)context.Node; + + CheckElements(context, parameterList.Parameters); + } + + private static void HandleParameter(SyntaxNodeAnalysisContext context) + { + var parameter = (ParameterSyntax)context.Node; + CheckAttributeLists(context, parameter.AttributeLists, parameter); + } + + private static void HandleArgumentList(SyntaxNodeAnalysisContext context) + { + var argumentList = (ArgumentListSyntax)context.Node; + + CheckElements(context, argumentList.Arguments); + } + + private static void HandleAttributeList(SyntaxNodeAnalysisContext context) + { + var attributeList = (AttributeListSyntax)context.Node; + + CheckElements(context, attributeList.Attributes); + } + + private static void HandleAttributeArgumentList(SyntaxNodeAnalysisContext context) + { + var attributeArgumentList = (AttributeArgumentListSyntax)context.Node; + + CheckElements(context, attributeArgumentList.Arguments); + } + + private static void HandleBlock(SyntaxNodeAnalysisContext context) + { + var block = (BlockSyntax)context.Node; + + var statements = ImmutableList.CreateBuilder(); + var labeledStatements = ImmutableList.CreateBuilder(); + + foreach (var statement in block.Statements) + { + if (statement.IsKind(SyntaxKind.LabeledStatement)) + { + labeledStatements.Add(statement); + statements.Add(((LabeledStatementSyntax)statement).Statement); + } + else + { + statements.Add(statement); + } + } + + CheckElements(context, statements.ToImmutable()); + CheckElements(context, labeledStatements.ToImmutable()); + } + + private static void HandleSwitchStatement(SyntaxNodeAnalysisContext context) + { + var switchStatement = (SwitchStatementSyntax)context.Node; + + var labels = ImmutableList.CreateBuilder(); + var statements = ImmutableList.CreateBuilder(); + var labeledStatements = ImmutableList.CreateBuilder(); + foreach (SwitchSectionSyntax switchSection in switchStatement.Sections) + { + labels.AddRange(switchSection.Labels); + foreach (var statement in switchSection.Statements) + { + if (statement.IsKind(SyntaxKind.LabeledStatement)) + { + labeledStatements.Add(statement); + statements.Add(((LabeledStatementSyntax)statement).Statement); + } + else + { + statements.Add(statement); + } + } + } + + CheckElements(context, labels.ToImmutable()); + CheckElements(context, statements.ToImmutable()); + CheckElements(context, labeledStatements.ToImmutable()); + } + + private static void CheckAttributeLists(SyntaxNodeAnalysisContext context, SyntaxList attributeLists, SyntaxNode parent) + { + if (attributeLists.Count == 0) + { + return; + } + + var nodes = ImmutableList.CreateBuilder(); + + // Placing the parent first in this list causes the analysis to prefer to align attribute lists with their + // parent syntax, assuming the parent also appears on its own line. + nodes.Add(parent); + nodes.AddRange(attributeLists); + + CheckElements(context, nodes.ToImmutable()); + } + + private static void CheckElements(SyntaxNodeAnalysisContext context, SyntaxList elements) + where T : SyntaxNode + { + if (elements.Count < 2) + { + return; + } + + CheckElements(context, elements.ToImmutableList()); + } + + private static void CheckElements(SyntaxNodeAnalysisContext context, SeparatedSyntaxList elements) + where T : SyntaxNode + { + if (elements.Count < 2) + { + return; + } + + CheckElements(context, elements.ToImmutableList()); + } + + private static void CheckElements(SyntaxNodeAnalysisContext context, ImmutableList elements) + where T : SyntaxNode + { + if (elements.Count < 2) + { + return; + } + + elements.RemoveAll( + element => + { + SyntaxToken firstToken = element.GetFirstToken(); + return firstToken.IsMissingOrDefault() || !firstToken.IsFirstInLine(); + }); + + if (elements.Count < 2) + { + return; + } + + bool first = true; + string expectedIndentation = null; + foreach (T element in elements) + { + SyntaxTrivia indentationTrivia = element.GetFirstToken().LeadingTrivia.LastOrDefault(); + string indentation = indentationTrivia == default(SyntaxTrivia) ? string.Empty : indentationTrivia.ToString(); + + if (first) + { + expectedIndentation = indentation; + first = false; + continue; + } + + if (string.Equals(expectedIndentation, indentation, StringComparison.Ordinal)) + { + // This handles the case where elements are indented properly + continue; + } + + Location location; + if (indentation.Length == 0) + { + location = element.GetFirstToken().GetLocation(); + } + else + { + location = indentationTrivia.GetLocation(); + } + + ImmutableDictionary properties = ImmutableDictionary.Create().SetItem(ExpectedIndentationKey, expectedIndentation); + context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, properties)); + } + } + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj b/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj index b5ce2feb9..7fa557db1 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj +++ b/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj @@ -267,6 +267,7 @@ + From 196a70eb25e5a1d7cc801ed27d54612d11145e1e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 04:55:09 -0600 Subject: [PATCH 02/47] Add handlers for field declarations and initializer expressions --- ...1137ElementsShouldHaveTheSameIndentation.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 2820d5069..453f458b9 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -36,6 +36,7 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; private static readonly Action EnumDeclarationAction = HandleEnumDeclaration; private static readonly Action EnumMemberDeclarationAction = HandleEnumMemberDeclaration; + private static readonly Action FieldDeclarationAction = HandleFieldDeclaration; private static readonly Action BaseMethodDeclarationAction = HandleBaseMethodDeclaration; private static readonly Action MethodDeclarationAction = HandleMethodDeclaration; private static readonly Action BasePropertyDeclarationAction = HandleBasePropertyDeclaration; @@ -51,6 +52,7 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action AttributeArgumentListAction = HandleAttributeArgumentList; private static readonly Action BlockAction = HandleBlock; private static readonly Action SwitchStatementAction = HandleSwitchStatement; + private static readonly Action InitializerExpressionAction = HandleInitializerExpression; /// public override ImmutableArray SupportedDiagnostics { get; } = @@ -70,6 +72,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte context.RegisterSyntaxNodeActionHonorExclusions(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(EnumDeclarationAction, SyntaxKind.EnumDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(EnumMemberDeclarationAction, SyntaxKind.EnumMemberDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(FieldDeclarationAction, SyntaxKind.FieldDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(BaseMethodDeclarationAction, SyntaxKinds.BaseMethodDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(MethodDeclarationAction, SyntaxKind.MethodDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(BasePropertyDeclarationAction, SyntaxKinds.BasePropertyDeclaration); @@ -85,6 +88,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte context.RegisterSyntaxNodeActionHonorExclusions(AttributeArgumentListAction, SyntaxKind.AttributeArgumentList); context.RegisterSyntaxNodeActionHonorExclusions(BlockAction, SyntaxKind.Block); context.RegisterSyntaxNodeActionHonorExclusions(SwitchStatementAction, SyntaxKind.SwitchStatement); + context.RegisterSyntaxNodeActionHonorExclusions(InitializerExpressionAction, SyntaxKinds.InitializerExpression); } private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context) @@ -141,6 +145,13 @@ private static void HandleEnumMemberDeclaration(SyntaxNodeAnalysisContext contex CheckAttributeLists(context, enumMemberDeclaration.AttributeLists, enumMemberDeclaration); } + private static void HandleFieldDeclaration(SyntaxNodeAnalysisContext context) + { + var fieldDeclaration = (FieldDeclarationSyntax)context.Node; + + CheckAttributeLists(context, fieldDeclaration.AttributeLists, fieldDeclaration); + } + private static void HandleBaseMethodDeclaration(SyntaxNodeAnalysisContext context) { var baseMethodDeclaration = (BaseMethodDeclarationSyntax)context.Node; @@ -283,6 +294,13 @@ private static void HandleSwitchStatement(SyntaxNodeAnalysisContext context) CheckElements(context, labeledStatements.ToImmutable()); } + private static void HandleInitializerExpression(SyntaxNodeAnalysisContext context) + { + var initializerExpression = (InitializerExpressionSyntax)context.Node; + + CheckElements(context, initializerExpression.Expressions); + } + private static void CheckAttributeLists(SyntaxNodeAnalysisContext context, SyntaxList attributeLists, SyntaxNode parent) { if (attributeLists.Count == 0) From 0281a319fbaeb7412c371eb08d3d75c83ae73be0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 05:33:32 -0600 Subject: [PATCH 03/47] Expand SA1137 support for additional syntax kinds --- ...137ElementsShouldHaveTheSameIndentation.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 453f458b9..09c2d0ae3 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -36,7 +36,7 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; private static readonly Action EnumDeclarationAction = HandleEnumDeclaration; private static readonly Action EnumMemberDeclarationAction = HandleEnumMemberDeclaration; - private static readonly Action FieldDeclarationAction = HandleFieldDeclaration; + private static readonly Action BaseFieldDeclarationAction = HandleBaseFieldDeclaration; private static readonly Action BaseMethodDeclarationAction = HandleBaseMethodDeclaration; private static readonly Action MethodDeclarationAction = HandleMethodDeclaration; private static readonly Action BasePropertyDeclarationAction = HandleBasePropertyDeclaration; @@ -45,9 +45,9 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action VariableDeclarationAction = HandleVariableDeclaration; private static readonly Action TypeParameterListAction = HandleTypeParameterList; private static readonly Action TypeParameterAction = HandleTypeParameter; - private static readonly Action ParameterListAction = HandleParameterList; + private static readonly Action BaseParameterListAction = HandleBaseParameterList; private static readonly Action ParameterAction = HandleParameter; - private static readonly Action ArgumentListAction = HandleArgumentList; + private static readonly Action BaseArgumentListAction = HandleBaseArgumentList; private static readonly Action AttributeListAction = HandleAttributeList; private static readonly Action AttributeArgumentListAction = HandleAttributeArgumentList; private static readonly Action BlockAction = HandleBlock; @@ -72,7 +72,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte context.RegisterSyntaxNodeActionHonorExclusions(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(EnumDeclarationAction, SyntaxKind.EnumDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(EnumMemberDeclarationAction, SyntaxKind.EnumMemberDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(FieldDeclarationAction, SyntaxKind.FieldDeclaration); + context.RegisterSyntaxNodeActionHonorExclusions(BaseFieldDeclarationAction, SyntaxKinds.BaseFieldDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(BaseMethodDeclarationAction, SyntaxKinds.BaseMethodDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(MethodDeclarationAction, SyntaxKind.MethodDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(BasePropertyDeclarationAction, SyntaxKinds.BasePropertyDeclaration); @@ -81,9 +81,9 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte context.RegisterSyntaxNodeActionHonorExclusions(VariableDeclarationAction, SyntaxKind.VariableDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterListAction, SyntaxKind.TypeParameterList); context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterAction, SyntaxKind.TypeParameter); - context.RegisterSyntaxNodeActionHonorExclusions(ParameterListAction, SyntaxKind.ParameterList); + context.RegisterSyntaxNodeActionHonorExclusions(BaseParameterListAction, SyntaxKinds.BaseParameterList); context.RegisterSyntaxNodeActionHonorExclusions(ParameterAction, SyntaxKind.Parameter); - context.RegisterSyntaxNodeActionHonorExclusions(ArgumentListAction, SyntaxKind.ArgumentList); + context.RegisterSyntaxNodeActionHonorExclusions(BaseArgumentListAction, SyntaxKinds.BaseArgumentList); context.RegisterSyntaxNodeActionHonorExclusions(AttributeListAction, SyntaxKind.AttributeList); context.RegisterSyntaxNodeActionHonorExclusions(AttributeArgumentListAction, SyntaxKind.AttributeArgumentList); context.RegisterSyntaxNodeActionHonorExclusions(BlockAction, SyntaxKind.Block); @@ -145,11 +145,11 @@ private static void HandleEnumMemberDeclaration(SyntaxNodeAnalysisContext contex CheckAttributeLists(context, enumMemberDeclaration.AttributeLists, enumMemberDeclaration); } - private static void HandleFieldDeclaration(SyntaxNodeAnalysisContext context) + private static void HandleBaseFieldDeclaration(SyntaxNodeAnalysisContext context) { - var fieldDeclaration = (FieldDeclarationSyntax)context.Node; + var baseFieldDeclaration = (BaseFieldDeclarationSyntax)context.Node; - CheckAttributeLists(context, fieldDeclaration.AttributeLists, fieldDeclaration); + CheckAttributeLists(context, baseFieldDeclaration.AttributeLists, baseFieldDeclaration); } private static void HandleBaseMethodDeclaration(SyntaxNodeAnalysisContext context) @@ -207,11 +207,11 @@ private static void HandleTypeParameter(SyntaxNodeAnalysisContext context) CheckAttributeLists(context, typeParameter.AttributeLists, typeParameter); } - private static void HandleParameterList(SyntaxNodeAnalysisContext context) + private static void HandleBaseParameterList(SyntaxNodeAnalysisContext context) { - var parameterList = (ParameterListSyntax)context.Node; + var baseParameterList = (BaseParameterListSyntax)context.Node; - CheckElements(context, parameterList.Parameters); + CheckElements(context, baseParameterList.Parameters); } private static void HandleParameter(SyntaxNodeAnalysisContext context) @@ -220,11 +220,11 @@ private static void HandleParameter(SyntaxNodeAnalysisContext context) CheckAttributeLists(context, parameter.AttributeLists, parameter); } - private static void HandleArgumentList(SyntaxNodeAnalysisContext context) + private static void HandleBaseArgumentList(SyntaxNodeAnalysisContext context) { - var argumentList = (ArgumentListSyntax)context.Node; + var baseArgumentList = (BaseArgumentListSyntax)context.Node; - CheckElements(context, argumentList.Arguments); + CheckElements(context, baseArgumentList.Arguments); } private static void HandleAttributeList(SyntaxNodeAnalysisContext context) From 0cdf3ecb4f244a19e421fd0396d3184e9a324a98 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 06:41:03 -0600 Subject: [PATCH 04/47] Add IndentationCodeFixProvider Currently this code fix only corrects SA1137, but the implementation is general enough to support other types of indentation corrections in the future. --- .../IndentationCodeFixProvider.cs | 119 ++++++++++++++++++ .../StyleCop.Analyzers.CodeFixes.csproj | 1 + .../ReadabilityResources.Designer.cs | 9 ++ .../ReadabilityResources.resx | 3 + 4 files changed, 132 insertions(+) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs new file mode 100644 index 000000000..99a7de15c --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs @@ -0,0 +1,119 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + +namespace StyleCop.Analyzers.ReadabilityRules +{ + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Composition; + using System.Threading; + using System.Threading.Tasks; + using Helpers; + using Microsoft.CodeAnalysis; + using Microsoft.CodeAnalysis.CodeActions; + using Microsoft.CodeAnalysis.CodeFixes; + using Microsoft.CodeAnalysis.Text; + + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(IndentationCodeFixProvider))] + [Shared] + internal class IndentationCodeFixProvider : CodeFixProvider + { + /// + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(SA1137ElementsShouldHaveTheSameIndentation.DiagnosticId); + + /// + public sealed override FixAllProvider GetFixAllProvider() => + FixAll.Instance; + + /// + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + foreach (var diagnostic in context.Diagnostics) + { + context.RegisterCodeFix( + CodeAction.Create( + ReadabilityResources.IndentationCodeFix, + cancellationToken => GetTransformedDocumentAsync(context.Document, diagnostic, cancellationToken), + nameof(IndentationCodeFixProvider)), + diagnostic); + } + + return SpecializedTasks.CompletedTask; + } + + private static async Task GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); + + TextChange textChange; + if (!TryGetTextChange(diagnostic, syntaxRoot, out textChange)) + { + return document; + } + + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + return document.WithText(text.WithChanges(textChange)); + } + + private static bool TryGetTextChange(Diagnostic diagnostic, SyntaxNode syntaxRoot, out TextChange textChange) + { + string replacement; + if (!diagnostic.Properties.TryGetValue(SA1137ElementsShouldHaveTheSameIndentation.ExpectedIndentationKey, out replacement)) + { + textChange = default(TextChange); + return false; + } + + var trivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start); + + TextSpan originalSpan; + if (trivia == default(SyntaxTrivia)) + { + originalSpan = trivia.Span; + } + else + { + originalSpan = new TextSpan(diagnostic.Location.SourceSpan.Start, 0); + } + + textChange = new TextChange(originalSpan, replacement); + return true; + } + + private class FixAll : DocumentBasedFixAllProvider + { + public static FixAllProvider Instance { get; } = + new FixAll(); + + protected override string CodeActionTitle => + ReadabilityResources.IndentationCodeFix; + + protected override async Task FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray diagnostics) + { + if (diagnostics.IsEmpty) + { + return null; + } + + var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); + + List changes = new List(); + + foreach (var diagnostic in diagnostics) + { + TextChange textChange; + if (TryGetTextChange(diagnostic, syntaxRoot, out textChange)) + { + changes.Add(textChange); + } + } + + changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); + + var text = await document.GetTextAsync().ConfigureAwait(false); + return await document.WithText(text.WithChanges(changes)).GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); + } + } + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/StyleCop.Analyzers.CodeFixes.csproj b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/StyleCop.Analyzers.CodeFixes.csproj index 7f2277e47..27997424a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/StyleCop.Analyzers.CodeFixes.csproj +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/StyleCop.Analyzers.CodeFixes.csproj @@ -108,6 +108,7 @@ + diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs index 0a78ff3e0..7ceb0a9ec 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs @@ -61,6 +61,15 @@ internal ReadabilityResources() { } } + /// + /// Looks up a localized string similar to Fix indentation. + /// + internal static string IndentationCodeFix { + get { + return ResourceManager.GetString("IndentationCodeFix", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remove region. /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx index 9d953c8f8..e20a9971c 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Fix indentation + Remove region From 505b920e81d94e8901b57e62192edb515cfba17d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 07:18:23 -0600 Subject: [PATCH 05/47] Add test for block statements and fix bugs * Fix handling of consecutive labels * Fix analysis of nodes which are not indented * Fix logic error in code fix --- .../IndentationCodeFixProvider.cs | 5 +- .../ReadabilityRules/SA1137UnitTests.cs | 110 ++++++++++++++++++ .../StyleCop.Analyzers.Test.csproj | 1 + ...137ElementsShouldHaveTheSameIndentation.cs | 28 +++-- 4 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs index 99a7de15c..0c0e984f5 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs @@ -70,11 +70,12 @@ private static bool TryGetTextChange(Diagnostic diagnostic, SyntaxNode syntaxRoo TextSpan originalSpan; if (trivia == default(SyntaxTrivia)) { - originalSpan = trivia.Span; + // The warning was reported on a token because the line is not indented + originalSpan = new TextSpan(diagnostic.Location.SourceSpan.Start, 0); } else { - originalSpan = new TextSpan(diagnostic.Location.SourceSpan.Start, 0); + originalSpan = trivia.Span; } textChange = new TextChange(originalSpan, replacement); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs new file mode 100644 index 000000000..f1ef475b2 --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -0,0 +1,110 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + +namespace StyleCop.Analyzers.Test.ReadabilityRules +{ + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.CodeAnalysis.CodeFixes; + using Microsoft.CodeAnalysis.Diagnostics; + using StyleCop.Analyzers.ReadabilityRules; + using TestHelper; + using Xunit; + + /// + /// This class contains unit tests for . + /// + public class SA1137UnitTests : CodeFixVerifier + { + [Fact] + public async Task TestBlockAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { + label1: + if (true) + { + } + + label2: + while (true) + { + } + +label3: +while (true) + { +label4a: + label4b: +int x; + + label5a: +label5b: + int y; + } + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + label1: + if (true) + { + } + + label2: + while (true) + { + } + + label3: + while (true) + { +label4a: +label4b: +int x; + +label5a: +label5b: +int y; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(17, 1), + this.CSharpDiagnostic().WithLocation(20, 1), + this.CSharpDiagnostic().WithLocation(23, 1), + this.CSharpDiagnostic().WithLocation(25, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + /// + protected override IEnumerable GetCSharpDiagnosticAnalyzers() + { + yield return new SA1137ElementsShouldHaveTheSameIndentation(); + } + + /// + protected override CodeFixProvider GetCSharpCodeFixProvider() + { + return new IndentationCodeFixProvider(); + } + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj b/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj index 67918296c..69d33ada0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj @@ -326,6 +326,7 @@ + diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 09c2d0ae3..b2e873945 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -250,15 +250,14 @@ private static void HandleBlock(SyntaxNodeAnalysisContext context) foreach (var statement in block.Statements) { - if (statement.IsKind(SyntaxKind.LabeledStatement)) + StatementSyntax statementToAlign = statement; + while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) { - labeledStatements.Add(statement); - statements.Add(((LabeledStatementSyntax)statement).Statement); - } - else - { - statements.Add(statement); + labeledStatements.Add(statementToAlign); + statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; } + + statements.Add(statementToAlign); } CheckElements(context, statements.ToImmutable()); @@ -277,15 +276,14 @@ private static void HandleSwitchStatement(SyntaxNodeAnalysisContext context) labels.AddRange(switchSection.Labels); foreach (var statement in switchSection.Statements) { - if (statement.IsKind(SyntaxKind.LabeledStatement)) + StatementSyntax statementToAlign = statement; + while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) { - labeledStatements.Add(statement); - statements.Add(((LabeledStatementSyntax)statement).Statement); - } - else - { - statements.Add(statement); + labeledStatements.Add(statementToAlign); + statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; } + + statements.Add(statementToAlign); } } @@ -365,7 +363,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl foreach (T element in elements) { SyntaxTrivia indentationTrivia = element.GetFirstToken().LeadingTrivia.LastOrDefault(); - string indentation = indentationTrivia == default(SyntaxTrivia) ? string.Empty : indentationTrivia.ToString(); + string indentation = indentationTrivia.IsKind(SyntaxKind.WhitespaceTrivia) ? indentationTrivia.ToString() : string.Empty; if (first) { From 20ac6963dd94ee06ea96a1f26fe1226c59209220 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 07:40:03 -0600 Subject: [PATCH 06/47] Add test for switch statements --- .../ReadabilityRules/SA1137UnitTests.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index f1ef475b2..fc358ed8c 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -95,6 +95,93 @@ void MethodName() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestSwitchStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } + + break; + + case 1: +case 2: + label2: + while (true) + { + } + + break; + +default: +label3a: + label3b: +break; + } + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } + + break; + + case 1: + case 2: + label2: + while (true) + { + } + + break; + + default: + label3a: + label3b: + break; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(14, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(17, 1), + this.CSharpDiagnostic().WithLocation(18, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(23, 1), + this.CSharpDiagnostic().WithLocation(25, 1), + this.CSharpDiagnostic().WithLocation(26, 1), + this.CSharpDiagnostic().WithLocation(27, 1), + this.CSharpDiagnostic().WithLocation(28, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + /// protected override IEnumerable GetCSharpDiagnosticAnalyzers() { From a0967d0693fafc5b8e5dc20462c1b055db3b928d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 08:10:55 -0600 Subject: [PATCH 07/47] Add tests for initializer expressions --- .../ReadabilityRules/SA1137UnitTests.cs | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index fc358ed8c..28af52ebb 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -182,6 +182,207 @@ void MethodName() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestInitializerExpressionAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = + { + 0, + 0, +0, + }; + + // collection initializer + List list = + new List + { + 0, + 0, +0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, +{ 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, +Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, + 0, + 0, + }; + + // collection initializer + List list = + new List + { +0, + 0, + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { +{ 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { +X = 0, + Y = 0, + Z = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + string fixedCode = @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = + { + 0, + 0, + 0, + }; + + // collection initializer + List list = + new List + { + 0, + 0, + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, + Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, +0, +0, + }; + + // collection initializer + List list = + new List + { +0, +0, +0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { +{ 0, 0 }, +{ 0, 0 }, +{ 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { +X = 0, +Y = 0, +Z = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic().WithLocation(20, 1), + this.CSharpDiagnostic().WithLocation(21, 1), + this.CSharpDiagnostic().WithLocation(29, 1), + this.CSharpDiagnostic().WithLocation(30, 1), + this.CSharpDiagnostic().WithLocation(38, 1), + this.CSharpDiagnostic().WithLocation(39, 1), + this.CSharpDiagnostic().WithLocation(49, 1), + this.CSharpDiagnostic().WithLocation(50, 1), + this.CSharpDiagnostic().WithLocation(58, 1), + this.CSharpDiagnostic().WithLocation(59, 1), + this.CSharpDiagnostic().WithLocation(67, 1), + this.CSharpDiagnostic().WithLocation(68, 1), + this.CSharpDiagnostic().WithLocation(76, 1), + this.CSharpDiagnostic().WithLocation(77, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + /// protected override IEnumerable GetCSharpDiagnosticAnalyzers() { From b4610a1cc50e9dfbb545147afa1c4bc9a0b57cd8 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 09:30:19 -0600 Subject: [PATCH 08/47] Additional tests for valid initializer expressions and fix bugs * Fix misuse of immutable collections API --- .../ReadabilityRules/SA1137UnitTests.cs | 107 ++++++++++++++++++ ...137ElementsShouldHaveTheSameIndentation.cs | 2 +- 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 28af52ebb..9d385535b 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -182,6 +182,113 @@ void MethodName() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestValidInitializerExpressionAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void EmptyInitializersMethod() + { + // array initializer + int[] array = { }; + + // collection initializer + List list = new List { }; + + // complex element initializer + Dictionary dictionary = new Dictionary { }; + + // object initializer + var obj = new StructName { }; + } + + void SingleLineInitializersMethod() + { + // array initializer + int[] array = { 0 }; + + // collection initializer + List list = new List { 0 }; + + // complex element initializer + Dictionary dictionary = new Dictionary { { 0, 0 } }; + + // object initializer + var obj = new StructName { X = 0 }; + } + + void SingleElementInitializersMethod() + { + // array initializer + int[] array = + { + 0, + }; + + // collection initializer + List list = + new List + { + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + }; + } + + void SharedLineInitializersMethod() + { + // array initializer + int[] array = + { + 0, 0, + }; + + // collection initializer + List list = + new List + { + 0, 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, Y = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestInitializerExpressionAsync() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index b2e873945..72bb518e8 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -346,7 +346,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl return; } - elements.RemoveAll( + elements = elements.RemoveAll( element => { SyntaxToken firstToken = element.GetFirstToken(); From 0b976baf01df2d70035abbfad651b260d001ebe8 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 10:07:43 -0600 Subject: [PATCH 09/47] Add tests for base type declarations and fix bugs * Ignore leading attribute lists when analyzing other element kinds --- .../ReadabilityRules/SA1137UnitTests.cs | 84 +++++++++++++++++++ ...137ElementsShouldHaveTheSameIndentation.cs | 23 ++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 9d385535b..4ef85b2b2 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -17,6 +17,90 @@ namespace StyleCop.Analyzers.Test.ReadabilityRules /// public class SA1137UnitTests : CodeFixVerifier { + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + [InlineData("enum")] + public async Task TestBaseTypeDeclarationAsync(string baseTypeKind) + { + // Need to test attribute lists here + string testCode = $@" +using System; + +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace1 +{{ + [My] + [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} +"; + string fixedCode = $@" +using System; + +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace1 +{{ + [My] + [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic().WithLocation(18, 1), + this.CSharpDiagnostic().WithLocation(24, 1), + this.CSharpDiagnostic().WithLocation(25, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestBlockAsync() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 72bb518e8..44e044ab7 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -349,7 +349,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl elements = elements.RemoveAll( element => { - SyntaxToken firstToken = element.GetFirstToken(); + SyntaxToken firstToken = GetFirstTokenForAnalysis(element); return firstToken.IsMissingOrDefault() || !firstToken.IsFirstInLine(); }); @@ -362,7 +362,8 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl string expectedIndentation = null; foreach (T element in elements) { - SyntaxTrivia indentationTrivia = element.GetFirstToken().LeadingTrivia.LastOrDefault(); + SyntaxToken firstToken = GetFirstTokenForAnalysis(element); + SyntaxTrivia indentationTrivia = firstToken.LeadingTrivia.LastOrDefault(); string indentation = indentationTrivia.IsKind(SyntaxKind.WhitespaceTrivia) ? indentationTrivia.ToString() : string.Empty; if (first) @@ -381,7 +382,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl Location location; if (indentation.Length == 0) { - location = element.GetFirstToken().GetLocation(); + location = firstToken.GetLocation(); } else { @@ -392,5 +393,21 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, properties)); } } + + private static SyntaxToken GetFirstTokenForAnalysis(SyntaxNode node) + { + SyntaxToken firstToken = node.GetFirstToken(); + if (!node.IsKind(SyntaxKind.AttributeList)) + { + while (firstToken.IsKind(SyntaxKind.OpenBracketToken) + && firstToken.Parent.IsKind(SyntaxKind.AttributeList)) + { + // Skip over the attribute list since it's not the focus of this check + firstToken = firstToken.Parent.GetLastToken().GetNextToken(); + } + } + + return firstToken; + } } } From f5f7d2d28cde3d503ad0e10451ce2705bd737723 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 10:18:37 -0600 Subject: [PATCH 10/47] Add tests for constraint clauses in type declarations --- .../ReadabilityRules/SA1137UnitTests.cs | 73 +++++++++++++++++++ ...137ElementsShouldHaveTheSameIndentation.cs | 1 + 2 files changed, 74 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 4ef85b2b2..9edaeb1e1 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -101,6 +101,79 @@ class MyAttribute : Attribute {{ }} await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) + { + string testCode = $@" +{typeKind} NonGenericType +{{ +}} + +{typeKind} TypeWithoutConstraints +{{ +}} + +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 +where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} +"; + string fixedCode = $@" +{typeKind} NonGenericType +{{ +}} + +{typeKind} TypeWithoutConstraints +{{ +}} + +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 +where T1 : new() +where T2 : new() +where T3 : new() +{{ +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(17, 1), + this.CSharpDiagnostic().WithLocation(23, 1), + this.CSharpDiagnostic().WithLocation(24, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestBlockAsync() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 44e044ab7..c47b994c8 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -128,6 +128,7 @@ private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context) { var typeDeclaration = (TypeDeclarationSyntax)context.Node; + CheckElements(context, typeDeclaration.ConstraintClauses); CheckElements(context, typeDeclaration.Members); } From 38ab7d36192a795b530735304dfc33896d7c86e7 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 12:33:15 -0600 Subject: [PATCH 11/47] Add edge cases and fix bugs * Attribute lists are now evaluated along with siblings of their parents --- .../ReadabilityRules/SA1137UnitTests.cs | 49 +++++ ...137ElementsShouldHaveTheSameIndentation.cs | 179 +++++++++--------- 2 files changed, 143 insertions(+), 85 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 9edaeb1e1..54b64be8b 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -53,6 +53,29 @@ namespace Namespace3 {baseTypeKind} TypeName {{ }} }} +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] class MyAttribute : Attribute {{ }} "; @@ -84,6 +107,29 @@ namespace Namespace3 {baseTypeKind} TypeName {{ }} }} +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] class MyAttribute : Attribute {{ }} "; @@ -94,6 +140,9 @@ class MyAttribute : Attribute {{ }} this.CSharpDiagnostic().WithLocation(18, 1), this.CSharpDiagnostic().WithLocation(24, 1), this.CSharpDiagnostic().WithLocation(25, 1), + this.CSharpDiagnostic().WithLocation(33, 1), + this.CSharpDiagnostic().WithLocation(41, 1), + this.CSharpDiagnostic().WithLocation(48, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index c47b994c8..b6474af4a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -32,21 +32,13 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action CompilationStartAction = HandleCompilationStart; private static readonly Action CompilationUnitAction = HandleCompilationUnit; private static readonly Action NamespaceDeclarationAction = HandleNamespaceDeclaration; - private static readonly Action BaseTypeDeclarationAction = HandleBaseTypeDeclaration; private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; private static readonly Action EnumDeclarationAction = HandleEnumDeclaration; - private static readonly Action EnumMemberDeclarationAction = HandleEnumMemberDeclaration; - private static readonly Action BaseFieldDeclarationAction = HandleBaseFieldDeclaration; - private static readonly Action BaseMethodDeclarationAction = HandleBaseMethodDeclaration; private static readonly Action MethodDeclarationAction = HandleMethodDeclaration; - private static readonly Action BasePropertyDeclarationAction = HandleBasePropertyDeclaration; private static readonly Action AccessorListAction = HandleAccessorList; - private static readonly Action AccessorDeclarationAction = HandleAccessorDeclaration; private static readonly Action VariableDeclarationAction = HandleVariableDeclaration; private static readonly Action TypeParameterListAction = HandleTypeParameterList; - private static readonly Action TypeParameterAction = HandleTypeParameter; private static readonly Action BaseParameterListAction = HandleBaseParameterList; - private static readonly Action ParameterAction = HandleParameter; private static readonly Action BaseArgumentListAction = HandleBaseArgumentList; private static readonly Action AttributeListAction = HandleAttributeList; private static readonly Action AttributeArgumentListAction = HandleAttributeArgumentList; @@ -68,21 +60,13 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte { context.RegisterSyntaxNodeActionHonorExclusions(CompilationUnitAction, SyntaxKind.CompilationUnit); context.RegisterSyntaxNodeActionHonorExclusions(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(BaseTypeDeclarationAction, SyntaxKinds.BaseTypeDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(EnumDeclarationAction, SyntaxKind.EnumDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(EnumMemberDeclarationAction, SyntaxKind.EnumMemberDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(BaseFieldDeclarationAction, SyntaxKinds.BaseFieldDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(BaseMethodDeclarationAction, SyntaxKinds.BaseMethodDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(MethodDeclarationAction, SyntaxKind.MethodDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(BasePropertyDeclarationAction, SyntaxKinds.BasePropertyDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(AccessorListAction, SyntaxKind.AccessorList); - context.RegisterSyntaxNodeActionHonorExclusions(AccessorDeclarationAction, SyntaxKinds.AccessorDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(VariableDeclarationAction, SyntaxKind.VariableDeclaration); context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterListAction, SyntaxKind.TypeParameterList); - context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterAction, SyntaxKind.TypeParameter); context.RegisterSyntaxNodeActionHonorExclusions(BaseParameterListAction, SyntaxKinds.BaseParameterList); - context.RegisterSyntaxNodeActionHonorExclusions(ParameterAction, SyntaxKind.Parameter); context.RegisterSyntaxNodeActionHonorExclusions(BaseArgumentListAction, SyntaxKinds.BaseArgumentList); context.RegisterSyntaxNodeActionHonorExclusions(AttributeListAction, SyntaxKind.AttributeList); context.RegisterSyntaxNodeActionHonorExclusions(AttributeArgumentListAction, SyntaxKind.AttributeArgumentList); @@ -100,7 +84,7 @@ private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context) elements.AddRange(compilationUnit.Externs); elements.AddRange(compilationUnit.Usings); elements.AddRange(compilationUnit.AttributeLists); - elements.AddRange(compilationUnit.Members); + AddMembersAndAttributes(elements, compilationUnit.Members); CheckElements(context, elements.ToImmutable()); } @@ -113,51 +97,34 @@ private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context elements.AddRange(namespaceDeclaration.Externs); elements.AddRange(namespaceDeclaration.Usings); - elements.AddRange(namespaceDeclaration.Members); + AddMembersAndAttributes(elements, namespaceDeclaration.Members); CheckElements(context, elements.ToImmutable()); } - private static void HandleBaseTypeDeclaration(SyntaxNodeAnalysisContext context) - { - var baseTypeDeclaration = (BaseTypeDeclarationSyntax)context.Node; - CheckAttributeLists(context, baseTypeDeclaration.AttributeLists, baseTypeDeclaration); - } - private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context) { var typeDeclaration = (TypeDeclarationSyntax)context.Node; CheckElements(context, typeDeclaration.ConstraintClauses); - CheckElements(context, typeDeclaration.Members); + + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, typeDeclaration.Members); + CheckElements(context, elements.ToImmutable()); } private static void HandleEnumDeclaration(SyntaxNodeAnalysisContext context) { var enumDeclaration = (EnumDeclarationSyntax)context.Node; - CheckElements(context, enumDeclaration.Members); - } - - private static void HandleEnumMemberDeclaration(SyntaxNodeAnalysisContext context) - { - var enumMemberDeclaration = (EnumMemberDeclarationSyntax)context.Node; - - CheckAttributeLists(context, enumMemberDeclaration.AttributeLists, enumMemberDeclaration); - } - - private static void HandleBaseFieldDeclaration(SyntaxNodeAnalysisContext context) - { - var baseFieldDeclaration = (BaseFieldDeclarationSyntax)context.Node; - - CheckAttributeLists(context, baseFieldDeclaration.AttributeLists, baseFieldDeclaration); - } - - private static void HandleBaseMethodDeclaration(SyntaxNodeAnalysisContext context) - { - var baseMethodDeclaration = (BaseMethodDeclarationSyntax)context.Node; + var elements = ImmutableList.CreateBuilder(); + foreach (EnumMemberDeclarationSyntax enumMemberDeclaration in enumDeclaration.Members) + { + elements.AddRange(enumMemberDeclaration.AttributeLists); + elements.Add(enumMemberDeclaration); + } - CheckAttributeLists(context, baseMethodDeclaration.AttributeLists, baseMethodDeclaration); + CheckElements(context, elements.ToImmutable()); } private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context) @@ -167,25 +134,13 @@ private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context) CheckElements(context, methodDeclaration.ConstraintClauses); } - private static void HandleBasePropertyDeclaration(SyntaxNodeAnalysisContext context) - { - var basePropertyDeclaration = (BasePropertyDeclarationSyntax)context.Node; - - CheckAttributeLists(context, basePropertyDeclaration.AttributeLists, basePropertyDeclaration); - } - private static void HandleAccessorList(SyntaxNodeAnalysisContext context) { var accessorList = (AccessorListSyntax)context.Node; - CheckElements(context, accessorList.Accessors); - } - - private static void HandleAccessorDeclaration(SyntaxNodeAnalysisContext context) - { - var accessorDeclaration = (AccessorDeclarationSyntax)context.Node; - - CheckAttributeLists(context, accessorDeclaration.AttributeLists, accessorDeclaration); + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, accessorList.Accessors); + CheckElements(context, elements.ToImmutable()); } private static void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) @@ -198,27 +153,18 @@ private static void HandleTypeParameterList(SyntaxNodeAnalysisContext context) { var typeParameterList = (TypeParameterListSyntax)context.Node; - CheckElements(context, typeParameterList.Parameters); - } - - private static void HandleTypeParameter(SyntaxNodeAnalysisContext context) - { - var typeParameter = (TypeParameterSyntax)context.Node; - - CheckAttributeLists(context, typeParameter.AttributeLists, typeParameter); + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, typeParameterList.Parameters); + CheckElements(context, elements.ToImmutable()); } private static void HandleBaseParameterList(SyntaxNodeAnalysisContext context) { var baseParameterList = (BaseParameterListSyntax)context.Node; - CheckElements(context, baseParameterList.Parameters); - } - - private static void HandleParameter(SyntaxNodeAnalysisContext context) - { - var parameter = (ParameterSyntax)context.Node; - CheckAttributeLists(context, parameter.AttributeLists, parameter); + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, baseParameterList.Parameters); + CheckElements(context, elements.ToImmutable()); } private static void HandleBaseArgumentList(SyntaxNodeAnalysisContext context) @@ -300,21 +246,75 @@ private static void HandleInitializerExpression(SyntaxNodeAnalysisContext contex CheckElements(context, initializerExpression.Expressions); } - private static void CheckAttributeLists(SyntaxNodeAnalysisContext context, SyntaxList attributeLists, SyntaxNode parent) + private static void AddMembersAndAttributes(ImmutableList.Builder elements, SeparatedSyntaxList members) + where T : SyntaxNode { - if (attributeLists.Count == 0) + foreach (SyntaxNode member in members) { - return; + AddMemberAndAttributes(elements, member); } + } - var nodes = ImmutableList.CreateBuilder(); + private static void AddMembersAndAttributes(ImmutableList.Builder elements, SyntaxList members) + where T : SyntaxNode + { + foreach (SyntaxNode member in members) + { + AddMemberAndAttributes(elements, member); + } + } - // Placing the parent first in this list causes the analysis to prefer to align attribute lists with their - // parent syntax, assuming the parent also appears on its own line. - nodes.Add(parent); - nodes.AddRange(attributeLists); + private static void AddMemberAndAttributes(ImmutableList.Builder elements, SyntaxNode member) + { + switch (member.Kind()) + { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.StructDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + elements.AddRange(((BaseTypeDeclarationSyntax)member).AttributeLists); + break; + + case SyntaxKind.FieldDeclaration: + case SyntaxKind.EventFieldDeclaration: + elements.AddRange(((BaseFieldDeclarationSyntax)member).AttributeLists); + break; + + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.EventDeclaration: + case SyntaxKind.IndexerDeclaration: + elements.AddRange(((BasePropertyDeclarationSyntax)member).AttributeLists); + break; + + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.OperatorDeclaration: + case SyntaxKind.ConversionOperatorDeclaration: + elements.AddRange(((BaseMethodDeclarationSyntax)member).AttributeLists); + break; + + case SyntaxKind.GetAccessorDeclaration: + case SyntaxKind.SetAccessorDeclaration: + case SyntaxKind.AddAccessorDeclaration: + case SyntaxKind.RemoveAccessorDeclaration: + case SyntaxKind.UnknownAccessorDeclaration: + elements.AddRange(((AccessorDeclarationSyntax)member).AttributeLists); + break; + + case SyntaxKind.TypeParameter: + elements.AddRange(((TypeParameterSyntax)member).AttributeLists); + break; + + case SyntaxKind.Parameter: + elements.AddRange(((ParameterSyntax)member).AttributeLists); + break; + + default: + break; + } - CheckElements(context, nodes.ToImmutable()); + elements.Add(member); } private static void CheckElements(SyntaxNodeAnalysisContext context, SyntaxList elements) @@ -359,6 +359,15 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl return; } + // Try to reorder the list so the first item is not an attribute list. This element will establish the + // expected indentation for the entire collection. + int desiredFirst = elements.FindIndex(x => !x.IsKind(SyntaxKind.AttributeList)); + if (desiredFirst >= 0) + { + T newFirstElement = elements[desiredFirst]; + elements = elements.RemoveAt(desiredFirst).Insert(0, newFirstElement); + } + bool first = true; string expectedIndentation = null; foreach (T element in elements) From c3ae121226c808a4b96331e9a4629cd702cc187c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 12:35:59 -0600 Subject: [PATCH 12/47] Avoid mutations if the result will match the input --- .../SA1137ElementsShouldHaveTheSameIndentation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index b6474af4a..5fbfcba90 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -362,7 +362,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl // Try to reorder the list so the first item is not an attribute list. This element will establish the // expected indentation for the entire collection. int desiredFirst = elements.FindIndex(x => !x.IsKind(SyntaxKind.AttributeList)); - if (desiredFirst >= 0) + if (desiredFirst > 0) { T newFirstElement = elements[desiredFirst]; elements = elements.RemoveAt(desiredFirst).Insert(0, newFirstElement); From b84892b7be62d5ce1f199221396a05aa28f9b5e2 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 12:54:32 -0600 Subject: [PATCH 13/47] Implement support for anonymous object creation expressions --- .../ReadabilityRules/SA1137UnitTests.cs | 103 ++++++++++++++++++ ...137ElementsShouldHaveTheSameIndentation.cs | 9 ++ 2 files changed, 112 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 54b64be8b..1d23a6954 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -696,6 +696,109 @@ struct StructName await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestValidAnonymousObjectCreationExpressionAsync() + { + string testCode = @" +class ClassName +{ + void SingleLineInitializersMethod() + { + var obj = new { X = 0 }; + } + + void SingleElementInitializersMethod() + { + var obj = + new + { + X = 0, + }; + } + + void SharedLineInitializersMethod() + { + var obj = + new + { + X = 0, Y = 0, + }; + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestAnonymousObjectCreationExpressionAsync() + { + string testCode = @" +class ClassName +{ + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, +Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, + Y = 0, + Z = 0, + }; + } +} +"; + string fixedCode = @" +class ClassName +{ + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, + Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, +Y = 0, +Z = 0, + }; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(10, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(21, 1), + this.CSharpDiagnostic().WithLocation(22, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + /// protected override IEnumerable GetCSharpDiagnosticAnalyzers() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 5fbfcba90..2ae3e9339 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -45,6 +45,7 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly Action BlockAction = HandleBlock; private static readonly Action SwitchStatementAction = HandleSwitchStatement; private static readonly Action InitializerExpressionAction = HandleInitializerExpression; + private static readonly Action AnonymousObjectCreationExpressionAction = HandleAnonymousObjectCreationExpression; /// public override ImmutableArray SupportedDiagnostics { get; } = @@ -73,6 +74,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte context.RegisterSyntaxNodeActionHonorExclusions(BlockAction, SyntaxKind.Block); context.RegisterSyntaxNodeActionHonorExclusions(SwitchStatementAction, SyntaxKind.SwitchStatement); context.RegisterSyntaxNodeActionHonorExclusions(InitializerExpressionAction, SyntaxKinds.InitializerExpression); + context.RegisterSyntaxNodeActionHonorExclusions(AnonymousObjectCreationExpressionAction, SyntaxKind.AnonymousObjectCreationExpression); } private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context) @@ -246,6 +248,13 @@ private static void HandleInitializerExpression(SyntaxNodeAnalysisContext contex CheckElements(context, initializerExpression.Expressions); } + private static void HandleAnonymousObjectCreationExpression(SyntaxNodeAnalysisContext context) + { + var anonymousObjectCreationExpression = (AnonymousObjectCreationExpressionSyntax)context.Node; + + CheckElements(context, anonymousObjectCreationExpression.Initializers); + } + private static void AddMembersAndAttributes(ImmutableList.Builder elements, SeparatedSyntaxList members) where T : SyntaxNode { From c19a1fe27b3195b62ef707cfc317f815325752b4 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 13:13:24 -0600 Subject: [PATCH 14/47] Add tests for type parameter lists --- .../ReadabilityRules/SA1137UnitTests.cs | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 1d23a6954..3b25cdb7b 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -223,6 +223,74 @@ public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestValidTypeParameterListAsync(string prefix, string suffix) + { + string testCode = $@" +class Container +{{ + {prefix} ClassName1{suffix} + + {prefix} ClassName2< + T>{suffix} + + {prefix} ClassName3< + T1, T2>{suffix} +}} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestTypeParameterListAsync(string prefix, string suffix) + { + string testCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, +Z>{suffix} + + {prefix} ZeroAlignment< +X, + Y, + Z>{suffix} +}} +"; + string fixedCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, + Z>{suffix} + + {prefix} ZeroAlignment< +X, +Y, +Z>{suffix} +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestBlockAsync() { From 2e34ba29219b3dc0dd9b2cd65e7bd4ab94b805b9 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 13:50:24 -0600 Subject: [PATCH 15/47] Add test for enum declarations --- .../ReadabilityRules/SA1137UnitTests.cs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 3b25cdb7b..76ca113cf 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -223,6 +223,80 @@ public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestEnumDeclarationAsync() + { + string testCode = @" +using System; +enum Enum1 +{ + [My] + Element1, + + Element2, +} + +enum Enum2 +{ + [My] +Element1, + + Element2, +} + +enum Enum3 +{ + [My] Element1, + + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; +enum Enum1 +{ + [My] + Element1, + + Element2, +} + +enum Enum2 +{ +[My] +Element1, + +Element2, +} + +enum Enum3 +{ + [My] Element1, + + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(5, 1), + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(13, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(21, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Theory] [InlineData("class", " { }")] [InlineData("void", "() { }")] From 26ee139f8b6c1588e2df24d70a7bd29604966872 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 14:59:05 -0600 Subject: [PATCH 16/47] Add tests for method declarations --- .../ReadabilityRules/SA1137UnitTests.cs | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 76ca113cf..5aa6aad79 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -297,6 +297,82 @@ class MyAttribute : Attribute { } await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestMethodDeclarationAsync() + { + string testCode = @" +class Container +{ + void NonGenericType() + { + } + + void TypeWithoutConstraints() + { + } + + void TypeWithOneConstraint() + where T : new() + { + } + + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } + + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { + } +} +"; + string fixedCode = @" +class Container +{ + void NonGenericType() + { + } + + void TypeWithoutConstraints() + { + } + + void TypeWithOneConstraint() + where T : new() + { + } + + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } + + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(25, 1), + this.CSharpDiagnostic().WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Theory] [InlineData("class", " { }")] [InlineData("void", "() { }")] From 18d33e4ccf52b029e3b721d6d6908d2a3e89b9d1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 15:06:07 -0600 Subject: [PATCH 17/47] Test field, event field, and variable declarations --- .../ReadabilityRules/SA1137UnitTests.cs | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 5aa6aad79..cfdd7dc8d 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -373,6 +373,140 @@ void TypeWithMultipleConstraints2() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestValidVariableDeclarationAsync() + { + string testCode = @" +using System; +class Container +{ + private int T1; + private int + T2; + private int + T3, T4; + + private event EventHandler T5; + private event EventHandler + T6; + private event EventHandler + T7, T8; + + void MethodName() + { + int t1; + int + t2; + int + t3, t4; + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestVariableDeclarationAsync() + { + string testCode = @" +using System; +class Container +{ + private int + X1, + Y1, +Z1; + + private int +X2, + Y2, + Z2; + + private event EventHandler + X3, + Y3, +Z3; + + private event EventHandler +X4, + Y4, + Z4; + + void MethodName() + { + int + X1, + Y1, +Z1; + + int +X2, + Y2, + Z2; + } +} +"; + string fixedCode = @" +using System; +class Container +{ + private int + X1, + Y1, + Z1; + + private int +X2, +Y2, +Z2; + + private event EventHandler + X3, + Y3, + Z3; + + private event EventHandler +X4, +Y4, +Z4; + + void MethodName() + { + int + X1, + Y1, + Z1; + + int +X2, +Y2, +Z2; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic().WithLocation(13, 1), + this.CSharpDiagnostic().WithLocation(17, 1), + this.CSharpDiagnostic().WithLocation(18, 1), + this.CSharpDiagnostic().WithLocation(22, 1), + this.CSharpDiagnostic().WithLocation(23, 1), + this.CSharpDiagnostic().WithLocation(29, 1), + this.CSharpDiagnostic().WithLocation(30, 1), + this.CSharpDiagnostic().WithLocation(34, 1), + this.CSharpDiagnostic().WithLocation(35, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Theory] [InlineData("class", " { }")] [InlineData("void", "() { }")] From b879caf8669c3718155b02654b3d087a5028710e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 15:20:48 -0600 Subject: [PATCH 18/47] Add tests for attribute lists --- .../ReadabilityRules/SA1137UnitTests.cs | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index cfdd7dc8d..3a036f798 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -575,6 +575,77 @@ class Container await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestAttributeListAsync() + { + string testCode = @" +using System; + +[My] +[ + My] +[ + My, My] +class TypeName1 +{ +} + +[ + My, + My, +My] +[ +My, + My, + My] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +[My] +[ + My] +[ + My, My] +class TypeName1 +{ +} + +[ + My, + My, + My] +[ +My, +My, +My] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(15, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(20, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestBlockAsync() { From e2e7ed3745822fd7d76c0ff21bc1be3d0fca65a1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 15:29:30 -0600 Subject: [PATCH 19/47] Add attribute argument list tests --- .../ReadabilityRules/SA1137UnitTests.cs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 3a036f798..5a983f897 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -646,6 +646,91 @@ class MyAttribute : Attribute { } await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestAttributeArgumentListAsync() + { + string testCode = @" +using System; + +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 +{ +} + +[My( + 0, + Y = 2, +Z = 3)] +[My( +0, + Y = 2, + Z = 3)] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute +{ + public MyAttribute() { } + public MyAttribute(int value) { } + + public int Y { get; set; } + public int Z { get; set; } +} +"; + string fixedCode = @" +using System; + +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 +{ +} + +[My( + 0, + Y = 2, + Z = 3)] +[My( +0, +Y = 2, +Z = 3)] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute +{ + public MyAttribute() { } + public MyAttribute(int value) { } + + public int Y { get; set; } + public int Z { get; set; } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(15, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(20, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestBlockAsync() { From c9506cf086f72b1eb16277a7a01fc36f47b3567b Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 15:55:17 -0600 Subject: [PATCH 20/47] Add accessor list tests --- .../ReadabilityRules/SA1137UnitTests.cs | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 5a983f897..0a9e0ef14 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -373,6 +373,264 @@ void TypeWithMultipleConstraints2() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestPropertyAccessorListAsync() + { + string testCode = @" +using System; + +class Container +{ + int Property1 + { + [My] + get; + + set; + } + + int Property2 + { + [My] +get; + + set; + } + + int Property3 + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +class Container +{ + int Property1 + { + [My] + get; + + set; + } + + int Property2 + { +[My] +get; + +set; + } + + int Property3 + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(24, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestIndexerAccessorListAsync() + { + string testCode = @" +using System; + +interface IContainer1 +{ + int this[int arg] + { + [My] + get; + + set; + } +} + +interface IContainer2 +{ + int this[int arg] + { + [My] +get; + + set; + } +} + +interface IContainer3 +{ + int this[int arg] + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +interface IContainer1 +{ + int this[int arg] + { + [My] + get; + + set; + } +} + +interface IContainer2 +{ + int this[int arg] + { +[My] +get; + +set; + } +} + +interface IContainer3 +{ + int this[int arg] + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(22, 1), + this.CSharpDiagnostic().WithLocation(30, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestEventAccessorListAsync() + { + string testCode = @" +using System; + +class Container +{ + event EventHandler Event1 + { + [My] + add { } + + remove { } + } + + event EventHandler Event2 + { + [My] +add { } + + remove { } + } + + event EventHandler Event3 + { + [My] add { } + + remove { } + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +class Container +{ + event EventHandler Event1 + { + [My] + add { } + + remove { } + } + + event EventHandler Event2 + { +[My] +add { } + +remove { } + } + + event EventHandler Event3 + { + [My] add { } + + remove { } + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(16, 1), + this.CSharpDiagnostic().WithLocation(19, 1), + this.CSharpDiagnostic().WithLocation(24, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestValidVariableDeclarationAsync() { From d94c6666b76a0c968cae4fb34fbb1e482de92eee Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 16:06:13 -0600 Subject: [PATCH 21/47] Add parameter list tests --- .../ReadabilityRules/SA1137UnitTests.cs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 0a9e0ef14..2059e0fe3 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -833,6 +833,102 @@ class Container await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestParameterListAsync() + { + string testCode = @" +class Container +{ + void NonZeroAlignment( + int X, + int Y, +int Z) { } + + void ZeroAlignment( +int X, + int Y, + int Z) { } +} +"; + string fixedCode = @" +class Container +{ + void NonZeroAlignment( + int X, + int Y, + int Z) { } + + void ZeroAlignment( +int X, +int Y, +int Z) { } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestBracketedParameterListAsync() + { + string testCode = @" +class Container1 +{ + int this[ + int X, + int Y, +int Z] => 0; +} + +class Container2 +{ + int this[ +int X, + int Y, + int Z] => 0; +} +"; + string fixedCode = @" +class Container1 +{ + int this[ + int X, + int Y, + int Z] => 0; +} + +class Container2 +{ + int this[ +int X, +int Y, +int Z] => 0; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(14, 1), + this.CSharpDiagnostic().WithLocation(15, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestAttributeListAsync() { From 59fccc3bc1706fa5af970ed1a04212bfc45c5d34 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 16:27:26 -0600 Subject: [PATCH 22/47] Add argument list tests --- .../ReadabilityRules/SA1137UnitTests.cs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 2059e0fe3..60364418a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -929,6 +929,102 @@ int this[ await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestArgumentListAsync() + { + string testCode = @" +class Container +{ + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, +0); + + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, + 0, + 0); +} +"; + string fixedCode = @" +class Container +{ + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, + 0); + + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, +0, +0); +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(11, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestBracketedArgumentListAsync() + { + string testCode = @" +class Container1 +{ + int this[int x, int y, int z] => this[ + 0, + 0, +0]; +} + +class Container2 +{ + int this[int x, int y, int z] => this[ +0, + 0, + 0]; +} +"; + string fixedCode = @" +class Container1 +{ + int this[int x, int y, int z] => this[ + 0, + 0, + 0]; +} + +class Container2 +{ + int this[int x, int y, int z] => this[ +0, +0, +0]; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(7, 1), + this.CSharpDiagnostic().WithLocation(14, 1), + this.CSharpDiagnostic().WithLocation(15, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestAttributeListAsync() { From 29208d07fbbbde1b2d96752abffe836720959bf4 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 17:27:31 -0600 Subject: [PATCH 23/47] Add documentation for SA1137 --- StyleCopAnalyzers.sln | 1 + documentation/SA1137.md | 149 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 documentation/SA1137.md diff --git a/StyleCopAnalyzers.sln b/StyleCopAnalyzers.sln index bd31f65d5..2a690e699 100644 --- a/StyleCopAnalyzers.sln +++ b/StyleCopAnalyzers.sln @@ -104,6 +104,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "documentation", "documentat documentation\SA1132.md = documentation\SA1132.md documentation\SA1133.md = documentation\SA1133.md documentation\SA1134.md = documentation\SA1134.md + documentation\SA1137.md = documentation\SA1137.md documentation\SA1200.md = documentation\SA1200.md documentation\SA1201.md = documentation\SA1201.md documentation\SA1202.md = documentation\SA1202.md diff --git a/documentation/SA1137.md b/documentation/SA1137.md new file mode 100644 index 000000000..228edaeec --- /dev/null +++ b/documentation/SA1137.md @@ -0,0 +1,149 @@ +## SA1137 + + + + + + + + + + + + + + +
TypeNameSA1137ElementsShouldHaveTheSameIndentation
CheckIdSA1137
CategoryReadability Rules
+ +:memo: This rule is new for StyleCop Analyzers, and was not present in StyleCop Classic. + +## Cause + +Two sibling elements which each start on their own line have different levels of indentation. + +## Rule description + +A violation of this rule occurs when two or more sibling elements each start on their own line but are not indented the +same amount. + +For example, the following code would produce a violation of this rule: + +```csharp +public void MethodName() +{ + A(); + B(); // SA1137: Expected the indentation to match the previous line +} +``` + +The following code would not produce any violations: + +```csharp +public void MethodName() +{ + A(); + B(); +} +``` + +Note that relative indentation and indentation in independent groups of siblings is not checked by this rule. The +following code shows a more complex example which would not produce any violations: + +```csharp +public void Method1() +{ + A(); + B(); +} + +public void Method2() +{ + A(); + B(); +} + +public void Method3() +{ +A(); +B(); +} + +public void Method4() + { + A(); + B(); + } +``` + +### Attributes + +Attribute lists are evaluated by this rule as individual elements at the same level as the element they are applied to. +However, when determining the expected indentation for sibling elements, attribute lists are given lower priority. In +other words, the first element in the same group which starts on its own line, if one exists, determines the expected +indentation for the group. If no such element exists, the indentation of the first attribute list is used instead. For +example, the following code shows locations where SA1137 is reported relative to attribute lists. + +```csharp + [Obsolete] // SA1137 (expected no indentation) +public void Method() // OK (this line establishes indentation for the group) +{ +} + + public Task MethodAsync() // SA1137 (expected no indentation) + { // OK (not part of the analysis group) + } +``` + +The following example shows a case where the indentation of an attribute list *is* used for the group. + +```csharp +public void Method(int x, // Ignored (parameter does not start on its own line) + [In] int y, // OK (this line establishes indentation for the group) + [In] int z) // SA1137 +{ +} +``` + +### Labels + +Labels which appear within a block statement are evaluated in a special manner. Each label within a block is expected to +have the same indentation, even if that indentation differs from the indentation used by statements within the block. +The specific indentation of labels relative to other statements is not examined for this rule. + +The following example shows a block with statements and labels. + +```csharp +public int MethodName() +{ + int x; + + beginning: // OK (label indentation may differ from other statements) + x = 3; // SA1137 (should be indented four spaces to match 'int x;' above) + +end: // SA1137 (should be indented two spaces to match 'beginning:' above) + return x; +} +``` + +Inside of a `switch` statement, the `case` and `default` labels form an additional category. The specific rules in this +case are: + +1. `case` and `default` labels in a `switch` statement need to use the same indentation. +2. Other labels in a `switch` statement need to use the same indentation (but this may differ from the indentation of + `case` labels) +3. Statements in a `switch` statement need to use the same indentation (but this may differ from both of the above + labels). + +## How to fix violations + +To fix a violation of this rule, adjust the indentation of sibling elements to match. + +## How to suppress violations + +```csharp +class TypeName { } + +#pragma warning disable SA1137 // Elements should have the same indentation + class Indented { } +#pragma warning restore SA1137 // Elements should have the same indentation +``` From 0eef07712d21a25ffaa02a913c169d544f9628ec Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 17:40:07 -0600 Subject: [PATCH 24/47] Enable SA1137 by default --- .../SA1137ElementsShouldHaveTheSameIndentation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 2ae3e9339..af82a610f 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -27,7 +27,7 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md"; private static readonly DiagnosticDescriptor Descriptor = - new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.DisabledNoTests, Description, HelpLink); + new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink); private static readonly Action CompilationStartAction = HandleCompilationStart; private static readonly Action CompilationUnitAction = HandleCompilationUnit; From 9ac894c44f2e56902416d6114bc324ddd1babb0a Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 5 Jan 2016 19:07:10 -0600 Subject: [PATCH 25/47] Add a test for documentation comment behavior --- .../ReadabilityRules/SA1137UnitTests.cs | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 60364418a..fa0a2f093 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -223,6 +223,122 @@ public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + /// + /// This test demonstrates the behavior of SA1137 and its code fix with respect to documentation comments. + /// Currently both operations ignore documentation comments, but in the future the implementation may be updated + /// to examine and correct them similarly to attribute lists. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestDocumentationCommentBehaviorAsync() + { + string testCode = @" +using System; +enum Enum1 +{ + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum2 +{ + /// + /// Summary. + /// + [My] +Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum3 +{ + /// + /// Summary. + /// + [My] Element1, + + /// + /// Summary. + /// + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; +enum Enum1 +{ + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum2 +{ + /// + /// Summary. + /// +[My] +Element1, + + /// + /// Summary. + /// +Element2, +} + +enum Enum3 +{ + /// + /// Summary. + /// + [My] Element1, + + /// + /// Summary. + /// + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(8, 1), + this.CSharpDiagnostic().WithLocation(14, 1), + this.CSharpDiagnostic().WithLocation(22, 1), + this.CSharpDiagnostic().WithLocation(28, 1), + this.CSharpDiagnostic().WithLocation(36, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestEnumDeclarationAsync() { From 89d3e3104099d108d19616e5200ea10a1cfea090 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 6 Jan 2016 06:52:47 -0600 Subject: [PATCH 26/47] Add test for members of a type declaration --- .../ReadabilityRules/SA1137UnitTests.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index fa0a2f093..46446411f 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -223,6 +223,56 @@ public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Theory] + [InlineData("class", "int", " { }")] + [InlineData("struct", "int", " { }")] + [InlineData("interface", "event System.EventHandler", ";")] + public async Task TestTypeDeclarationMembersAsync(string typeKind, string fieldType, string methodBody) + { + string testCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} +void Z1(){methodBody} +}} + +{typeKind} Container2 +{{ +{fieldType} X2; + int Y2 {{ get; }} + void Z2(){methodBody} +}} +"; + string fixedCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} + void Z1(){methodBody} +}} + +{typeKind} Container2 +{{ +{fieldType} X2; +int Y2 {{ get; }} +void Z2(){methodBody} +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic().WithLocation(5, 1), + this.CSharpDiagnostic().WithLocation(6, 1), + this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic().WithLocation(13, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + /// /// This test demonstrates the behavior of SA1137 and its code fix with respect to documentation comments. /// Currently both operations ignore documentation comments, but in the future the implementation may be updated From b660fa62e893ef8823ded7b6b0be702137ce83e0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 6 Jan 2016 06:53:07 -0600 Subject: [PATCH 27/47] Rename TestBaseTypeDeclarationAsync to TestNamespaceDeclarationAsync --- .../ReadabilityRules/SA1137UnitTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 46446411f..8db85bfda 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -22,9 +22,8 @@ public class SA1137UnitTests : CodeFixVerifier [InlineData("struct")] [InlineData("interface")] [InlineData("enum")] - public async Task TestBaseTypeDeclarationAsync(string baseTypeKind) + public async Task TestNamespaceDeclarationAsync(string baseTypeKind) { - // Need to test attribute lists here string testCode = $@" using System; From 990b6bdd5378072dc4b1b7203d9074e99e3f396f Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 14 Jan 2016 17:45:31 -0600 Subject: [PATCH 28/47] For SA1137, first in line means whitespace only --- .../ReadabilityRules/SA1137UnitTests.cs | 18 ++++++++++ .../StyleCop.Analyzers/Helpers/TokenHelper.cs | 36 ++++++++++++++++--- ...137ElementsShouldHaveTheSameIndentation.cs | 2 +- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 8db85bfda..b5af1a552 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -1424,6 +1424,24 @@ void MethodName() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestLeadingCommentAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void MethodName() + { + /* var x = */ new List(); + var y = new List(); + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestSwitchStatementAsync() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs index 44ca8547d..6e7ebb733 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs @@ -15,18 +15,44 @@ internal static class TokenHelper /// Gets a value indicating whether the is first in line. /// /// The token to process. - /// true if token is first in line, otherwise false. - internal static bool IsFirstInLine(this SyntaxToken token) + /// to consider the token first-in-line even when + /// non-whitespace trivia precedes the token; otherwise, to only consider tokens first + /// in line if they are preceded solely by whitespace. + /// + /// if is first in line; otherwise, . + /// + internal static bool IsFirstInLine(this SyntaxToken token, bool allowNonWhitespaceTrivia = true) { var fullLineSpan = token.SyntaxTree.GetLineSpan(token.FullSpan); + bool firstInLine; if (token.SyntaxTree == null || fullLineSpan.StartLinePosition.Character == 0) { - return true; + firstInLine = true; + } + else + { + var tokenLineSpan = token.SyntaxTree.GetLineSpan(token.Span); + firstInLine = tokenLineSpan.StartLinePosition.Line != fullLineSpan.StartLinePosition.Line; } - var tokenLineSpan = token.SyntaxTree.GetLineSpan(token.Span); - return tokenLineSpan.StartLinePosition.Line != fullLineSpan.StartLinePosition.Line; + if (firstInLine && !allowNonWhitespaceTrivia) + { + foreach (var trivia in token.LeadingTrivia.Reverse()) + { + if (!trivia.IsKind(SyntaxKind.WhitespaceTrivia)) + { + if (!trivia.HasBuiltinEndLine()) + { + firstInLine = false; + } + + break; + } + } + } + + return firstInLine; } /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index af82a610f..46678ca4d 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -360,7 +360,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl element => { SyntaxToken firstToken = GetFirstTokenForAnalysis(element); - return firstToken.IsMissingOrDefault() || !firstToken.IsFirstInLine(); + return firstToken.IsMissingOrDefault() || !firstToken.IsFirstInLine(allowNonWhitespaceTrivia: false); }); if (elements.Count < 2) From aac884465598fcce921eff9a2a88de6398b3474b Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 7 Jan 2016 14:44:00 -0600 Subject: [PATCH 29/47] Initial implementation of SA1138 (Indent elements correctly) --- .../IndentationCodeFixProvider.cs | 4 +- .../StyleCop.Analyzers/AnalyzerExtensions.cs | 37 + .../ReadabilityResources.Designer.cs | 27 + .../ReadabilityResources.resx | 9 + ...137ElementsShouldHaveTheSameIndentation.cs | 870 +++++++++++++----- .../ObjectModel/IndentationSettings.cs | 41 + .../Settings/ObjectModel/LabelPositioning.cs | 23 + .../Settings/stylecop.schema.json | 53 ++ .../StyleCop.Analyzers.csproj | 1 + 9 files changed, 837 insertions(+), 228 deletions(-) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/LabelPositioning.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs index 0c0e984f5..0942a2cd0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs @@ -20,7 +20,9 @@ internal class IndentationCodeFixProvider : CodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds { get; } = - ImmutableArray.Create(SA1137ElementsShouldHaveTheSameIndentation.DiagnosticId); + ImmutableArray.Create( + SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId, + SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId); /// public sealed override FixAllProvider GetFixAllProvider() => diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs b/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs index 783354a2a..87d17e689 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs @@ -95,6 +95,43 @@ public static void RegisterSyntaxTreeActionHonorExclusions(this CompilationStart }); } + /// + /// Register an action to be executed at completion of parsing of a code document. A syntax tree action reports + /// diagnostics about the of a document. + /// + /// This method honors exclusions. + /// The analysis context. + /// Action to be executed at completion of parsing of a document. + public static void RegisterSyntaxTreeActionHonorExclusions(this CompilationStartAnalysisContext context, Action action) + { + Compilation compilation = context.Compilation; + ConcurrentDictionary cache = GetOrCreateGeneratedDocumentCache(compilation); + StrongBox settingsCache = GetOrCreateStyleCopSettingsCache(compilation); + + context.RegisterSyntaxTreeAction( + c => + { + if (c.IsGeneratedDocument(cache)) + { + return; + } + + // Honor the containing document item's ExcludeFromStylecop=True + // MSBuild metadata, if analyzers have access to it. + //// TODO: code here + + StyleCopSettings settings = settingsCache.Value; + if (settings == null) + { + StyleCopSettings updatedSettings = SettingsHelper.GetStyleCopSettings(c.Options, c.CancellationToken); + StyleCopSettings previous = Interlocked.CompareExchange(ref settingsCache.Value, updatedSettings, null); + settings = previous ?? updatedSettings; + } + + action(c, compilation, settings); + }); + } + /// /// Gets or creates a cache which can be used with methods to /// efficiently determine whether or not a source file is considered generated. diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs index 7ceb0a9ec..7da74e923 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.Designer.cs @@ -1195,6 +1195,33 @@ internal static string SA1137Title { } } + /// + /// Looks up a localized string similar to Code elements should be properly indented to avoid misinterpretation by readers.. + /// + internal static string SA1138Description { + get { + return ResourceManager.GetString("SA1138Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Indent elements correctly. + /// + internal static string SA1138MessageFormat { + get { + return ResourceManager.GetString("SA1138MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Indent elements correctly. + /// + internal static string SA1138Title { + get { + return ResourceManager.GetString("SA1138Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remove 'this.' prefix. /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx index e20a9971c..9592bb24f 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/ReadabilityResources.resx @@ -495,6 +495,15 @@ Elements should have the same indentation + + Code elements should be properly indented to avoid misinterpretation by readers. + + + Indent elements correctly + + + Indent elements correctly + Remove 'this.' prefix diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 46678ca4d..234c578ec 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -5,12 +5,14 @@ namespace StyleCop.Analyzers.ReadabilityRules { using System; using System.Collections.Immutable; + using System.Diagnostics; using System.Linq; using Helpers; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; + using Settings.ObjectModel; [DiagnosticAnalyzer(LanguageNames.CSharp)] internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer @@ -20,36 +22,37 @@ internal class SA1137ElementsShouldHaveTheSameIndentation : DiagnosticAnalyzer /// /// The ID for diagnostics produced by the analyzer. /// - public const string DiagnosticId = "SA1137"; - private static readonly LocalizableString Title = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Title), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); - private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(ReadabilityResources.SA1137MessageFormat), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); - private static readonly LocalizableString Description = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Description), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); - private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md"; + public const string SA1137DiagnosticId = "SA1137"; - private static readonly DiagnosticDescriptor Descriptor = - new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink); + /// + /// The ID for diagnostics produced by the SA1138 (Indent elements correctly) analyzer. + /// + public const string SA1138DiagnosticId = "SA1138"; + + private static readonly LocalizableString SA1137Title = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Title), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString SA1137MessageFormat = new LocalizableResourceString(nameof(ReadabilityResources.SA1137MessageFormat), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString SA1137Description = new LocalizableResourceString(nameof(ReadabilityResources.SA1137Description), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly string SA1137HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1137.md"; + + private static readonly DiagnosticDescriptor SA1137Descriptor = + new DiagnosticDescriptor(SA1137DiagnosticId, SA1137Title, SA1137MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, SA1137Description, SA1137HelpLink); + + private static readonly LocalizableString SA1138Title = new LocalizableResourceString(nameof(ReadabilityResources.SA1138Title), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString SA1138MessageFormat = new LocalizableResourceString(nameof(ReadabilityResources.SA1138MessageFormat), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly LocalizableString SA1138Description = new LocalizableResourceString(nameof(ReadabilityResources.SA1138Description), ReadabilityResources.ResourceManager, typeof(ReadabilityResources)); + private static readonly string SA1138HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1138.md"; + + private static readonly DiagnosticDescriptor SA1138Descriptor = + new DiagnosticDescriptor(SA1138DiagnosticId, SA1138Title, SA1138MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, SA1138Description, SA1138HelpLink); private static readonly Action CompilationStartAction = HandleCompilationStart; - private static readonly Action CompilationUnitAction = HandleCompilationUnit; - private static readonly Action NamespaceDeclarationAction = HandleNamespaceDeclaration; - private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; - private static readonly Action EnumDeclarationAction = HandleEnumDeclaration; - private static readonly Action MethodDeclarationAction = HandleMethodDeclaration; - private static readonly Action AccessorListAction = HandleAccessorList; - private static readonly Action VariableDeclarationAction = HandleVariableDeclaration; - private static readonly Action TypeParameterListAction = HandleTypeParameterList; - private static readonly Action BaseParameterListAction = HandleBaseParameterList; - private static readonly Action BaseArgumentListAction = HandleBaseArgumentList; - private static readonly Action AttributeListAction = HandleAttributeList; - private static readonly Action AttributeArgumentListAction = HandleAttributeArgumentList; - private static readonly Action BlockAction = HandleBlock; - private static readonly Action SwitchStatementAction = HandleSwitchStatement; - private static readonly Action InitializerExpressionAction = HandleInitializerExpression; - private static readonly Action AnonymousObjectCreationExpressionAction = HandleAnonymousObjectCreationExpression; +#pragma warning disable RS1008 // Avoid storing per-compilation data into the fields of a diagnostic analyzer. + private static readonly Action SyntaxTreeAction = HandleSyntaxTree; +#pragma warning restore RS1008 // Avoid storing per-compilation data into the fields of a diagnostic analyzer. /// public override ImmutableArray SupportedDiagnostics { get; } = - ImmutableArray.Create(Descriptor); + ImmutableArray.Create(SA1137Descriptor, SA1138Descriptor); /// public override void Initialize(AnalysisContext context) @@ -59,200 +62,13 @@ public override void Initialize(AnalysisContext context) private static void HandleCompilationStart(CompilationStartAnalysisContext context) { - context.RegisterSyntaxNodeActionHonorExclusions(CompilationUnitAction, SyntaxKind.CompilationUnit); - context.RegisterSyntaxNodeActionHonorExclusions(NamespaceDeclarationAction, SyntaxKind.NamespaceDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(EnumDeclarationAction, SyntaxKind.EnumDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(MethodDeclarationAction, SyntaxKind.MethodDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(AccessorListAction, SyntaxKind.AccessorList); - context.RegisterSyntaxNodeActionHonorExclusions(VariableDeclarationAction, SyntaxKind.VariableDeclaration); - context.RegisterSyntaxNodeActionHonorExclusions(TypeParameterListAction, SyntaxKind.TypeParameterList); - context.RegisterSyntaxNodeActionHonorExclusions(BaseParameterListAction, SyntaxKinds.BaseParameterList); - context.RegisterSyntaxNodeActionHonorExclusions(BaseArgumentListAction, SyntaxKinds.BaseArgumentList); - context.RegisterSyntaxNodeActionHonorExclusions(AttributeListAction, SyntaxKind.AttributeList); - context.RegisterSyntaxNodeActionHonorExclusions(AttributeArgumentListAction, SyntaxKind.AttributeArgumentList); - context.RegisterSyntaxNodeActionHonorExclusions(BlockAction, SyntaxKind.Block); - context.RegisterSyntaxNodeActionHonorExclusions(SwitchStatementAction, SyntaxKind.SwitchStatement); - context.RegisterSyntaxNodeActionHonorExclusions(InitializerExpressionAction, SyntaxKinds.InitializerExpression); - context.RegisterSyntaxNodeActionHonorExclusions(AnonymousObjectCreationExpressionAction, SyntaxKind.AnonymousObjectCreationExpression); - } - - private static void HandleCompilationUnit(SyntaxNodeAnalysisContext context) - { - var compilationUnit = (CompilationUnitSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - - elements.AddRange(compilationUnit.Externs); - elements.AddRange(compilationUnit.Usings); - elements.AddRange(compilationUnit.AttributeLists); - AddMembersAndAttributes(elements, compilationUnit.Members); - - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleNamespaceDeclaration(SyntaxNodeAnalysisContext context) - { - var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - - elements.AddRange(namespaceDeclaration.Externs); - elements.AddRange(namespaceDeclaration.Usings); - AddMembersAndAttributes(elements, namespaceDeclaration.Members); - - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context) - { - var typeDeclaration = (TypeDeclarationSyntax)context.Node; - - CheckElements(context, typeDeclaration.ConstraintClauses); - - var elements = ImmutableList.CreateBuilder(); - AddMembersAndAttributes(elements, typeDeclaration.Members); - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleEnumDeclaration(SyntaxNodeAnalysisContext context) - { - var enumDeclaration = (EnumDeclarationSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - foreach (EnumMemberDeclarationSyntax enumMemberDeclaration in enumDeclaration.Members) - { - elements.AddRange(enumMemberDeclaration.AttributeLists); - elements.Add(enumMemberDeclaration); - } - - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context) - { - var methodDeclaration = (MethodDeclarationSyntax)context.Node; - - CheckElements(context, methodDeclaration.ConstraintClauses); - } - - private static void HandleAccessorList(SyntaxNodeAnalysisContext context) - { - var accessorList = (AccessorListSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - AddMembersAndAttributes(elements, accessorList.Accessors); - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) - { - var variableDeclaration = (VariableDeclarationSyntax)context.Node; - CheckElements(context, variableDeclaration.Variables); + context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction); } - private static void HandleTypeParameterList(SyntaxNodeAnalysisContext context) + private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings) { - var typeParameterList = (TypeParameterListSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - AddMembersAndAttributes(elements, typeParameterList.Parameters); - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleBaseParameterList(SyntaxNodeAnalysisContext context) - { - var baseParameterList = (BaseParameterListSyntax)context.Node; - - var elements = ImmutableList.CreateBuilder(); - AddMembersAndAttributes(elements, baseParameterList.Parameters); - CheckElements(context, elements.ToImmutable()); - } - - private static void HandleBaseArgumentList(SyntaxNodeAnalysisContext context) - { - var baseArgumentList = (BaseArgumentListSyntax)context.Node; - - CheckElements(context, baseArgumentList.Arguments); - } - - private static void HandleAttributeList(SyntaxNodeAnalysisContext context) - { - var attributeList = (AttributeListSyntax)context.Node; - - CheckElements(context, attributeList.Attributes); - } - - private static void HandleAttributeArgumentList(SyntaxNodeAnalysisContext context) - { - var attributeArgumentList = (AttributeArgumentListSyntax)context.Node; - - CheckElements(context, attributeArgumentList.Arguments); - } - - private static void HandleBlock(SyntaxNodeAnalysisContext context) - { - var block = (BlockSyntax)context.Node; - - var statements = ImmutableList.CreateBuilder(); - var labeledStatements = ImmutableList.CreateBuilder(); - - foreach (var statement in block.Statements) - { - StatementSyntax statementToAlign = statement; - while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) - { - labeledStatements.Add(statementToAlign); - statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; - } - - statements.Add(statementToAlign); - } - - CheckElements(context, statements.ToImmutable()); - CheckElements(context, labeledStatements.ToImmutable()); - } - - private static void HandleSwitchStatement(SyntaxNodeAnalysisContext context) - { - var switchStatement = (SwitchStatementSyntax)context.Node; - - var labels = ImmutableList.CreateBuilder(); - var statements = ImmutableList.CreateBuilder(); - var labeledStatements = ImmutableList.CreateBuilder(); - foreach (SwitchSectionSyntax switchSection in switchStatement.Sections) - { - labels.AddRange(switchSection.Labels); - foreach (var statement in switchSection.Statements) - { - StatementSyntax statementToAlign = statement; - while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) - { - labeledStatements.Add(statementToAlign); - statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; - } - - statements.Add(statementToAlign); - } - } - - CheckElements(context, labels.ToImmutable()); - CheckElements(context, statements.ToImmutable()); - CheckElements(context, labeledStatements.ToImmutable()); - } - - private static void HandleInitializerExpression(SyntaxNodeAnalysisContext context) - { - var initializerExpression = (InitializerExpressionSyntax)context.Node; - - CheckElements(context, initializerExpression.Expressions); - } - - private static void HandleAnonymousObjectCreationExpression(SyntaxNodeAnalysisContext context) - { - var anonymousObjectCreationExpression = (AnonymousObjectCreationExpressionSyntax)context.Node; - - CheckElements(context, anonymousObjectCreationExpression.Initializers); + var walker = new IndentationWalker(context, compilation, settings); + walker.Visit(context.Tree.GetRoot(context.CancellationToken)); } private static void AddMembersAndAttributes(ImmutableList.Builder elements, SeparatedSyntaxList members) @@ -326,32 +142,46 @@ private static void AddMemberAndAttributes(ImmutableList.Builder ele elements.Add(member); } - private static void CheckElements(SyntaxNodeAnalysisContext context, SyntaxList elements) + private static void CheckElements(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, SyntaxList elements) where T : SyntaxNode { - if (elements.Count < 2) + if (!elements.Any()) + { + return; + } + + if (elements.Count == 1 && compilation.IsAnalyzerSuppressed(SA1138DiagnosticId)) { return; } - CheckElements(context, elements.ToImmutableList()); + CheckElements(context, compilation, settings, indentationLevel, elements.ToImmutableList()); } - private static void CheckElements(SyntaxNodeAnalysisContext context, SeparatedSyntaxList elements) + private static void CheckElements(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, SeparatedSyntaxList elements) where T : SyntaxNode { - if (elements.Count < 2) + if (!elements.Any()) + { + return; + } + + if (elements.Count == 1 && compilation.IsAnalyzerSuppressed(SA1138DiagnosticId)) { return; } - CheckElements(context, elements.ToImmutableList()); + CheckElements(context, compilation, settings, indentationLevel, elements.ToImmutableList()); } - private static void CheckElements(SyntaxNodeAnalysisContext context, ImmutableList elements) + private static void CheckElements(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, ImmutableList elements) where T : SyntaxNode { - if (elements.Count < 2) + DiagnosticDescriptor descriptor = SA1137Descriptor; + + bool enableAbsoluteIndentationAnalysis = !compilation.IsAnalyzerSuppressed(SA1138DiagnosticId); + + if (elements.IsEmpty || (elements.Count == 1 && !enableAbsoluteIndentationAnalysis)) { return; } @@ -363,7 +193,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl return firstToken.IsMissingOrDefault() || !firstToken.IsFirstInLine(allowNonWhitespaceTrivia: false); }); - if (elements.Count < 2) + if (elements.IsEmpty || (elements.Count == 1 && !enableAbsoluteIndentationAnalysis)) { return; } @@ -387,9 +217,29 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl if (first) { - expectedIndentation = indentation; + if (enableAbsoluteIndentationAnalysis && indentationLevel != null) + { + descriptor = SA1138Descriptor; + if (settings.Indentation.UseTabs) + { + expectedIndentation = new string('\t', indentationLevel.Value); + } + else + { + expectedIndentation = new string(' ', settings.Indentation.IndentationSize * indentationLevel.Value); + } + } + else + { + expectedIndentation = indentation; + } + first = false; - continue; + + if (!enableAbsoluteIndentationAnalysis) + { + continue; + } } if (string.Equals(expectedIndentation, indentation, StringComparison.Ordinal)) @@ -409,7 +259,7 @@ private static void CheckElements(SyntaxNodeAnalysisContext context, Immutabl } ImmutableDictionary properties = ImmutableDictionary.Create().SetItem(ExpectedIndentationKey, expectedIndentation); - context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, properties)); + context.ReportDiagnostic(Diagnostic.Create(descriptor, location, properties)); } } @@ -428,5 +278,571 @@ private static SyntaxToken GetFirstTokenForAnalysis(SyntaxNode node) return firstToken; } + + private class IndentationWalker : CSharpSyntaxWalker + { + private readonly SyntaxTreeAnalysisContext context; + private readonly Compilation compilation; + private readonly StyleCopSettings settings; + + private int indentationLevel; + private int unknownIndentationLevel; + + public IndentationWalker(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings) + { + this.context = context; + this.compilation = compilation; + this.settings = settings; + } + + private int? IndentationLevel + { + get + { + if (this.unknownIndentationLevel > 0) + { + return null; + } + + return this.indentationLevel; + } + } + + private int? BlockIndentation + { + get + { + switch (this.settings.Indentation.IndentBlock) + { + case true: + return 1; + + case false: + return 0; + + default: + return null; + } + } + } + + private int? LabelAdjustment + { + get + { + switch (this.settings.Indentation.LabelPositioning) + { + case LabelPositioning.LeftMost: + return -this.IndentationLevel; + + case LabelPositioning.OneLess: + return this.IndentationLevel > 0 ? -1 : 0; + + case LabelPositioning.NoIndent: + return 0; + + default: + // Disable indentation check for labels + return null; + } + } + } + + private int? SwitchStatementAdjustment + { + get + { + switch (this.settings.Indentation.IndentSwitchCaseSection) + { + case true: + return 1; + + case false: + return 0; + + default: + return null; + } + } + } + + public override void DefaultVisit(SyntaxNode node) + { + this.unknownIndentationLevel++; + try + { + base.DefaultVisit(node); + } + finally + { + this.unknownIndentationLevel--; + } + } + + public override void VisitCompilationUnit(CompilationUnitSyntax node) + { + using (this.AdjustIndentation(0)) + { + this.AnalyzeCompilationUnit(node); + base.VisitCompilationUnit(node); + } + } + + public override void VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeNamespaceDeclaration(node); + base.VisitNamespaceDeclaration(node); + } + } + + public override void VisitClassDeclaration(ClassDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeTypeDeclaration(node); + base.VisitClassDeclaration(node); + } + } + + public override void VisitStructDeclaration(StructDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeTypeDeclaration(node); + base.VisitStructDeclaration(node); + } + } + + public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeTypeDeclaration(node); + base.VisitInterfaceDeclaration(node); + } + } + + public override void VisitEnumDeclaration(EnumDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeEnumDeclaration(node); + base.VisitEnumDeclaration(node); + } + } + + public override void VisitMethodDeclaration(MethodDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeMethodDeclaration(node); + base.VisitMethodDeclaration(node); + } + } + + public override void VisitAccessorList(AccessorListSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeAccessorList(node); + base.VisitAccessorList(node); + } + } + + public override void VisitVariableDeclaration(VariableDeclarationSyntax node) + { + this.AnalyzeVariableDeclaration(node); + base.VisitVariableDeclaration(node); + } + + public override void VisitTypeParameterList(TypeParameterListSyntax node) + { + using (this.AdjustIndentation(0)) + { + this.AnalyzeTypeParameterList(node); + base.VisitTypeParameterList(node); + } + } + + public override void VisitParameterList(ParameterListSyntax node) + { + this.AnalyzeBaseParameterList(node); + base.VisitParameterList(node); + } + + public override void VisitBracketedParameterList(BracketedParameterListSyntax node) + { + this.AnalyzeBaseParameterList(node); + base.VisitBracketedParameterList(node); + } + + public override void VisitArgumentList(ArgumentListSyntax node) + { + this.AnalyzeBaseArgumentList(node); + base.VisitArgumentList(node); + } + + public override void VisitBracketedArgumentList(BracketedArgumentListSyntax node) + { + this.AnalyzeBaseArgumentList(node); + base.VisitBracketedArgumentList(node); + } + + public override void VisitAttributeList(AttributeListSyntax node) + { + using (this.AdjustIndentation(1)) + { + this.AnalyzeAttributeList(node); + base.VisitAttributeList(node); + } + } + + public override void VisitAttributeArgumentList(AttributeArgumentListSyntax node) + { + this.AnalyzeAttributeArgumentList(node); + base.VisitAttributeArgumentList(node); + } + + public override void VisitBlock(BlockSyntax node) + { + int? adjustment; + if (node.Parent.IsKind(SyntaxKind.Block)) + { + // The current indentation level is the level of the block itself + adjustment = this.BlockIndentation; + } + else + { + // The parent indented by 1; update to match the BlockIndentation value + adjustment = this.BlockIndentation - 1; + } + + using (this.AdjustIndentation(adjustment)) + { + this.AnalyzeBlock(node); + base.VisitBlock(node); + } + } + + public override void VisitSwitchStatement(SwitchStatementSyntax node) + { + int? indentationAmount = + this.settings.Indentation.IndentSwitchSection == null + ? default(int?) + : this.settings.Indentation.IndentSwitchSection == true ? 1 : 0; + + using (this.AdjustIndentation(indentationAmount)) + { + this.AnalyzeSwitchStatement(node); + base.VisitSwitchStatement(node); + } + } + + public override void VisitInitializerExpression(InitializerExpressionSyntax node) + { + this.AnalyzeInitializerExpression(node); + base.VisitInitializerExpression(node); + } + + public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node) + { + this.AnalyzeAnonymousObjectCreationExpression(node); + base.VisitAnonymousObjectCreationExpression(node); + } + + public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) + { + using (this.AdjustIndentation(0)) + { + base.VisitAccessorDeclaration(node); + } + } + + public override void VisitLabeledStatement(LabeledStatementSyntax node) + { + using (this.AdjustIndentation(0)) + { + base.VisitLabeledStatement(node); + } + } + + public override void VisitCheckedStatement(CheckedStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitCheckedStatement(node); + } + } + + public override void VisitDoStatement(DoStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitDoStatement(node); + } + } + + public override void VisitFixedStatement(FixedStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitFixedStatement(node); + } + } + + public override void VisitForEachStatement(ForEachStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitForEachStatement(node); + } + } + + public override void VisitForStatement(ForStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitForStatement(node); + } + } + + public override void VisitIfStatement(IfStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitIfStatement(node); + } + } + + public override void VisitLockStatement(LockStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitLockStatement(node); + } + } + + public override void VisitUsingStatement(UsingStatementSyntax node) + { + // Allow consecutive using statements without nesting indentation. + using (this.AdjustIndentation(node.Statement.IsKind(SyntaxKind.UsingStatement) ? 0 : 1)) + { + base.VisitUsingStatement(node); + } + } + + public override void VisitWhileStatement(WhileStatementSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitWhileStatement(node); + } + } + + private void AnalyzeCompilationUnit(CompilationUnitSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + + elements.AddRange(node.Externs); + elements.AddRange(node.Usings); + elements.AddRange(node.AttributeLists); + AddMembersAndAttributes(elements, node.Members); + + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeNamespaceDeclaration(NamespaceDeclarationSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + + elements.AddRange(node.Externs); + elements.AddRange(node.Usings); + AddMembersAndAttributes(elements, node.Members); + + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeTypeDeclaration(TypeDeclarationSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.ConstraintClauses); + + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, node.Members); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeEnumDeclaration(EnumDeclarationSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + foreach (EnumMemberDeclarationSyntax enumMemberDeclaration in node.Members) + { + elements.AddRange(enumMemberDeclaration.AttributeLists); + elements.Add(enumMemberDeclaration); + } + + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeMethodDeclaration(MethodDeclarationSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.ConstraintClauses); + } + + private void AnalyzeAccessorList(AccessorListSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, node.Accessors); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeVariableDeclaration(VariableDeclarationSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Variables); + } + + private void AnalyzeTypeParameterList(TypeParameterListSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, node.Parameters); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeBaseParameterList(BaseParameterListSyntax node) + { + var elements = ImmutableList.CreateBuilder(); + AddMembersAndAttributes(elements, node.Parameters); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); + } + + private void AnalyzeBaseArgumentList(BaseArgumentListSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Arguments); + } + + private void AnalyzeAttributeList(AttributeListSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Attributes); + } + + private void AnalyzeAttributeArgumentList(AttributeArgumentListSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Arguments); + } + + private void AnalyzeBlock(BlockSyntax node) + { + var statements = ImmutableList.CreateBuilder(); + var labeledStatements = ImmutableList.CreateBuilder(); + + foreach (var statement in node.Statements) + { + StatementSyntax statementToAlign = statement; + while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) + { + labeledStatements.Add(statementToAlign); + statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; + } + + statements.Add(statementToAlign); + } + + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, statements.ToImmutable()); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel + this.LabelAdjustment, labeledStatements.ToImmutable()); + } + + private void AnalyzeSwitchStatement(SwitchStatementSyntax node) + { + var labels = ImmutableList.CreateBuilder(); + var statements = ImmutableList.CreateBuilder(); + var labeledStatements = ImmutableList.CreateBuilder(); + foreach (SwitchSectionSyntax switchSection in node.Sections) + { + labels.AddRange(switchSection.Labels); + foreach (var statement in switchSection.Statements) + { + StatementSyntax statementToAlign = statement; + while (statementToAlign.IsKind(SyntaxKind.LabeledStatement)) + { + labeledStatements.Add(statementToAlign); + statementToAlign = ((LabeledStatementSyntax)statementToAlign).Statement; + } + + statements.Add(statementToAlign); + } + } + + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, labels.ToImmutable()); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel + this.SwitchStatementAdjustment, statements.ToImmutable()); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel + this.SwitchStatementAdjustment + this.LabelAdjustment, labeledStatements.ToImmutable()); + } + + private void AnalyzeInitializerExpression(InitializerExpressionSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Expressions); + } + + private void AnalyzeAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Initializers); + } + + private IndentationAdjuster AdjustIndentation(int? levels) + { + return new IndentationAdjuster(this, levels); + } + + private struct IndentationAdjuster : IDisposable + { + private readonly IndentationWalker walker; + private readonly int? levels; + + public IndentationAdjuster(IndentationWalker walker, int? levels) + { + this.walker = walker; + this.levels = levels; + + if (levels != null) + { + IncreaseIndentationLevel(walker, levels.Value); + } + } + + public void Dispose() + { + if (this.levels != null) + { + DecreaseIndentationLevel(this.walker, this.levels.Value); + } + } + + private static void IncreaseIndentationLevel(IndentationWalker walker, int levels) + { + if (walker.IndentationLevel == null) + { + return; + } + + Debug.Assert(walker.indentationLevel >= 0, "Assertion failed: walker.indentationLevel >= 0"); + Debug.Assert(walker.unknownIndentationLevel == 0, "Assertion failed: walker.unknownIndentationLevel == 0"); + walker.indentationLevel += levels; + walker.unknownIndentationLevel--; + } + + private static void DecreaseIndentationLevel(IndentationWalker walker, int levels) + { + if (walker.IndentationLevel == null) + { + return; + } + + Debug.Assert(walker.indentationLevel >= levels, "Assertion failed: walker.indentationLevel >= levels"); + Debug.Assert(walker.unknownIndentationLevel == -1, "Assertion failed: walker.unknownIndentationLevel == -1"); + walker.indentationLevel -= levels; + walker.unknownIndentationLevel++; + } + } + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/IndentationSettings.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/IndentationSettings.cs index 38e0f1512..5eef0ca7e 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/IndentationSettings.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/IndentationSettings.cs @@ -26,6 +26,30 @@ internal class IndentationSettings [JsonProperty("useTabs", DefaultValueHandling = DefaultValueHandling.Include)] private bool useTabs; + /// + /// This is the backing field for the property. + /// + [JsonProperty("indentBlock", DefaultValueHandling = DefaultValueHandling.Include)] + private bool? indentBlock; + + /// + /// This is the backing field for the property. + /// + [JsonProperty("indentSwitchSection", DefaultValueHandling = DefaultValueHandling.Include)] + private bool? indentSwitchSection; + + /// + /// This is the backing field for the property. + /// + [JsonProperty("indentSwitchCaseSection", DefaultValueHandling = DefaultValueHandling.Include)] + private bool? indentSwitchCaseSection; + + /// + /// This is the backing field for the property. + /// + [JsonProperty("labelPositioning", DefaultValueHandling = DefaultValueHandling.Include)] + private LabelPositioning? labelPositioning; + /// /// Initializes a new instance of the class during JSON deserialization. /// @@ -35,6 +59,11 @@ protected internal IndentationSettings() this.indentationSize = 4; this.tabSize = 4; this.useTabs = false; + + this.indentBlock = true; + this.indentSwitchSection = true; + this.indentSwitchCaseSection = true; + this.labelPositioning = ObjectModel.LabelPositioning.OneLess; } public int IndentationSize => @@ -45,5 +74,17 @@ protected internal IndentationSettings() public bool UseTabs => this.useTabs; + + public bool? IndentBlock => + this.indentBlock; + + public bool? IndentSwitchSection => + this.indentSwitchSection; + + public bool? IndentSwitchCaseSection => + this.indentSwitchCaseSection; + + public LabelPositioning? LabelPositioning => + this.labelPositioning; } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/LabelPositioning.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/LabelPositioning.cs new file mode 100644 index 000000000..94c8655c7 --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/LabelPositioning.cs @@ -0,0 +1,23 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + +namespace StyleCop.Analyzers.Settings.ObjectModel +{ + internal enum LabelPositioning + { + /// + /// Placed in the Zeroth column of the text editor. + /// + LeftMost, + + /// + /// Placed at one less indent to the current context. + /// + OneLess, + + /// + /// Placed at the same indent as the current context. + /// + NoIndent, + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json index d2aa0fb63..7e8c6bb96 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json @@ -31,6 +31,59 @@ "description": "Specifies whether indentation should use hard tabs instead of spaces.", "type": "boolean", "default": false + }, + "indentBlock": { + "description": "Specifies the indentation behavior for the contents of blocks.\r\ntrue: Indent the contents of blocks.\r\nfalse: Do not indent the contents of blocks.\r\nnull: Do not check the absolute indentation of blocks.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": true + }, + "indentSwitchSection": { + "description": "Specifies the indentation behavior for case contents.\r\ntrue: Indent case labels within a switch statement.\r\nfalse: Do not indent case labels within a switch statement.\r\nnull: Do not check the absolute indentation of switch section labels.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": true + }, + "indentSwitchCaseSection": { + "description": "Specifies the indentation behavior for case labels.\r\ntrue: Indent the contents of a switch section.\r\nfalse: Do not indent the contents of a switch section.\r\nnull: Do not check the absolute indentation of switch section contents.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": true + }, + "labelPositioning": { + "description": "Specifies the indentation behavior for labels.\r\nleftMost: Labels are placed in the left-most column.\r\noneLess: Labels are indented one less than other statements.\r\nnoIndent: Labels are indented in the same manner as other statements.\r\nnull: Do not check the absolute indentation of labels.", + "anyOf": [ + { + "type": "string", + "enum": [ + "leftMost", + "oneLess", + "noIndent" + ] + }, + { + "type": "null" + } + ], + "default": "oneLess" } } }, diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj b/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj index 7fa557db1..787cfbcdc 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj +++ b/StyleCop.Analyzers/StyleCop.Analyzers/StyleCop.Analyzers.csproj @@ -274,6 +274,7 @@ + From 5f33d6289ec21c509aa7fa197549f9b13210b243 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 9 Jan 2016 12:30:18 -0600 Subject: [PATCH 30/47] Fix indentation handling of base method and property declarations --- ...137ElementsShouldHaveTheSameIndentation.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 234c578ec..c91bb5af7 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -552,6 +552,62 @@ public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreat base.VisitAnonymousObjectCreationExpression(node); } + public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitConstructorDeclaration(node); + } + } + + public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitDestructorDeclaration(node); + } + } + + public override void VisitOperatorDeclaration(OperatorDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitOperatorDeclaration(node); + } + } + + public override void VisitConversionOperatorDeclaration(ConversionOperatorDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitConversionOperatorDeclaration(node); + } + } + + public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitPropertyDeclaration(node); + } + } + + public override void VisitEventDeclaration(EventDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitEventDeclaration(node); + } + } + + public override void VisitIndexerDeclaration(IndexerDeclarationSyntax node) + { + using (this.AdjustIndentation(1)) + { + base.VisitIndexerDeclaration(node); + } + } + public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) { using (this.AdjustIndentation(0)) From 9860c7e4982ef681643b4fe3ff2c0957cd32ed55 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 9 Jan 2016 12:30:41 -0600 Subject: [PATCH 31/47] Fix indentation handling for blocks inside else clauses --- .../SA1137ElementsShouldHaveTheSameIndentation.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index c91bb5af7..6fabea8f7 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -672,6 +672,15 @@ public override void VisitIfStatement(IfStatementSyntax node) } } + public override void VisitElseClause(ElseClauseSyntax node) + { + // This clause inherits the indentation from the if statement + using (this.AdjustIndentation(0)) + { + base.VisitElseClause(node); + } + } + public override void VisitLockStatement(LockStatementSyntax node) { using (this.AdjustIndentation(1)) From 23417d6c0990cc3fdc7438aaddf4ebd1cf07a6f8 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 9 Jan 2016 13:38:20 -0600 Subject: [PATCH 32/47] Fix handling of curly braces and statements without braces --- .../StyleCop.Analyzers/Helpers/TokenHelper.cs | 2 +- ...137ElementsShouldHaveTheSameIndentation.cs | 359 +++++++++++++++++- 2 files changed, 352 insertions(+), 9 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs index 6e7ebb733..8aad5f521 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/TokenHelper.cs @@ -26,7 +26,7 @@ internal static bool IsFirstInLine(this SyntaxToken token, bool allowNonWhitespa var fullLineSpan = token.SyntaxTree.GetLineSpan(token.FullSpan); bool firstInLine; - if (token.SyntaxTree == null || fullLineSpan.StartLinePosition.Character == 0) + if (fullLineSpan.StartLinePosition.Character == 0) { firstInLine = true; } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 6fabea8f7..31e48717a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -263,6 +263,83 @@ private static void CheckElements(SyntaxTreeAnalysisContext context, Compilat } } + private static void CheckTokens(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, ImmutableArray tokens) + { + DiagnosticDescriptor descriptor = SA1137Descriptor; + + bool enableAbsoluteIndentationAnalysis = !compilation.IsAnalyzerSuppressed(SA1138DiagnosticId); + + if (tokens.IsEmpty || (tokens.Length == 1 && !enableAbsoluteIndentationAnalysis)) + { + return; + } + + tokens = tokens.RemoveAll( + token => + { + return token.IsMissingOrDefault() || !token.IsFirstInLine(); + }); + + if (tokens.IsEmpty || (tokens.Length == 1 && !enableAbsoluteIndentationAnalysis)) + { + return; + } + + bool first = true; + string expectedIndentation = null; + foreach (SyntaxToken token in tokens) + { + SyntaxTrivia indentationTrivia = token.LeadingTrivia.LastOrDefault(); + string indentation = indentationTrivia.IsKind(SyntaxKind.WhitespaceTrivia) ? indentationTrivia.ToString() : string.Empty; + + if (first) + { + if (enableAbsoluteIndentationAnalysis && indentationLevel != null) + { + descriptor = SA1138Descriptor; + if (settings.Indentation.UseTabs) + { + expectedIndentation = new string('\t', indentationLevel.Value); + } + else + { + expectedIndentation = new string(' ', settings.Indentation.IndentationSize * indentationLevel.Value); + } + } + else + { + expectedIndentation = indentation; + } + + first = false; + + if (!enableAbsoluteIndentationAnalysis) + { + continue; + } + } + + if (string.Equals(expectedIndentation, indentation, StringComparison.Ordinal)) + { + // This handles the case where elements are indented properly + continue; + } + + Location location; + if (indentation.Length == 0) + { + location = token.GetLocation(); + } + else + { + location = indentationTrivia.GetLocation(); + } + + ImmutableDictionary properties = ImmutableDictionary.Create().SetItem(ExpectedIndentationKey, expectedIndentation); + context.ReportDiagnostic(Diagnostic.Create(descriptor, location, properties)); + } + } + private static SyntaxToken GetFirstTokenForAnalysis(SyntaxNode node) { SyntaxToken firstToken = node.GetFirstToken(); @@ -326,6 +403,24 @@ private int? BlockIndentation } } + private int? SwitchSectionIndentation + { + get + { + switch (this.settings.Indentation.IndentSwitchSection) + { + case true: + return 1; + + case false: + return 0; + + default: + return null; + } + } + } + private int? LabelAdjustment { get @@ -444,7 +539,7 @@ public override void VisitMethodDeclaration(MethodDeclarationSyntax node) public override void VisitAccessorList(AccessorListSyntax node) { - using (this.AdjustIndentation(1)) + using (this.AdjustIndentation(0)) { this.AnalyzeAccessorList(node); base.VisitAccessorList(node); @@ -528,12 +623,7 @@ public override void VisitBlock(BlockSyntax node) public override void VisitSwitchStatement(SwitchStatementSyntax node) { - int? indentationAmount = - this.settings.Indentation.IndentSwitchSection == null - ? default(int?) - : this.settings.Indentation.IndentSwitchSection == true ? 1 : 0; - - using (this.AdjustIndentation(indentationAmount)) + using (this.AdjustIndentation(this.SwitchSectionIndentation)) { this.AnalyzeSwitchStatement(node); base.VisitSwitchStatement(node); @@ -556,6 +646,7 @@ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax no { using (this.AdjustIndentation(1)) { + this.AnalyzeBaseMethodDeclaration(node); base.VisitConstructorDeclaration(node); } } @@ -564,6 +655,7 @@ public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node { using (this.AdjustIndentation(1)) { + this.AnalyzeBaseMethodDeclaration(node); base.VisitDestructorDeclaration(node); } } @@ -572,6 +664,7 @@ public override void VisitOperatorDeclaration(OperatorDeclarationSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeBaseMethodDeclaration(node); base.VisitOperatorDeclaration(node); } } @@ -580,6 +673,7 @@ public override void VisitConversionOperatorDeclaration(ConversionOperatorDeclar { using (this.AdjustIndentation(1)) { + this.AnalyzeBaseMethodDeclaration(node); base.VisitConversionOperatorDeclaration(node); } } @@ -588,6 +682,7 @@ public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeBasePropertyDeclaration(node); base.VisitPropertyDeclaration(node); } } @@ -596,6 +691,7 @@ public override void VisitEventDeclaration(EventDeclarationSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeBasePropertyDeclaration(node); base.VisitEventDeclaration(node); } } @@ -604,14 +700,16 @@ public override void VisitIndexerDeclaration(IndexerDeclarationSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeBasePropertyDeclaration(node); base.VisitIndexerDeclaration(node); } } public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node) { - using (this.AdjustIndentation(0)) + using (this.AdjustIndentation(1)) { + this.AnalyzeAccessorDeclaration(node); base.VisitAccessorDeclaration(node); } } @@ -628,6 +726,7 @@ public override void VisitCheckedStatement(CheckedStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeCheckedStatement(node); base.VisitCheckedStatement(node); } } @@ -636,6 +735,7 @@ public override void VisitDoStatement(DoStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeDoStatement(node); base.VisitDoStatement(node); } } @@ -644,6 +744,7 @@ public override void VisitFixedStatement(FixedStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeFixedStatement(node); base.VisitFixedStatement(node); } } @@ -652,6 +753,7 @@ public override void VisitForEachStatement(ForEachStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeForEachStatement(node); base.VisitForEachStatement(node); } } @@ -660,6 +762,7 @@ public override void VisitForStatement(ForStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeForStatement(node); base.VisitForStatement(node); } } @@ -668,6 +771,7 @@ public override void VisitIfStatement(IfStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeIfStatement(node); base.VisitIfStatement(node); } } @@ -685,6 +789,7 @@ public override void VisitLockStatement(LockStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeLockStatement(node); base.VisitLockStatement(node); } } @@ -694,6 +799,7 @@ public override void VisitUsingStatement(UsingStatementSyntax node) // Allow consecutive using statements without nesting indentation. using (this.AdjustIndentation(node.Statement.IsKind(SyntaxKind.UsingStatement) ? 0 : 1)) { + this.AnalyzeUsingStatement(node); base.VisitUsingStatement(node); } } @@ -702,6 +808,7 @@ public override void VisitWhileStatement(WhileStatementSyntax node) { using (this.AdjustIndentation(1)) { + this.AnalyzeWhileStatement(node); base.VisitWhileStatement(node); } } @@ -720,6 +827,9 @@ private void AnalyzeCompilationUnit(CompilationUnitSyntax node) private void AnalyzeNamespaceDeclaration(NamespaceDeclarationSyntax node) { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.OpenBraceToken, node.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + var elements = ImmutableList.CreateBuilder(); elements.AddRange(node.Externs); @@ -731,6 +841,9 @@ private void AnalyzeNamespaceDeclaration(NamespaceDeclarationSyntax node) private void AnalyzeTypeDeclaration(TypeDeclarationSyntax node) { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.OpenBraceToken, node.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.ConstraintClauses); var elements = ImmutableList.CreateBuilder(); @@ -740,6 +853,9 @@ private void AnalyzeTypeDeclaration(TypeDeclarationSyntax node) private void AnalyzeEnumDeclaration(EnumDeclarationSyntax node) { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.OpenBraceToken, node.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + var elements = ImmutableList.CreateBuilder(); foreach (EnumMemberDeclarationSyntax enumMemberDeclaration in node.Members) { @@ -750,11 +866,30 @@ private void AnalyzeEnumDeclaration(EnumDeclarationSyntax node) CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); } + private void AnalyzeBaseMethodDeclaration(BaseMethodDeclarationSyntax node) + { + if (node.Body != null) + { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.Body.OpenBraceToken, node.Body.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + } + private void AnalyzeMethodDeclaration(MethodDeclarationSyntax node) { + this.AnalyzeBaseMethodDeclaration(node); CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.ConstraintClauses); } + private void AnalyzeBasePropertyDeclaration(BasePropertyDeclarationSyntax node) + { + if (node.AccessorList != null) + { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.AccessorList.OpenBraceToken, node.AccessorList.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + } + private void AnalyzeAccessorList(AccessorListSyntax node) { var elements = ImmutableList.CreateBuilder(); @@ -762,6 +897,15 @@ private void AnalyzeAccessorList(AccessorListSyntax node) CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, elements.ToImmutable()); } + private void AnalyzeAccessorDeclaration(AccessorDeclarationSyntax node) + { + if (node.Body != null) + { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.Body.OpenBraceToken, node.Body.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + } + private void AnalyzeVariableDeclaration(VariableDeclarationSyntax node) { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Variables); @@ -813,12 +957,20 @@ private void AnalyzeBlock(BlockSyntax node) statements.Add(statementToAlign); } + if (node.Parent.IsKind(SyntaxKind.Block)) + { + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - this.BlockIndentation, ImmutableArray.Create(node.OpenBraceToken, node.CloseBraceToken)); + } + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, statements.ToImmutable()); CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel + this.LabelAdjustment, labeledStatements.ToImmutable()); } private void AnalyzeSwitchStatement(SwitchStatementSyntax node) { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.OpenBraceToken, node.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - this.SwitchSectionIndentation, tokens); + var labels = ImmutableList.CreateBuilder(); var statements = ImmutableList.CreateBuilder(); var labeledStatements = ImmutableList.CreateBuilder(); @@ -843,6 +995,197 @@ private void AnalyzeSwitchStatement(SwitchStatementSyntax node) CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel + this.SwitchStatementAdjustment + this.LabelAdjustment, labeledStatements.ToImmutable()); } + private void AnalyzeCheckedStatement(CheckedStatementSyntax node) + { + if (node.Block != null) + { + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.Block.OpenBraceToken, node.Block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + } + + private void AnalyzeDoStatement(DoStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken, node.WhileKeyword); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + + private void AnalyzeFixedStatement(FixedStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + + private void AnalyzeForEachStatement(ForEachStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + + private void AnalyzeForStatement(ForStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + + private void AnalyzeIfStatement(IfStatementSyntax node) + { + if (node.Parent.IsKind(SyntaxKind.ElseClause)) + { + // Already checked. + return; + } + + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(6); + IfStatementSyntax current = node; + while (current != null) + { + builder.Add(current.IfKeyword); + if (current.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)current.Statement; + builder.Add(block.OpenBraceToken); + builder.Add(block.CloseBraceToken); + } + else if (current.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Statement)); + } + + if (current.Else != null) + { + builder.Add(current.Else.ElseKeyword); + if (current.Else.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)current.Else.Statement; + builder.Add(block.OpenBraceToken); + builder.Add(block.CloseBraceToken); + + current = null; + } + else if (current.Else.Statement.IsKind(SyntaxKind.IfStatement)) + { + current = (IfStatementSyntax)current.Else.Statement; + } + else + { + if (current.Else.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Else.Statement)); + } + + current = null; + } + } + else + { + current = null; + } + } + + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, builder.ToImmutable()); + } + + private void AnalyzeLockStatement(LockStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + + private void AnalyzeUsingStatement(UsingStatementSyntax node) + { + if (node.Parent.IsKind(SyntaxKind.UsingStatement)) + { + // Already checked. + return; + } + + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(3); + + UsingStatementSyntax current = node; + while (current != null) + { + builder.Add(current.UsingKeyword); + if (current.Statement.IsKind(SyntaxKind.UsingStatement)) + { + current = (UsingStatementSyntax)current.Statement; + continue; + } + else if (current.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)current.Statement; + builder.Add(block.OpenBraceToken); + builder.Add(block.CloseBraceToken); + current = null; + } + else + { + if (current.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Statement)); + } + + current = null; + } + } + + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, builder.ToImmutable()); + } + + private void AnalyzeWhileStatement(WhileStatementSyntax node) + { + if (node.Statement.IsKind(SyntaxKind.Block)) + { + BlockSyntax block = (BlockSyntax)node.Statement; + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + } + else if (node.Statement != null) + { + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); + } + } + private void AnalyzeInitializerExpression(InitializerExpressionSyntax node) { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, node.Expressions); From 3549addacadee246d67df020da2c73abfcfccd46 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 9 Jan 2016 13:49:47 -0600 Subject: [PATCH 33/47] Fix errors running the SA1137 unit tests --- .../ReadabilityRules/SA1137UnitTests.cs | 258 +++++++++--------- 1 file changed, 135 insertions(+), 123 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index b5af1a552..48180e4bb 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -135,13 +135,13 @@ class MyAttribute : Attribute {{ }} DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(12, 1), - this.CSharpDiagnostic().WithLocation(18, 1), - this.CSharpDiagnostic().WithLocation(24, 1), - this.CSharpDiagnostic().WithLocation(25, 1), - this.CSharpDiagnostic().WithLocation(33, 1), - this.CSharpDiagnostic().WithLocation(41, 1), - this.CSharpDiagnostic().WithLocation(48, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(33, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(48, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -212,9 +212,9 @@ public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(17, 1), - this.CSharpDiagnostic().WithLocation(23, 1), - this.CSharpDiagnostic().WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(24, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -261,10 +261,10 @@ void Z2(){methodBody} DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(5, 1), - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(12, 1), - this.CSharpDiagnostic().WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -376,11 +376,11 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(14, 1), - this.CSharpDiagnostic().WithLocation(22, 1), - this.CSharpDiagnostic().WithLocation(28, 1), - this.CSharpDiagnostic().WithLocation(36, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(28, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(36, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -450,11 +450,11 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(5, 1), - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(13, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -528,9 +528,9 @@ void TypeWithMultipleConstraints2() DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(25, 1), - this.CSharpDiagnostic().WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(26, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -608,11 +608,11 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(24, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -702,11 +702,11 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(22, 1), - this.CSharpDiagnostic().WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -784,11 +784,11 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(24, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -911,18 +911,18 @@ void MethodName() DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(8, 1), - this.CSharpDiagnostic().WithLocation(12, 1), - this.CSharpDiagnostic().WithLocation(13, 1), - this.CSharpDiagnostic().WithLocation(17, 1), - this.CSharpDiagnostic().WithLocation(18, 1), - this.CSharpDiagnostic().WithLocation(22, 1), - this.CSharpDiagnostic().WithLocation(23, 1), - this.CSharpDiagnostic().WithLocation(29, 1), - this.CSharpDiagnostic().WithLocation(30, 1), - this.CSharpDiagnostic().WithLocation(34, 1), - this.CSharpDiagnostic().WithLocation(35, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(34, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(35, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -987,10 +987,10 @@ class Container DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1032,10 +1032,10 @@ void ZeroAlignment( DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1083,10 +1083,10 @@ int this[ DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(14, 1), - this.CSharpDiagnostic().WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1128,10 +1128,10 @@ int ZeroAlignment(int x, int y, int z) => ZeroAlignment( DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1179,10 +1179,10 @@ class Container2 DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(6, 1), - this.CSharpDiagnostic().WithLocation(7, 1), - this.CSharpDiagnostic().WithLocation(14, 1), - this.CSharpDiagnostic().WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1250,10 +1250,10 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(15, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1335,10 +1335,10 @@ public MyAttribute(int value) { } DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(15, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1395,7 +1395,7 @@ void MethodName() label3: while (true) - { + { label4a: label4b: int x; @@ -1403,25 +1403,29 @@ void MethodName() label5a: label5b: int y; - } + } } } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(12, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(17, 1), - this.CSharpDiagnostic().WithLocation(20, 1), - this.CSharpDiagnostic().WithLocation(23, 1), - this.CSharpDiagnostic().WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(26, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] @@ -1512,21 +1516,23 @@ void MethodName() DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(14, 1), - this.CSharpDiagnostic().WithLocation(16, 1), - this.CSharpDiagnostic().WithLocation(17, 1), - this.CSharpDiagnostic().WithLocation(18, 1), - this.CSharpDiagnostic().WithLocation(19, 1), - this.CSharpDiagnostic().WithLocation(23, 1), - this.CSharpDiagnostic().WithLocation(25, 1), - this.CSharpDiagnostic().WithLocation(26, 1), - this.CSharpDiagnostic().WithLocation(27, 1), - this.CSharpDiagnostic().WithLocation(28, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(28, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] @@ -1814,22 +1820,22 @@ struct StructName DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(12, 1), - this.CSharpDiagnostic().WithLocation(20, 1), - this.CSharpDiagnostic().WithLocation(21, 1), - this.CSharpDiagnostic().WithLocation(29, 1), - this.CSharpDiagnostic().WithLocation(30, 1), - this.CSharpDiagnostic().WithLocation(38, 1), - this.CSharpDiagnostic().WithLocation(39, 1), - this.CSharpDiagnostic().WithLocation(49, 1), - this.CSharpDiagnostic().WithLocation(50, 1), - this.CSharpDiagnostic().WithLocation(58, 1), - this.CSharpDiagnostic().WithLocation(59, 1), - this.CSharpDiagnostic().WithLocation(67, 1), - this.CSharpDiagnostic().WithLocation(68, 1), - this.CSharpDiagnostic().WithLocation(76, 1), - this.CSharpDiagnostic().WithLocation(77, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(38, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(39, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(49, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(50, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(58, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(59, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(67, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(68, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(76, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(77, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1929,10 +1935,10 @@ void ZeroAlignmentMethod() DiagnosticResult[] expected = { - this.CSharpDiagnostic().WithLocation(10, 1), - this.CSharpDiagnostic().WithLocation(11, 1), - this.CSharpDiagnostic().WithLocation(21, 1), - this.CSharpDiagnostic().WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1940,6 +1946,12 @@ void ZeroAlignmentMethod() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + /// + protected override IEnumerable GetDisabledDiagnostics() + { + yield return SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId; + } + /// protected override IEnumerable GetCSharpDiagnosticAnalyzers() { From 4082322e0a3fb685909e91af52d9f56d750a9af8 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sat, 9 Jan 2016 17:23:41 -0600 Subject: [PATCH 34/47] Add tests for SA1138 Also fixes a bug where some lines would get duplicate diagnostics --- .../ReadabilityRules/SA1138UnitTests.cs | 1964 +++++++++++++++++ .../StyleCop.Analyzers.Test.csproj | 1 + ...137ElementsShouldHaveTheSameIndentation.cs | 8 +- 3 files changed, 1972 insertions(+), 1 deletion(-) create mode 100644 StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs new file mode 100644 index 000000000..419465cb2 --- /dev/null +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -0,0 +1,1964 @@ +// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + +namespace StyleCop.Analyzers.Test.ReadabilityRules +{ + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.CodeAnalysis.CodeFixes; + using Microsoft.CodeAnalysis.Diagnostics; + using StyleCop.Analyzers.ReadabilityRules; + using TestHelper; + using Xunit; + + /// + /// This class contains unit tests for . + /// + /// + /// This set of tests is run with both SA1137 and SA1138 enabled, since they are intended to be used + /// together. + /// + public class SA1138UnitTests : CodeFixVerifier + { + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + [InlineData("enum")] + public async Task TestNamespaceDeclarationAsync(string baseTypeKind) + { + string testCode = $@" +using System; + +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace1 +{{ + [My] + [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} +"; + string fixedCode = $@" +using System; + +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace1 +{{ + [My] + [My] {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} + +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} + + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) + { + string testCode = $@" +{typeKind} NonGenericType +{{ +}} + +{typeKind} TypeWithoutConstraints +{{ +}} + +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 +where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} +"; + string fixedCode = $@" +{typeKind} NonGenericType +{{ +}} + +{typeKind} TypeWithoutConstraints +{{ +}} + +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 + where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class", "int", " { }")] + [InlineData("struct", "int", " { }")] + [InlineData("interface", "event System.EventHandler", ";")] + public async Task TestTypeDeclarationMembersAsync(string typeKind, string fieldType, string methodBody) + { + string testCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} +void Z1(){methodBody} +}} + +{typeKind} Container2 +{{ +{fieldType} X2; + int Y2 {{ get; }} + void Z2(){methodBody} +}} +"; + string fixedCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} + void Z1(){methodBody} +}} + +{typeKind} Container2 +{{ + {fieldType} X2; + int Y2 {{ get; }} + void Z2(){methodBody} +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + /// + /// This test demonstrates the behavior of SA1137 and its code fix with respect to documentation comments. + /// Currently both operations ignore documentation comments, but in the future the implementation may be updated + /// to examine and correct them similarly to attribute lists. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task TestDocumentationCommentBehaviorAsync() + { + string testCode = @" +using System; +enum Enum1 +{ + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum2 +{ + /// + /// Summary. + /// + [My] +Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum3 +{ + /// + /// Summary. + /// + [My] Element1, + + /// + /// Summary. + /// + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; +enum Enum1 +{ + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum2 +{ + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, +} + +enum Enum3 +{ + /// + /// Summary. + /// + [My] Element1, + + /// + /// Summary. + /// + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestEnumDeclarationAsync() + { + string testCode = @" +using System; +enum Enum1 +{ + [My] + Element1, + + Element2, +} + +enum Enum2 +{ + [My] +Element1, + + Element2, +} + +enum Enum3 +{ + [My] Element1, + + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; +enum Enum1 +{ + [My] + Element1, + + Element2, +} + +enum Enum2 +{ + [My] + Element1, + + Element2, +} + +enum Enum3 +{ + [My] Element1, + + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestMethodDeclarationAsync() + { + string testCode = @" +class Container +{ + void NonGenericType() + { + } + + void TypeWithoutConstraints() + { + } + + void TypeWithOneConstraint() + where T : new() + { + } + + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } + + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { + } +} +"; + string fixedCode = @" +class Container +{ + void NonGenericType() + { + } + + void TypeWithoutConstraints() + { + } + + void TypeWithOneConstraint() + where T : new() + { + } + + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } + + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestPropertyAccessorListAsync() + { + string testCode = @" +using System; + +class Container +{ + int Property1 + { + [My] + get; + + set; + } + + int Property2 + { + [My] +get; + + set; + } + + int Property3 + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +class Container +{ + int Property1 + { + [My] + get; + + set; + } + + int Property2 + { + [My] + get; + + set; + } + + int Property3 + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestIndexerAccessorListAsync() + { + string testCode = @" +using System; + +interface IContainer1 +{ + int this[int arg] + { + [My] + get; + + set; + } +} + +interface IContainer2 +{ + int this[int arg] + { + [My] +get; + + set; + } +} + +interface IContainer3 +{ + int this[int arg] + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +interface IContainer1 +{ + int this[int arg] + { + [My] + get; + + set; + } +} + +interface IContainer2 +{ + int this[int arg] + { + [My] + get; + + set; + } +} + +interface IContainer3 +{ + int this[int arg] + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(32, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestEventAccessorListAsync() + { + string testCode = @" +using System; + +class Container +{ + event EventHandler Event1 + { + [My] + add { } + + remove { } + } + + event EventHandler Event2 + { + [My] +add { } + + remove { } + } + + event EventHandler Event3 + { + [My] add { } + + remove { } + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +class Container +{ + event EventHandler Event1 + { + [My] + add { } + + remove { } + } + + event EventHandler Event2 + { + [My] + add { } + + remove { } + } + + event EventHandler Event3 + { + [My] add { } + + remove { } + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestValidVariableDeclarationAsync() + { + string testCode = @" +using System; +class Container +{ + private int T1; + private int + T2; + private int + T3, T4; + + private event EventHandler T5; + private event EventHandler + T6; + private event EventHandler + T7, T8; + + void MethodName() + { + int t1; + int + t2; + int + t3, t4; + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestVariableDeclarationAsync() + { + string testCode = @" +using System; +class Container +{ + private int + X1, + Y1, +Z1; + + private int +X2, + Y2, + Z2; + + private event EventHandler + X3, + Y3, +Z3; + + private event EventHandler +X4, + Y4, + Z4; + + void MethodName() + { + int + X1, + Y1, +Z1; + + int +X2, + Y2, + Z2; + } +} +"; + string fixedCode = @" +using System; +class Container +{ + private int + X1, + Y1, + Z1; + + private int +X2, +Y2, +Z2; + + private event EventHandler + X3, + Y3, + Z3; + + private event EventHandler +X4, +Y4, +Z4; + + void MethodName() + { + int + X1, + Y1, + Z1; + + int +X2, +Y2, +Z2; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(34, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(35, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestValidTypeParameterListAsync(string prefix, string suffix) + { + string testCode = $@" +class Container +{{ + {prefix} ClassName1{suffix} + + {prefix} ClassName2< + T>{suffix} + + {prefix} ClassName3< + T1, T2>{suffix} +}} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestTypeParameterListAsync(string prefix, string suffix) + { + string testCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, +Z>{suffix} + + {prefix} ZeroAlignment< +X, + Y, + Z>{suffix} +}} +"; + string fixedCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, + Z>{suffix} + + {prefix} ZeroAlignment< + X, + Y, + Z>{suffix} +}} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestParameterListAsync() + { + string testCode = @" +class Container +{ + void NonZeroAlignment( + int X, + int Y, +int Z) { } + + void ZeroAlignment( +int X, + int Y, + int Z) { } +} +"; + string fixedCode = @" +class Container +{ + void NonZeroAlignment( + int X, + int Y, + int Z) { } + + void ZeroAlignment( + int X, + int Y, + int Z) { } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestBracketedParameterListAsync() + { + string testCode = @" +class Container1 +{ + int this[ + int X, + int Y, +int Z] => 0; +} + +class Container2 +{ + int this[ +int X, + int Y, + int Z] => 0; +} +"; + string fixedCode = @" +class Container1 +{ + int this[ + int X, + int Y, + int Z] => 0; +} + +class Container2 +{ + int this[ + int X, + int Y, + int Z] => 0; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestArgumentListAsync() + { + string testCode = @" +class Container +{ + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, +0); + + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, + 0, + 0); +} +"; + string fixedCode = @" +class Container +{ + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, + 0); + + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, +0, +0); +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestBracketedArgumentListAsync() + { + string testCode = @" +class Container1 +{ + int this[int x, int y, int z] => this[ + 0, + 0, +0]; +} + +class Container2 +{ + int this[int x, int y, int z] => this[ +0, + 0, + 0]; +} +"; + string fixedCode = @" +class Container1 +{ + int this[int x, int y, int z] => this[ + 0, + 0, + 0]; +} + +class Container2 +{ + int this[int x, int y, int z] => this[ +0, +0, +0]; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestAttributeListAsync() + { + string testCode = @" +using System; + +[My] +[ + My] +[ + My, My] +class TypeName1 +{ +} + +[ + My, + My, +My] +[ +My, + My, + My] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +[My] +[ + My] +[ + My, My] +class TypeName1 +{ +} + +[ + My, + My, + My] +[ + My, + My, + My] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestAttributeArgumentListAsync() + { + string testCode = @" +using System; + +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 +{ +} + +[My( + 0, + Y = 2, +Z = 3)] +[My( +0, + Y = 2, + Z = 3)] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute +{ + public MyAttribute() { } + public MyAttribute(int value) { } + + public int Y { get; set; } + public int Z { get; set; } +} +"; + string fixedCode = @" +using System; + +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 +{ +} + +[My( + 0, + Y = 2, + Z = 3)] +[My( +0, +Y = 2, +Z = 3)] +class TypeName2 +{ +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute +{ + public MyAttribute() { } + public MyAttribute(int value) { } + + public int Y { get; set; } + public int Z { get; set; } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestBlockAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { + label1: + if (true) + { + } + + label2: + while (true) + { + } + +label3: +while (true) + { +label4a: + label4b: +int x; + + label5a: +label5b: + int y; + } + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + label1: + if (true) + { + } + + label2: + while (true) + { + } + + label3: + while (true) + { + label4a: + label4b: + int x; + + label5a: + label5b: + int y; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestSwitchStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } + + break; + + case 1: +case 2: + label2: + while (true) + { + } + + break; + +default: +label3a: + label3b: +break; + } + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } + + break; + + case 1: + case 2: + label2: + while (true) + { + } + + break; + + default: + label3a: + label3b: + break; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestValidInitializerExpressionAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void EmptyInitializersMethod() + { + // array initializer + int[] array = { }; + + // collection initializer + List list = new List { }; + + // complex element initializer + Dictionary dictionary = new Dictionary { }; + + // object initializer + var obj = new StructName { }; + } + + void SingleLineInitializersMethod() + { + // array initializer + int[] array = { 0 }; + + // collection initializer + List list = new List { 0 }; + + // complex element initializer + Dictionary dictionary = new Dictionary { { 0, 0 } }; + + // object initializer + var obj = new StructName { X = 0 }; + } + + void SingleElementInitializersMethod() + { + // array initializer + int[] array = + { + 0, + }; + + // collection initializer + List list = + new List + { + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + }; + } + + void SharedLineInitializersMethod() + { + // array initializer + int[] array = + { + 0, 0, + }; + + // collection initializer + List list = + new List + { + 0, 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, Y = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestInitializerExpressionAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = + { + 0, + 0, +0, + }; + + // collection initializer + List list = + new List + { + 0, + 0, +0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, +{ 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, +Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, + 0, + 0, + }; + + // collection initializer + List list = + new List + { +0, + 0, + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { +{ 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { +X = 0, + Y = 0, + Z = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + string fixedCode = @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = + { + 0, + 0, + 0, + }; + + // collection initializer + List list = + new List + { + 0, + 0, + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, + Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, +0, +0, + }; + + // collection initializer + List list = + new List + { +0, +0, +0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { +{ 0, 0 }, +{ 0, 0 }, +{ 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { +X = 0, +Y = 0, +Z = 0, + }; + } +} + +struct StructName +{ + public int X, Y, Z; +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(38, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(39, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(49, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(50, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(58, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(59, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(67, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(68, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(76, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(77, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestValidAnonymousObjectCreationExpressionAsync() + { + string testCode = @" +class ClassName +{ + void SingleLineInitializersMethod() + { + var obj = new { X = 0 }; + } + + void SingleElementInitializersMethod() + { + var obj = + new + { + X = 0, + }; + } + + void SharedLineInitializersMethod() + { + var obj = + new + { + X = 0, Y = 0, + }; + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestAnonymousObjectCreationExpressionAsync() + { + string testCode = @" +class ClassName +{ + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, +Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, + Y = 0, + Z = 0, + }; + } +} +"; + string fixedCode = @" +class ClassName +{ + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, + Z = 0, + }; + } + + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, +Y = 0, +Z = 0, + }; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + /// + protected override IEnumerable GetCSharpDiagnosticAnalyzers() + { + yield return new SA1137ElementsShouldHaveTheSameIndentation(); + } + + /// + protected override CodeFixProvider GetCSharpCodeFixProvider() + { + return new IndentationCodeFixProvider(); + } + } +} diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj b/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj index 69d33ada0..19c033bc4 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/StyleCop.Analyzers.Test.csproj @@ -327,6 +327,7 @@ + diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 31e48717a..2edc164fc 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -263,9 +263,10 @@ private static void CheckElements(SyntaxTreeAnalysisContext context, Compilat } } - private static void CheckTokens(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, ImmutableArray tokens) + private static void CheckTokens(SyntaxTreeAnalysisContext context, Compilation compilation, StyleCopSettings settings, int? indentationLevel, ImmutableArray tokens, bool reportFirstToken = false) { DiagnosticDescriptor descriptor = SA1137Descriptor; + SyntaxToken originalFirstToken = tokens.FirstOrDefault(); bool enableAbsoluteIndentationAnalysis = !compilation.IsAnalyzerSuppressed(SA1138DiagnosticId); @@ -335,6 +336,11 @@ private static void CheckTokens(SyntaxTreeAnalysisContext context, Compilation c location = indentationTrivia.GetLocation(); } + if (!reportFirstToken && token == originalFirstToken) + { + continue; + } + ImmutableDictionary properties = ImmutableDictionary.Create().SetItem(ExpectedIndentationKey, expectedIndentation); context.ReportDiagnostic(Diagnostic.Create(descriptor, location, properties)); } From a50fe42762e3213ed384948126a9652340547538 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 10 Jan 2016 15:49:17 -0600 Subject: [PATCH 35/47] Add tests for additional method and statement kinds --- .../ReadabilityRules/SA1138UnitTests.cs | 661 ++++++++++++++++++ 1 file changed, 661 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index 419465cb2..dd3b1cd04 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -1949,6 +1949,667 @@ void ZeroAlignmentMethod() await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestDestructorDeclarationAsync() + { + string testCode = @" +class ClassName +{ +~ClassName() +{ +return; +} +} +"; + string fixedCode = @" +class ClassName +{ + ~ClassName() + { + return; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestOperatorDeclarationAsync() + { + string testCode = @" +class ClassName +{ +public static bool operator !(ClassName obj) +{ +return false; +} +} +"; + string fixedCode = @" +class ClassName +{ + public static bool operator !(ClassName obj) + { + return false; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestConversionOperatorDeclarationAsync() + { + string testCode = @" +class ClassName +{ +public static explicit operator bool(ClassName obj) +{ +return false; +} +} +"; + string fixedCode = @" +class ClassName +{ + public static explicit operator bool(ClassName obj) + { + return false; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestCheckedStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +checked +{ +int y = 3 + 2; +} + +unchecked +{ +int y = 3 + 2; +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + checked + { + int y = 3 + 2; + } + + unchecked + { + int y = 3 + 2; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestDoStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +do +{ +int y = 3 + 2; +} +while (true); + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + do + { + int y = 3 + 2; + } + while (true); + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestFixedStatementAsync() + { + string testCode = @" +class ClassName +{ + unsafe void MethodName() + { + int[] x = new int[1]; +fixed (int* p = &x[0]) +{ +int y = 3 + 2; +} + } +} +"; + string fixedCode = @" +class ClassName +{ + unsafe void MethodName() + { + int[] x = new int[1]; + fixed (int* p = &x[0]) + { + int y = 3 + 2; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestForEachStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +foreach (int x in new int[3]) +{ +int y = 3 + 2; +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + foreach (int x in new int[3]) + { + int y = 3 + 2; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestForStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +for (int i = 0; i < 3; i++) +{ +int y = 3 + 2; +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + for (int i = 0; i < 3; i++) + { + int y = 3 + 2; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestIfStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +if (1 == 2) +{ +int y = 3 + 2; +} +else if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +int y = 3 + 2; +} + +if (1 == 2) +return; +else if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +int y = 3 + 2; +} + +if (1 == 2) +{ +int y = 3 + 2; +} +else if (2 == 3) +return; +else +{ +int y = 3 + 2; +} + +if (1 == 2) +{ +int y = 3 + 2; +} +else if (2 == 3) +{ +int y = 3 + 2; +} +else +return; + +if (1 == 2) +{ +int y = 3 + 2; +} +else +{ +if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +return; +} +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + { + int y = 3 + 2; + } + else + { + int y = 3 + 2; + } + + if (1 == 2) + return; + else if (2 == 3) + { + int y = 3 + 2; + } + else + { + int y = 3 + 2; + } + + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + return; + else + { + int y = 3 + 2; + } + + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + { + int y = 3 + 2; + } + else + return; + + if (1 == 2) + { + int y = 3 + 2; + } + else + { + if (2 == 3) + { + int y = 3 + 2; + } + else + { + return; + } + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(32, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(34, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(35, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(37, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(38, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(39, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(42, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(43, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(44, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(45, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(46, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(47, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(49, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(50, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(52, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(53, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(54, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(55, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(56, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(57, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(58, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(59, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(60, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(61, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(62, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(63, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(64, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(65, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(66, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestLockStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +lock (new object()) +{ +int y = 3 + 2; +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + lock (new object()) + { + int y = 3 + 2; + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestUsingStatementAsync() + { + string testCode = @" +using System; +class ClassName +{ + void MethodName() + { +using (default(IDisposable)) +{ +int y = 3 + 2; +} + +using (default(IDisposable)) +using (default(IDisposable)) +{ +int y = 3 + 2; +} + +using (default(IDisposable)) +{ +using (default(IDisposable)) +{ +int y = 3 + 2; +} +} + } +} +"; + string fixedCode = @" +using System; +class ClassName +{ + void MethodName() + { + using (default(IDisposable)) + { + int y = 3 + 2; + } + + using (default(IDisposable)) + using (default(IDisposable)) + { + int y = 3 + 2; + } + + using (default(IDisposable)) + { + using (default(IDisposable)) + { + int y = 3 + 2; + } + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + /// protected override IEnumerable GetCSharpDiagnosticAnalyzers() { From b221643fb38a04ec15bf210ec2aecb96100d9db3 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 10 Jan 2016 20:19:38 -0600 Subject: [PATCH 36/47] Add tests for assembly attribute lists --- .../ReadabilityRules/SA1138UnitTests.cs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index dd3b1cd04..e90d4a1b4 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -1206,6 +1206,67 @@ class Container2 await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestAssemblyAttributeListAsync() + { + string testCode = @" +using System; + +[assembly: My] +[assembly: + My] +[assembly: + My, My] + +[assembly: + My, + My, +My] +[assembly: +My, + My, + My] + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +[assembly: My] +[assembly: + My] +[assembly: + My, My] + +[assembly: + My, + My, + My] +[assembly: + My, + My, + My] + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestAttributeListAsync() { From 6ed11d07cb6343bc50e246cbd4fd47dcd6bd9f8e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 10 Jan 2016 20:20:09 -0600 Subject: [PATCH 37/47] Fix indentation of attributes in an attribute list --- .../ReadabilityRules/SA1138UnitTests.cs | 20 +++++++++---------- ...137ElementsShouldHaveTheSameIndentation.cs | 5 ++++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index e90d4a1b4..c854e64ad 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -1302,21 +1302,21 @@ class MyAttribute : Attribute { } [My] [ - My] + My] [ - My, My] + My, My] class TypeName1 { } [ - My, - My, - My] + My, + My, + My] [ - My, - My, - My] + My, + My, + My] class TypeName2 { } @@ -1327,12 +1327,12 @@ class MyAttribute : Attribute { } DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 2edc164fc..f27c9cf99 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -593,7 +593,10 @@ public override void VisitBracketedArgumentList(BracketedArgumentListSyntax node public override void VisitAttributeList(AttributeListSyntax node) { - using (this.AdjustIndentation(1)) + // Indentation is provided by the owner of the attribute list unless the owner is the compilation unit + // itself (assembly and module attributes). + int adjustment = node.Parent.IsKind(SyntaxKind.CompilationUnit) ? 1 : 0; + using (this.AdjustIndentation(adjustment)) { this.AnalyzeAttributeList(node); base.VisitAttributeList(node); From deefc6f655384645d067bd1d6e201dfe8b71b6f7 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 04:37:59 -0600 Subject: [PATCH 38/47] Add tests for control flow statements with expressions --- .../ReadabilityRules/SA1138UnitTests.cs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index c854e64ad..a0f7b6c8f 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -2182,6 +2182,10 @@ void MethodName() { int y = 3 + 2; } +while (true); + +do +return; while (true); } } @@ -2196,6 +2200,10 @@ void MethodName() int y = 3 + 2; } while (true); + + do + return; +while (true); } } "; @@ -2207,6 +2215,8 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2227,6 +2237,9 @@ unsafe void MethodName() { int y = 3 + 2; } + +fixed (int* p = &x[0]) +return; } } "; @@ -2240,6 +2253,9 @@ unsafe void MethodName() { int y = 3 + 2; } + + fixed (int* p = &x[0]) + return; } } "; @@ -2250,6 +2266,8 @@ unsafe void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2269,6 +2287,9 @@ void MethodName() { int y = 3 + 2; } + +foreach (int x in new int[3]) +return; } } "; @@ -2281,6 +2302,9 @@ void MethodName() { int y = 3 + 2; } + + foreach (int x in new int[3]) + return; } } "; @@ -2291,6 +2315,8 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2310,6 +2336,9 @@ void MethodName() { int y = 3 + 2; } + +for (int i = 0; i < 3; i++) +return; } } "; @@ -2322,6 +2351,9 @@ void MethodName() { int y = 3 + 2; } + + for (int i = 0; i < 3; i++) + return; } } "; @@ -2332,6 +2364,8 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2559,6 +2593,9 @@ void MethodName() { int y = 3 + 2; } + +lock (new object()) +return; } } "; @@ -2571,6 +2608,9 @@ void MethodName() { int y = 3 + 2; } + + lock (new object()) + return; } } "; @@ -2581,6 +2621,8 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2615,6 +2657,13 @@ void MethodName() int y = 3 + 2; } } + +using (default(IDisposable)) +return; + +using (default(IDisposable)) +using (default(IDisposable)) +return; } } "; @@ -2642,6 +2691,13 @@ void MethodName() int y = 3 + 2; } } + + using (default(IDisposable)) + return; + + using (default(IDisposable)) + using (default(IDisposable)) + return; } } "; @@ -2664,6 +2720,104 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestWhileStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +while (true) +{ +int y = 3 + 2; +} + +while (true) +return; + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + while (true) + { + int y = 3 + 2; + } + + while (true) + return; + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestNestedBlockStatementAsync() + { + string testCode = @" +class ClassName +{ + void MethodName() + { +{ +{ +int y = 3 + 2; +} +} + } +} +"; + string fixedCode = @" +class ClassName +{ + void MethodName() + { + { + { + int y = 3 + 2; + } + } + } +} +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); From 2e04003a490019d66be60c4864dd7a8140a73f1d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 04:42:40 -0600 Subject: [PATCH 39/47] Expand test cases for nested statements --- .../ReadabilityRules/SA1138UnitTests.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index a0f7b6c8f..4fc6c9fb0 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -2186,6 +2186,12 @@ void MethodName() do return; +while (true); + +do +do +return; +while (true); while (true); } } @@ -2203,6 +2209,12 @@ void MethodName() do return; +while (true); + + do + do + return; +while (true); while (true); } } @@ -2217,6 +2229,9 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2239,6 +2254,10 @@ unsafe void MethodName() } fixed (int* p = &x[0]) +return; + +fixed (int* p = &x[0]) +fixed (int* q = &x[0]) return; } } @@ -2256,6 +2275,10 @@ unsafe void MethodName() fixed (int* p = &x[0]) return; + + fixed (int* p = &x[0]) + fixed (int* q = &x[0]) + return; } } "; @@ -2268,6 +2291,9 @@ unsafe void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2289,6 +2315,10 @@ void MethodName() } foreach (int x in new int[3]) +return; + +foreach (int x in new int[3]) +foreach (int y in new int[3]) return; } } @@ -2305,6 +2335,10 @@ void MethodName() foreach (int x in new int[3]) return; + + foreach (int x in new int[3]) + foreach (int y in new int[3]) + return; } } "; @@ -2317,6 +2351,9 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2338,6 +2375,10 @@ void MethodName() } for (int i = 0; i < 3; i++) +return; + +for (int i = 0; i < 3; i++) +for (int j = 0; j < 3; j++) return; } } @@ -2354,6 +2395,10 @@ void MethodName() for (int i = 0; i < 3; i++) return; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + return; } } "; @@ -2366,6 +2411,9 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2594,6 +2642,10 @@ void MethodName() int y = 3 + 2; } +lock (new object()) +return; + +lock (new object()) lock (new object()) return; } @@ -2611,6 +2663,10 @@ void MethodName() lock (new object()) return; + + lock (new object()) + lock (new object()) + return; } } "; @@ -2623,6 +2679,9 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2745,6 +2804,10 @@ void MethodName() int y = 3 + 2; } +while (true) +return; + +while (true) while (true) return; } @@ -2762,6 +2825,10 @@ void MethodName() while (true) return; + + while (true) + while (true) + return; } } "; @@ -2774,6 +2841,9 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); From 77a14161aefdd9ef9262901242214bca504f5922 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 04:43:09 -0600 Subject: [PATCH 40/47] Remove unnecessary null checks --- ...137ElementsShouldHaveTheSameIndentation.cs | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index f27c9cf99..3ed858444 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -1006,11 +1006,8 @@ private void AnalyzeSwitchStatement(SwitchStatementSyntax node) private void AnalyzeCheckedStatement(CheckedStatementSyntax node) { - if (node.Block != null) - { - var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.Block.OpenBraceToken, node.Block.CloseBraceToken); - CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); - } + var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.Block.OpenBraceToken, node.Block.CloseBraceToken); + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } private void AnalyzeDoStatement(DoStatementSyntax node) @@ -1021,7 +1018,7 @@ private void AnalyzeDoStatement(DoStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken, node.WhileKeyword); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } @@ -1035,7 +1032,7 @@ private void AnalyzeFixedStatement(FixedStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } @@ -1049,7 +1046,7 @@ private void AnalyzeForEachStatement(ForEachStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } @@ -1063,7 +1060,7 @@ private void AnalyzeForStatement(ForStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } @@ -1088,7 +1085,7 @@ private void AnalyzeIfStatement(IfStatementSyntax node) builder.Add(block.OpenBraceToken); builder.Add(block.CloseBraceToken); } - else if (current.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Statement)); } @@ -1110,10 +1107,7 @@ private void AnalyzeIfStatement(IfStatementSyntax node) } else { - if (current.Else.Statement != null) - { - CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Else.Statement)); - } + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Else.Statement)); current = null; } @@ -1135,7 +1129,7 @@ private void AnalyzeLockStatement(LockStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } @@ -1169,10 +1163,7 @@ private void AnalyzeUsingStatement(UsingStatementSyntax node) } else { - if (current.Statement != null) - { - CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Statement)); - } + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(current.Statement)); current = null; } @@ -1189,7 +1180,7 @@ private void AnalyzeWhileStatement(WhileStatementSyntax node) var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken); CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } - else if (node.Statement != null) + else { CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } From 398f25a46598fdc22f17a195a0e99a3ab470626d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 05:23:15 -0600 Subject: [PATCH 41/47] Refactor a bunch of test cases to properties This change will make it much easier to run a complete set of tests using different indentation configurations. --- .../ReadabilityRules/SA1138UnitTests.cs | 4128 +++++++++-------- 1 file changed, 2080 insertions(+), 2048 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index 4fc6c9fb0..f32bc5859 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -21,1184 +21,1320 @@ namespace StyleCop.Analyzers.Test.ReadabilityRules /// public class SA1138UnitTests : CodeFixVerifier { - [Theory] - [InlineData("class")] - [InlineData("struct")] - [InlineData("interface")] - [InlineData("enum")] - public async Task TestNamespaceDeclarationAsync(string baseTypeKind) + protected string BlockStatementTestCode => @" +class ClassName +{ + void MethodName() + { + label1: + if (true) { - string testCode = $@" -using System; - -namespace Namespace0 -{{ - [My] [My] {baseTypeKind} TypeName {{ }} -}} - -namespace Namespace1 -{{ - [My] - [My] {baseTypeKind} TypeName {{ }} -}} - -namespace Namespace2 -{{ - [My] - [My] - {baseTypeKind} TypeName {{ }} -}} - -namespace Namespace3 -{{ - [My] - [My] - {baseTypeKind} TypeName {{ }} -}} + } -namespace Namespace4 -{{ - {baseTypeKind} TypeName1 {{ }} + label2: + while (true) + { + } - [My] {baseTypeKind} TypeName2 {{ }} -}} +label3: +while (true) + { +label4a: + label4b: +int x; -namespace Namespace5 -{{ - {baseTypeKind} TypeName1 {{ }} + label5a: +label5b: + int y; + } + } +} +"; - [My] - [My] {baseTypeKind} TypeName2 {{ }} -}} + protected virtual string BlockStatementFixedCode => @" +class ClassName +{ + void MethodName() + { + label1: + if (true) + { + } -namespace Namespace6 -{{ - {baseTypeKind} TypeName1 {{ }} + label2: + while (true) + { + } - [My] - [My] {baseTypeKind} TypeName2 {{ }} -}} + label3: + while (true) + { + label4a: + label4b: + int x; -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute {{ }} + label5a: + label5b: + int y; + } + } +} "; - string fixedCode = $@" -using System; -namespace Namespace0 -{{ - [My] [My] {baseTypeKind} TypeName {{ }} -}} + protected virtual DiagnosticResult[] BlockStatementExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; -namespace Namespace1 -{{ - [My] - [My] {baseTypeKind} TypeName {{ }} -}} + protected string SwitchStatementTestCode => @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } -namespace Namespace2 -{{ - [My] - [My] - {baseTypeKind} TypeName {{ }} -}} + break; -namespace Namespace3 -{{ - [My] - [My] - {baseTypeKind} TypeName {{ }} -}} + case 1: +case 2: + label2: + while (true) + { + } -namespace Namespace4 -{{ - {baseTypeKind} TypeName1 {{ }} + break; - [My] {baseTypeKind} TypeName2 {{ }} -}} +default: +label3a: + label3b: +break; + } + } +} +"; -namespace Namespace5 -{{ - {baseTypeKind} TypeName1 {{ }} + protected virtual string SwitchStatementFixedCode => @" +class ClassName +{ + void MethodName() + { + switch (0) + { + case 0: + label1: + if (true) + { + } - [My] - [My] {baseTypeKind} TypeName2 {{ }} -}} + break; -namespace Namespace6 -{{ - {baseTypeKind} TypeName1 {{ }} + case 1: + case 2: + label2: + while (true) + { + } - [My] - [My] {baseTypeKind} TypeName2 {{ }} -}} + break; -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute {{ }} + default: + label3a: + label3b: + break; + } + } +} "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] SwitchStatementExpectedDiagnostics => + new[] { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Theory] - [InlineData("class")] - [InlineData("struct")] - [InlineData("interface")] - public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) + protected string InitializerExpressionTestCode => @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = { - string testCode = $@" -{typeKind} NonGenericType -{{ -}} + 0, + 0, +0, + }; -{typeKind} TypeWithoutConstraints -{{ -}} + // collection initializer + List list = + new List + { + 0, + 0, +0, + }; -{typeKind} TypeWithOneConstraint - where T : new() -{{ -}} + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, +{ 0, 0 }, + }; -{typeKind} TypeWithMultipleConstraints1 where T1 : new() - where T2 : new() - where T3 : new() -{{ -}} + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, +Z = 0, + }; + } -{typeKind} TypeWithMultipleConstraints2 -where T1 : new() - where T2 : new() - where T3 : new() -{{ -}} -"; - string fixedCode = $@" -{typeKind} NonGenericType -{{ -}} + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, + 0, + 0, + }; -{typeKind} TypeWithoutConstraints -{{ -}} + // collection initializer + List list = + new List + { +0, + 0, + 0, + }; -{typeKind} TypeWithOneConstraint - where T : new() -{{ -}} + // complex element initializer + Dictionary dictionary = + new Dictionary + { +{ 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; -{typeKind} TypeWithMultipleConstraints1 where T1 : new() - where T2 : new() - where T3 : new() -{{ -}} + // object initializer + var obj = + new StructName + { +X = 0, + Y = 0, + Z = 0, + }; + } +} -{typeKind} TypeWithMultipleConstraints2 - where T1 : new() - where T2 : new() - where T3 : new() -{{ -}} +struct StructName +{ + public int X, Y, Z; +} "; - DiagnosticResult[] expected = + protected virtual string InitializerExpressionFixedCode => @" +using System.Collections.Generic; +class ClassName +{ + void NonZeroAlignmentMethod() + { + // array initializer + int[] array = + { + 0, + 0, + 0, + }; + + // collection initializer + List list = + new List { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + 0, + 0, + 0, }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + }; - [Theory] - [InlineData("class", "int", " { }")] - [InlineData("struct", "int", " { }")] - [InlineData("interface", "event System.EventHandler", ";")] - public async Task TestTypeDeclarationMembersAsync(string typeKind, string fieldType, string methodBody) - { - string testCode = $@" -{typeKind} Container1 -{{ - {fieldType} X1; - int Y1 {{ get; }} -void Z1(){methodBody} -}} + // object initializer + var obj = + new StructName + { + X = 0, + Y = 0, + Z = 0, + }; + } -{typeKind} Container2 -{{ -{fieldType} X2; - int Y2 {{ get; }} - void Z2(){methodBody} -}} -"; - string fixedCode = $@" -{typeKind} Container1 -{{ - {fieldType} X1; - int Y1 {{ get; }} - void Z1(){methodBody} -}} + void ZeroAlignmentMethod() + { + // array initializer + int[] array = + { +0, +0, +0, + }; -{typeKind} Container2 -{{ - {fieldType} X2; - int Y2 {{ get; }} - void Z2(){methodBody} -}} -"; + // collection initializer + List list = + new List + { +0, +0, +0, + }; - DiagnosticResult[] expected = + // complex element initializer + Dictionary dictionary = + new Dictionary { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), +{ 0, 0 }, +{ 0, 0 }, +{ 0, 0 }, }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } + // object initializer + var obj = + new StructName + { +X = 0, +Y = 0, +Z = 0, + }; + } +} - /// - /// This test demonstrates the behavior of SA1137 and its code fix with respect to documentation comments. - /// Currently both operations ignore documentation comments, but in the future the implementation may be updated - /// to examine and correct them similarly to attribute lists. - /// - /// A representing the asynchronous unit test. - [Fact] - public async Task TestDocumentationCommentBehaviorAsync() - { - string testCode = @" -using System; -enum Enum1 +struct StructName { - /// - /// Summary. - /// - [My] - Element1, - - /// - /// Summary. - /// - Element2, + public int X, Y, Z; } +"; -enum Enum2 + protected virtual DiagnosticResult[] InitializerExpressionExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(38, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(39, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(49, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(50, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(58, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(59, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(67, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(68, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(76, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(77, 1), + }; + + protected string AnonymousObjectCreationExpressionTestCode => @" +class ClassName { - /// - /// Summary. - /// - [My] -Element1, + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, +Z = 0, + }; + } - /// - /// Summary. - /// - Element2, + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, + Y = 0, + Z = 0, + }; + } } +"; -enum Enum3 + protected virtual string AnonymousObjectCreationExpressionFixedCode => @" +class ClassName { - /// - /// Summary. - /// - [My] Element1, + void NonZeroAlignmentMethod() + { + var obj = + new + { + X = 0, + Y = 0, + Z = 0, + }; + } - /// - /// Summary. - /// - Element2, + void ZeroAlignmentMethod() + { + var obj = + new + { +X = 0, +Y = 0, +Z = 0, + }; + } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - string fixedCode = @" -using System; -enum Enum1 -{ - /// - /// Summary. - /// - [My] - Element1, - /// - /// Summary. - /// - Element2, -} + protected virtual DiagnosticResult[] AnonymousObjectCreationExpressionExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + }; -enum Enum2 + protected string DestructorDeclarationTestCode => @" +class ClassName { - /// - /// Summary. - /// - [My] - Element1, - - /// - /// Summary. - /// - Element2, +~ClassName() +{ +return; } +} +"; -enum Enum3 + protected virtual string DestructorDeclarationFixedCode => @" +class ClassName { - /// - /// Summary. - /// - [My] Element1, - - /// - /// Summary. - /// - Element2, + ~ClassName() + { + return; + } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] DestructorDeclarationExpectedDiagnostics => + new[] { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestEnumDeclarationAsync() - { - string testCode = @" -using System; -enum Enum1 + protected string OperatorDeclarationTestCode => @" +class ClassName { - [My] - Element1, +public static bool operator !(ClassName obj) +{ +return false; +} +} +"; - Element2, + protected virtual string OperatorDeclarationFixedCode => @" +class ClassName +{ + public static bool operator !(ClassName obj) + { + return false; + } } +"; + + protected virtual DiagnosticResult[] OperatorDeclarationExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + }; -enum Enum2 + protected string ConversionOperatorDeclarationTestCode => @" +class ClassName { - [My] -Element1, - - Element2, +public static explicit operator bool(ClassName obj) +{ +return false; } +} +"; -enum Enum3 + protected virtual string ConversionOperatorDeclarationFixedCode => @" +class ClassName { - [My] Element1, - - Element2, + public static explicit operator bool(ClassName obj) + { + return false; + } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - string fixedCode = @" -using System; -enum Enum1 -{ - [My] - Element1, - Element2, -} + protected virtual DiagnosticResult[] ConversionOperatorExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + }; -enum Enum2 + protected string CheckedStatementTestCode => @" +class ClassName { - [My] - Element1, + void MethodName() + { +checked +{ +int y = 3 + 2; +} - Element2, +unchecked +{ +int y = 3 + 2; +} + } } +"; -enum Enum3 + protected virtual string CheckedStatementFixedCode => @" +class ClassName { - [My] Element1, + void MethodName() + { + checked + { + int y = 3 + 2; + } - Element2, + unchecked + { + int y = 3 + 2; + } + } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] CheckedStatementExpectedDiagnostics => + new[] { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestMethodDeclarationAsync() - { - string testCode = @" -class Container + protected string DoStatementTestCode => @" +class ClassName { - void NonGenericType() + void MethodName() { - } +do +{ +int y = 3 + 2; +} +while (true); - void TypeWithoutConstraints() - { - } +do +return; +while (true); - void TypeWithOneConstraint() - where T : new() - { +do +do +return; +while (true); +while (true); } +} +"; - void TypeWithMultipleConstraints1() where T1 : new() - where T2 : new() - where T3 : new() + protected virtual string DoStatementFixedCode => @" +class ClassName +{ + void MethodName() { - } + do + { + int y = 3 + 2; + } + while (true); - void TypeWithMultipleConstraints2() - where T1 : new() - where T2 : new() - where T3 : new() - { + do + return; +while (true); + + do + do + return; +while (true); +while (true); } } "; - string fixedCode = @" -class Container + + protected virtual DiagnosticResult[] DoStatementExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + }; + + protected string FixedStatementTestCode => @" +class ClassName { - void NonGenericType() + unsafe void MethodName() { - } + int[] x = new int[1]; +fixed (int* p = &x[0]) +{ +int y = 3 + 2; +} - void TypeWithoutConstraints() - { - } +fixed (int* p = &x[0]) +return; - void TypeWithOneConstraint() - where T : new() - { +fixed (int* p = &x[0]) +fixed (int* q = &x[0]) +return; } +} +"; - void TypeWithMultipleConstraints1() where T1 : new() - where T2 : new() - where T3 : new() + protected virtual string FixedStatementFixedCode => @" +class ClassName +{ + unsafe void MethodName() { - } + int[] x = new int[1]; + fixed (int* p = &x[0]) + { + int y = 3 + 2; + } - void TypeWithMultipleConstraints2() - where T1 : new() - where T2 : new() - where T3 : new() - { + fixed (int* p = &x[0]) + return; + + fixed (int* p = &x[0]) + fixed (int* q = &x[0]) + return; } } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] FixedStatementExpectedDiagnostics => + new[] { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestPropertyAccessorListAsync() - { - string testCode = @" -using System; - -class Container + protected string ForEachStatementTestCode => @" +class ClassName { - int Property1 - { - [My] - get; - - set; - } - - int Property2 + void MethodName() { - [My] -get; - - set; - } +foreach (int x in new int[3]) +{ +int y = 3 + 2; +} - int Property3 - { - [My] get; +foreach (int x in new int[3]) +return; - set; +foreach (int x in new int[3]) +foreach (int y in new int[3]) +return; } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - string fixedCode = @" -using System; -class Container + protected virtual string ForEachStatementFixedCode => @" +class ClassName { - int Property1 - { - [My] - get; - - set; - } - - int Property2 + void MethodName() { - [My] - get; - - set; - } + foreach (int x in new int[3]) + { + int y = 3 + 2; + } - int Property3 - { - [My] get; + foreach (int x in new int[3]) + return; - set; + foreach (int x in new int[3]) + foreach (int y in new int[3]) + return; } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] ForEachStatementExpectedDiagnostics => + new[] { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestIndexerAccessorListAsync() - { - string testCode = @" -using System; - -interface IContainer1 + protected string ForStatementTestCode => @" +class ClassName { - int this[int arg] + void MethodName() { - [My] - get; - - set; - } +for (int i = 0; i < 3; i++) +{ +int y = 3 + 2; } -interface IContainer2 -{ - int this[int arg] - { - [My] -get; +for (int i = 0; i < 3; i++) +return; - set; +for (int i = 0; i < 3; i++) +for (int j = 0; j < 3; j++) +return; } } +"; -interface IContainer3 + protected virtual string ForStatementFixedCode => @" +class ClassName { - int this[int arg] + void MethodName() { - [My] get; + for (int i = 0; i < 3; i++) + { + int y = 3 + 2; + } - set; + for (int i = 0; i < 3; i++) + return; + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + return; } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - string fixedCode = @" -using System; -interface IContainer1 + protected virtual DiagnosticResult[] ForStatementExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + }; + + protected string IfStatementTestCode => @" +class ClassName { - int this[int arg] + void MethodName() { - [My] - get; +if (1 == 2) +{ +int y = 3 + 2; +} +else if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +int y = 3 + 2; +} - set; - } +if (1 == 2) +return; +else if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +int y = 3 + 2; } -interface IContainer2 +if (1 == 2) { - int this[int arg] - { - [My] - get; +int y = 3 + 2; +} +else if (2 == 3) +return; +else +{ +int y = 3 + 2; +} - set; +if (1 == 2) +{ +int y = 3 + 2; +} +else if (2 == 3) +{ +int y = 3 + 2; +} +else +return; + +if (1 == 2) +{ +int y = 3 + 2; +} +else +{ +if (2 == 3) +{ +int y = 3 + 2; +} +else +{ +return; +} +} } } +"; -interface IContainer3 + protected virtual string IfStatementFixedCode => @" +class ClassName { - int this[int arg] + void MethodName() { - [My] get; + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + { + int y = 3 + 2; + } + else + { + int y = 3 + 2; + } - set; + if (1 == 2) + return; + else if (2 == 3) + { + int y = 3 + 2; + } + else + { + int y = 3 + 2; + } + + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + return; + else + { + int y = 3 + 2; + } + + if (1 == 2) + { + int y = 3 + 2; + } + else if (2 == 3) + { + int y = 3 + 2; + } + else + return; + + if (1 == 2) + { + int y = 3 + 2; + } + else + { + if (2 == 3) + { + int y = 3 + 2; + } + else + { + return; + } + } } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] IfStatementExpectedDiagnostics => + new[] { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(32, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(34, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(35, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(37, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(38, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(39, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(42, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(43, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(44, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(45, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(46, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(47, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(49, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(50, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(52, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(53, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(54, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(55, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(56, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(57, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(58, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(59, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(60, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(61, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(62, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(63, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(64, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(65, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(66, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestEventAccessorListAsync() - { - string testCode = @" -using System; - -class Container + protected string LockStatementTestCode => @" +class ClassName { - event EventHandler Event1 - { - [My] - add { } - - remove { } - } - - event EventHandler Event2 + void MethodName() { - [My] -add { } - - remove { } - } +lock (new object()) +{ +int y = 3 + 2; +} - event EventHandler Event3 - { - [My] add { } +lock (new object()) +return; - remove { } +lock (new object()) +lock (new object()) +return; } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - string fixedCode = @" -using System; -class Container + protected virtual string LockStatementFixedCode => @" +class ClassName { - event EventHandler Event1 - { - [My] - add { } - - remove { } - } - - event EventHandler Event2 + void MethodName() { - [My] - add { } - - remove { } - } + lock (new object()) + { + int y = 3 + 2; + } - event EventHandler Event3 - { - [My] add { } + lock (new object()) + return; - remove { } + lock (new object()) + lock (new object()) + return; } } - -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] LockStatementExpectedDiagnostics => + new[] { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - - [Fact] - public async Task TestValidVariableDeclarationAsync() - { - string testCode = @" + protected string UsingStatementTestCode => @" using System; -class Container +class ClassName { - private int T1; - private int - T2; - private int - T3, T4; - - private event EventHandler T5; - private event EventHandler - T6; - private event EventHandler - T7, T8; - void MethodName() { - int t1; - int - t2; - int - t3, t4; +using (default(IDisposable)) +{ +int y = 3 + 2; +} + +using (default(IDisposable)) +using (default(IDisposable)) +{ +int y = 3 + 2; +} + +using (default(IDisposable)) +{ +using (default(IDisposable)) +{ +int y = 3 + 2; +} +} + +using (default(IDisposable)) +return; + +using (default(IDisposable)) +using (default(IDisposable)) +return; } } "; - await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + protected virtual string UsingStatementFixedCode => @" +using System; +class ClassName +{ + void MethodName() + { + using (default(IDisposable)) + { + int y = 3 + 2; } - [Fact] - public async Task TestVariableDeclarationAsync() + using (default(IDisposable)) + using (default(IDisposable)) + { + int y = 3 + 2; + } + + using (default(IDisposable)) { - string testCode = @" -using System; -class Container -{ - private int - X1, - Y1, -Z1; + using (default(IDisposable)) + { + int y = 3 + 2; + } + } - private int -X2, - Y2, - Z2; + using (default(IDisposable)) + return; - private event EventHandler - X3, - Y3, -Z3; + using (default(IDisposable)) + using (default(IDisposable)) + return; + } +} +"; - private event EventHandler -X4, - Y4, - Z4; + protected virtual DiagnosticResult[] UsingStatementExpectedDiagnostics => + new[] + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), + }; + protected string WhileStatementTestCode => @" +class ClassName +{ void MethodName() { - int - X1, - Y1, -Z1; +while (true) +{ +int y = 3 + 2; +} - int -X2, - Y2, - Z2; +while (true) +return; + +while (true) +while (true) +return; } } "; - string fixedCode = @" -using System; -class Container -{ - private int - X1, - Y1, - Z1; - - private int -X2, -Y2, -Z2; - - private event EventHandler - X3, - Y3, - Z3; - - private event EventHandler -X4, -Y4, -Z4; + protected virtual string WhileStatementFixedCode => @" +class ClassName +{ void MethodName() { - int - X1, - Y1, - Z1; + while (true) + { + int y = 3 + 2; + } - int -X2, -Y2, -Z2; + while (true) + return; + + while (true) + while (true) + return; } } "; - DiagnosticResult[] expected = + protected virtual DiagnosticResult[] WhileStatementExpectedDiagnostics => + new[] { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(34, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(35, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } - [Theory] - [InlineData("class", " { }")] - [InlineData("void", "() { }")] - public async Task TestValidTypeParameterListAsync(string prefix, string suffix) + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + [InlineData("enum")] + public async Task TestNamespaceDeclarationAsync(string baseTypeKind) { string testCode = $@" -class Container -{{ - {prefix} ClassName1{suffix} - - {prefix} ClassName2< - T>{suffix} +using System; - {prefix} ClassName3< - T1, T2>{suffix} +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} }} -"; - - await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - } - [Theory] - [InlineData("class", " { }")] - [InlineData("void", "() { }")] - public async Task TestTypeParameterListAsync(string prefix, string suffix) - { - string testCode = $@" -class Container +namespace Namespace1 {{ - {prefix} NonZeroAlignment< - X, - Y, -Z>{suffix} - - {prefix} ZeroAlignment< -X, - Y, - Z>{suffix} + [My] + [My] {baseTypeKind} TypeName {{ }} }} -"; - string fixedCode = $@" -class Container -{{ - {prefix} NonZeroAlignment< - X, - Y, - Z>{suffix} - {prefix} ZeroAlignment< - X, - Y, - Z>{suffix} +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} }} -"; - - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - }; - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} - [Fact] - public async Task TestParameterListAsync() - { - string testCode = @" -class Container -{ - void NonZeroAlignment( - int X, - int Y, -int Z) { } +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} - void ZeroAlignment( -int X, - int Y, - int Z) { } -} -"; - string fixedCode = @" -class Container -{ - void NonZeroAlignment( - int X, - int Y, - int Z) { } + [My] {baseTypeKind} TypeName2 {{ }} +}} - void ZeroAlignment( - int X, - int Y, - int Z) { } -} -"; +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - }; + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} - [Fact] - public async Task TestBracketedParameterListAsync() - { - string testCode = @" -class Container1 -{ - int this[ - int X, - int Y, -int Z] => 0; -} + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} -class Container2 -{ - int this[ -int X, - int Y, - int Z] => 0; -} +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} "; - string fixedCode = @" -class Container1 -{ - int this[ - int X, - int Y, - int Z] => 0; -} + string fixedCode = $@" +using System; -class Container2 -{ - int this[ - int X, - int Y, - int Z] => 0; -} -"; +namespace Namespace0 +{{ + [My] [My] {baseTypeKind} TypeName {{ }} +}} - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - }; +namespace Namespace1 +{{ + [My] + [My] {baseTypeKind} TypeName {{ }} +}} - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } +namespace Namespace2 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} - [Fact] - public async Task TestArgumentListAsync() - { - string testCode = @" -class Container -{ - int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( - 0, - 0, -0); +namespace Namespace3 +{{ + [My] + [My] + {baseTypeKind} TypeName {{ }} +}} - int ZeroAlignment(int x, int y, int z) => ZeroAlignment( -0, - 0, - 0); -} -"; - string fixedCode = @" -class Container -{ - int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( - 0, - 0, - 0); +namespace Namespace4 +{{ + {baseTypeKind} TypeName1 {{ }} - int ZeroAlignment(int x, int y, int z) => ZeroAlignment( -0, -0, -0); -} -"; + [My] {baseTypeKind} TypeName2 {{ }} +}} - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), - }; +namespace Namespace5 +{{ + {baseTypeKind} TypeName1 {{ }} - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); - } + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} - [Fact] - public async Task TestBracketedArgumentListAsync() - { - string testCode = @" -class Container1 -{ - int this[int x, int y, int z] => this[ - 0, - 0, -0]; -} +namespace Namespace6 +{{ + {baseTypeKind} TypeName1 {{ }} -class Container2 -{ - int this[int x, int y, int z] => this[ -0, - 0, - 0]; -} -"; - string fixedCode = @" -class Container1 -{ - int this[int x, int y, int z] => this[ - 0, - 0, - 0]; -} + [My] + [My] {baseTypeKind} TypeName2 {{ }} +}} -class Container2 -{ - int this[int x, int y, int z] => this[ -0, -0, -0]; -} +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute {{ }} "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1206,60 +1342,72 @@ class Container2 await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } - [Fact] - public async Task TestAssemblyAttributeListAsync() + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("interface")] + public async Task TestTypeDeclarationConstraintClausesAsync(string typeKind) { - string testCode = @" -using System; + string testCode = $@" +{typeKind} NonGenericType +{{ +}} -[assembly: My] -[assembly: - My] -[assembly: - My, My] +{typeKind} TypeWithoutConstraints +{{ +}} -[assembly: - My, - My, -My] -[assembly: -My, - My, - My] +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 +where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} "; - string fixedCode = @" -using System; + string fixedCode = $@" +{typeKind} NonGenericType +{{ +}} -[assembly: My] -[assembly: - My] -[assembly: - My, My] +{typeKind} TypeWithoutConstraints +{{ +}} -[assembly: - My, - My, - My] -[assembly: - My, - My, - My] +{typeKind} TypeWithOneConstraint + where T : new() +{{ +}} -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } +{typeKind} TypeWithMultipleConstraints1 where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} + +{typeKind} TypeWithMultipleConstraints2 + where T1 : new() + where T2 : new() + where T3 : new() +{{ +}} "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1267,72 +1415,51 @@ class MyAttribute : Attribute { } await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } - [Fact] - public async Task TestAttributeListAsync() + [Theory] + [InlineData("class", "int", " { }")] + [InlineData("struct", "int", " { }")] + [InlineData("interface", "event System.EventHandler", ";")] + public async Task TestTypeDeclarationMembersAsync(string typeKind, string fieldType, string methodBody) { - string testCode = @" -using System; - -[My] -[ - My] -[ - My, My] -class TypeName1 -{ -} - -[ - My, - My, -My] -[ -My, - My, - My] -class TypeName2 -{ -} + string testCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} +void Z1(){methodBody} +}} -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } +{typeKind} Container2 +{{ +{fieldType} X2; + int Y2 {{ get; }} + void Z2(){methodBody} +}} "; - string fixedCode = @" -using System; - -[My] -[ - My] -[ - My, My] -class TypeName1 -{ -} - -[ - My, - My, - My] -[ - My, - My, - My] -class TypeName2 -{ -} + string fixedCode = $@" +{typeKind} Container1 +{{ + {fieldType} X1; + int Y1 {{ get; }} + void Z1(){methodBody} +}} -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute { } +{typeKind} Container2 +{{ + {fieldType} X2; + int Y2 {{ get; }} + void Z2(){methodBody} +}} "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1340,84 +1467,117 @@ class MyAttribute : Attribute { } await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + /// + /// This test demonstrates the behavior of SA1137 and its code fix with respect to documentation comments. + /// Currently both operations ignore documentation comments, but in the future the implementation may be updated + /// to examine and correct them similarly to attribute lists. + /// + /// A representing the asynchronous unit test. [Fact] - public async Task TestAttributeArgumentListAsync() + public async Task TestDocumentationCommentBehaviorAsync() { string testCode = @" using System; - -[My(0)] -[My( - 0)] -[My( - 0, Y = 2)] -class TypeName1 +enum Enum1 { + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, } -[My( - 0, - Y = 2, -Z = 3)] -[My( -0, - Y = 2, - Z = 3)] -class TypeName2 +enum Enum2 { + /// + /// Summary. + /// + [My] +Element1, + + /// + /// Summary. + /// + Element2, } -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute +enum Enum3 { - public MyAttribute() { } - public MyAttribute(int value) { } + /// + /// Summary. + /// + [My] Element1, - public int Y { get; set; } - public int Z { get; set; } + /// + /// Summary. + /// + Element2, } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; string fixedCode = @" using System; - -[My(0)] -[My( - 0)] -[My( - 0, Y = 2)] -class TypeName1 +enum Enum1 { + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, } -[My( - 0, - Y = 2, - Z = 3)] -[My( -0, -Y = 2, -Z = 3)] -class TypeName2 +enum Enum2 { + /// + /// Summary. + /// + [My] + Element1, + + /// + /// Summary. + /// + Element2, } -[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] -class MyAttribute : Attribute +enum Enum3 { - public MyAttribute() { } - public MyAttribute(int value) { } + /// + /// Summary. + /// + [My] Element1, - public int Y { get; set; } - public int Z { get; set; } + /// + /// Summary. + /// + Element2, } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1426,81 +1586,74 @@ public MyAttribute(int value) { } } [Fact] - public async Task TestBlockAsync() + public async Task TestEnumDeclarationAsync() { string testCode = @" -class ClassName +using System; +enum Enum1 { - void MethodName() - { - label1: - if (true) - { - } + [My] + Element1, - label2: - while (true) - { - } + Element2, +} -label3: -while (true) - { -label4a: - label4b: -int x; +enum Enum2 +{ + [My] +Element1, + + Element2, +} - label5a: -label5b: - int y; - } - } +enum Enum3 +{ + [My] Element1, + + Element2, } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; string fixedCode = @" -class ClassName +using System; +enum Enum1 { - void MethodName() - { - label1: - if (true) - { - } + [My] + Element1, - label2: - while (true) - { - } + Element2, +} - label3: - while (true) - { - label4a: - label4b: - int x; +enum Enum2 +{ + [My] + Element1, - label5a: - label5b: - int y; - } - } + Element2, } + +enum Enum3 +{ + [My] Element1, + + Element2, +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1509,397 +1662,254 @@ void MethodName() } [Fact] - public async Task TestSwitchStatementAsync() + public async Task TestMethodDeclarationAsync() { string testCode = @" -class ClassName +class Container { - void MethodName() + void NonGenericType() { - switch (0) - { - case 0: - label1: - if (true) - { - } + } - break; + void TypeWithoutConstraints() + { + } - case 1: -case 2: - label2: - while (true) - { - } + void TypeWithOneConstraint() + where T : new() + { + } - break; + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } -default: -label3a: - label3b: -break; - } + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { } } "; string fixedCode = @" -class ClassName +class Container { - void MethodName() + void NonGenericType() { - switch (0) - { - case 0: - label1: - if (true) - { - } + } - break; + void TypeWithoutConstraints() + { + } - case 1: - case 2: - label2: - while (true) - { - } + void TypeWithOneConstraint() + where T : new() + { + } - break; + void TypeWithMultipleConstraints1() where T1 : new() + where T2 : new() + where T3 : new() + { + } - default: - label3a: - label3b: - break; - } + void TypeWithMultipleConstraints2() + where T1 : new() + where T2 : new() + where T3 : new() + { } } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] - public async Task TestValidInitializerExpressionAsync() + public async Task TestPropertyAccessorListAsync() { string testCode = @" -using System.Collections.Generic; -class ClassName +using System; + +class Container { - void EmptyInitializersMethod() + int Property1 { - // array initializer - int[] array = { }; - - // collection initializer - List list = new List { }; - - // complex element initializer - Dictionary dictionary = new Dictionary { }; + [My] + get; - // object initializer - var obj = new StructName { }; + set; } - void SingleLineInitializersMethod() + int Property2 { - // array initializer - int[] array = { 0 }; + [My] +get; - // collection initializer - List list = new List { 0 }; + set; + } - // complex element initializer - Dictionary dictionary = new Dictionary { { 0, 0 } }; + int Property3 + { + [My] get; - // object initializer - var obj = new StructName { X = 0 }; + set; } +} - void SingleElementInitializersMethod() +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; + +class Container +{ + int Property1 { - // array initializer - int[] array = - { - 0, - }; + [My] + get; - // collection initializer - List list = - new List - { - 0, - }; + set; + } - // complex element initializer - Dictionary dictionary = - new Dictionary - { - { 0, 0 }, - }; + int Property2 + { + [My] + get; - // object initializer - var obj = - new StructName - { - X = 0, - }; + set; } - void SharedLineInitializersMethod() + int Property3 { - // array initializer - int[] array = - { - 0, 0, - }; - - // collection initializer - List list = - new List - { - 0, 0, - }; - - // complex element initializer - Dictionary dictionary = - new Dictionary - { - { 0, 0 }, { 0, 0 }, - }; + [My] get; - // object initializer - var obj = - new StructName - { - X = 0, Y = 0, - }; + set; } } -struct StructName -{ - public int X, Y, Z; -} +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; - await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), + }; + + await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] - public async Task TestInitializerExpressionAsync() + public async Task TestIndexerAccessorListAsync() { string testCode = @" -using System.Collections.Generic; -class ClassName +using System; + +interface IContainer1 { - void NonZeroAlignmentMethod() + int this[int arg] { - // array initializer - int[] array = - { - 0, - 0, -0, - }; - - // collection initializer - List list = - new List - { - 0, - 0, -0, - }; - - // complex element initializer - Dictionary dictionary = - new Dictionary - { - { 0, 0 }, - { 0, 0 }, -{ 0, 0 }, - }; + [My] + get; - // object initializer - var obj = - new StructName - { - X = 0, - Y = 0, -Z = 0, - }; + set; } +} - void ZeroAlignmentMethod() +interface IContainer2 +{ + int this[int arg] { - // array initializer - int[] array = - { -0, - 0, - 0, - }; - - // collection initializer - List list = - new List - { -0, - 0, - 0, - }; - - // complex element initializer - Dictionary dictionary = - new Dictionary - { -{ 0, 0 }, - { 0, 0 }, - { 0, 0 }, - }; + [My] +get; - // object initializer - var obj = - new StructName - { -X = 0, - Y = 0, - Z = 0, - }; + set; } } -struct StructName +interface IContainer3 { - public int X, Y, Z; + int this[int arg] + { + [My] get; + + set; + } } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; string fixedCode = @" -using System.Collections.Generic; -class ClassName +using System; + +interface IContainer1 { - void NonZeroAlignmentMethod() + int this[int arg] { - // array initializer - int[] array = - { - 0, - 0, - 0, - }; - - // collection initializer - List list = - new List - { - 0, - 0, - 0, - }; - - // complex element initializer - Dictionary dictionary = - new Dictionary - { - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - }; + [My] + get; - // object initializer - var obj = - new StructName - { - X = 0, - Y = 0, - Z = 0, - }; + set; } +} - void ZeroAlignmentMethod() +interface IContainer2 +{ + int this[int arg] { - // array initializer - int[] array = - { -0, -0, -0, - }; - - // collection initializer - List list = - new List - { -0, -0, -0, - }; - - // complex element initializer - Dictionary dictionary = - new Dictionary - { -{ 0, 0 }, -{ 0, 0 }, -{ 0, 0 }, - }; + [My] + get; - // object initializer - var obj = - new StructName - { -X = 0, -Y = 0, -Z = 0, - }; + set; } } -struct StructName +interface IContainer3 { - public int X, Y, Z; -} -"; - - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(38, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(39, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(49, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(50, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(58, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(59, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(67, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(68, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(76, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(77, 1), + int this[int arg] + { + [My] get; + + set; + } +} + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + + DiagnosticResult[] expected = + { + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(32, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -1908,101 +1918,82 @@ struct StructName } [Fact] - public async Task TestValidAnonymousObjectCreationExpressionAsync() + public async Task TestEventAccessorListAsync() { string testCode = @" -class ClassName +using System; + +class Container { - void SingleLineInitializersMethod() + event EventHandler Event1 { - var obj = new { X = 0 }; + [My] + add { } + + remove { } } - void SingleElementInitializersMethod() + event EventHandler Event2 { - var obj = - new - { - X = 0, - }; + [My] +add { } + + remove { } } - void SharedLineInitializersMethod() + event EventHandler Event3 { - var obj = - new - { - X = 0, Y = 0, - }; + [My] add { } + + remove { } } } -"; - await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - } +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } +"; + string fixedCode = @" +using System; - [Fact] - public async Task TestAnonymousObjectCreationExpressionAsync() - { - string testCode = @" -class ClassName +class Container { - void NonZeroAlignmentMethod() + event EventHandler Event1 { - var obj = - new - { - X = 0, - Y = 0, -Z = 0, - }; - } + [My] + add { } - void ZeroAlignmentMethod() - { - var obj = - new - { -X = 0, - Y = 0, - Z = 0, - }; + remove { } } -} -"; - string fixedCode = @" -class ClassName -{ - void NonZeroAlignmentMethod() + + event EventHandler Event2 { - var obj = - new - { - X = 0, - Y = 0, - Z = 0, - }; + [My] + add { } + + remove { } } - void ZeroAlignmentMethod() + event EventHandler Event3 { - var obj = - new - { -X = 0, -Y = 0, -Z = 0, - }; + [My] add { } + + remove { } } } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2011,33 +2002,132 @@ void ZeroAlignmentMethod() } [Fact] - public async Task TestDestructorDeclarationAsync() + public async Task TestValidVariableDeclarationAsync() { string testCode = @" -class ClassName -{ -~ClassName() +using System; +class Container { -return; + private int T1; + private int + T2; + private int + T3, T4; + + private event EventHandler T5; + private event EventHandler + T6; + private event EventHandler + T7, T8; + + void MethodName() + { + int t1; + int + t2; + int + t3, t4; + } } +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestVariableDeclarationAsync() + { + string testCode = @" +using System; +class Container +{ + private int + X1, + Y1, +Z1; + + private int +X2, + Y2, + Z2; + + private event EventHandler + X3, + Y3, +Z3; + + private event EventHandler +X4, + Y4, + Z4; + + void MethodName() + { + int + X1, + Y1, +Z1; + + int +X2, + Y2, + Z2; + } } "; string fixedCode = @" -class ClassName +using System; +class Container { - ~ClassName() + private int + X1, + Y1, + Z1; + + private int +X2, +Y2, +Z2; + + private event EventHandler + X3, + Y3, + Z3; + + private event EventHandler +X4, +Y4, +Z4; + + void MethodName() { - return; + int + X1, + Y1, + Z1; + + int +X2, +Y2, +Z2; } } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(8, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(22, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(23, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(29, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(30, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(34, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(35, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2045,34 +2135,67 @@ class ClassName await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } - [Fact] - public async Task TestOperatorDeclarationAsync() + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestValidTypeParameterListAsync(string prefix, string suffix) { - string testCode = @" -class ClassName -{ -public static bool operator !(ClassName obj) -{ -return false; -} -} + string testCode = $@" +class Container +{{ + {prefix} ClassName1{suffix} + + {prefix} ClassName2< + T>{suffix} + + {prefix} ClassName3< + T1, T2>{suffix} +}} "; - string fixedCode = @" -class ClassName -{ - public static bool operator !(ClassName obj) - { - return false; - } -} + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [InlineData("class", " { }")] + [InlineData("void", "() { }")] + public async Task TestTypeParameterListAsync(string prefix, string suffix) + { + string testCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, +Z>{suffix} + + {prefix} ZeroAlignment< +X, + Y, + Z>{suffix} +}} +"; + string fixedCode = $@" +class Container +{{ + {prefix} NonZeroAlignment< + X, + Y, + Z>{suffix} + + {prefix} ZeroAlignment< + X, + Y, + Z>{suffix} +}} "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2081,33 +2204,43 @@ class ClassName } [Fact] - public async Task TestConversionOperatorDeclarationAsync() + public async Task TestParameterListAsync() { string testCode = @" -class ClassName -{ -public static explicit operator bool(ClassName obj) +class Container { -return false; -} + void NonZeroAlignment( + int X, + int Y, +int Z) { } + + void ZeroAlignment( +int X, + int Y, + int Z) { } } "; string fixedCode = @" -class ClassName +class Container { - public static explicit operator bool(ClassName obj) - { - return false; - } + void NonZeroAlignment( + int X, + int Y, + int Z) { } + + void ZeroAlignment( + int X, + int Y, + int Z) { } } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(4, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(5, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2116,40 +2249,40 @@ public static explicit operator bool(ClassName obj) } [Fact] - public async Task TestCheckedStatementAsync() + public async Task TestBracketedParameterListAsync() { string testCode = @" -class ClassName -{ - void MethodName() - { -checked +class Container1 { -int y = 3 + 2; + int this[ + int X, + int Y, +int Z] => 0; } -unchecked +class Container2 { -int y = 3 + 2; -} - } + int this[ +int X, + int Y, + int Z] => 0; } "; string fixedCode = @" -class ClassName +class Container1 { - void MethodName() - { - checked - { - int y = 3 + 2; - } + int this[ + int X, + int Y, + int Z] => 0; +} - unchecked - { - int y = 3 + 2; - } - } +class Container2 +{ + int this[ + int X, + int Y, + int Z] => 0; } "; @@ -2157,10 +2290,6 @@ void MethodName() { this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), }; @@ -2171,67 +2300,43 @@ void MethodName() } [Fact] - public async Task TestDoStatementAsync() + public async Task TestArgumentListAsync() { string testCode = @" -class ClassName -{ - void MethodName() - { -do +class Container { -int y = 3 + 2; -} -while (true); - -do -return; -while (true); + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, +0); -do -do -return; -while (true); -while (true); - } + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, + 0, + 0); } "; string fixedCode = @" -class ClassName +class Container { - void MethodName() - { - do - { - int y = 3 + 2; - } - while (true); - - do - return; -while (true); + int NonZeroAlignment(int x, int y, int z) => NonZeroAlignment( + 0, + 0, + 0); - do - do - return; -while (true); -while (true); - } + int ZeroAlignment(int x, int y, int z) => ZeroAlignment( +0, +0, +0); } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(11, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(12, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2240,60 +2345,49 @@ void MethodName() } [Fact] - public async Task TestFixedStatementAsync() + public async Task TestBracketedArgumentListAsync() { string testCode = @" -class ClassName -{ - unsafe void MethodName() - { - int[] x = new int[1]; -fixed (int* p = &x[0]) +class Container1 { -int y = 3 + 2; + int this[int x, int y, int z] => this[ + 0, + 0, +0]; } -fixed (int* p = &x[0]) -return; - -fixed (int* p = &x[0]) -fixed (int* q = &x[0]) -return; - } +class Container2 +{ + int this[int x, int y, int z] => this[ +0, + 0, + 0]; } "; string fixedCode = @" -class ClassName +class Container1 { - unsafe void MethodName() - { - int[] x = new int[1]; - fixed (int* p = &x[0]) - { - int y = 3 + 2; - } - - fixed (int* p = &x[0]) - return; + int this[int x, int y, int z] => this[ + 0, + 0, + 0]; +} - fixed (int* p = &x[0]) - fixed (int* q = &x[0]) - return; - } +class Container2 +{ + int this[int x, int y, int z] => this[ +0, +0, +0]; } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(6, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(7, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2302,58 +2396,59 @@ unsafe void MethodName() } [Fact] - public async Task TestForEachStatementAsync() + public async Task TestAssemblyAttributeListAsync() { string testCode = @" -class ClassName -{ - void MethodName() - { -foreach (int x in new int[3]) -{ -int y = 3 + 2; -} +using System; -foreach (int x in new int[3]) -return; +[assembly: My] +[assembly: + My] +[assembly: + My, My] -foreach (int x in new int[3]) -foreach (int y in new int[3]) -return; - } -} +[assembly: + My, + My, +My] +[assembly: +My, + My, + My] + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; string fixedCode = @" -class ClassName -{ - void MethodName() - { - foreach (int x in new int[3]) - { - int y = 3 + 2; - } +using System; - foreach (int x in new int[3]) - return; +[assembly: My] +[assembly: + My] +[assembly: + My, My] - foreach (int x in new int[3]) - foreach (int y in new int[3]) - return; - } -} +[assembly: + My, + My, + My] +[assembly: + My, + My, + My] + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2362,58 +2457,71 @@ void MethodName() } [Fact] - public async Task TestForStatementAsync() + public async Task TestAttributeListAsync() { string testCode = @" -class ClassName -{ - void MethodName() - { -for (int i = 0; i < 3; i++) +using System; + +[My] +[ + My] +[ + My, My] +class TypeName1 { -int y = 3 + 2; } -for (int i = 0; i < 3; i++) -return; - -for (int i = 0; i < 3; i++) -for (int j = 0; j < 3; j++) -return; - } +[ + My, + My, +My] +[ +My, + My, + My] +class TypeName2 +{ } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; string fixedCode = @" -class ClassName -{ - void MethodName() - { - for (int i = 0; i < 3; i++) - { - int y = 3 + 2; - } +using System; - for (int i = 0; i < 3; i++) - return; +[My] +[ + My] +[ + My, My] +class TypeName1 +{ +} - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) - return; - } +[ + My, + My, + My] +[ + My, + My, + My] +class TypeName2 +{ } + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2422,206 +2530,83 @@ void MethodName() } [Fact] - public async Task TestIfStatementAsync() + public async Task TestAttributeArgumentListAsync() { string testCode = @" -class ClassName -{ - void MethodName() - { -if (1 == 2) -{ -int y = 3 + 2; -} -else if (2 == 3) -{ -int y = 3 + 2; -} -else -{ -int y = 3 + 2; -} - -if (1 == 2) -return; -else if (2 == 3) -{ -int y = 3 + 2; -} -else -{ -int y = 3 + 2; -} - -if (1 == 2) -{ -int y = 3 + 2; -} -else if (2 == 3) -return; -else -{ -int y = 3 + 2; -} - -if (1 == 2) -{ -int y = 3 + 2; -} -else if (2 == 3) -{ -int y = 3 + 2; -} -else -return; +using System; -if (1 == 2) +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 { -int y = 3 + 2; } -else -{ -if (2 == 3) + +[My( + 0, + Y = 2, +Z = 3)] +[My( +0, + Y = 2, + Z = 3)] +class TypeName2 { -int y = 3 + 2; } -else + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute { -return; -} -} - } + public MyAttribute() { } + public MyAttribute(int value) { } + + public int Y { get; set; } + public int Z { get; set; } } "; string fixedCode = @" -class ClassName -{ - void MethodName() - { - if (1 == 2) - { - int y = 3 + 2; - } - else if (2 == 3) - { - int y = 3 + 2; - } - else - { - int y = 3 + 2; - } +using System; - if (1 == 2) - return; - else if (2 == 3) - { - int y = 3 + 2; - } - else - { - int y = 3 + 2; - } +[My(0)] +[My( + 0)] +[My( + 0, Y = 2)] +class TypeName1 +{ +} - if (1 == 2) - { - int y = 3 + 2; - } - else if (2 == 3) - return; - else - { - int y = 3 + 2; - } +[My( + 0, + Y = 2, + Z = 3)] +[My( +0, +Y = 2, +Z = 3)] +class TypeName2 +{ +} - if (1 == 2) - { - int y = 3 + 2; - } - else if (2 == 3) - { - int y = 3 + 2; - } - else - return; +[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] +class MyAttribute : Attribute +{ + public MyAttribute() { } + public MyAttribute(int value) { } - if (1 == 2) - { - int y = 3 + 2; - } - else - { - if (2 == 3) - { - int y = 3 + 2; - } - else - { - return; - } - } - } + public int Y { get; set; } + public int Z { get; set; } } "; DiagnosticResult[] expected = { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(25, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(28, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(32, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(33, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(34, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(35, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(36, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(37, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(38, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(39, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(41, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(42, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(43, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(44, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(45, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(46, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(47, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(48, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(49, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(50, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(52, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(53, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(54, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(55, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(56, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(57, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(58, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(59, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(60, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(61, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(62, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(63, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(64, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(65, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(66, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(15, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(16, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1137DiagnosticId).WithLocation(20, 1), }; await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); @@ -2630,225 +2615,272 @@ void MethodName() } [Fact] - public async Task TestLockStatementAsync() + public async Task TestBlockStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.BlockStatementTestCode, this.BlockStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.BlockStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.BlockStatementTestCode, this.BlockStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestSwitchStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.SwitchStatementTestCode, this.SwitchStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.SwitchStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.SwitchStatementTestCode, this.SwitchStatementFixedCode, numberOfFixAllIterations: 2, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + public async Task TestValidInitializerExpressionAsync() { string testCode = @" +using System.Collections.Generic; class ClassName { - void MethodName() + void EmptyInitializersMethod() { -lock (new object()) -{ -int y = 3 + 2; -} + // array initializer + int[] array = { }; -lock (new object()) -return; + // collection initializer + List list = new List { }; -lock (new object()) -lock (new object()) -return; + // complex element initializer + Dictionary dictionary = new Dictionary { }; + + // object initializer + var obj = new StructName { }; } -} -"; - string fixedCode = @" -class ClassName -{ - void MethodName() + + void SingleLineInitializersMethod() + { + // array initializer + int[] array = { 0 }; + + // collection initializer + List list = new List { 0 }; + + // complex element initializer + Dictionary dictionary = new Dictionary { { 0, 0 } }; + + // object initializer + var obj = new StructName { X = 0 }; + } + + void SingleElementInitializersMethod() + { + // array initializer + int[] array = + { + 0, + }; + + // collection initializer + List list = + new List + { + 0, + }; + + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, + }; + } + + void SharedLineInitializersMethod() { - lock (new object()) + // array initializer + int[] array = { - int y = 3 + 2; - } + 0, 0, + }; - lock (new object()) - return; + // collection initializer + List list = + new List + { + 0, 0, + }; - lock (new object()) - lock (new object()) - return; + // complex element initializer + Dictionary dictionary = + new Dictionary + { + { 0, 0 }, { 0, 0 }, + }; + + // object initializer + var obj = + new StructName + { + X = 0, Y = 0, + }; } } + +struct StructName +{ + public int X, Y, Z; +} "; - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - }; + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + [Fact] + public async Task TestInitializerExpressionAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.InitializerExpressionTestCode, this.InitializerExpressionExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.InitializerExpressionFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.InitializerExpressionTestCode, this.InitializerExpressionFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] - public async Task TestUsingStatementAsync() + public async Task TestValidAnonymousObjectCreationExpressionAsync() { string testCode = @" -using System; class ClassName { - void MethodName() + void SingleLineInitializersMethod() { -using (default(IDisposable)) -{ -int y = 3 + 2; -} - -using (default(IDisposable)) -using (default(IDisposable)) -{ -int y = 3 + 2; -} - -using (default(IDisposable)) -{ -using (default(IDisposable)) -{ -int y = 3 + 2; -} -} + var obj = new { X = 0 }; + } -using (default(IDisposable)) -return; + void SingleElementInitializersMethod() + { + var obj = + new + { + X = 0, + }; + } -using (default(IDisposable)) -using (default(IDisposable)) -return; + void SharedLineInitializersMethod() + { + var obj = + new + { + X = 0, Y = 0, + }; } } "; - string fixedCode = @" -using System; -class ClassName -{ - void MethodName() - { - using (default(IDisposable)) - { - int y = 3 + 2; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); } - using (default(IDisposable)) - using (default(IDisposable)) - { - int y = 3 + 2; - } + [Fact] + public async Task TestAnonymousObjectCreationExpressionAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.AnonymousObjectCreationExpressionTestCode, this.AnonymousObjectCreationExpressionExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.AnonymousObjectCreationExpressionFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.AnonymousObjectCreationExpressionTestCode, this.AnonymousObjectCreationExpressionFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - using (default(IDisposable)) + [Fact] + public async Task TestDestructorDeclarationAsync() { - using (default(IDisposable)) - { - int y = 3 + 2; - } + await this.VerifyCSharpDiagnosticAsync(this.DestructorDeclarationTestCode, this.DestructorDeclarationExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.DestructorDeclarationFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.DestructorDeclarationTestCode, this.DestructorDeclarationFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } - using (default(IDisposable)) - return; + [Fact] + public async Task TestOperatorDeclarationAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.OperatorDeclarationTestCode, this.OperatorDeclarationExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.OperatorDeclarationFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.OperatorDeclarationTestCode, this.OperatorDeclarationFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - using (default(IDisposable)) - using (default(IDisposable)) - return; - } -} -"; + [Fact] + public async Task TestConversionOperatorDeclarationAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.ConversionOperatorDeclarationTestCode, this.ConversionOperatorExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.ConversionOperatorDeclarationFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.ConversionOperatorDeclarationTestCode, this.ConversionOperatorDeclarationFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(21, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(22, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(23, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(24, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(26, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(27, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(29, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(30, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(31, 1), - }; + [Fact] + public async Task TestCheckedStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.CheckedStatementTestCode, this.CheckedStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.CheckedStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.CheckedStatementTestCode, this.CheckedStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + [Fact] + public async Task TestDoStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.DoStatementTestCode, this.DoStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.DoStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.DoStatementTestCode, this.DoStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] - public async Task TestWhileStatementAsync() + public async Task TestFixedStatementAsync() { - string testCode = @" -class ClassName -{ - void MethodName() - { -while (true) -{ -int y = 3 + 2; -} + await this.VerifyCSharpDiagnosticAsync(this.FixedStatementTestCode, this.FixedStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.FixedStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.FixedStatementTestCode, this.FixedStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } -while (true) -return; + [Fact] + public async Task TestForEachStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.ForEachStatementTestCode, this.ForEachStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.ForEachStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.ForEachStatementTestCode, this.ForEachStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } -while (true) -while (true) -return; - } -} -"; - string fixedCode = @" -class ClassName -{ - void MethodName() - { - while (true) + [Fact] + public async Task TestForStatementAsync() { - int y = 3 + 2; + await this.VerifyCSharpDiagnosticAsync(this.ForStatementTestCode, this.ForStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.ForStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.ForStatementTestCode, this.ForStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } - while (true) - return; + [Fact] + public async Task TestIfStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.IfStatementTestCode, this.IfStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.IfStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.IfStatementTestCode, this.IfStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - while (true) - while (true) - return; - } -} -"; + [Fact] + public async Task TestLockStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.LockStatementTestCode, this.LockStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.LockStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.LockStatementTestCode, this.LockStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - DiagnosticResult[] expected = - { - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(6, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(7, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(8, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(9, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(11, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(15, 1), - this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), - }; + [Fact] + public async Task TestUsingStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.UsingStatementTestCode, this.UsingStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.UsingStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.UsingStatementTestCode, this.UsingStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + } - await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); - await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); + [Fact] + public async Task TestWhileStatementAsync() + { + await this.VerifyCSharpDiagnosticAsync(this.WhileStatementTestCode, this.WhileStatementExpectedDiagnostics, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpDiagnosticAsync(this.WhileStatementFixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + await this.VerifyCSharpFixAsync(this.WhileStatementTestCode, this.WhileStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } [Fact] From ce0ee0509aa577f37edd1928339445d711a56cdf Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 05:27:26 -0600 Subject: [PATCH 42/47] Check while token of do statement with a non-block body --- .../ReadabilityRules/SA1138UnitTests.cs | 9 ++++++--- .../SA1137ElementsShouldHaveTheSameIndentation.cs | 9 +++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index f32bc5859..2427181a2 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -614,13 +614,13 @@ void MethodName() do return; -while (true); + while (true); do do return; -while (true); -while (true); + while (true); + while (true); } } "; @@ -635,9 +635,12 @@ void MethodName() this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(10, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(12, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(13, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(14, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(16, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(17, 1), this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(18, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(19, 1), + this.CSharpDiagnostic(SA1137ElementsShouldHaveTheSameIndentation.SA1138DiagnosticId).WithLocation(20, 1), }; protected string FixedStatementTestCode => @" diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 3ed858444..ee21b1b41 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -1012,16 +1012,21 @@ private void AnalyzeCheckedStatement(CheckedStatementSyntax node) private void AnalyzeDoStatement(DoStatementSyntax node) { + ImmutableArray tokens; + if (node.Statement.IsKind(SyntaxKind.Block)) { BlockSyntax block = (BlockSyntax)node.Statement; - var tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken, node.WhileKeyword); - CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); + tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), block.OpenBraceToken, block.CloseBraceToken, node.WhileKeyword); } else { + tokens = ImmutableArray.Create(GetFirstTokenForAnalysis(node), node.WhileKeyword); + CheckElements(this.context, this.compilation, this.settings, this.IndentationLevel, ImmutableList.Create(node.Statement)); } + + CheckTokens(this.context, this.compilation, this.settings, this.IndentationLevel - 1, tokens); } private void AnalyzeFixedStatement(FixedStatementSyntax node) From 0a08feb77a9b2fcfeef5dcb934f5a0a30c664543 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 05:33:32 -0600 Subject: [PATCH 43/47] Fix indentation of 'else if' --- .../ReadabilityRules/SA1138UnitTests.cs | 12 ++++++------ .../SA1137ElementsShouldHaveTheSameIndentation.cs | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index 2427181a2..c0879b795 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -888,22 +888,22 @@ void MethodName() } else if (2 == 3) { - int y = 3 + 2; + int y = 3 + 2; } else { - int y = 3 + 2; + int y = 3 + 2; } if (1 == 2) return; else if (2 == 3) { - int y = 3 + 2; + int y = 3 + 2; } else { - int y = 3 + 2; + int y = 3 + 2; } if (1 == 2) @@ -914,7 +914,7 @@ void MethodName() return; else { - int y = 3 + 2; + int y = 3 + 2; } if (1 == 2) @@ -923,7 +923,7 @@ void MethodName() } else if (2 == 3) { - int y = 3 + 2; + int y = 3 + 2; } else return; diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index ee21b1b41..97514fce5 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -778,7 +778,8 @@ public override void VisitForStatement(ForStatementSyntax node) public override void VisitIfStatement(IfStatementSyntax node) { - using (this.AdjustIndentation(1)) + int adjustment = node.Parent.IsKind(SyntaxKind.ElseClause) ? 0 : 1; + using (this.AdjustIndentation(adjustment)) { this.AnalyzeIfStatement(node); base.VisitIfStatement(node); From aa57c35456130b7e09c88ed855d80addc1290c9c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 11 Jan 2016 05:36:14 -0600 Subject: [PATCH 44/47] Fix indentation of consecutive using statements --- .../ReadabilityRules/SA1138UnitTests.cs | 10 +++++----- .../SA1137ElementsShouldHaveTheSameIndentation.cs | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index c0879b795..d81fefcc9 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -1110,10 +1110,10 @@ void MethodName() } using (default(IDisposable)) - using (default(IDisposable)) - { + using (default(IDisposable)) + { int y = 3 + 2; - } + } using (default(IDisposable)) { @@ -1127,8 +1127,8 @@ void MethodName() return; using (default(IDisposable)) - using (default(IDisposable)) - return; + using (default(IDisposable)) + return; } } "; diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 97514fce5..1e822019c 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -807,7 +807,8 @@ public override void VisitLockStatement(LockStatementSyntax node) public override void VisitUsingStatement(UsingStatementSyntax node) { // Allow consecutive using statements without nesting indentation. - using (this.AdjustIndentation(node.Statement.IsKind(SyntaxKind.UsingStatement) ? 0 : 1)) + int adjustment = node.Parent.IsKind(SyntaxKind.UsingStatement) ? 0 : 1; + using (this.AdjustIndentation(adjustment)) { this.AnalyzeUsingStatement(node); base.VisitUsingStatement(node); From 2dac7e2aa9f1722f90c13be2a91bc438767d72db Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 15 Jan 2016 15:08:35 -0600 Subject: [PATCH 45/47] Make sure token alignment considers non-whitespace leading trivia --- .../ReadabilityRules/SA1138UnitTests.cs | 22 +++++++++++++++++++ ...137ElementsShouldHaveTheSameIndentation.cs | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index d81fefcc9..e5c1928c8 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -2625,6 +2625,28 @@ public async Task TestBlockStatementAsync() await this.VerifyCSharpFixAsync(this.BlockStatementTestCode, this.BlockStatementFixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false); } + [Fact] + public async Task TestLeadingCommentAsync() + { + string testCode = @" +using System.Collections.Generic; +class ClassName +{ + void MethodName() + { + /* var x = */ new List(); + var y = new List(); + + if (true) + /* things */ { + } + } +} +"; + + await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + [Fact] public async Task TestSwitchStatementAsync() { diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs index 1e822019c..b591a93e4 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1137ElementsShouldHaveTheSameIndentation.cs @@ -278,7 +278,7 @@ private static void CheckTokens(SyntaxTreeAnalysisContext context, Compilation c tokens = tokens.RemoveAll( token => { - return token.IsMissingOrDefault() || !token.IsFirstInLine(); + return token.IsMissingOrDefault() || !token.IsFirstInLine(allowNonWhitespaceTrivia: false); }); if (tokens.IsEmpty || (tokens.Length == 1 && !enableAbsoluteIndentationAnalysis)) From 2bd4822b21f4cb6a9e0f27d0f02a1327d0118c62 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 17 Jan 2016 12:46:33 -0600 Subject: [PATCH 46/47] Rename GenerateIndentationString to GenerateIndentationStringForSteps This method doesn't produce an indentation string for an arbitrary width, which makes it not suitable for general indentation adjustments. Renaming the method allows for the creation of a more general GenerateIndentationString method later. --- .../Helpers/IndentationHelper.cs | 4 ++-- .../LayoutRules/SA1501CodeFixProvider.cs | 8 ++++---- .../LayoutRules/SA1502CodeFixProvider.cs | 4 ++-- .../OrderingRules/ElementOrderCodeFixProvider.cs | 2 +- .../OrderingRules/UsingCodeFixProvider.cs | 6 +++--- .../ReadabilityRules/SA1116CodeFixProvider.cs | 2 +- .../ReadabilityRules/SA1127CodeFixProvider.cs | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs index 5df50b460..d9a4c8aa7 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs @@ -65,7 +65,7 @@ public static int GetIndentationSteps(IndentationSettings indentationSettings, S /// The indentation settings to use. /// The number of indentation steps. /// A string containing the amount of whitespace needed for the given indentation steps. - public static string GenerateIndentationString(IndentationSettings indentationSettings, int indentationSteps) + public static string GenerateIndentationStringForSteps(IndentationSettings indentationSettings, int indentationSteps) { string result; var indentationCount = indentationSteps * indentationSettings.IndentationSize; @@ -91,7 +91,7 @@ public static string GenerateIndentationString(IndentationSettings indentationSe /// A containing the indentation whitespace. public static SyntaxTrivia GenerateWhitespaceTrivia(IndentationSettings indentationSettings, int indentationSteps) { - return SyntaxFactory.Whitespace(GenerateIndentationString(indentationSettings, indentationSteps)); + return SyntaxFactory.Whitespace(GenerateIndentationStringForSteps(indentationSettings, indentationSteps)); } private static int GetIndentationSteps(IndentationSettings indentationSettings, SyntaxTree syntaxTree, SyntaxTriviaList leadingTrivia) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1501CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1501CodeFixProvider.cs index 3fc40f955..df5b1df0a 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1501CodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1501CodeFixProvider.cs @@ -135,7 +135,7 @@ private static SyntaxNode ReformatStatementAndParent(Document document, Indentat if (nextTokenLine == statementCloseLine) { var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(statement.Parent)); - var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); + var indentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel); newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } @@ -179,8 +179,8 @@ private static BlockSyntax ReformatBlock(Document document, IndentationSettings break; } - var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); - var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); + var indentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel); + var statementIndentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel + 1); var newOpenBraceLeadingTrivia = block.OpenBraceToken.LeadingTrivia .WithoutTrailingWhitespace() @@ -258,7 +258,7 @@ private static StatementSyntax ReformatStatement(Document document, IndentationS break; } - var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); + var statementIndentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel + 1); var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia .WithoutTrailingWhitespace() diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1502CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1502CodeFixProvider.cs index 699963de4..ef1f6e1f6 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1502CodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1502CodeFixProvider.cs @@ -132,8 +132,8 @@ private SyntaxNode ReformatElement(SyntaxNode syntaxRoot, SyntaxNode element, Sy } var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, element); - var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel); - var contentIndentationString = IndentationHelper.GenerateIndentationString(indentationSettings, parentIndentationLevel + 1); + var indentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel); + var contentIndentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, parentIndentationLevel + 1); // reformat opening brace tokenSubstitutions.Add(openBraceToken, this.FormatBraceToken(openBraceToken, indentationString)); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/ElementOrderCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/ElementOrderCodeFixProvider.cs index 8edffa7ab..688a589e2 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/ElementOrderCodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/ElementOrderCodeFixProvider.cs @@ -141,7 +141,7 @@ private static SyntaxNode MoveMember(SyntaxNode syntaxRoot, MemberDeclarationSyn if (!memberToMove.HasLeadingTrivia) { var targetIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, targetMember); - var indentationString = IndentationHelper.GenerateIndentationString(indentationSettings, targetIndentationLevel); + var indentationString = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, targetIndentationLevel); memberToMove = memberToMove.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs index 7f2457ed9..7817bae10 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/OrderingRules/UsingCodeFixProvider.cs @@ -123,7 +123,7 @@ private static async Task GetTransformedDocumentAsync(Document documen { var rootNamespace = compilationUnit.Members.OfType().First(); var indentationLevel = IndentationHelper.GetIndentationSteps(settings.Indentation, rootNamespace); - usingsIndentation = IndentationHelper.GenerateIndentationString(settings.Indentation, indentationLevel + 1); + usingsIndentation = IndentationHelper.GenerateIndentationStringForSteps(settings.Indentation, indentationLevel + 1); } else { @@ -203,7 +203,7 @@ private static void BuildReplaceMapForNamespaces(UsingsHelper usingsHelper, Dict indentationSteps++; } - var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); + var indentation = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(usingList, indentation, false, qualifyNames); @@ -231,7 +231,7 @@ private static void BuildReplaceMapForConditionalDirectives(UsingsHelper usingsH indentationSteps++; } - var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); + var indentation = IndentationHelper.GenerateIndentationStringForSteps(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(childSpan, indentation, false, qualifyNames: false); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1116CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1116CodeFixProvider.cs index 2c4b8fb9b..3e941790b 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1116CodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1116CodeFixProvider.cs @@ -74,7 +74,7 @@ private static async Task GetTransformedDocumentAsync(Document documen SyntaxTriviaList newTrivia = SyntaxFactory.TriviaList( SyntaxFactory.CarriageReturnLineFeed, - SyntaxFactory.Whitespace(lineText.Substring(0, indentLength) + IndentationHelper.GenerateIndentationString(settings.Indentation, 1))); + SyntaxFactory.Whitespace(lineText.Substring(0, indentLength) + IndentationHelper.GenerateIndentationStringForSteps(settings.Indentation, 1))); SyntaxToken updatedToken = originalToken.WithLeadingTrivia(originalToken.LeadingTrivia.AddRange(newTrivia)); SyntaxNode updatedRoot = root.ReplaceToken(originalToken, updatedToken); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1127CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1127CodeFixProvider.cs index 1eebf0589..f4dbc03dc 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1127CodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1127CodeFixProvider.cs @@ -61,7 +61,7 @@ private static async Task GetTransformedDocumentAsync(Document documen var parentIndentation = GetParentIndentation(whereToken); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); - var indentationTrivia = SyntaxFactory.Whitespace(parentIndentation + IndentationHelper.GenerateIndentationString(settings.Indentation, 1)); + var indentationTrivia = SyntaxFactory.Whitespace(parentIndentation + IndentationHelper.GenerateIndentationStringForSteps(settings.Indentation, 1)); var replaceMap = new Dictionary() { From d95082a4e8c95cb322cfc41fc0d0aebdff9f0c1a Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Sun, 17 Jan 2016 12:50:14 -0600 Subject: [PATCH 47/47] Update indentation code fix provider to adjust an entire element This change allows for for accurate indentation adjustments of single code elements which span multiple lines. Since the fix all provider has not been updated to account for the new behavior, it is disabled for now. --- .../Helpers/IndentationHelper.cs | 37 ++++ .../IndentationCodeFixProvider.cs | 162 ++++++++++++++++-- .../ReadabilityRules/SA1137UnitTests.cs | 42 ++--- .../ReadabilityRules/SA1138UnitTests.cs | 36 ++-- .../Helpers/SyntaxTreeHelpers.cs | 114 ++++++++++++ 5 files changed, 337 insertions(+), 54 deletions(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs index d9a4c8aa7..a9717335b 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/IndentationHelper.cs @@ -3,6 +3,7 @@ namespace StyleCop.Analyzers.Helpers { + using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Settings.ObjectModel; @@ -83,6 +84,42 @@ public static string GenerateIndentationStringForSteps(IndentationSettings inden return result; } + /// + /// Generate a new indentation string for the given indentation width. + /// + /// The indentation settings to use. + /// The width of the indentation string. + /// A string containing the whitespace needed to indent code to the specified width. + public static string GenerateIndentationString(IndentationSettings indentationSettings, int indentationWidth) => + GenerateIndentationString(indentationSettings, indentationWidth, 0); + + /// + /// Generate a new indentation string for the given indentation width. + /// + /// The indentation settings to use. + /// The width of the indentation string. + /// The starting column for the indentation. + /// A string containing the whitespace needed to indent code to the specified width. + public static string GenerateIndentationString(IndentationSettings indentationSettings, int indentationWidth, int startColumn) + { + if (!indentationSettings.UseTabs) + { + return new string(' ', indentationWidth); + } + + // Adjust the indentation width so a narrower first tab doesn't affect the outcome + indentationWidth += startColumn % indentationSettings.TabSize; + + int tabCount = indentationWidth / indentationSettings.TabSize; + int spaceCount = indentationWidth - (tabCount * indentationSettings.TabSize); + + StringBuilder builder = StringBuilderPool.Allocate(); + builder.EnsureCapacity(tabCount + spaceCount); + builder.Append('\t', tabCount); + builder.Append(' ', spaceCount); + return StringBuilderPool.ReturnAndFree(builder); + } + /// /// Generates a whitespace trivia with the requested indentation. /// diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs index 0942a2cd0..4456da340 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/IndentationCodeFixProvider.cs @@ -12,7 +12,9 @@ namespace StyleCop.Analyzers.ReadabilityRules using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; + using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Text; + using Settings.ObjectModel; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(IndentationCodeFixProvider))] [Shared] @@ -26,7 +28,7 @@ internal class IndentationCodeFixProvider : CodeFixProvider /// public sealed override FixAllProvider GetFixAllProvider() => - FixAll.Instance; + null; /// public override Task RegisterCodeFixesAsync(CodeFixContext context) @@ -48,26 +50,28 @@ private static async Task GetTransformedDocumentAsync(Document documen { var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); - TextChange textChange; - if (!TryGetTextChange(diagnostic, syntaxRoot, out textChange)) + StyleCopSettings settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); + ImmutableArray textChanges = await GetTextChangesAsync(diagnostic, syntaxRoot, settings.Indentation, cancellationToken).ConfigureAwait(false); + if (textChanges.IsEmpty) { return document; } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - return document.WithText(text.WithChanges(textChange)); + return document.WithText(text.WithChanges(textChanges)); } - private static bool TryGetTextChange(Diagnostic diagnostic, SyntaxNode syntaxRoot, out TextChange textChange) + private static async Task> GetTextChangesAsync(Diagnostic diagnostic, SyntaxNode syntaxRoot, IndentationSettings indentationSettings, CancellationToken cancellationToken) { string replacement; if (!diagnostic.Properties.TryGetValue(SA1137ElementsShouldHaveTheSameIndentation.ExpectedIndentationKey, out replacement)) { - textChange = default(TextChange); - return false; + return ImmutableArray.Empty; } - var trivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start); + SyntaxTrivia trivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start); + SyntaxToken token = trivia != default(SyntaxTrivia) ? trivia.Token : syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start, findInsideTrivia: true); + SyntaxNode node = GetNodeForAdjustment(token); TextSpan originalSpan; if (trivia == default(SyntaxTrivia)) @@ -80,8 +84,139 @@ private static bool TryGetTextChange(Diagnostic diagnostic, SyntaxNode syntaxRoo originalSpan = trivia.Span; } - textChange = new TextChange(originalSpan, replacement); - return true; + FileLinePositionSpan fullSpan = syntaxRoot.SyntaxTree.GetLineSpan(node.FullSpan, cancellationToken); + if (fullSpan.StartLinePosition.Line == fullSpan.EndLinePosition.Line) + { + return ImmutableArray.Create(new TextChange(originalSpan, replacement)); + } + + SyntaxTree tree = node.SyntaxTree; + SourceText sourceText = await tree.GetTextAsync(cancellationToken).ConfigureAwait(false); + + int originalIndentation = GetIndentationWidth(indentationSettings, sourceText.ToString(originalSpan)); + int newIndentation = GetIndentationWidth(indentationSettings, replacement); + + ImmutableArray excludedSpans = SyntaxTreeHelpers.GetExcludedSpans(node); + TextLineCollection lines = sourceText.Lines; + + // For each line in the full span of the syntax node: + // 1. If the line is indented less than originalIndentation, ignore the line + // 2. If the indentation characters are not located within the full span, ignore the line + // 2. If the indentation characters of the line overlap with an excluded span, ignore the line + // 3. Replace the first original.Length characters on the line with replacement + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(); + for (int i = fullSpan.StartLinePosition.Line; i <= fullSpan.EndLinePosition.Line; i++) + { + TextLine line = lines[i]; + string lineText = sourceText.ToString(line.Span); + + int indentationCount; + int indentationWidth = GetIndentationWidth(indentationSettings, lineText, out indentationCount); + if (indentationWidth < originalIndentation) + { + continue; + } + + if (indentationCount == line.Span.Length) + { + // The line is just whitespace + continue; + } + + TextSpan indentationSpan = new TextSpan(line.Start, indentationCount); + if (indentationSpan.Start >= node.FullSpan.End) + { + // The line does not contain any non-whitespace content which is part of the full span of the node + continue; + } + + if (!node.FullSpan.Contains(indentationSpan)) + { + // The indentation of the line is not part of the full span of the node + continue; + } + + if (IsExcluded(excludedSpans, indentationSpan)) + { + // The line indentation is partially- or fully-excluded from adjustments + continue; + } + + if (originalIndentation == indentationWidth) + { + builder.Add(new TextChange(indentationSpan, replacement)); + } + else if (newIndentation > originalIndentation) + { + // TODO: This needs to handle UseTabs setting + builder.Add(new TextChange(new TextSpan(indentationSpan.End, 0), new string(' ', newIndentation - originalIndentation))); + } + else if (newIndentation < originalIndentation) + { + builder.Add(new TextChange(indentationSpan, IndentationHelper.GenerateIndentationString(indentationSettings, indentationWidth + (newIndentation - originalIndentation)))); + } + } + + return builder.ToImmutable(); + } + + private static SyntaxNode GetNodeForAdjustment(SyntaxToken token) + { + return token.Parent; + } + + private static int GetIndentationWidth(IndentationSettings indentationSettings, string text) + { + int ignored; + return GetIndentationWidth(indentationSettings, text, out ignored); + } + + private static int GetIndentationWidth(IndentationSettings indentationSettings, string text, out int count) + { + int tabSize = indentationSettings.TabSize; + int indentationWidth = 0; + for (int i = 0; i < text.Length; i++) + { + switch (text[i]) + { + case ' ': + indentationWidth++; + break; + + case '\t': + indentationWidth = tabSize * ((indentationWidth / tabSize) + 1); + break; + + default: + count = i; + return indentationWidth; + } + } + + count = text.Length; + return indentationWidth; + } + + private static bool IsExcluded(ImmutableArray excludedSpans, TextSpan textSpan) + { + int index = excludedSpans.BinarySearch(textSpan); + if (index > 0) + { + return true; + } + + int nextLarger = ~index; + if (nextLarger > 0 && excludedSpans[nextLarger - 1].OverlapsWith(textSpan)) + { + return true; + } + + if (nextLarger < excludedSpans.Length - 1 && excludedSpans[nextLarger].OverlapsWith(textSpan)) + { + return true; + } + + return false; } private class FixAll : DocumentBasedFixAllProvider @@ -100,16 +235,13 @@ protected override async Task FixAllInDocumentAsync(FixAllContext fi } var syntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); + StyleCopSettings settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, fixAllContext.CancellationToken); List changes = new List(); foreach (var diagnostic in diagnostics) { - TextChange textChange; - if (TryGetTextChange(diagnostic, syntaxRoot, out textChange)) - { - changes.Add(textChange); - } + changes.AddRange(await GetTextChangesAsync(diagnostic, syntaxRoot, settings.Indentation, fixAllContext.CancellationToken).ConfigureAwait(false)); } changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs index 48180e4bb..6dfe7c278 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1137UnitTests.cs @@ -331,37 +331,37 @@ class MyAttribute : Attribute { } using System; enum Enum1 { - /// - /// Summary. - /// + /// + /// Summary. + /// [My] Element1, - /// - /// Summary. - /// + /// + /// Summary. + /// Element2, } enum Enum2 { - /// - /// Summary. - /// +/// +/// Summary. +/// [My] Element1, - /// - /// Summary. - /// +/// +/// Summary. +/// Element2, } enum Enum3 { - /// - /// Summary. - /// + /// + /// Summary. + /// [My] Element1, /// @@ -1396,13 +1396,13 @@ void MethodName() label3: while (true) { -label4a: -label4b: -int x; + label4a: + label4b: + int x; -label5a: -label5b: -int y; + label5a: + label5b: + int y; } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs index e5c1928c8..e87d2c2c4 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1138UnitTests.cs @@ -1529,42 +1529,42 @@ class MyAttribute : Attribute { } using System; enum Enum1 { - /// - /// Summary. - /// + /// + /// Summary. + /// [My] Element1, - /// - /// Summary. - /// + /// + /// Summary. + /// Element2, } enum Enum2 { - /// - /// Summary. - /// + /// + /// Summary. + /// [My] Element1, - /// - /// Summary. - /// + /// + /// Summary. + /// Element2, } enum Enum3 { - /// - /// Summary. - /// + /// + /// Summary. + /// [My] Element1, - /// - /// Summary. - /// + /// + /// Summary. + /// Element2, } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs index c9e509682..ceff1c9d7 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs @@ -5,11 +5,13 @@ namespace StyleCop.Analyzers.Helpers { using System; using System.Collections.Concurrent; + using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; + using Microsoft.CodeAnalysis.Text; internal static class SyntaxTreeHelpers { @@ -69,6 +71,118 @@ internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictiona return generated; } + /// + /// Locates all spans within the of a syntax node which should be excluded + /// from formatting operations. + /// + /// + /// Spans are excluded from formatting operations any time they have a direct impact on the semantics of + /// the compiled application. Spans are also excluded in cases where the impact is unknown. + /// + /// Spans disabled due to preprocessor directives (). + /// The contents of commented code (comments starting with ////). + /// Content in a CDATA section of an XML comment (). + /// Content in a character literal (). + /// Content in a string literal (). + /// Literal content in an interpolated string literal (). + /// + /// + /// The syntax node to examine. + /// + /// A collection of instances indicating the spans to exclude from formatting operations. + /// The collection is ordered according to the start position of spans, and does not contain any overlapping or + /// adjacent spans. + /// + internal static ImmutableArray GetExcludedSpans(SyntaxNode root) + { + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(); + + // Locate disabled text + foreach (var trivia in root.DescendantTrivia(descendIntoTrivia: true)) + { + if (trivia.IsKind(SyntaxKind.DisabledTextTrivia)) + { + builder.Add(trivia.Span); + } + else if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia)) + { + if (trivia.ToString().StartsWith("////")) + { + // Exclude comments starting with //// because they could contain commented code which contains + // string or character literals, and we don't want to change the contents of those strings. + builder.Add(trivia.Span); + } + } + } + + // Locate string literals + foreach (var token in root.DescendantTokens(descendIntoTrivia: true)) + { + switch (token.Kind()) + { + case SyntaxKind.XmlTextLiteralToken: + if (token.Parent.IsKind(SyntaxKind.XmlCDataSection)) + { + builder.Add(token.Span); + } + + break; + + case SyntaxKind.CharacterLiteralToken: + case SyntaxKind.StringLiteralToken: + case SyntaxKind.InterpolatedStringTextToken: + builder.Add(token.Span); + break; + + default: + break; + } + } + + // Sort the results + builder.Sort(); + + // Combine adjacent and overlapping spans + ReduceTextSpans(builder); + + return builder.ToImmutable(); + } + + private static void ReduceTextSpans(ImmutableArray.Builder sortedTextSpans) + { + if (sortedTextSpans.Count == 0) + { + return; + } + + int currentIndex = 0; + for (int nextIndex = 1; nextIndex < sortedTextSpans.Count; nextIndex++) + { + TextSpan current = sortedTextSpans[currentIndex]; + TextSpan next = sortedTextSpans[nextIndex]; + if (current.End < next.Start) + { + // Increment currentIndex this iteration + currentIndex++; + + // Only increment nextIndex this iteration if necessary to ensure nextIndex > currentIndex on the + // next iteration. At this point we already incremented currentIndex, but haven't incremented + // nextIndex. + if (currentIndex > nextIndex) + { + nextIndex--; + } + + continue; + } + + // Since sortedTextSpans is sorted, we already know current and next overlap + sortedTextSpans[currentIndex] = TextSpan.FromBounds(current.Start, next.End); + } + + sortedTextSpans.Count = currentIndex + 1; + } + private static bool ContainsUsingAliasNoCache(SyntaxTree tree) { var nodes = tree.GetRoot().DescendantNodes(node => node.IsKind(SyntaxKind.CompilationUnit) || node.IsKind(SyntaxKind.NamespaceDeclaration));