diff --git a/SourceKit.sln b/SourceKit.sln index 643eede..0b96d59 100644 --- a/SourceKit.sln +++ b/SourceKit.sln @@ -89,6 +89,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Analyzers.Propert EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Reflect.Samples", "samples\SourceKit.Reflect.Samples\SourceKit.Reflect.Samples.csproj", "{B3EEEF25-A90E-404F-9874-93A2E6990468}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Analyzers.MemberAccessibility.Samples", "samples\analyzers\SourceKit.Analyzers.MemberAccessibility.Samples\SourceKit.Analyzers.MemberAccessibility.Samples.csproj", "{6D49F53F-4765-4108-9AA7-1470D5FB8FD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Analyzers.MemberAccessibility.Tests", "tests\SourceKit.Analyzers.MemberAccessibility.Tests\SourceKit.Analyzers.MemberAccessibility.Tests.csproj", "{EACEDBCD-081E-4F95-A81E-B62CD18D3028}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -131,6 +135,8 @@ Global {35F679FA-4F45-4870-B7C6-7B31A6CD014F} = {365210F4-5F33-49FD-9E14-552154E26285} {4B54BDA0-D16F-428F-97D2-03654311CE22} = {CB9AFB88-6DC1-436D-8F6F-398E065A07DE} {B3EEEF25-A90E-404F-9874-93A2E6990468} = {68973D47-37E1-492E-8F62-E94B002349BB} + {6D49F53F-4765-4108-9AA7-1470D5FB8FD7} = {365210F4-5F33-49FD-9E14-552154E26285} + {EACEDBCD-081E-4F95-A81E-B62CD18D3028} = {CB9AFB88-6DC1-436D-8F6F-398E065A07DE} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {637C01C1-3A3C-4FC6-9874-6CFBA4319A79}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -249,5 +255,13 @@ Global {B3EEEF25-A90E-404F-9874-93A2E6990468}.Debug|Any CPU.Build.0 = Debug|Any CPU {B3EEEF25-A90E-404F-9874-93A2E6990468}.Release|Any CPU.ActiveCfg = Release|Any CPU {B3EEEF25-A90E-404F-9874-93A2E6990468}.Release|Any CPU.Build.0 = Release|Any CPU + {6D49F53F-4765-4108-9AA7-1470D5FB8FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D49F53F-4765-4108-9AA7-1470D5FB8FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D49F53F-4765-4108-9AA7-1470D5FB8FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D49F53F-4765-4108-9AA7-1470D5FB8FD7}.Release|Any CPU.Build.0 = Release|Any CPU + {EACEDBCD-081E-4F95-A81E-B62CD18D3028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EACEDBCD-081E-4F95-A81E-B62CD18D3028}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EACEDBCD-081E-4F95-A81E-B62CD18D3028}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EACEDBCD-081E-4F95-A81E-B62CD18D3028}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/.editorconfig b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/.editorconfig new file mode 100644 index 0000000..e0f917d --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/.editorconfig @@ -0,0 +1,5 @@ +[*.cs] + +dotnet_diagnostic.SK1100.severity = warning +dotnet_diagnostic.SK1101.severity = warning +dotnet_diagnostic.SK1102.severity = warning diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.Fixed.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.Fixed.cs new file mode 100644 index 0000000..457fc2b --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.Fixed.cs @@ -0,0 +1,8 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class MultipleFieldsCaseFixed +{ + private object _first; + private object _second; + private object _third; +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.cs new file mode 100644 index 0000000..0e47701 --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.cs @@ -0,0 +1,6 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class MultipleFieldsCase +{ + private object _first, _second, _third; +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.Fixed.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.Fixed.cs new file mode 100644 index 0000000..43e8c56 --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.Fixed.cs @@ -0,0 +1,6 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class PrivatePropertyCaseFixed +{ + public object PrivateProperty { get; } +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.cs new file mode 100644 index 0000000..1ea7a4b --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.cs @@ -0,0 +1,6 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class PrivatePropertyCase +{ + private object PrivateProperty { get; } +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.Fixed.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.Fixed.cs new file mode 100644 index 0000000..6c7a194 --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.Fixed.cs @@ -0,0 +1,6 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class PublicFieldTestCaseFixed +{ + private object _publicField; +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.cs b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.cs new file mode 100644 index 0000000..29b611d --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.cs @@ -0,0 +1,6 @@ +namespace SourceKit.Analyzers.MemberAccessibility.Samples; + +public class PublicFieldTestCase +{ + public object _publicField; +} diff --git a/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/SourceKit.Analyzers.MemberAccessibility.Samples.csproj b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/SourceKit.Analyzers.MemberAccessibility.Samples.csproj new file mode 100644 index 0000000..0fd3d83 --- /dev/null +++ b/samples/analyzers/SourceKit.Analyzers.MemberAccessibility.Samples/SourceKit.Analyzers.MemberAccessibility.Samples.csproj @@ -0,0 +1,23 @@ + + + + disable + + + + + + + + + MultipleFieldsCase.cs + + + PrivatePropertyCase.cs + + + PublicFieldTestCase.cs + + + + diff --git a/src/analyzers/SourceKit.Analyzers.Collections/Analyzers/DictionaryKeyTypeMustImplementEquatableAnalyzer.cs b/src/analyzers/SourceKit.Analyzers.Collections/Analyzers/DictionaryKeyTypeMustImplementEquatableAnalyzer.cs index a283d09..45b35ac 100644 --- a/src/analyzers/SourceKit.Analyzers.Collections/Analyzers/DictionaryKeyTypeMustImplementEquatableAnalyzer.cs +++ b/src/analyzers/SourceKit.Analyzers.Collections/Analyzers/DictionaryKeyTypeMustImplementEquatableAnalyzer.cs @@ -36,7 +36,7 @@ private void AnalyzeGeneric(SyntaxNodeAnalysisContext context) { var node = (GenericNameSyntax)context.Node; - if (context.SemanticModel.GetDeclaredSymbol(node) is not INamedTypeSymbol symbol) + if (context.SemanticModel.GetSymbolInfo(node).Symbol is not INamedTypeSymbol symbol) return; if (TryGetDictionaryKeySymbol(symbol, typeof(Dictionary<,>), context, out INamedTypeSymbol? keySymbol) is false @@ -54,17 +54,14 @@ private void AnalyzeGeneric(SyntaxNodeAnalysisContext context) INamedTypeSymbol equatableSymbol = context.Compilation.GetTypeSymbol(typeof(IEquatable<>)); - INamedTypeSymbol madeEquatableSymbol = equatableSymbol - .Construct(keySymbol.WithNullableAnnotation(NullableAnnotation.None)); - IEnumerable foundEquatableSymbols = keySymbol .FindAssignableTypesConstructedFrom(equatableSymbol); bool hasCorrectEquatableImplementation = foundEquatableSymbols .Select(x => x.TypeArguments.First()) - .Any(x => madeEquatableSymbol.Equals(x, SymbolEqualityComparer.Default)); + .Any(x => keySymbol.Equals(x, SymbolEqualityComparer.Default) || keySymbol.IsAssignableTo(x)); - if (hasCorrectEquatableImplementation is false) + if (hasCorrectEquatableImplementation) return; var diag = Diagnostic.Create(Descriptor, node.GetLocation()); diff --git a/src/analyzers/SourceKit.Analyzers.Collections/CodeFixes/ConvertListForEachIntoForEachLoopCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.Collections/CodeFixes/ConvertListForEachIntoForEachLoopCodeFixProvider.cs index 03981bb..b31acd8 100644 --- a/src/analyzers/SourceKit.Analyzers.Collections/CodeFixes/ConvertListForEachIntoForEachLoopCodeFixProvider.cs +++ b/src/analyzers/SourceKit.Analyzers.Collections/CodeFixes/ConvertListForEachIntoForEachLoopCodeFixProvider.cs @@ -42,8 +42,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( - equivalenceKey: ListForEachNotAllowedAnalyzer.DiagnosticId, title: Title, + priority: CodeActionPriority.High, + equivalenceKey: ListForEachNotAllowedAnalyzer.DiagnosticId, createChangedDocument: cancellationToken => ConvertListForEachIntoLoop(context.Document, invocationExpression, cancellationToken)), diagnostic); diff --git a/src/analyzers/SourceKit.Analyzers.Enumerable/CodeFixes/RemoveTerminalOperationCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.Enumerable/CodeFixes/RemoveTerminalOperationCodeFixProvider.cs index 29489b5..afbffa3 100644 --- a/src/analyzers/SourceKit.Analyzers.Enumerable/CodeFixes/RemoveTerminalOperationCodeFixProvider.cs +++ b/src/analyzers/SourceKit.Analyzers.Enumerable/CodeFixes/RemoveTerminalOperationCodeFixProvider.cs @@ -34,6 +34,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) var codeFixAction = CodeAction.Create( title: title, + priority: CodeActionPriority.High, createChangedSolution: c => RemoveToList(context.Document, node, c), equivalenceKey: title); diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/AnalyzerReleases.Unshipped.md b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/AnalyzerReleases.Unshipped.md index be321c3..c00b7bb 100644 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/AnalyzerReleases.Unshipped.md +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/AnalyzerReleases.Unshipped.md @@ -3,4 +3,5 @@ Rule ID | Category | Severity | Notes --------|----------|----------|-------------------- SK1100 | Design | Error | Do not use private properties -SK1101 | Design | Error | Do not use public fields \ No newline at end of file +SK1101 | Design | Error | Do not use public fields +SK1102 | Design | Error | Do not use multiple fields \ No newline at end of file diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotBePublicAnalyzer.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotBePublicAnalyzer.cs index a30fe73..fd35376 100644 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotBePublicAnalyzer.cs +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotBePublicAnalyzer.cs @@ -1,5 +1,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; namespace SourceKit.Analyzers.MemberAccessibility.Analyzers; @@ -8,9 +10,9 @@ namespace SourceKit.Analyzers.MemberAccessibility.Analyzers; public class FieldCannotBePublicAnalyzer : DiagnosticAnalyzer { public const string DiagnosticId = "SK1101"; - public const string Title = nameof(PropertyCannotBePrivateAnalyzer); + public const string Title = nameof(FieldCannotBePublicAnalyzer); - public const string Format = """Field {0} {1} cannot be public"""; + public const string Format = """Field '{0} {1}' cannot be public"""; public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor( DiagnosticId, @@ -27,5 +29,24 @@ public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.RegisterSyntaxNodeAction(AnalyzeField, SyntaxKind.FieldDeclaration); } -} \ No newline at end of file + + private void AnalyzeField(SyntaxNodeAnalysisContext context) + { + var fieldSyntax = (FieldDeclarationSyntax)context.Node; + + if (fieldSyntax.Modifiers.All(x => x.IsKind(SyntaxKind.PublicKeyword) is false)) + { + return; + } + + foreach (VariableDeclaratorSyntax variable in fieldSyntax.Declaration.Variables) + { + Location location = variable.GetLocation(); + var diagnostic = Diagnostic.Create(Descriptor, location, fieldSyntax.Declaration.Type, variable.Identifier.Text); + + context.ReportDiagnostic(diagnostic); + } + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotHaveMultipleVariablesAnalyzer.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotHaveMultipleVariablesAnalyzer.cs new file mode 100644 index 0000000..50247dd --- /dev/null +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/FieldCannotHaveMultipleVariablesAnalyzer.cs @@ -0,0 +1,48 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace SourceKit.Analyzers.MemberAccessibility.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] +public class FieldCannotHaveMultipleVariablesAnalyzer : DiagnosticAnalyzer +{ + public const string DiagnosticId = "SK1102"; + public const string Title = nameof(FieldCannotHaveMultipleVariablesAnalyzer); + + public const string Format = """Each field must have separate declaration"""; + + public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(DiagnosticId, + Title, + Format, + "Design", + DiagnosticSeverity.Error, + true); + + public override ImmutableArray SupportedDiagnostics { get; } = + ImmutableArray.Create(Descriptor); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.RegisterSyntaxNodeAction(AnalyzeField, SyntaxKind.FieldDeclaration); + } + + private void AnalyzeField(SyntaxNodeAnalysisContext context) + { + var fieldSyntax = (FieldDeclarationSyntax)context.Node; + + if (fieldSyntax.Declaration.Variables.Count <= 1) + { + return; + } + + Location location = fieldSyntax.GetLocation(); + var diagnostic = Diagnostic.Create(Descriptor, location); + + context.ReportDiagnostic(diagnostic); + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/PropertyCannotBePrivateAnalyzer.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/PropertyCannotBePrivateAnalyzer.cs index 6351a60..f64bf33 100644 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/PropertyCannotBePrivateAnalyzer.cs +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/Analyzers/PropertyCannotBePrivateAnalyzer.cs @@ -1,5 +1,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; namespace SourceKit.Analyzers.MemberAccessibility.Analyzers; @@ -10,10 +12,9 @@ public class PropertyCannotBePrivateAnalyzer : DiagnosticAnalyzer public const string DiagnosticId = "SK1100"; public const string Title = nameof(PropertyCannotBePrivateAnalyzer); - public const string Format = """Property {0} {1} cannot be private"""; + public const string Format = """Property '{0} {1}' cannot be private"""; - public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor( - DiagnosticId, + public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(DiagnosticId, Title, Format, "Design", @@ -27,5 +28,21 @@ public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.RegisterSyntaxNodeAction(AnalyzeProperty, SyntaxKind.PropertyDeclaration); } -} \ No newline at end of file + + private void AnalyzeProperty(SyntaxNodeAnalysisContext context) + { + var propertySyntax = (PropertyDeclarationSyntax)context.Node; + + if (propertySyntax.Modifiers.All(x => x.IsKind(SyntaxKind.PrivateKeyword) is false)) + { + return; + } + + Location location = propertySyntax.GetLocation(); + var diagnostic = Diagnostic.Create(Descriptor, location, propertySyntax.Type, propertySyntax.Identifier.Text); + + context.ReportDiagnostic(diagnostic); + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldAccessibilityCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldAccessibilityCodeFixProvider.cs deleted file mode 100644 index 698e242..0000000 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldAccessibilityCodeFixProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using SourceKit.Analyzers.MemberAccessibility.Analyzers; - -namespace SourceKit.Analyzers.MemberAccessibility.CodeFixes; - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(FieldAccessibilityCodeFixProvider))] -public class FieldAccessibilityCodeFixProvider : CodeFixProvider -{ - public const string Title = "Make field private"; - - public override ImmutableArray FixableDiagnosticIds { get; } = - ImmutableArray.Create(FieldCannotBePublicAnalyzer.DiagnosticId); - - public override FixAllProvider GetFixAllProvider() - => WellKnownFixAllProviders.BatchFixer; - - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotBePublicCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotBePublicCodeFixProvider.cs new file mode 100644 index 0000000..e612cb2 --- /dev/null +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotBePublicCodeFixProvider.cs @@ -0,0 +1,62 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace SourceKit.Analyzers.MemberAccessibility.CodeFixes; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(FieldCannotBePublicCodeFixProvider))] +public class FieldCannotBePublicCodeFixProvider : CodeFixProvider +{ + public const string Title = "Make field private"; + + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(FieldCannotBePublicAnalyzer.DiagnosticId); + + public override FixAllProvider GetFixAllProvider() + => WellKnownFixAllProviders.BatchFixer; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.CancellationToken.ThrowIfCancellationRequested(); + + IEnumerable derivativesMustBePartialDiagnostics = context.Diagnostics + .Select(x => ProvideDerivativesMustBePartial(context, x)); + + await Task.WhenAll(derivativesMustBePartialDiagnostics); + } + + private static async Task ProvideDerivativesMustBePartial(CodeFixContext context, Diagnostic diagnostic) + { + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); + + if (root?.FindNode(diagnostic.Location.SourceSpan) is not { Parent.Parent: FieldDeclarationSyntax fieldSyntax }) + return; + + var action = CodeAction.Create( + title: Title, + priority: CodeActionPriority.High, + equivalenceKey: nameof(FieldCannotBePublicCodeFixProvider), + createChangedDocument: _ => + { + SyntaxToken privateModifier = fieldSyntax.Modifiers.First(x => x.IsKind(SyntaxKind.PublicKeyword)); + + SyntaxTokenList fixedModifiers = fieldSyntax.Modifiers + .Replace(privateModifier, Token(SyntaxKind.PrivateKeyword)); + + FieldDeclarationSyntax fixedSyntax = fieldSyntax.WithModifiers(fixedModifiers); + + SyntaxNode newRoot = root.ReplaceNode(fieldSyntax, fixedSyntax); + + Document document = context.Document.WithSyntaxRoot(newRoot); + + return Task.FromResult(document); + }); + + context.RegisterCodeFix(action, diagnostic); + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixProvider.cs new file mode 100644 index 0000000..9180303 --- /dev/null +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixProvider.cs @@ -0,0 +1,62 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace SourceKit.Analyzers.MemberAccessibility.CodeFixes; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PropertyCannotBePrivateCodeFixProvider))] +public class FieldCannotHaveMultipleVariablesCodeFixProvider : CodeFixProvider +{ + public const string Title = "Separate field declarations"; + + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(FieldCannotHaveMultipleVariablesAnalyzer.DiagnosticId); + + public override FixAllProvider GetFixAllProvider() + => WellKnownFixAllProviders.BatchFixer; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.CancellationToken.ThrowIfCancellationRequested(); + + IEnumerable derivativesMustBePartialDiagnostics = context.Diagnostics + .Select(x => ProvideDerivativesMustBePartial(context, x)); + + await Task.WhenAll(derivativesMustBePartialDiagnostics); + } + + private static async Task ProvideDerivativesMustBePartial(CodeFixContext context, Diagnostic diagnostic) + { + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); + + if (root?.FindNode(diagnostic.Location.SourceSpan) is not FieldDeclarationSyntax fieldSyntax) + return; + + var action = CodeAction.Create( + title: Title, + priority: CodeActionPriority.High, + equivalenceKey: nameof(FieldCannotHaveMultipleVariablesCodeFixProvider), + createChangedDocument: _ => + { + IEnumerable fixedFields = fieldSyntax.Declaration.Variables.Select(x => + { + VariableDeclarationSyntax declaration = fieldSyntax.Declaration + .WithVariables(SingletonSeparatedList(x)); + + return fieldSyntax.WithDeclaration(declaration); + }); + + SyntaxNode newRoot = root.ReplaceNode(fieldSyntax, fixedFields); + + Document document = context.Document.WithSyntaxRoot(newRoot); + + return Task.FromResult(document); + }); + + context.RegisterCodeFix(action, diagnostic); + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyAccessibilityCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyAccessibilityCodeFixProvider.cs deleted file mode 100644 index bb6bfe9..0000000 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyAccessibilityCodeFixProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using SourceKit.Analyzers.MemberAccessibility.Analyzers; - -namespace SourceKit.Analyzers.MemberAccessibility.CodeFixes; - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PropertyAccessibilityCodeFixProvider))] -public class PropertyAccessibilityCodeFixProvider : CodeFixProvider -{ - public const string PublicTitle = "Make property public"; - public const string ProtectedTitle = "Make property protected"; - - public override ImmutableArray FixableDiagnosticIds { get; } = - ImmutableArray.Create(PropertyCannotBePrivateAnalyzer.DiagnosticId); - - public override FixAllProvider GetFixAllProvider() - => WellKnownFixAllProviders.BatchFixer; - - public override Task RegisterCodeFixesAsync(CodeFixContext context) - { - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyCannotBePrivateCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyCannotBePrivateCodeFixProvider.cs new file mode 100644 index 0000000..4872508 --- /dev/null +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/CodeFixes/PropertyCannotBePrivateCodeFixProvider.cs @@ -0,0 +1,62 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace SourceKit.Analyzers.MemberAccessibility.CodeFixes; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(PropertyCannotBePrivateCodeFixProvider))] +public class PropertyCannotBePrivateCodeFixProvider : CodeFixProvider +{ + public const string Title = "Make property public"; + + public override ImmutableArray FixableDiagnosticIds { get; } = + ImmutableArray.Create(PropertyCannotBePrivateAnalyzer.DiagnosticId); + + public override FixAllProvider GetFixAllProvider() + => WellKnownFixAllProviders.BatchFixer; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.CancellationToken.ThrowIfCancellationRequested(); + + IEnumerable derivativesMustBePartialDiagnostics = context.Diagnostics + .Select(x => ProvideDerivativesMustBePartial(context, x)); + + await Task.WhenAll(derivativesMustBePartialDiagnostics); + } + + private static async Task ProvideDerivativesMustBePartial(CodeFixContext context, Diagnostic diagnostic) + { + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); + + if (root?.FindNode(diagnostic.Location.SourceSpan) is not PropertyDeclarationSyntax propertySyntax) + return; + + var action = CodeAction.Create( + title: Title, + priority: CodeActionPriority.High, + equivalenceKey: nameof(PropertyCannotBePrivateCodeFixProvider), + createChangedDocument: _ => + { + SyntaxToken privateModifier = propertySyntax.Modifiers.First(x => x.IsKind(SyntaxKind.PrivateKeyword)); + + SyntaxTokenList fixedModifiers = propertySyntax.Modifiers + .Replace(privateModifier, Token(SyntaxKind.PublicKeyword)); + + PropertyDeclarationSyntax fixedSyntax = propertySyntax.WithModifiers(fixedModifiers); + + SyntaxNode newRoot = root.ReplaceNode(propertySyntax, fixedSyntax); + + Document document = context.Document.WithSyntaxRoot(newRoot); + + return Task.FromResult(document); + }); + + context.RegisterCodeFix(action, diagnostic); + } +} diff --git a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/SourceKit.Analyzers.MemberAccessibility.csproj b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/SourceKit.Analyzers.MemberAccessibility.csproj index 33c1cf8..010d4bc 100644 --- a/src/analyzers/SourceKit.Analyzers.MemberAccessibility/SourceKit.Analyzers.MemberAccessibility.csproj +++ b/src/analyzers/SourceKit.Analyzers.MemberAccessibility/SourceKit.Analyzers.MemberAccessibility.csproj @@ -8,7 +8,7 @@ true false - false + true diff --git a/src/analyzers/SourceKit.Analyzers.MustBePartial/CodeFixes/MakeTypePartialCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.MustBePartial/CodeFixes/MakeTypePartialCodeFixProvider.cs index fba458c..0349941 100644 --- a/src/analyzers/SourceKit.Analyzers.MustBePartial/CodeFixes/MakeTypePartialCodeFixProvider.cs +++ b/src/analyzers/SourceKit.Analyzers.MustBePartial/CodeFixes/MakeTypePartialCodeFixProvider.cs @@ -35,11 +35,12 @@ private static async Task ProvideDerivativesMustBePartial(CodeFixContext context { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); - if (root?.FindNode(context.Span) is not TypeDeclarationSyntax syntax) + if (root?.FindNode(diagnostic.Location.SourceSpan) is not TypeDeclarationSyntax syntax) return; var action = CodeAction.Create( - Title, + title: Title, + priority: CodeActionPriority.High, equivalenceKey: nameof(Title), createChangedDocument: _ => { diff --git a/src/analyzers/SourceKit.Analyzers.Nullable/CodeFixes/PropagateNullableCorrectlyCodeFixProvider.cs b/src/analyzers/SourceKit.Analyzers.Nullable/CodeFixes/PropagateNullableCorrectlyCodeFixProvider.cs index 5927c8b..8b99c12 100644 --- a/src/analyzers/SourceKit.Analyzers.Nullable/CodeFixes/PropagateNullableCorrectlyCodeFixProvider.cs +++ b/src/analyzers/SourceKit.Analyzers.Nullable/CodeFixes/PropagateNullableCorrectlyCodeFixProvider.cs @@ -66,6 +66,7 @@ private async Task FixDiagnostic(CodeFixContext context, DocumentEditor editor, context.RegisterCodeFix( CodeAction.Create( title: Title, + priority: CodeActionPriority.High, createChangedDocument: c => { var changedDocument = editor.GetChangedDocument(); diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotBePublicAnalyzerTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotBePublicAnalyzerTests.cs new file mode 100644 index 0000000..ab1710d --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotBePublicAnalyzerTests.cs @@ -0,0 +1,28 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.Analyzers; + +public class FieldCannotBePublicAnalyzerTests : AnalyzerTestBase +{ + [Fact] + public async Task ShouldReportDiagnostic_WhenFieldIsPublic() + { + SourceFile sourceFile = await SourceFile + .LoadAsync("SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.cs"); + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(FieldCannotBePublicAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 19) + .WithArguments("object", "_publicField"); + + await AnalyzerTest + .WithSource(sourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotHaveMultipleVariablesAnalyzerTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotHaveMultipleVariablesAnalyzerTests.cs new file mode 100644 index 0000000..cbe517d --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/FieldCannotHaveMultipleVariablesAnalyzerTests.cs @@ -0,0 +1,27 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.Analyzers; + +public class FieldCannotHaveMultipleVariablesAnalyzerTests : AnalyzerTestBase +{ + [Fact] + public async Task ShouldReportDiagnostic_WhenMultipleFields() + { + SourceFile sourceFile = await SourceFile + .LoadAsync("SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.cs"); + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(FieldCannotHaveMultipleVariablesAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 5); + + await AnalyzerTest + .WithSource(sourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/PropertyCannotBePrivateAnalyzerTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/PropertyCannotBePrivateAnalyzerTests.cs new file mode 100644 index 0000000..5d05353 --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/Analyzers/PropertyCannotBePrivateAnalyzerTests.cs @@ -0,0 +1,28 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.Analyzers; + +public class PropertyCannotBePrivateAnalyzerTests : AnalyzerTestBase +{ + [Fact] + public async Task ShouldReportDiagnostic_WhenPropertyIsPrivate() + { + SourceFile sourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.cs"); + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(PropertyCannotBePrivateAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 5) + .WithArguments("object", "PrivateProperty"); + + await AnalyzerTest + .WithSource(sourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotBePublicCodeFixTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotBePublicCodeFixTests.cs new file mode 100644 index 0000000..78a89ca --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotBePublicCodeFixTests.cs @@ -0,0 +1,37 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Analyzers.MemberAccessibility.CodeFixes; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.CodeFixes; + +public class FieldCannotBePublicCodeFixTests : CodeFixTestBase +{ + [Fact] + public async Task ShouldMakePropertyPublic_WhenDiagnosticReported() + { + SourceFile sourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.cs"); + + SourceFile fixedSourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/PublicFieldTestCase.Fixed.cs"); + + string fixedContent = fixedSourceFile.Content.Replace("PublicFieldTestCaseFixed", "PublicFieldTestCase"); + + fixedSourceFile = sourceFile with { Content = fixedContent }; + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(FieldCannotBePublicAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 19) + .WithArguments("object", "_publicField"); + + await CodeFixTest + .WithSource(sourceFile) + .WithFixedSource(fixedSourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixTests.cs new file mode 100644 index 0000000..0d427c5 --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/FieldCannotHaveMultipleVariablesCodeFixTests.cs @@ -0,0 +1,36 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Analyzers.MemberAccessibility.CodeFixes; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.CodeFixes; + +public class FieldCannotHaveMultipleVariablesCodeFixTests : CodeFixTestBase +{ + [Fact] + public async Task ShouldMakePropertyPublic_WhenDiagnosticReported() + { + SourceFile sourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.cs"); + + SourceFile fixedSourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/MultipleFieldsCase.Fixed.cs"); + + string fixedContent = fixedSourceFile.Content.Replace("MultipleFieldsCaseFixed", "MultipleFieldsCase"); + + fixedSourceFile = sourceFile with { Content = fixedContent }; + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(FieldCannotHaveMultipleVariablesAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 5); + + await CodeFixTest + .WithSource(sourceFile) + .WithFixedSource(fixedSourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/PropertyCannotBePrivateCodeFixTests.cs b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/PropertyCannotBePrivateCodeFixTests.cs new file mode 100644 index 0000000..4bfc862 --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/CodeFixes/PropertyCannotBePrivateCodeFixTests.cs @@ -0,0 +1,37 @@ +using Microsoft.CodeAnalysis.Testing; +using SourceKit.Analyzers.MemberAccessibility.Analyzers; +using SourceKit.Analyzers.MemberAccessibility.CodeFixes; +using SourceKit.Tests.Common; +using SourceKit.Tests.Common.TestBases; +using Xunit; + +namespace SourceKit.Analyzers.MemberAccessibility.Tests.CodeFixes; + +public class PropertyCannotBePrivateCodeFixTests : CodeFixTestBase +{ + [Fact] + public async Task ShouldMakePropertyPublic_WhenDiagnosticReported() + { + SourceFile sourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.cs"); + + SourceFile fixedSourceFile = await SourceFile.LoadAsync( + "SourceKit.Analyzers.MemberAccessibility.Samples/PrivatePropertyCase.Fixed.cs"); + + string fixedContent = fixedSourceFile.Content.Replace("PrivatePropertyCaseFixed", "PrivatePropertyCase"); + + fixedSourceFile = sourceFile with { Content = fixedContent }; + + DiagnosticResult diagnostic = AnalyzerVerifier + .Diagnostic(PropertyCannotBePrivateAnalyzer.Descriptor) + .WithLocation(sourceFile.Name, 5, 5) + .WithArguments("object", "PrivateProperty"); + + await CodeFixTest + .WithSource(sourceFile) + .WithFixedSource(fixedSourceFile) + .WithExpectedDiagnostic(diagnostic) + .Build() + .RunAsync(); + } +} diff --git a/tests/SourceKit.Analyzers.MemberAccessibility.Tests/SourceKit.Analyzers.MemberAccessibility.Tests.csproj b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/SourceKit.Analyzers.MemberAccessibility.Tests.csproj new file mode 100644 index 0000000..4ae33fe --- /dev/null +++ b/tests/SourceKit.Analyzers.MemberAccessibility.Tests/SourceKit.Analyzers.MemberAccessibility.Tests.csproj @@ -0,0 +1,30 @@ + + + + false + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SourceKit.Generators.Builder.Tests/BuilderSourceGeneratorTests.cs b/tests/SourceKit.Generators.Builder.Tests/BuilderSourceGeneratorTests.cs index 6b71bc5..ed95d2a 100644 --- a/tests/SourceKit.Generators.Builder.Tests/BuilderSourceGeneratorTests.cs +++ b/tests/SourceKit.Generators.Builder.Tests/BuilderSourceGeneratorTests.cs @@ -28,6 +28,7 @@ public async Task ShouldGenerateCorrectBuilderType() using System.Collections.Generic; using System.Linq; + #nullable enable namespace SourceKit.Generators.Builder.Samples { public partial record SomeQuery @@ -39,39 +40,39 @@ public static SomeQuery Build(Func action) public sealed partial class Builder { - private readonly List _ids; - private Int32 _count; - private Nullable _orderById; + private readonly global::System.Collections.Generic.List _ids; + private int _count; + private int? _orderById; public Builder() { - _ids = new List(); + _ids = new global::System.Collections.Generic.List(); _count = default; _orderById = default; } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithId(Guid element) + public Builder WithId(global::System.Guid element) { _ids.Add(element); return this; } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithIds(IEnumerable elements) + public Builder WithIds(global::System.Collections.Generic.IEnumerable elements) { _ids.AddRange(elements); return this; } [InitializesPropertyAttribute(nameof(Count))] - public Builder WithCount(Int32 value) + public Builder WithCount(int value) { _count = value; return this; } [InitializesPropertyAttribute(nameof(OrderById))] - public Builder WithOrderById(Nullable value) + public Builder WithOrderById(int? value) { _orderById = value; return this; @@ -114,6 +115,7 @@ public async Task ShouldGenerateCorrectBuilderType_WhenPropertyIsArray() using System.Collections.Generic; using System.Linq; + #nullable enable namespace SourceKit.Generators.Builder.Samples { public partial record ArrayQuery @@ -125,21 +127,21 @@ public static ArrayQuery Build(Func action) public sealed partial class Builder { - private readonly List _ids; + private readonly global::System.Collections.Generic.List _ids; public Builder() { - _ids = new List(); + _ids = new global::System.Collections.Generic.List(); } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithId(Guid element) + public Builder WithId(global::System.Guid element) { _ids.Add(element); return this; } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithIds(IEnumerable elements) + public Builder WithIds(global::System.Collections.Generic.IEnumerable elements) { _ids.AddRange(elements); return this; @@ -182,6 +184,7 @@ public async Task ShouldGenerateCorrectBuilderType_WhenPropertyHasCustomType() using System.Collections.Generic; using System.Linq; + #nullable enable namespace SourceKit.Generators.Builder.Samples { public partial record ArrayQuery @@ -193,21 +196,21 @@ public static ArrayQuery Build(Func action) public sealed partial class Builder { - private readonly List _ids; + private readonly global::System.Collections.Generic.List _ids; public Builder() { - _ids = new List(); + _ids = new global::System.Collections.Generic.List(); } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithId(Guid element) + public Builder WithId(global::System.Guid element) { _ids.Add(element); return this; } [InitializesPropertyAttribute(nameof(Ids))] - public Builder WithIds(IEnumerable elements) + public Builder WithIds(global::System.Collections.Generic.IEnumerable elements) { _ids.AddRange(elements); return this; @@ -251,34 +254,35 @@ public async Task ShouldGenerateCorrectBuilderType_WhenPropertyHasBuilderConstru using System.Collections.Generic; using System.Linq; + #nullable enable namespace SourceKit.Generators.Builder.Samples.BuilderConstructorParameter { public partial record IntegerConstructorParameterQuery { - public static IntegerConstructorParameterQuery Build(Nullable Id, Func action) + public static IntegerConstructorParameterQuery Build(int? Id, Func action) { return action(new Builder(Id)).Build(); } public sealed partial class Builder { - private Nullable _id; - private String _value; - public Builder(Nullable Id) + private int? _id; + private string? _value; + public Builder(int? Id) { _id = Id; _value = string.Empty; } [InitializesPropertyAttribute(nameof(Id))] - public Builder WithId(Nullable value) + public Builder WithId(int? value) { _id = value; return this; } [InitializesPropertyAttribute(nameof(Value))] - public Builder WithValue(String value) + public Builder WithValue(string value) { _value = value; return this; @@ -286,7 +290,7 @@ public Builder WithValue(String value) public IntegerConstructorParameterQuery Build() { - return new IntegerConstructorParameterQuery(_id, _value); + return new IntegerConstructorParameterQuery(_id, _value ?? throw new System.ArgumentNullException(nameof(_value))); } } } diff --git a/tests/SourceKit.Generators.Grpc.Tests/ProtoMessageConstructorGeneratorTests.cs b/tests/SourceKit.Generators.Grpc.Tests/ProtoMessageConstructorGeneratorTests.cs index 46fd128..de39567 100644 --- a/tests/SourceKit.Generators.Grpc.Tests/ProtoMessageConstructorGeneratorTests.cs +++ b/tests/SourceKit.Generators.Grpc.Tests/ProtoMessageConstructorGeneratorTests.cs @@ -648,12 +648,12 @@ public void MergeFrom(pb::CodedInputStream input) { var generatedSource = new SourceFile( Name: """ - SourceKit.Generators.Grpc/SourceKit.Generators.Grpc.Generators.ProtoMessageConstructorGenerator/ProtoModel.SourceKit.Generators.Grpc.g.cs + SourceKit.Generators.Grpc/SourceKit.Generators.Grpc.Generators.ProtoMessageConstructorGenerator/Playground.ProtoModel.SourceKit.Generators.Grpc.g.cs """, Content: """ // - // This code was generated by a SourceKit.Generators.Grpc code generator. - // https://github.com/itmo-is-dev/SourceKit + // This code was generated by a SourceKit.Generators.Grpc code generator. + // https://github.com/itmo-is-dev/SourceKit // #pragma warning disable CS1591 using System; @@ -665,7 +665,7 @@ namespace Playground { public partial class ProtoModel { - public ProtoModel(String? pageToken, IEnumerable values, Int32 pageSize, IEnumerable intValues, Int32? intOneofValue, String? stringOneofValue, String notNullStringValue, Nullable nullIntValue, String? nullStringValue, IEnumerable> mapValue) + public ProtoModel(string? pageToken, IEnumerable values, int pageSize, IEnumerable intValues, int? intOneofValue, string? stringOneofValue, string notNullStringValue, int? nullIntValue, string? nullStringValue, IEnumerable> mapValue) { PageToken = pageToken; Values.Add(values); @@ -684,7 +684,7 @@ public ProtoModel(String? pageToken, IEnumerable values, Int32 pageSize, NotNullStringValue = notNullStringValue; NullIntValue = nullIntValue; NullStringValue = nullStringValue; - foreach (KeyValuePair item in mapValue) + foreach (KeyValuePair item in mapValue) { MapValue.Add(item.Key, item.Value); }