diff --git a/StyleChecker/StyleChecker.Test/Framework/BeliefsTests.cs b/StyleChecker/StyleChecker.Test/Framework/BeliefsTests.cs index 6c38d42b..21e5beee 100644 --- a/StyleChecker/StyleChecker.Test/Framework/BeliefsTests.cs +++ b/StyleChecker/StyleChecker.Test/Framework/BeliefsTests.cs @@ -382,7 +382,7 @@ static Result ToResult(Belief b) Assert.AreEqual(3, firstResult.Locations[0].Line); } - private void ExpectCompilationException(string encodedSource) + private static void ExpectCompilationException(string encodedSource) { static Result ToResult(Belief b) => b.ToResult("TestId", b.Message); diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/AnalyzerTest.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/AnalyzerTest.cs new file mode 100644 index 00000000..5a98b5d0 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/AnalyzerTest.cs @@ -0,0 +1,39 @@ +namespace StyleChecker.Test.Spacing.NoSpaceAfterBrace +{ + using Microsoft.VisualStudio.TestTools.UnitTesting; + using StyleChecker.Spacing.NoSpaceAfterBrace; + using StyleChecker.Test.Framework; + + [TestClass] + public sealed class AnalyzerTest : CodeFixVerifier + { + public AnalyzerTest() + : base(new Analyzer(), new CodeFixer()) + { + } + + [TestMethod] + public void Empty() + => VerifyDiagnostic("", Atmosphere.Default); + + [TestMethod] + public void Okay() + { + var code = ReadText("Okay"); + VerifyDiagnostic(code, Atmosphere.Default); + } + + [TestMethod] + public void Code() + { + var code = ReadText("Code"); + var codeFix = ReadText("CodeFix"); + static Result Expected(Belief b) => b.ToResult( + Analyzer.DiagnosticId, + m => $"A white space is needed after '{m}'"); + + VerifyDiagnosticAndFix( + code, Atmosphere.Default, Expected, codeFix); + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Code.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Code.cs new file mode 100644 index 00000000..cf371208 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Code.cs @@ -0,0 +1,34 @@ +#pragma warning disable CS0162 + +namespace Application +{ + using System; + + public sealed class Code + { + public void NG() + { + string[] array = {"" }; + //@ ^{ + + Action doNothing = () => {return; }; + //@ ^{ + + if (array is {Length: 0 }z) + //@ ^{ + //@ ^} + { + } + + if (true) {return; }else{} + //@ ^{ + //@ ^} + + do {}while (false); + //@ ^} + + {}; + //@ ^} + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/CodeFix.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/CodeFix.cs new file mode 100644 index 00000000..4af58517 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/CodeFix.cs @@ -0,0 +1,26 @@ +#pragma warning disable CS0162 + +namespace Application +{ + using System; + + public sealed class Code + { + public void NG() + { + string[] array = { "" }; + + Action doNothing = () => { return; }; + + if (array is { Length: 0 } z) + { + } + + if (true) { return; } else{} + + do {} while (false); + + {} ; + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Okay.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Okay.cs new file mode 100644 index 00000000..bc602a78 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceAfterBrace/Okay.cs @@ -0,0 +1,45 @@ +namespace Application +{ + using System; + + public sealed class Okay + { + public void Basic() + { + if (true) + { + } + var array = new[] { "" }; + var array2 = new[] { + "" }; + var array3 = new[] + { + "", + }; + var array4 = new[] { new[] { "" }, }; + Action doNothing = () => {}; + if (array is { Length: 0 } z) + { + } + if (array is {} e) + { + } + + static void M(string[] a) + { + } + + M(new[] { "" }); + + _ = new[] { "" }.ToString(); + _ = new[] { "" }?.ToString(); + _ = new[] { "" }!; + _ = new[] { "" }[0]; + } + + public void Interpolation(string m) + { + _ = $"{m}"; + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/AnalyzerTest.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/AnalyzerTest.cs new file mode 100644 index 00000000..7248e153 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/AnalyzerTest.cs @@ -0,0 +1,39 @@ +namespace StyleChecker.Test.Spacing.NoSpaceBeforeBrace +{ + using Microsoft.VisualStudio.TestTools.UnitTesting; + using StyleChecker.Spacing.NoSpaceBeforeBrace; + using StyleChecker.Test.Framework; + + [TestClass] + public sealed class AnalyzerTest : CodeFixVerifier + { + public AnalyzerTest() + : base(new Analyzer(), new CodeFixer()) + { + } + + [TestMethod] + public void Empty() + => VerifyDiagnostic("", Atmosphere.Default); + + [TestMethod] + public void Okay() + { + var code = ReadText("Okay"); + VerifyDiagnostic(code, Atmosphere.Default); + } + + [TestMethod] + public void Code() + { + var code = ReadText("Code"); + var codeFix = ReadText("CodeFix"); + static Result Expected(Belief b) => b.ToResult( + Analyzer.DiagnosticId, + m => $"A white space is needed before '{m}'"); + + VerifyDiagnosticAndFix( + code, Atmosphere.Default, Expected, codeFix); + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Code.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Code.cs new file mode 100644 index 00000000..3aa6432c --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Code.cs @@ -0,0 +1,37 @@ +#pragma warning disable CS0162 + +namespace Application +{ + using System; + + public sealed class Code + { + public void NG() + { + string[] array ={ ""}; + //@ ^{ + //@ ^} + + Action doNothing = () =>{ return;}; + //@ ^{ + //@ ^} + + if (array is{ Length: 0} z) + //@ ^{ + //@ ^} + { + } + + if (true){ return;} else{} + //@ ^{ + //@ ^} + //@ ^{ + + do{} while (false); + //@ ^{ + + ;{} + //@ ^{ + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/CodeFix.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/CodeFix.cs new file mode 100644 index 00000000..d3e2305a --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/CodeFix.cs @@ -0,0 +1,26 @@ +#pragma warning disable CS0162 + +namespace Application +{ + using System; + + public sealed class Code + { + public void NG() + { + string[] array = { "" }; + + Action doNothing = () => { return; }; + + if (array is { Length: 0 } z) + { + } + + if (true) { return; } else {} + + do {} while (false); + + ; {} + } + } +} diff --git a/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Okay.cs b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Okay.cs new file mode 100644 index 00000000..e6c8fda6 --- /dev/null +++ b/StyleChecker/StyleChecker.Test/Spacing/NoSpaceBeforeBrace/Okay.cs @@ -0,0 +1,40 @@ +namespace Application +{ + using System; + + public sealed class Okay + { + public void Basic() + { + if (true) + { + } + var array = new[] { "" }; + var array2 = new[] { + "" }; + var array3 = new[] + { + "", + }; + var array4 = new[] { new[] { "" }, }; + Action doNothing = () => {}; + if (array is { Length: 0 } z) + { + } + if (array is {} e) + { + } + + static void M(string[] a) + { + } + + M(new[] { "" }); + } + + public void Interpolation(string m) + { + _ = $"{m}"; + } + } +} diff --git a/StyleChecker/StyleChecker.Test/StyleChecker.Test.csproj b/StyleChecker/StyleChecker.Test/StyleChecker.Test.csproj index 740ba528..166a27b3 100644 --- a/StyleChecker/StyleChecker.Test/StyleChecker.Test.csproj +++ b/StyleChecker/StyleChecker.Test/StyleChecker.Test.csproj @@ -96,6 +96,12 @@ + + + + + + @@ -420,6 +426,24 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Analyzer.cs b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Analyzer.cs index 0a938742..d1e5d017 100644 --- a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Analyzer.cs +++ b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Analyzer.cs @@ -30,7 +30,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/BomKit.cs b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/BomKit.cs index a7b9dc2a..c760479c 100644 --- a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/BomKit.cs +++ b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/BomKit.cs @@ -11,7 +11,7 @@ namespace StyleChecker.Cleaning.ByteOrderMark; public static class BomKit { private static readonly ImmutableArray Utf8ByteOrderMark - = ImmutableArray.Create(0xef, 0xbb, 0xbf); + = [0xef, 0xbb, 0xbf]; /// /// Gets whether the file of the specified path starts with UTF-8 BOM. diff --git a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Globs.cs b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Globs.cs index d0207186..8c1940a9 100644 --- a/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Globs.cs +++ b/StyleChecker/StyleChecker/Cleaning/ByteOrderMark/Globs.cs @@ -17,22 +17,10 @@ public static class Globs private static readonly Regex SlashSequencePattern = new("//+"); - private static readonly ImmutableHashSet NeedsEscapeCharSet - = ImmutableHashSet.Create( - '\\', - '[', - ']', - '.', - '*', - '+', - '?', - '^', - '$', - '(', - ')', - '{', - '}', - '|'); + private static readonly ImmutableHashSet NeedsEscapeCharSet = [ + '\\', '[', ']', '.', '*', '+', '?', '^', '$', '(', ')', '{', '}', + '|', + ]; private static readonly Action DoNothing = () => {}; diff --git a/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/Analyzer.cs b/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/Analyzer.cs index fe40e5d0..d0343108 100644 --- a/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/Analyzer.cs +++ b/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/Analyzer.cs @@ -29,7 +29,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/CodeFixer.cs b/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/CodeFixer.cs index 8c2c9218..cecbbcee 100644 --- a/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Cleaning/RedundantTypedArrayCreation/CodeFixer.cs @@ -22,7 +22,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Cleaning/UnusedUsing/Analyzer.cs b/StyleChecker/StyleChecker/Cleaning/UnusedUsing/Analyzer.cs index 20e47271..59c8bf21 100644 --- a/StyleChecker/StyleChecker/Cleaning/UnusedUsing/Analyzer.cs +++ b/StyleChecker/StyleChecker/Cleaning/UnusedUsing/Analyzer.cs @@ -22,7 +22,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Cleaning/UnusedVariable/Analyzer.cs b/StyleChecker/StyleChecker/Cleaning/UnusedVariable/Analyzer.cs index d0c27744..a9ff47d8 100644 --- a/StyleChecker/StyleChecker/Cleaning/UnusedVariable/Analyzer.cs +++ b/StyleChecker/StyleChecker/Cleaning/UnusedVariable/Analyzer.cs @@ -30,7 +30,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Document/NoDocumentation/Analyzer.cs b/StyleChecker/StyleChecker/Document/NoDocumentation/Analyzer.cs index 47e73024..889300a0 100644 --- a/StyleChecker/StyleChecker/Document/NoDocumentation/Analyzer.cs +++ b/StyleChecker/StyleChecker/Document/NoDocumentation/Analyzer.cs @@ -35,7 +35,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Document/StrayText/Analyzer.cs b/StyleChecker/StyleChecker/Document/StrayText/Analyzer.cs index 8d26f259..57dd580f 100644 --- a/StyleChecker/StyleChecker/Document/StrayText/Analyzer.cs +++ b/StyleChecker/StyleChecker/Document/StrayText/Analyzer.cs @@ -25,7 +25,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Naming/SingleTypeParameter/Analyzer.cs b/StyleChecker/StyleChecker/Naming/SingleTypeParameter/Analyzer.cs index 71ecae74..7e3a27b4 100644 --- a/StyleChecker/StyleChecker/Naming/SingleTypeParameter/Analyzer.cs +++ b/StyleChecker/StyleChecker/Naming/SingleTypeParameter/Analyzer.cs @@ -25,7 +25,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Naming/SingleTypeParameter/CodeFixer.cs b/StyleChecker/StyleChecker/Naming/SingleTypeParameter/CodeFixer.cs index a4c4e3dc..e2937bc1 100644 --- a/StyleChecker/StyleChecker/Naming/SingleTypeParameter/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Naming/SingleTypeParameter/CodeFixer.cs @@ -20,7 +20,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Naming/ThoughtlessName/Analyzer.cs b/StyleChecker/StyleChecker/Naming/ThoughtlessName/Analyzer.cs index 52a104e8..cb7308c7 100644 --- a/StyleChecker/StyleChecker/Naming/ThoughtlessName/Analyzer.cs +++ b/StyleChecker/StyleChecker/Naming/ThoughtlessName/Analyzer.cs @@ -28,7 +28,7 @@ public sealed class Analyzer : AbstractAnalyzer private static readonly DiagnosticDescriptor Rule = NewRule(); private static readonly ImmutableHashSet - SinglePrefixTypeSet = ImmutableHashSet.Create( + SinglePrefixTypeSet = [ SpecialType.System_Boolean, SpecialType.System_Byte, SpecialType.System_Int16, @@ -39,14 +39,14 @@ private static readonly ImmutableHashSet SpecialType.System_Double, SpecialType.System_Object, SpecialType.System_String, - SpecialType.System_Decimal); + SpecialType.System_Decimal]; private static readonly ImmutableHashSet - DoublePrefixTypeSet = ImmutableHashSet.Create( + DoublePrefixTypeSet = [ SpecialType.System_SByte, SpecialType.System_UInt16, SpecialType.System_UInt32, - SpecialType.System_UInt64); + SpecialType.System_UInt64]; private static readonly IReadOnlyDictionary SpecialTypeNameMap = new Dictionary() @@ -70,7 +70,7 @@ private static readonly IReadOnlyDictionary /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Naming/Underscore/Analyzer.cs b/StyleChecker/StyleChecker/Naming/Underscore/Analyzer.cs index a4707513..f2b3b093 100644 --- a/StyleChecker/StyleChecker/Naming/Underscore/Analyzer.cs +++ b/StyleChecker/StyleChecker/Naming/Underscore/Analyzer.cs @@ -25,8 +25,7 @@ private static readonly DiagnosticDescriptor IncludeRule /// public override ImmutableArray - SupportedDiagnostics - => ImmutableArray.Create(IncludeRule, IsRule); + SupportedDiagnostics => [IncludeRule, IsRule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Naming/Underscore/CodeFixer.cs b/StyleChecker/StyleChecker/Naming/Underscore/CodeFixer.cs index 74c36429..bbb02dfb 100644 --- a/StyleChecker/StyleChecker/Naming/Underscore/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Naming/Underscore/CodeFixer.cs @@ -24,7 +24,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Ordering/PostIncrement/Analyzer.cs b/StyleChecker/StyleChecker/Ordering/PostIncrement/Analyzer.cs index bb62d23e..d1b86922 100644 --- a/StyleChecker/StyleChecker/Ordering/PostIncrement/Analyzer.cs +++ b/StyleChecker/StyleChecker/Ordering/PostIncrement/Analyzer.cs @@ -25,7 +25,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Ordering/PostIncrement/CodeFixer.cs b/StyleChecker/StyleChecker/Ordering/PostIncrement/CodeFixer.cs index 6dfac7e8..de8e6f05 100644 --- a/StyleChecker/StyleChecker/Ordering/PostIncrement/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Ordering/PostIncrement/CodeFixer.cs @@ -26,7 +26,7 @@ private static readonly Func KindMap /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/AssignmentToParameter/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/AssignmentToParameter/Analyzer.cs index 819a5a4f..f197ef9c 100644 --- a/StyleChecker/StyleChecker/Refactoring/AssignmentToParameter/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/AssignmentToParameter/Analyzer.cs @@ -26,7 +26,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/DiscardingReturnValue/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/DiscardingReturnValue/Analyzer.cs index 1a5ee1bf..efdf9c48 100644 --- a/StyleChecker/StyleChecker/Refactoring/DiscardingReturnValue/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/DiscardingReturnValue/Analyzer.cs @@ -57,7 +57,7 @@ private static readonly SymbolDisplayFormat SignatureFormat /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/Analyzer.cs index f737a0c9..62025aee 100644 --- a/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/Analyzer.cs @@ -26,7 +26,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/CodeFixer.cs index abc8519c..3b7c8cfd 100644 --- a/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EmptyArrayCreation/CodeFixer.cs @@ -22,7 +22,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/EqualsNull/AbstractCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/EqualsNull/AbstractCodeFixer.cs index dac15c5a..6bca1581 100644 --- a/StyleChecker/StyleChecker/Refactoring/EqualsNull/AbstractCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EqualsNull/AbstractCodeFixer.cs @@ -16,7 +16,7 @@ public abstract class AbstractCodeFixer : AbstractRevisingCodeFixer { /// public sealed override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// protected sealed override Func Localize diff --git a/StyleChecker/StyleChecker/Refactoring/EqualsNull/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/EqualsNull/Analyzer.cs index 21f8f9ed..5d4b3909 100644 --- a/StyleChecker/StyleChecker/Refactoring/EqualsNull/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EqualsNull/Analyzer.cs @@ -26,7 +26,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsBracesCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsBracesCodeFixer.cs index 56e8b4a6..759a3d55 100644 --- a/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsBracesCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsBracesCodeFixer.cs @@ -15,14 +15,13 @@ namespace StyleChecker.Refactoring.EqualsNull; [Shared] public sealed class IsBracesCodeFixer : AbstractCodeFixer { - private static readonly ImmutableList KitList - = ImmutableList.Create( - new ReviserKit( - nameof(R.FixTitleIsBraces), - Replace(SyntaxKind.ExclamationEqualsToken, NotEqual)), - new ReviserKit( - nameof(R.FixTitleIsNotBraces), - Replace(SyntaxKind.EqualsEqualsToken, EqualEqual))); + private static readonly ImmutableList KitList = [ + new ReviserKit( + nameof(R.FixTitleIsBraces), + Replace(SyntaxKind.ExclamationEqualsToken, NotEqual)), + new ReviserKit( + nameof(R.FixTitleIsNotBraces), + Replace(SyntaxKind.EqualsEqualsToken, EqualEqual))]; /// protected override ImmutableList ReviserKitList => KitList; diff --git a/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsNullCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsNullCodeFixer.cs index f6ac4149..52b96ce4 100644 --- a/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsNullCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/EqualsNull/IsNullCodeFixer.cs @@ -15,14 +15,13 @@ namespace StyleChecker.Refactoring.EqualsNull; [Shared] public sealed class IsNullCodeFixer : AbstractCodeFixer { - private static readonly ImmutableList KitList - = ImmutableList.Create( - new ReviserKit( - nameof(R.FixTitleIsNotNull), - Replace(SyntaxKind.EqualsEqualsToken, NotEqual)), - new ReviserKit( - nameof(R.FixTitleIsNull), - Replace(SyntaxKind.ExclamationEqualsToken, EqualEqual))); + private static readonly ImmutableList KitList = [ + new ReviserKit( + nameof(R.FixTitleIsNotNull), + Replace(SyntaxKind.EqualsEqualsToken, NotEqual)), + new ReviserKit( + nameof(R.FixTitleIsNull), + Replace(SyntaxKind.ExclamationEqualsToken, EqualEqual))]; /// protected override ImmutableList ReviserKitList => KitList; diff --git a/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/Analyzer.cs index b48864a1..1efc14fa 100644 --- a/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/Analyzer.cs @@ -27,7 +27,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/CodeFixer.cs index 6902560c..a87e5a9a 100644 --- a/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IneffectiveReadByte/CodeFixer.cs @@ -22,7 +22,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/IsNull/AbstractCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/IsNull/AbstractCodeFixer.cs index b888aacf..3e9bcea0 100644 --- a/StyleChecker/StyleChecker/Refactoring/IsNull/AbstractCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IsNull/AbstractCodeFixer.cs @@ -14,7 +14,7 @@ public abstract class AbstractCodeFixer : AbstractRevisingCodeFixer { /// public sealed override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// protected sealed override Func Localize diff --git a/StyleChecker/StyleChecker/Refactoring/IsNull/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/IsNull/Analyzer.cs index 53607c08..a2bc93a3 100644 --- a/StyleChecker/StyleChecker/Refactoring/IsNull/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IsNull/Analyzer.cs @@ -26,7 +26,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/IsNull/EqualNullCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/IsNull/EqualNullCodeFixer.cs index 88737f8e..d686f494 100644 --- a/StyleChecker/StyleChecker/Refactoring/IsNull/EqualNullCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IsNull/EqualNullCodeFixer.cs @@ -19,13 +19,12 @@ namespace StyleChecker.Refactoring.IsNull; [Shared] public sealed class EqualNullCodeFixer : AbstractCodeFixer { - private static readonly ImmutableList KitList - = ImmutableList.Create( - new ReviserKit( - nameof(R.FixTitleEqualNull), ReplaceIsNullWithEqualOperator), - new ReviserKit( - nameof(R.FixTitleNotEqualNull), - ReplaceNotIsNullWithNotEqualOperator)); + private static readonly ImmutableList KitList = [ + new ReviserKit( + nameof(R.FixTitleEqualNull), ReplaceIsNullWithEqualOperator), + new ReviserKit( + nameof(R.FixTitleNotEqualNull), + ReplaceNotIsNullWithNotEqualOperator)]; /// protected override ImmutableList ReviserKitList => KitList; diff --git a/StyleChecker/StyleChecker/Refactoring/IsNull/IsBracesCodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/IsNull/IsBracesCodeFixer.cs index 01be3bde..44601973 100644 --- a/StyleChecker/StyleChecker/Refactoring/IsNull/IsBracesCodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/IsNull/IsBracesCodeFixer.cs @@ -18,12 +18,11 @@ namespace StyleChecker.Refactoring.IsNull; [Shared] public sealed class IsBracesCodeFixer : AbstractCodeFixer { - private static readonly ImmutableList KitList - = ImmutableList.Create( - new ReviserKit( - nameof(R.FixTitleIsBraces), ReplaceIsNullWithNotIsBraces), - new ReviserKit( - nameof(R.FixTitleNotIsBraces), ReplaceNotIsNullWithIsBraces)); + private static readonly ImmutableList KitList = [ + new ReviserKit( + nameof(R.FixTitleIsBraces), ReplaceIsNullWithNotIsBraces), + new ReviserKit( + nameof(R.FixTitleNotIsBraces), ReplaceNotIsNullWithIsBraces)]; /// protected override ImmutableList ReviserKitList => KitList; diff --git a/StyleChecker/StyleChecker/Refactoring/NotDesignedForExtension/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/NotDesignedForExtension/Analyzer.cs index 3f6939ee..54696423 100644 --- a/StyleChecker/StyleChecker/Refactoring/NotDesignedForExtension/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/NotDesignedForExtension/Analyzer.cs @@ -26,7 +26,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/NotOneShotInitialization/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/NotOneShotInitialization/Analyzer.cs index 1a0557ba..aead281f 100644 --- a/StyleChecker/StyleChecker/Refactoring/NotOneShotInitialization/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/NotOneShotInitialization/Analyzer.cs @@ -30,14 +30,14 @@ public sealed class Analyzer : AbstractAnalyzer private static readonly DiagnosticDescriptor Rule = NewRule(); private static readonly ImmutableHashSet - NoLocalSymbols = ImmutableHashSet.Empty; + NoLocalSymbols = []; private static readonly IEnumerable<(ILocalSymbol, SyntaxToken)> EmptyLocalSymbolTokens = []; /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/Analyzer.cs index 70f024c3..96212d5d 100644 --- a/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/Analyzer.cs @@ -27,7 +27,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/CodeFixer.cs index bfb4cb70..e07a6dc2 100644 --- a/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/StaticGenericClass/CodeFixer.cs @@ -60,7 +60,7 @@ private delegate SyntaxTriviaList CommentKit( /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/Analyzer.cs index 2b05c360..102dc925 100644 --- a/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/Analyzer.cs @@ -26,12 +26,12 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; private static ImmutableHashSet - BoolLiteralExpressionSet { get; } = ImmutableHashSet.Create( + BoolLiteralExpressionSet { get; } = [ SyntaxKind.TrueLiteralExpression, - SyntaxKind.FalseLiteralExpression); + SyntaxKind.FalseLiteralExpression]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/CodeFixer.cs index 197152b1..e8e4b9df 100644 --- a/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/StinkyBooleanExpression/CodeFixer.cs @@ -22,7 +22,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/Analyzer.cs index 6bd63ceb..e222eb50 100644 --- a/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/Analyzer.cs @@ -28,7 +28,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/CodeFixer.cs index 50dce611..bc4dbdeb 100644 --- a/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/TypeClassParameter/CodeFixer.cs @@ -35,7 +35,7 @@ private static readonly Func /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Refactoring/UninitializedLocalVariable/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/UninitializedLocalVariable/Analyzer.cs index c7ae829b..ba5d0107 100644 --- a/StyleChecker/StyleChecker/Refactoring/UninitializedLocalVariable/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/UninitializedLocalVariable/Analyzer.cs @@ -23,7 +23,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Analyzer.cs b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Analyzer.cs index 04ff805b..4999e77d 100644 --- a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Analyzer.cs +++ b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Analyzer.cs @@ -3,7 +3,6 @@ namespace StyleChecker.Refactoring.UnnecessaryUsing; using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.IO; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -29,7 +28,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) @@ -52,19 +51,6 @@ private static DiagnosticDescriptor NewRule() helpLinkUri: HelpLink.ToUri(DiagnosticId)); } - private static Func NewDisposesNothing() - { - var classSet = new HashSet() - { - typeof(MemoryStream).FullName, - typeof(StringReader).FullName, - typeof(StringWriter).FullName, - "System.IO.UnmanagedMemoryAccessor", - "System.IO.UnmanagedMemoryStream", - }; - return classSet.Contains; - } - private static void AnalyzeModel( SemanticModelAnalysisContext context) { diff --git a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Classes.cs b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Classes.cs index 5ad89139..b3f62683 100644 --- a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Classes.cs +++ b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/Classes.cs @@ -24,12 +24,11 @@ public static class Classes public static bool DisposesNothing(string className) => ClassNameSet.Contains(className); - private static ImmutableHashSet NewClassNameSet() - => ImmutableHashSet.Create([ - typeof(MemoryStream).FullName, - typeof(StringReader).FullName, - typeof(StringWriter).FullName, - "System.IO.UnmanagedMemoryAccessor", - "System.IO.UnmanagedMemoryStream", - ]); + private static ImmutableHashSet NewClassNameSet() => [ + typeof(MemoryStream).FullName, + typeof(StringReader).FullName, + typeof(StringWriter).FullName, + "System.IO.UnmanagedMemoryAccessor", + "System.IO.UnmanagedMemoryStream", + ]; } diff --git a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/CodeFixer.cs b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/CodeFixer.cs index 364c1971..9eb649df 100644 --- a/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Refactoring/UnnecessaryUsing/CodeFixer.cs @@ -24,7 +24,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Settings/InvalidConfig/Analyzer.cs b/StyleChecker/StyleChecker/Settings/InvalidConfig/Analyzer.cs index e353dd9b..388e8875 100644 --- a/StyleChecker/StyleChecker/Settings/InvalidConfig/Analyzer.cs +++ b/StyleChecker/StyleChecker/Settings/InvalidConfig/Analyzer.cs @@ -27,7 +27,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Size/LongLine/Analyzer.cs b/StyleChecker/StyleChecker/Size/LongLine/Analyzer.cs index 761963ad..bdd2490e 100644 --- a/StyleChecker/StyleChecker/Size/LongLine/Analyzer.cs +++ b/StyleChecker/StyleChecker/Size/LongLine/Analyzer.cs @@ -24,7 +24,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/Analyzer.cs b/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/Analyzer.cs index deba9959..bbe61a73 100644 --- a/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/Analyzer.cs +++ b/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/Analyzer.cs @@ -25,11 +25,11 @@ public const string DiagnosticId private static readonly DiagnosticDescriptor Rule = NewRule(); private static readonly ImmutableHashSet WhitespaceCharSet - = ImmutableHashSet.Create(' ', '\t'); + = [' ', '\t']; /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/CodeFixer.cs b/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/CodeFixer.cs index e073c7b7..02bd9829 100644 --- a/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Spacing/NoSingleSpaceAfterTripleSlash/CodeFixer.cs @@ -21,7 +21,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Analyzer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Analyzer.cs new file mode 100644 index 00000000..78f2cb29 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Analyzer.cs @@ -0,0 +1,121 @@ +namespace StyleChecker.Spacing.NoSpaceAfterBrace; + +using System; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using R = Resources; + +/// +/// NoSpaceAfterBrace analyzer. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class Analyzer : AbstractAnalyzer +{ + /// + /// The ID of this analyzer. + /// + public const string DiagnosticId = "NoSpaceAfterBrace"; + + private const string Category = Categories.Spacing; + private static readonly DiagnosticDescriptor Rule = NewRule(); + + /// + public override ImmutableArray + SupportedDiagnostics => [Rule]; + + /// + private protected override void Register(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.RegisterSyntaxTreeAction(SyntaxTreeAction); + } + + private static DiagnosticDescriptor NewRule() + { + var localize = Localizers.Of(R.ResourceManager); + return new DiagnosticDescriptor( + DiagnosticId, + localize(nameof(R.Title)), + localize(nameof(R.MessageFormat)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: localize(nameof(R.Description)), + helpLinkUri: HelpLink.ToUri(DiagnosticId)); + } + + private static void SyntaxTreeAction(SyntaxTreeAnalysisContext context) + { + static bool StartsWithSpace(SyntaxTriviaList list) + { + return list.First() + .IsKindOneOf( + SyntaxKind.WhitespaceTrivia, + SyntaxKind.EndOfLineTrivia); + } + + static bool DoesBraceNeedSpace( + SyntaxToken token, Func otherwiseNext) + { + return token.HasTrailingTrivia + ? !StartsWithSpace(token.TrailingTrivia) + : token.GetNextToken() is {} next + && next.HasLeadingTrivia + ? !StartsWithSpace(next.LeadingTrivia) + : otherwiseNext(next); + } + + static bool DoesCloseBraceNeedSpace(SyntaxToken token) + { + return DoesBraceNeedSpace( + token, + next => !next.IsKindOneOf( + SyntaxKind.CloseParenToken, + SyntaxKind.CommaToken, + SyntaxKind.DotToken, + SyntaxKind.ExclamationToken, + SyntaxKind.None, + SyntaxKind.OpenBracketToken, + SyntaxKind.QuestionToken) + && !(next.IsKind(SyntaxKind.SemicolonToken) + && next.Parent is not EmptyStatementSyntax)); + } + + static bool DoesOpenBraceNeedSpace(SyntaxToken token) + { + return DoesBraceNeedSpace( + token, + next => !next.IsKindOneOf( + SyntaxKind.None, + SyntaxKind.CloseBraceToken)); + } + + static bool IsExceptional(SyntaxToken token) + { + return token.IsMissing + || token.Parent.IsKind(SyntaxKind.Interpolation); + } + + var root = context.Tree + .GetCompilationUnitRoot(context.CancellationToken); + var leftBraces = root.DescendantTokens() + .Where(t => t.IsKind(SyntaxKind.OpenBraceToken) + && !IsExceptional(t) + && DoesOpenBraceNeedSpace(t)); + var rightBraces = root.DescendantTokens() + .Where(t => t.IsKind(SyntaxKind.CloseBraceToken) + && !IsExceptional(t) + && DoesCloseBraceNeedSpace(t)); + var all = leftBraces.Concat(rightBraces) + .Select(t => Diagnostic.Create(Rule, t.GetLocation(), t.Text)) + .ToList(); + foreach (var d in all) + { + context.ReportDiagnostic(d); + } + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/CodeFixer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/CodeFixer.cs new file mode 100644 index 00000000..5068350a --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/CodeFixer.cs @@ -0,0 +1,49 @@ +namespace StyleChecker.Spacing.NoSpaceAfterBrace; + +using System.Collections.Immutable; +using System.Composition; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using R = Resources; + +/// +/// NoSpaceAfterBrace code fix provider. +/// +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CodeFixer))] +[Shared] +public sealed class CodeFixer : AbstractCodeFixProvider +{ + /// + public override ImmutableArray FixableDiagnosticIds + => [Analyzer.DiagnosticId]; + + /// + public override FixAllProvider GetFixAllProvider() + => WellKnownFixAllProviders.BatchFixer; + + /// + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + var localize = Localizers.Of(R.ResourceManager); + var title = localize(nameof(R.FixTitle)).ToString(CompilerCulture); + + var document = context.Document; + if (await document.GetSyntaxRootAsync(context.CancellationToken) + .ConfigureAwait(false) is not {} root) + { + return; + } + var diagnostic = context.Diagnostics[0]; + var span = diagnostic.Location.SourceSpan; + var token = root.FindToken(span.Start, findInsideTrivia: true); + var fixTask = TokenFix.NewTask( + () => TokenFix.AddSpaceAfterToken(document, root, token)); + var action = CodeAction.Create( + title: title, + createChangedDocument: fixTask, + equivalenceKey: title); + context.RegisterCodeFix(action, diagnostic); + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.Designer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.Designer.cs new file mode 100644 index 00000000..2f6d2723 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace StyleChecker.Spacing.NoSpaceAfterBrace { + using System; + using System.Reflection; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StyleChecker.Spacing.NoSpaceAfterBrace.Resources", typeof(Resources).GetTypeInfo().Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to A brace should be followed by a white space.. + /// + internal static string Description { + get { + return ResourceManager.GetString("Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Insert a white space.. + /// + internal static string FixTitle { + get { + return ResourceManager.GetString("FixTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A white space is needed after '{0}'. + /// + internal static string MessageFormat { + get { + return ResourceManager.GetString("MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A brace is not followed by a white space.. + /// + internal static string Title { + get { + return ResourceManager.GetString("Title", resourceCulture); + } + } + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.resx b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.resx new file mode 100644 index 00000000..f93d9e6c --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterBrace/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A brace should be followed by a white space. + + + Insert a white space. + + + A white space is needed after '{0}' + + + A brace is not followed by a white space. + + \ No newline at end of file diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/Analyzer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/Analyzer.cs index 5253797d..35a71b33 100644 --- a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/Analyzer.cs +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/Analyzer.cs @@ -23,7 +23,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/CodeFixer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/CodeFixer.cs index fbbb45ae..b846242a 100644 --- a/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceAfterSemicolon/CodeFixer.cs @@ -1,14 +1,11 @@ namespace StyleChecker.Spacing.NoSpaceAfterSemicolon; -using System; using System.Collections.Immutable; using System.Composition; -using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; using R = Resources; /// @@ -20,7 +17,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() @@ -33,38 +30,21 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) var title = localize(nameof(R.FixTitle)) .ToString(CompilerCulture); - if (await context.Document - .GetSyntaxRootAsync(context.CancellationToken) + var document = context.Document; + if (await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false) is not {} root) { return; } - var diagnostic = context.Diagnostics[0]; var span = diagnostic.Location.SourceSpan; var token = root.FindToken(span.Start, findInsideTrivia: true); - + var fixTask = TokenFix.NewTask( + () => TokenFix.AddSpaceAfterToken(document, root, token)); var action = CodeAction.Create( title: title, - createChangedDocument: Fix(context.Document, root, token), + createChangedDocument: fixTask, equivalenceKey: title); context.RegisterCodeFix(action, diagnostic); } - - private Document FixDocument( - Document document, SyntaxNode root, SyntaxToken token) - { - var list = token.TrailingTrivia; - var space = SyntaxFactory.ParseTrailingTrivia(" "); - var newList = list.InsertRange(0, space); - var newToken = token.WithTrailingTrivia(newList); - var newRoot = root.ReplaceToken(token, newToken); - return document.WithSyntaxRoot(newRoot); - } - - private Func> Fix( - Document document, SyntaxNode root, SyntaxToken token) - { - return c => Task.Run(() => FixDocument(document, root, token), c); - } } diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Analyzer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Analyzer.cs new file mode 100644 index 00000000..9da29554 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Analyzer.cs @@ -0,0 +1,122 @@ +namespace StyleChecker.Spacing.NoSpaceBeforeBrace; + +using System; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; +using R = Resources; + +/// +/// NoSpaceBeforeBrace analyzer. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class Analyzer : AbstractAnalyzer +{ + /// + /// The ID of this analyzer. + /// + public const string DiagnosticId = "NoSpaceBeforeBrace"; + + private const string Category = Categories.Spacing; + private static readonly DiagnosticDescriptor Rule = NewRule(); + + /// + public override ImmutableArray + SupportedDiagnostics => [Rule]; + + /// + private protected override void Register(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.RegisterSyntaxTreeAction(SyntaxTreeAction); + } + + private static DiagnosticDescriptor NewRule() + { + var localize = Localizers.Of(R.ResourceManager); + return new DiagnosticDescriptor( + DiagnosticId, + localize(nameof(R.Title)), + localize(nameof(R.MessageFormat)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: localize(nameof(R.Description)), + helpLinkUri: HelpLink.ToUri(DiagnosticId)); + } + + private static void SyntaxTreeAction(SyntaxTreeAnalysisContext context) + { + static bool EndsWithSpace(SyntaxTriviaList list) + { + return list.Last() + .IsKindOneOf( + SyntaxKind.WhitespaceTrivia, + SyntaxKind.EndOfLineTrivia); + } + + static bool IsOnFirstColumn(SyntaxToken token) + { + return token.GetLocation() + .GetLineSpan() + .StartLinePosition + .Character is 0; + } + + static bool DoesBraceNeedSpace( + SyntaxToken token, Func otherwisePrev) + { + return !IsOnFirstColumn(token) + && token.HasLeadingTrivia + ? !EndsWithSpace(token.LeadingTrivia) + : token.GetPreviousToken() is {} prev + && prev.HasTrailingTrivia + ? !EndsWithSpace(prev.TrailingTrivia) + : otherwisePrev(prev); + } + + static bool DoesOpenBraceNeedSpace(SyntaxToken token) + { + return DoesBraceNeedSpace( + token, + prev => !prev.IsKindOneOf( + SyntaxKind.None, + SyntaxKind.OpenParenToken)); + } + + static bool DoesCloseBraceNeedSpace(SyntaxToken token) + { + return DoesBraceNeedSpace( + token, + prev => !prev.IsKindOneOf( + SyntaxKind.None, + SyntaxKind.OpenBraceToken)); + } + + static bool IsExceptional(SyntaxToken token) + { + return token.IsMissing + || token.Parent.IsKind(SyntaxKind.Interpolation); + } + + var root = context.Tree + .GetCompilationUnitRoot(context.CancellationToken); + var leftBraces = root.DescendantTokens() + .Where(t => t.IsKind(SyntaxKind.OpenBraceToken) + && !IsExceptional(t) + && DoesOpenBraceNeedSpace(t)); + var rightBraces = root.DescendantTokens() + .Where(t => t.IsKind(SyntaxKind.CloseBraceToken) + && !IsExceptional(t) + && DoesCloseBraceNeedSpace(t)); + var all = leftBraces.Concat(rightBraces) + .Select(t => Diagnostic.Create(Rule, t.GetLocation(), t.Text)) + .ToList(); + foreach (var d in all) + { + context.ReportDiagnostic(d); + } + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/CodeFixer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/CodeFixer.cs new file mode 100644 index 00000000..60a92404 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/CodeFixer.cs @@ -0,0 +1,50 @@ +namespace StyleChecker.Spacing.NoSpaceBeforeBrace; + +using System.Collections.Immutable; +using System.Composition; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using R = Resources; + +/// +/// NoSpaceBeforeBrace code fix provider. +/// +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CodeFixer))] +[Shared] +public sealed class CodeFixer : AbstractCodeFixProvider +{ + /// + public override ImmutableArray FixableDiagnosticIds + => [Analyzer.DiagnosticId]; + + /// + public override FixAllProvider GetFixAllProvider() + => WellKnownFixAllProviders.BatchFixer; + + /// + public override async Task RegisterCodeFixesAsync( + CodeFixContext context) + { + var localize = Localizers.Of(R.ResourceManager); + var title = localize(nameof(R.FixTitle)).ToString(CompilerCulture); + + var document = context.Document; + if (await document.GetSyntaxRootAsync(context.CancellationToken) + .ConfigureAwait(false) is not {} root) + { + return; + } + var diagnostic = context.Diagnostics[0]; + var span = diagnostic.Location.SourceSpan; + var token = root.FindToken(span.Start, findInsideTrivia: true); + var fixTask = TokenFix.NewTask( + () => TokenFix.AddSpaceBeforeToken(document, root, token)); + var action = CodeAction.Create( + title: title, + createChangedDocument: fixTask, + equivalenceKey: title); + context.RegisterCodeFix(action, diagnostic); + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.Designer.cs b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.Designer.cs new file mode 100644 index 00000000..909934f0 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace StyleChecker.Spacing.NoSpaceBeforeBrace { + using System; + using System.Reflection; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StyleChecker.Spacing.NoSpaceBeforeBrace.Resources", typeof(Resources).GetTypeInfo().Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to A brace should be preceded by a white space.. + /// + internal static string Description { + get { + return ResourceManager.GetString("Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Insert a white space.. + /// + internal static string FixTitle { + get { + return ResourceManager.GetString("FixTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A white space is needed before '{0}'. + /// + internal static string MessageFormat { + get { + return ResourceManager.GetString("MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A brace is not preceded by a white space.. + /// + internal static string Title { + get { + return ResourceManager.GetString("Title", resourceCulture); + } + } + } +} diff --git a/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.resx b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.resx new file mode 100644 index 00000000..822a44c8 --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/NoSpaceBeforeBrace/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A brace should be preceded by a white space. + + + Insert a white space. + + + A white space is needed before '{0}' + + + A brace is not preceded by a white space. + + \ No newline at end of file diff --git a/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/Analyzer.cs b/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/Analyzer.cs index c22b25b2..c1587465 100644 --- a/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/Analyzer.cs +++ b/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/Analyzer.cs @@ -23,7 +23,7 @@ public sealed class Analyzer : AbstractAnalyzer /// public override ImmutableArray - SupportedDiagnostics => ImmutableArray.Create(Rule); + SupportedDiagnostics => [Rule]; /// private protected override void Register(AnalysisContext context) diff --git a/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/CodeFixer.cs b/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/CodeFixer.cs index 2b1466e7..eed2556f 100644 --- a/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/CodeFixer.cs +++ b/StyleChecker/StyleChecker/Spacing/SpaceBeforeSemicolon/CodeFixer.cs @@ -1,10 +1,8 @@ namespace StyleChecker.Spacing.SpaceBeforeSemicolon; -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; -using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; @@ -21,7 +19,7 @@ public sealed class CodeFixer : AbstractCodeFixProvider { /// public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(Analyzer.DiagnosticId); + => [Analyzer.DiagnosticId]; /// public override FixAllProvider GetFixAllProvider() @@ -34,21 +32,20 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) var title = localize(nameof(R.FixTitle)) .ToString(CompilerCulture); - var root = await context.Document - .GetSyntaxRootAsync(context.CancellationToken) - .ConfigureAwait(false); - if (root is null) + var document = context.Document; + if (await document.GetSyntaxRootAsync(context.CancellationToken) + .ConfigureAwait(false) is not {} root) { return; } - var diagnostic = context.Diagnostics[0]; var span = diagnostic.Location.SourceSpan; var token = root.FindToken(span.Start, findInsideTrivia: true); - + var fixTask = TokenFix.NewTask( + () => FixDocument(document, root, token)); var action = CodeAction.Create( title: title, - createChangedDocument: Fix(context.Document, root, token), + createChangedDocument: fixTask, equivalenceKey: title); context.RegisterCodeFix(action, diagnostic); } @@ -100,10 +97,4 @@ static SyntaxTriviaList Trim(SyntaxTriviaList triviaList) var newRoot = root.ReplaceTokens(keys, (k, n) => map[k]); return document.WithSyntaxRoot(newRoot); } - - private Func> Fix( - Document document, SyntaxNode root, SyntaxToken token) - { - return c => Task.Run(() => FixDocument(document, root, token), c); - } } diff --git a/StyleChecker/StyleChecker/Spacing/TokenFix.cs b/StyleChecker/StyleChecker/Spacing/TokenFix.cs new file mode 100644 index 00000000..a7d8784e --- /dev/null +++ b/StyleChecker/StyleChecker/Spacing/TokenFix.cs @@ -0,0 +1,95 @@ +namespace StyleChecker.Spacing; + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +/// +/// Provides utility methods for fixing tokens. +/// +public static class TokenFix +{ + /// + /// Creates a new task that represents the asynchronous operation of fixing + /// tokens in a document. + /// + /// + /// A function that returns the new document after fixing tokens. + /// + /// + /// A task that represents the asynchronous operation of fixing tokens. + /// + public static Func> NewTask( + Func newDocument) + { + return c => Task.Run(newDocument, c); + } + + /// + /// Gets the new document created by adding a white space immediately after + /// the specified token in the specified document. + /// + /// + /// The document containing the . + /// + /// + /// The root node of the syntax tree of the . + /// + /// + /// The token to add a white space after. + /// + /// + /// The new document. + /// + public static Document AddSpaceAfterToken( + Document document, + SyntaxNode root, + SyntaxToken token) + { + var list = token.TrailingTrivia; + var space = SyntaxFactory.ParseTrailingTrivia(" "); + var newList = list.InsertRange(0, space); + var newToken = token.WithTrailingTrivia(newList); + return Replace(document, root, token, newToken); + } + + /// + /// Gets the new document created by adding a white space immediately + /// before the specified token in the specified document. + /// + /// + /// The document containing the . + /// + /// + /// The root node of the syntax tree of the . + /// + /// + /// The token to add a white space before. + /// + /// + /// The new document. + /// + public static Document AddSpaceBeforeToken( + Document document, + SyntaxNode root, + SyntaxToken token) + { + var list = token.LeadingTrivia; + var space = SyntaxFactory.ParseLeadingTrivia(" "); + var newList = list.AddRange(space); + var newToken = token.WithLeadingTrivia(newList); + return Replace(document, root, token, newToken); + } + + private static Document Replace( + Document document, + SyntaxNode root, + SyntaxToken token, + SyntaxToken newToken) + { + var newRoot = root.ReplaceToken(token, newToken); + return document.WithSyntaxRoot(newRoot); + } +} diff --git a/StyleChecker/StyleChecker/StyleChecker.csproj b/StyleChecker/StyleChecker/StyleChecker.csproj index b2184197..3bf38be9 100644 --- a/StyleChecker/StyleChecker/StyleChecker.csproj +++ b/StyleChecker/StyleChecker/StyleChecker.csproj @@ -183,6 +183,16 @@ True True + + Resources.resx + True + True + + + Resources.resx + True + True + True True @@ -297,6 +307,14 @@ Resources.Designer.cs ResXFileCodeGenerator + + Resources.Designer.cs + ResXFileCodeGenerator + + + Resources.Designer.cs + ResXFileCodeGenerator + ResXFileCodeGenerator Resources.Designer.cs diff --git a/StyleChecker/StyleChecker/Syntaxes.cs b/StyleChecker/StyleChecker/Syntaxes.cs index ebea769c..fa466dcd 100644 --- a/StyleChecker/StyleChecker/Syntaxes.cs +++ b/StyleChecker/StyleChecker/Syntaxes.cs @@ -54,7 +54,28 @@ public static bool IsKindOneOf( } /// - /// Gets the node of the specified type, corresponging to the specified + /// Returns whether the SyntaxKind of the specified + /// SyntaxToken is included in the specified SyntaxKinds or + /// not. + /// + /// + /// The SyntaxToken object. + /// + /// + /// SyntaxKind objects. + /// + /// + /// true if the SyntaxKind of + /// is included in , false otherwise. + /// + public static bool IsKindOneOf( + this SyntaxToken token, params SyntaxKind[] kinds) + { + return kinds.Any(k => token.IsKind(k)); + } + + /// + /// Gets the node of the specified type, corresponding to the specified /// span. /// /// diff --git a/doc/rules/NoSpaceAfterBrace.md b/doc/rules/NoSpaceAfterBrace.md new file mode 100644 index 00000000..28a9a50d --- /dev/null +++ b/doc/rules/NoSpaceAfterBrace.md @@ -0,0 +1,81 @@ + +
+ +# NoSpaceAfterBrace + +
+ +![NoSpaceAfterBrace][fig-NoSpaceAfterBrace] + +
+ +## Summary + +A brace (‘`{`’ or ‘`}`’) must be followed by a white +space. + +## Default severity + +Warning + +## Description + +An opening brace (‘`{`’) that is not the last character on the line +must be followed by a single space or a closing brace (‘`}`’). + +A closing brace (‘`}`’) that is not the last character on the line +must be followed by a single space, a closing parenthesis (‘`)`’), +an opening bracket (‘`[`’), a comma (‘`,`’), a period +(‘`.`’), an exclamation mark (‘`!`’), a question mark +(‘`?`’), or a semicolon (‘`;`’). + +Note that this analyzer and [NoSpaceBeforeBrace](NoSpaceBeforeBrace.md) +analyzer are designed to use them together and replace [SA1012][sa1012] and +[SA1013][sa1013] with them, allowing us to write empty braces +(“`{}`”) as follows: + +```csharp +Action doNothing = () => {}; + +if (maybeString is {} s) +{ + ⋮ +} +``` + +## Code fix + +The code fix provides an option inserting a space after the brace. + +## Example + +### Diagnostic + +```csharp +string[] array = {"" }; + +Action doNothing = () => {return; }; + +if (array is {Length: 0 }z) +{ +} +``` + +### Code fix + +```csharp +string[] array = { "" }; + +Action doNothing = () => { return; }; + +if (array is { Length: 0 } z) +{ +} +``` + +[sa1012]: + https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1012.md +[sa1013]: + https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1013.md +[fig-NoSpaceAfterBrace]: + https://maroontress.github.io/StyleChecker/images/NoSpaceAfterBrace.png diff --git a/doc/rules/NoSpaceBeforeBrace.md b/doc/rules/NoSpaceBeforeBrace.md new file mode 100644 index 00000000..cdebede4 --- /dev/null +++ b/doc/rules/NoSpaceBeforeBrace.md @@ -0,0 +1,79 @@ + +
+ +# NoSpaceBeforeBrace + +
+ +![NoSpaceBeforeBrace][fig-NoSpaceBeforeBrace] + +
+ +## Summary + +A brace (‘`{`’ or ‘`}`’) must be preceded by a white +space. + +## Default severity + +Warning + +## Description + +An opening brace (‘`{`’) that is not the first character on the +line must be preceded by a single space or an opening parenthesis +(‘`(`’). + +A closing brace (‘`}`’) that is not the first character on the line +must be preceded by a single space or an opening brace (‘`{`’). + +Note that this analyzer and [NoSpaceAfterBrace](NoSpaceAfterBrace.md) analyzer +are designed to use them together and replace [SA1012][sa1012] and +[SA1013][sa1013] with them, allowing us to write empty braces +(“`{}`”) as follows: + +```csharp +Action doNothing = () => {}; + +if (maybeString is {} s) +{ + ⋮ +} +``` + +## Code fix + +The code fix provides an option inserting a space before the brace. + +## Example + +### Diagnostic + +```csharp +string[] array ={ ""}; + +Action doNothing = () =>{ return;}; + +if (array is{ Length: 0} z) +{ +} +``` + +### Code fix + +```csharp +string[] array = { "" }; + +Action doNothing = () => { return; }; + +if (array is { Length: 0 } z) +{ +} +``` + +[sa1012]: + https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1012.md +[sa1013]: + https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1013.md +[fig-NoSpaceBeforeBrace]: + https://maroontress.github.io/StyleChecker/images/NoSpaceBeforeBrace.png