Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Documentation/Diagnostics/PH2134.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
| Diagnostic ID | PH2134 |
| Category | [Maintainability](../Maintainability.md) |
| Analyzer | [NamespaceMatchAssemblyNameAnalyzer](https://github.com/philips-software/roslyn-analyzers/blob/main/Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderAnalyzer.cs)
| CodeFix | No |
| CodeFix | Yes |
| Severity | Error |
| Enabled By Default | Yes |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// © 2025 Koninklijke Philips N.V. See License.md in the project root for license information.

using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Philips.CodeAnalysis.Common;

namespace Philips.CodeAnalysis.MaintainabilityAnalyzers.Maintainability
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(SetPropertiesInAnyOrderCodeFixProvider)), Shared]
public class SetPropertiesInAnyOrderCodeFixProvider : SingleDiagnosticCodeFixProvider<AccessorDeclarationSyntax>
{
protected override string Title => "Convert to auto-property";

protected override DiagnosticId DiagnosticId => DiagnosticId.SetPropertiesInAnyOrder;

protected override async Task<Document> ApplyFix(Document document, AccessorDeclarationSyntax node, ImmutableDictionary<string, string> properties, CancellationToken cancellationToken)
{
SyntaxNode rootNode = await document.GetSyntaxRootAsync(cancellationToken);

// Find the parent property declaration
PropertyDeclarationSyntax propertyDeclaration = node.Ancestors().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (propertyDeclaration == null)
{
return document;
}

// Create a simple auto-property with { get; set; }

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 35 in Philips.CodeAnalysis.MaintainabilityAnalyzers/Maintainability/SetPropertiesInAnyOrderCodeFixProvider.cs

View workflow job for this annotation

GitHub Actions / sonarcloud / SonarCloud

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)
PropertyDeclarationSyntax newPropertyDeclaration = SyntaxFactory.PropertyDeclaration(
attributeLists: propertyDeclaration.AttributeLists,
modifiers: propertyDeclaration.Modifiers,
type: propertyDeclaration.Type,
explicitInterfaceSpecifier: propertyDeclaration.ExplicitInterfaceSpecifier,
identifier: propertyDeclaration.Identifier,
accessorList: SyntaxFactory.AccessorList(
SyntaxFactory.List(new[]
{
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
}))
).WithLeadingTrivia(propertyDeclaration.GetLeadingTrivia())
.WithTrailingTrivia(propertyDeclaration.GetTrailingTrivia())
.WithAdditionalAnnotations(Formatter.Annotation);

// Replace the property in the syntax tree
SyntaxNode newRoot = rootNode.ReplaceNode(propertyDeclaration, newPropertyDeclaration);

return document.WithSyntaxRoot(newRoot);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// © 2025 Koninklijke Philips N.V. See License.md in the project root for license information.

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Philips.CodeAnalysis.MaintainabilityAnalyzers.Maintainability;
using Philips.CodeAnalysis.Test.Helpers;
using Philips.CodeAnalysis.Test.Verifiers;

namespace Philips.CodeAnalysis.Test.Maintainability.Maintainability
{
[TestClass]
public class SetPropertiesInAnyOrderCodeFixProviderTest : CodeFixVerifier
{
[TestMethod]
[TestCategory(TestDefinitions.UnitTests)]
public async Task ConvertPropertyWithCustomSetterToAutoproperty()
{
var given = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two {
set {
One = value - 1;
}
}
}
}";

var expected = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two { get; set; }
}
}";

await VerifyFix(given, expected).ConfigureAwait(false);
}

[TestMethod]
[TestCategory(TestDefinitions.UnitTests)]
public async Task ConvertPropertyWithCustomSetterAndGetterToAutoproperty()
{
var given = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two {
get { return _two; }
set {
One = value - 1;
_two = value;
}
}
private int _two;
}
}";

var expected = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two { get; set; }
private int _two;
}
}";

await VerifyFix(given, expected).ConfigureAwait(false);
}

[TestMethod]
[TestCategory(TestDefinitions.UnitTests)]
public async Task ConvertPropertyWithOnlyCustomSetterToAutoproperty()
{
var given = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two {
set {
One = value;
}
}
}
}";

var expected = @"
namespace PropertiesinOrderTests {
public class Number {
public int One { get; set; }
public int Two { get; set; }
}
}";

await VerifyFix(given, expected).ConfigureAwait(false);
}

protected override CodeFixProvider GetCodeFixProvider()
{
return new SetPropertiesInAnyOrderCodeFixProvider();
}

protected override DiagnosticAnalyzer GetDiagnosticAnalyzer()
{
return new SetPropertiesInAnyOrderAnalyzer();
}
}
}
Loading