diff --git a/.omnisharp/omnisharp.json b/.omnisharp/omnisharp.json
new file mode 100644
index 0000000..28c2827
--- /dev/null
+++ b/.omnisharp/omnisharp.json
@@ -0,0 +1,9 @@
+{
+ "RoslynExtensionsOptions": {
+ "enableImportCompletion": true,
+ "enableAnalyzersSupport": true,
+ "locationPaths": [
+ "../src/ImmutableAnalyzer/ImmutableAnalyzer/bin/Release/netstandard2.0/publish/ImmutableAnalyzer.dll"
+ ]
+ }
+}
diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json
new file mode 100644
index 0000000..850a95c
--- /dev/null
+++ b/src/.vscode/launch.json
@@ -0,0 +1,26 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ // Use IntelliSense to find out which attributes exist for C# debugging
+ // Use hover for the description of the existing attributes
+ // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // If you have changed target frameworks, make sure to update the program path.
+ "program": "${workspaceFolder}/ImmutableAnalyzer/ImmutableAnalyzer.Tests/bin/Debug/net6.0/ImmutableAnalyzer.Tests.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/ImmutableAnalyzer/ImmutableAnalyzer.Tests",
+ // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/.vscode/tasks.json b/src/.vscode/tasks.json
new file mode 100644
index 0000000..4a7b073
--- /dev/null
+++ b/src/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/ImmutableAnalyzer.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/ImmutableAnalyzer.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/ImmutableAnalyzer.sln"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/Factories/SourceFactory.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/Factories/SourceFactory.cs
index 49ad3ac..713d90d 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/Factories/SourceFactory.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/Factories/SourceFactory.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
namespace ImmutableAnalyzer.Tests.Factories;
@@ -114,4 +114,4 @@ private static (int Line, int Column) GetLineAndColumn(string source, string tex
return (line + 1, column + 1);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorAnalyzerTests.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorAnalyzerTests.cs
index 790e1b6..70c701e 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorAnalyzerTests.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorAnalyzerTests.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using ImmutableAnalyzer.PropertyAnalyzers.SetAccessor;
using ImmutableAnalyzer.Tests.Factories;
using Xunit;
@@ -44,4 +44,4 @@ public async Task Immutable_class_property_could_have_no_setter()
var source = SourceFactory.ImmutableClassWithGetOnlyPropertyAccessor();
await Verifier.VerifyAnalyzerAsync(source);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorCodeFixTests.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorCodeFixTests.cs
index 2ca5656..3d8bcf8 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorCodeFixTests.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/PropertyAnalyzersTests/SetAccessorTests/SetAccessorCodeFixTests.cs
@@ -5,15 +5,15 @@
using Microsoft.CodeAnalysis.Testing;
using Xunit;
using FixStrategy = ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorCodeFixProvider.FixStrategy;
-using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.CodeFixVerifier<
- ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorAnalyzer,
- ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorCodeFixProvider
->;
using SetAccessorCodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest<
ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorAnalyzer,
ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorCodeFixProvider,
Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier
>;
+using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.CodeFixVerifier<
+ ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorAnalyzer,
+ ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.SetAccessorCodeFixProvider
+>;
namespace ImmutableAnalyzer.Tests.PropertyAnalyzersTests.SetAccessorTests;
@@ -60,10 +60,10 @@ private static SetAccessorCodeFixTest CreateTest(FixStrategy fixStrategy)
var fixedSource = fixStrategy switch
{
- FixStrategy.Remove => SourceFactory.ImmutableClassWithGetOnlyPropertyAccessor(),
- FixStrategy.ToInit => SourceFactory.ImmutableClassWithPropertyAccessor("init", out _, out _),
+ FixStrategy.Remove => SourceFactory.ImmutableClassWithGetOnlyPropertyAccessor(),
+ FixStrategy.ToInit => SourceFactory.ImmutableClassWithPropertyAccessor("init", out _, out _),
FixStrategy.ToPrivate => SourceFactory.ImmutableClassWithPropertyAccessor("private set", out _, out _),
- _ => throw new ArgumentOutOfRangeException(nameof(fixStrategy), fixStrategy, null)
+ _ => throw new ArgumentOutOfRangeException(nameof(fixStrategy), fixStrategy, null)
};
return new SetAccessorCodeFixTest
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/RecordAnalyzersTests/ParameterTypeAnalyzerTests.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/RecordAnalyzersTests/ParameterTypeAnalyzerTests.cs
index febf4ad..78a1729 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/RecordAnalyzersTests/ParameterTypeAnalyzerTests.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/RecordAnalyzersTests/ParameterTypeAnalyzerTests.cs
@@ -1,4 +1,4 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using ImmutableAnalyzer.ParameterAnalyzers;
using ImmutableAnalyzer.Tests.Factories;
using Xunit;
@@ -31,4 +31,4 @@ public async Task Record_with_mutable_property_should_not_be_immutable(string pr
var expected = Verifier.Diagnostic().WithLocation(line, column).WithArguments(property);
await Verifier.VerifyAnalyzerAsync(source, expected);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/TestData.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/TestData.cs
index eedd7f8..21c67f9 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/TestData.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer.Tests/TestData.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;
-using TypeCheckerConst = ImmutableAnalyzer.Utils.TypeChecking.Const.TypeCheckerConst;
+using Types = ImmutableAnalyzer.Utils.TypeChecking.Const.Types;
namespace ImmutableAnalyzer.Tests;
@@ -13,26 +13,26 @@ public static class TestData
{
///
/// Represent immutable built-in types.
- ///
+ ///
///
public class ImmutableTypes : TheoryData
{
public ImmutableTypes()
{
- foreach (var typeName in TypeCheckerConst.ImmutableTypes)
+ foreach (var typeName in Types.ImmutableTypes)
Add(typeName);
}
}
///
/// Represent immutable built-in generic types.
- ///
+ ///
///
public class ImmutableGenericsTypes : TheoryData
{
public ImmutableGenericsTypes()
{
- foreach (var typeName in TypeCheckerConst.ImmutableGenericTypes)
+ foreach (var typeName in Types.Generic)
Add(CreateGenericTypeStringWithParams(typeName, nameof(Int32)));
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/AssemblyInfo.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/AssemblyInfo.cs
index a0250af..11f07ef 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/AssemblyInfo.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/AssemblyInfo.cs
@@ -1,3 +1,3 @@
-using System.Runtime.CompilerServices;
+using System.Runtime.CompilerServices;
-[assembly:InternalsVisibleTo("ImmutableAnalyzer.Tests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("ImmutableAnalyzer.Tests")]
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/MemberAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/MemberAnalyzer.cs
similarity index 84%
rename from src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/MemberAnalyzer.cs
rename to src/ImmutableAnalyzer/ImmutableAnalyzer/Common/MemberAnalyzer.cs
index 6aad35d..259b9ec 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/MemberAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/MemberAnalyzer.cs
@@ -1,13 +1,14 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-namespace ImmutableAnalyzer.Abstractions;
+namespace ImmutableAnalyzer.Common;
///
/// Base class for member analyzers in immutable class.
/// Type of class member to analyze.
///
-internal abstract class MemberAnalyzer : TypeDeclarationAnalyzer
+internal abstract class MemberAnalyzer
+ : TypeDeclarationAnalyzer
{
///
/// Execute analyzer.
@@ -18,8 +19,7 @@ internal abstract class MemberAnalyzer : TypeDeclarationAnalyzer<
///
/// Execute analyzer.
- /// Executes only if class declaration
- /// marked by .
+ /// Executes only if class declaration marked by .
///
/// Type declaration node.
/// Analysis context.
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/ParameterAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/ParameterAnalyzer.cs
similarity index 90%
rename from src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/ParameterAnalyzer.cs
rename to src/ImmutableAnalyzer/ImmutableAnalyzer/Common/ParameterAnalyzer.cs
index e2c495e..fccc484 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/ParameterAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/ParameterAnalyzer.cs
@@ -1,7 +1,7 @@
-using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-namespace ImmutableAnalyzer.Abstractions;
+namespace ImmutableAnalyzer.Common;
///
/// Base class for parameter analyzer in immutable records.
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/TypeDeclarationAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/TypeDeclarationAnalyzer.cs
similarity index 87%
rename from src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/TypeDeclarationAnalyzer.cs
rename to src/ImmutableAnalyzer/ImmutableAnalyzer/Common/TypeDeclarationAnalyzer.cs
index 193c9e2..a01c565 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Abstractions/TypeDeclarationAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Common/TypeDeclarationAnalyzer.cs
@@ -1,9 +1,9 @@
-using ImmutableAnalyzer.Extensions;
+using ImmutableAnalyzer.Extensions;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-namespace ImmutableAnalyzer.Abstractions;
+namespace ImmutableAnalyzer.Common;
///
/// Base class for type declaration analyzer.
@@ -40,7 +40,9 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
if (context.ContainingSymbol is { } symbol && !symbol.HasAttribute())
return;
- if (context.Node is TDeclarationSyntax typeDeclarationSyntax)
- AnalyzeTypeDeclaration(typeDeclarationSyntax, context);
+ if (context.Node is not TDeclarationSyntax typeDeclarationSyntax)
+ return;
+
+ AnalyzeTypeDeclaration(typeDeclarationSyntax, context);
}
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Extensions/SymbolExtensions.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Extensions/SymbolExtensions.cs
index 7fea587..5cb8e2f 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Extensions/SymbolExtensions.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Extensions/SymbolExtensions.cs
@@ -10,15 +10,15 @@ namespace ImmutableAnalyzer.Extensions;
internal static class SymbolExtensions
{
///
- /// Checks if marked by given attribute.
+ /// Checks if marked by given attribute.
///
/// Symbol, exposed by compiler.
- /// true - if symbol marked by given attribute, otherwise - false.
+ /// true - if marked by given attribute, otherwise - false.
public static bool HasAttribute(this ISymbol symbol) =>
symbol.GetAttributes().Any(data => data.AttributeClass?.Name == typeof(T).Name);
///
- /// Returns symbol from type and context.
+ /// Returns symbol from type.
///
/// Type syntax expression.
/// Semantic model.
@@ -30,8 +30,8 @@ public static ITypeSymbol GetTypeSymbolFromSyntaxNode(this SemanticModel semanti
return symbol switch
{
IArrayTypeSymbol arrayTypeSymbol => arrayTypeSymbol.ElementType, // detect arrays e.g. int[] -> int
- not null => symbol, // just return type symbol
- _ => throw new NotSupportedException("Not supported symbol")
+ not null => symbol, // just return type symbol
+ _ => throw new NotSupportedException("Not supported symbol")
};
}
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/ImmutableAttribute.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/ImmutableAttribute.cs
index 0285297..4add122 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/ImmutableAttribute.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/ImmutableAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace ImmutableAnalyzer;
@@ -6,4 +6,4 @@ namespace ImmutableAnalyzer;
/// Attribute, that represent immutable class.
///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)]
-public class ImmutableAttribute : Attribute { }
\ No newline at end of file
+public class ImmutableAttribute : Attribute { }
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/ParameterAnalyzers/ParameterTypeAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/ParameterAnalyzers/ParameterTypeAnalyzer.cs
index 1437339..59aaba7 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/ParameterAnalyzers/ParameterTypeAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/ParameterAnalyzers/ParameterTypeAnalyzer.cs
@@ -1,5 +1,5 @@
using System.Collections.Immutable;
-using ImmutableAnalyzer.Abstractions;
+using ImmutableAnalyzer.Common;
using ImmutableAnalyzer.Extensions;
using ImmutableAnalyzer.Utils.TypeChecking;
using Microsoft.CodeAnalysis;
@@ -20,20 +20,22 @@ internal class ParameterTypeAnalyzer : ParameterAnalyzer
private static readonly TypeChecker Checker = TypeCheckerFactory.GetOrCreate();
///
- public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule);
+ public override ImmutableArray SupportedDiagnostics { get; } =
+ ImmutableArray.Create(Rule);
///
/// Diagnostic descriptor.
///
- private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
- id: "IM0003",
- title: "Mutable parameter in record parameter list",
- messageFormat: "Immutable record can't have parameter of type '{0}'",
- category: "Design",
- defaultSeverity: DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: "Record parameter must have immutable type."
- );
+ private static readonly DiagnosticDescriptor Rule =
+ new(
+ id: "IM0003",
+ title: "Mutable parameter in record parameter list",
+ messageFormat: "Immutable record can't have parameter of type '{0}'",
+ category: "Design",
+ defaultSeverity: DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ description: "Record parameter must have immutable type."
+ );
///
protected override void AnalyzeParameter(ParameterSyntax node, SyntaxNodeAnalysisContext ctx)
@@ -42,7 +44,8 @@ protected override void AnalyzeParameter(ParameterSyntax node, SyntaxNodeAnalysi
return;
var diagnostic = Diagnostic.Create(
- Rule, node.Type!.GetLocation(),
+ Rule,
+ node.Type!.GetLocation(),
node.Type.ToFullString().Trim()
);
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyAnalyzer.cs
index 81aedfb..b8fd86e 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyAnalyzer.cs
@@ -1,4 +1,4 @@
-using ImmutableAnalyzer.Abstractions;
+using ImmutableAnalyzer.Common;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ImmutableAnalyzer.PropertyAnalyzers;
@@ -6,4 +6,4 @@ namespace ImmutableAnalyzer.PropertyAnalyzers;
///
/// Base class for property analyzer in immutable type.
///
-internal abstract class PropertyAnalyzer : MemberAnalyzer { }
\ No newline at end of file
+internal abstract class PropertyAnalyzer : MemberAnalyzer { }
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyType/PropertyTypeAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyType/PropertyTypeAnalyzer.cs
index 3e5d2be..30d933a 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyType/PropertyTypeAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/PropertyType/PropertyTypeAnalyzer.cs
@@ -1,4 +1,4 @@
-using System.Collections.Immutable;
+using System.Collections.Immutable;
using ImmutableAnalyzer.Extensions;
using ImmutableAnalyzer.Utils.TypeChecking;
using Microsoft.CodeAnalysis;
@@ -24,14 +24,14 @@ internal sealed class PropertyTypeAnalyzer : PropertyAnalyzer
///
/// Diagnostic descriptor.
///
- private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
- id: "IM0001",
- title: "Mutable property in immutable type",
- messageFormat: "Immutable type can't have property of type '{0}'",
- category: "Design",
- defaultSeverity: DiagnosticSeverity.Error,
+ private static readonly DiagnosticDescriptor Rule = new(
+ id: "IM0001",
+ title: "Mutable property in immutable type",
+ messageFormat: "Immutable type can't have property of type '{0}'",
+ category: "Design",
+ defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
- description: "Class member must have immutable type."
+ description: "Class member must have immutable type."
);
///
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ChangeSetAccessorStrategy.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ChangeSetAccessorStrategy.cs
index 43ebc63..6fa8f3c 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ChangeSetAccessorStrategy.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ChangeSetAccessorStrategy.cs
@@ -1,4 +1,4 @@
-using System.Threading;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -9,13 +9,13 @@ namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
///
/// Base class for change set accessor strategy.
///
-internal abstract class ChangeSetAccessorStrategy
+internal abstract class ChangeSetAccessorCodeFix
{
///
/// Delegate, which used to get new from given.
///
/// We must return new accessor instead of modifying given because it's immutable.
- protected delegate AccessorDeclarationSyntax? AccessorModifier(AccessorDeclarationSyntax originalNode);
+ protected delegate void AccessorModifier(AccessorDeclarationSyntax originalNode, DocumentEditor editor);
///
/// Gets title for code fix.
@@ -30,7 +30,7 @@ internal abstract class ChangeSetAccessorStrategy
protected abstract AccessorModifier Modifier { get; }
///
- /// Applies to given node.
+ /// Applies to given .
///
/// Original .
/// Node to apply changes.
@@ -39,13 +39,8 @@ internal abstract class ChangeSetAccessorStrategy
public async Task ChangeDocument(Document originalDocument, AccessorDeclarationSyntax node, CancellationToken ct)
{
var editor = await DocumentEditor.CreateAsync(originalDocument, ct).ConfigureAwait(false);
- var newNode = Modifier.Invoke(node);
-
- if (newNode is null)
- editor.RemoveNode(node);
- else
- editor.ReplaceNode(node, newNode);
+ Modifier.Invoke(node, editor);
return editor.GetChangedDocument();
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/RemoveSetAccessor.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/RemoveSetAccessor.cs
index dd39bbe..3736c5f 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/RemoveSetAccessor.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/RemoveSetAccessor.cs
@@ -1,13 +1,13 @@
-namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
+namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
///
/// Removes 'set' accessor.
///
-internal class RemoveSetAccessor : ChangeSetAccessorStrategy
+internal class RemoveSetAccessor : ChangeSetAccessorCodeFix
{
///
public override string GetTitle(string format) => "Remove set accessor";
///
- protected override AccessorModifier Modifier { get; } = _ => null;
-}
\ No newline at end of file
+ protected override AccessorModifier Modifier { get; } = (node, editor) => editor.RemoveNode(node);
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToInit.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToInit.cs
index 8c9a7a1..dae7afb 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToInit.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToInit.cs
@@ -5,11 +5,11 @@ namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
///
/// Changes 'set' accessor to 'init'.
///
-internal class ToInit : ChangeSetAccessorStrategy
+internal class ToInit : ChangeSetAccessorCodeFix
{
///
public override string GetTitle(string format) => string.Format(format, "init");
///
- protected override AccessorModifier Modifier { get; } = syntax => syntax.WithKeyword(SyntaxFactory.Token(SyntaxKind.InitKeyword));
+ protected override AccessorModifier Modifier { get; } = (node, editor) => editor.ReplaceNode(node, node.WithKeyword(SyntaxFactory.Token(SyntaxKind.InitKeyword)));
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToPrivate.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToPrivate.cs
index d3d526a..31ee510 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToPrivate.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/CodeFixes/ToPrivate.cs
@@ -1,4 +1,4 @@
-using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
@@ -6,12 +6,12 @@ namespace ImmutableAnalyzer.PropertyAnalyzers.SetAccessor.CodeFixes;
///
/// Changes access modifier of 'set' accessor to private.
///
-internal class ToPrivate : ChangeSetAccessorStrategy
+internal class ToPrivate : ChangeSetAccessorCodeFix
{
///
public override string GetTitle(string format) => string.Format(format, "private set");
///
- protected override AccessorModifier Modifier { get; } =
- syntax => syntax.WithModifiers(new SyntaxTokenList(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)));
-}
\ No newline at end of file
+ protected override AccessorModifier Modifier { get; } = (node, editor) =>
+ editor.ReplaceNode(node, node.WithModifiers(new SyntaxTokenList(SyntaxFactory.Token(SyntaxKind.PrivateKeyword))));
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorAnalyzer.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorAnalyzer.cs
index 9634037..4d041e6 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorAnalyzer.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorAnalyzer.cs
@@ -1,4 +1,4 @@
-using System.Collections.Immutable;
+using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -24,21 +24,20 @@ internal sealed class SetAccessorAnalyzer : PropertyAnalyzer
///
/// Diagnostic descriptor.
///
- private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
- id: DiagnosticId,
- title: "Public setter violates type immutability",
- messageFormat: "Member of immutable type can't have '{0}' accessor",
- category: "Design",
- defaultSeverity: DiagnosticSeverity.Error,
+ private static readonly DiagnosticDescriptor Rule = new(
+ id: DiagnosticId,
+ title: "Public setter violates type immutability",
+ messageFormat: "Member of immutable type can't have '{0}' accessor",
+ category: "Design",
+ defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
- description: "Setter can't be public, because it's give possibility to change member from the outer."
+ description: "Setter can't be public, because it's give possibility to change member from the outer."
);
///
protected override void AnalyzeMember(PropertyDeclarationSyntax node, SyntaxNodeAnalysisContext ctx)
{
- var setAccessor = node.AccessorList?
- .Accessors
+ var setAccessor = node.AccessorList?.Accessors
.FirstOrDefault(syntax => syntax.IsKind(SyntaxKind.SetAccessorDeclaration));
if (setAccessor is null || !ShouldReport(setAccessor))
@@ -63,4 +62,4 @@ private static bool ShouldReport(AccessorDeclarationSyntax setAccessor)
var modifiers = setAccessor.Modifiers;
return !(modifiers.Any(SyntaxKind.PrivateKeyword) || modifiers.Any(SyntaxKind.InitKeyword));
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorCodeFixProvider.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorCodeFixProvider.cs
index 12fe8ba..120d4a4 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorCodeFixProvider.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/PropertyAnalyzers/SetAccessor/SetAccessorCodeFixProvider.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
@@ -23,11 +23,11 @@ public class SetAccessorCodeFixProvider : CodeFixProvider
public enum FixStrategy
{
/// Mapped to .
- ToInit = 0,
+ ToInit = 0,
/// Mapped to .
ToPrivate = 1,
/// Mapped to .
- Remove = 2,
+ Remove = 2,
}
///
@@ -43,8 +43,8 @@ public enum FixStrategy
///
/// Key-Value pairs of strategies to codefix.
///
- private static readonly IReadOnlyDictionary ChangeSetAccessorStrategies =
- new SortedDictionary
+ private static readonly IReadOnlyDictionary ChangeSetAccessorFixes =
+ new SortedDictionary
{
{ FixStrategy.ToInit, new ToInit() },
{ FixStrategy.ToPrivate, new ToPrivate() },
@@ -67,15 +67,15 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (root?.FindNode(diagnostic.Location.SourceSpan) is not AccessorDeclarationSyntax node)
return;
- foreach (var strategy in ChangeSetAccessorStrategies.Values)
+ foreach (var strategy in ChangeSetAccessorFixes.Values)
{
var action = CodeAction.Create(
- title: strategy.GetTitle(TitleFormat),
+ title: strategy.GetTitle(TitleFormat),
createChangedDocument: ct => strategy.ChangeDocument(context.Document, node, ct),
- equivalenceKey: EquivalencyKey
+ equivalenceKey: EquivalencyKey
);
context.RegisterCodeFix(action, diagnostic);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.GenericsTypes.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.Generics.cs
similarity index 76%
rename from src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.GenericsTypes.cs
rename to src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.Generics.cs
index 7b98ad5..7da2d58 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.GenericsTypes.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.Generics.cs
@@ -1,17 +1,17 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Collections.Immutable;
namespace ImmutableAnalyzer.Utils.TypeChecking.Const;
-internal partial struct TypeCheckerConst
+internal readonly partial struct Types
{
///
/// Set of generic immutable class types.
///
- public static readonly ImmutableArray ImmutableGenericTypes = ImmutableArray.Create(
+ public static readonly ImmutableArray Generic = ImmutableArray.Create(
typeof(ImmutableArray<>).Name, typeof(ImmutableDictionary<,>).Name, typeof(ImmutableList<>).Name,
typeof(ImmutableHashSet<>).Name, typeof(ImmutableSortedDictionary<,>).Name, typeof(ImmutableSortedSet<>).Name,
typeof(ImmutableStack<>).Name, typeof(ImmutableQueue<>).Name, typeof(IReadOnlyList<>).Name,
typeof(IReadOnlyCollection<>).Name, typeof(IReadOnlyDictionary<,>).Name
);
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.Types.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.cs
similarity index 90%
rename from src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.Types.cs
rename to src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.cs
index 9a28222..2a50b16 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/TypeCheckerConst.Types.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/Const/Types.cs
@@ -1,9 +1,9 @@
-using System;
+using System;
using System.Collections.Immutable;
namespace ImmutableAnalyzer.Utils.TypeChecking.Const;
-internal partial struct TypeCheckerConst
+internal partial struct Types
{
///
/// Set of valid immutable types.
@@ -13,4 +13,4 @@ internal partial struct TypeCheckerConst
nameof(Int32), nameof(UInt32), nameof(Int64), nameof(UInt64), nameof(Int16), nameof(UInt16), nameof(String),
nameof(DateTime), nameof(Guid), nameof(Enum)
);
-}
\ No newline at end of file
+}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/DeclaredTypeSymbolChecker.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/DeclaredTypeSymbolChecker.cs
index 82d7162..0846d3e 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/DeclaredTypeSymbolChecker.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/DeclaredTypeSymbolChecker.cs
@@ -1,30 +1,23 @@
-using ImmutableAnalyzer.Extensions;
using Microsoft.CodeAnalysis;
+using ImmutableAnalyzer.Extensions;
namespace ImmutableAnalyzer.Utils.TypeChecking;
///
/// Checks for immutability by declared types.
///
-internal class DeclaredTypeSymbolChecker : TypeChecker
+internal class DeclaredTypeSymbolChecker(TypeChecker? inner = null) : TypeChecker
{
- private readonly TypeChecker? _inner;
-
- public DeclaredTypeSymbolChecker(TypeChecker? inner = null)
- {
- _inner = inner;
- }
+ private readonly TypeChecker? _inner = inner;
///
public override bool IsImmutable(ITypeSymbol typeSymbol)
{
- var isImmutableFromInner = _inner?.IsImmutable(typeSymbol);
-
- if (isImmutableFromInner.HasValue && !isImmutableFromInner.Value)
+ if (_inner?.IsImmutable(typeSymbol) == false)
return false;
- return ((isImmutableFromInner ?? true) && typeSymbol.HasAttribute()) ||
- Const.TypeCheckerConst.ImmutableTypes.Contains(typeSymbol.Name) ||
- Const.TypeCheckerConst.ImmutableGenericTypes.Contains(typeSymbol.MetadataName);
+ return typeSymbol.HasAttribute() ||
+ Const.Types.ImmutableTypes.Contains(typeSymbol.Name) ||
+ Const.Types.Generic.Contains(typeSymbol.MetadataName);
}
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/RecursiveTypeSymbolChecker.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/RecursiveTypeSymbolChecker.cs
index 9a257b0..31eb6ae 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/RecursiveTypeSymbolChecker.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/RecursiveTypeSymbolChecker.cs
@@ -6,27 +6,18 @@ namespace ImmutableAnalyzer.Utils.TypeChecking;
///
/// Decorator to check recursively.
///
-internal class RecursiveTypeSymbolChecker : TypeChecker
+internal class RecursiveTypeSymbolChecker(TypeChecker inner) : TypeChecker
{
- private readonly TypeChecker _inner;
-
- public RecursiveTypeSymbolChecker(TypeChecker inner)
- {
- _inner = inner;
- }
+ private readonly TypeChecker _inner = inner;
///
public override bool IsImmutable(ITypeSymbol typeSymbol)
{
- while (true)
- {
- if (_inner.IsImmutable(typeSymbol))
- return true;
-
- if (typeSymbol.BaseType is not { } baseType)
- return typeSymbol.AllInterfaces.Any(IsImmutable);
+ if (_inner.IsImmutable(typeSymbol))
+ return true;
- typeSymbol = baseType;
- }
+ return typeSymbol.BaseType is not null
+ ? IsImmutable(typeSymbol.BaseType)
+ : typeSymbol.AllInterfaces.Any(IsImmutable);
}
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeChecker.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeChecker.cs
index 572b8f1..8d8ded1 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeChecker.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeChecker.cs
@@ -1,4 +1,4 @@
-using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis;
namespace ImmutableAnalyzer.Utils.TypeChecking;
@@ -8,9 +8,9 @@ namespace ImmutableAnalyzer.Utils.TypeChecking;
internal abstract class TypeChecker
{
///
- /// Checks given type symbol for immutability.
+ /// Checks for immutability.
///
/// Type symbol.
- /// true - if given type symbol is immutable, otherwise - false.
+ /// true - if is immutable, otherwise - false.
public abstract bool IsImmutable(ITypeSymbol typeSymbol);
}
diff --git a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeCheckerFactory.cs b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeCheckerFactory.cs
index 132928b..4d8d850 100644
--- a/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeCheckerFactory.cs
+++ b/src/ImmutableAnalyzer/ImmutableAnalyzer/Utils/TypeChecking/TypeCheckerFactory.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
namespace ImmutableAnalyzer.Utils.TypeChecking;
@@ -26,4 +26,4 @@ private static TypeChecker Create()
return new RecursiveTypeSymbolChecker(declaredTypesChecker);
}
-}
\ No newline at end of file
+}