Skip to content

Commit 64faca8

Browse files
Ledjon BehluliLedjon Behluli
authored andcommitted
.
1 parent a8cf7aa commit 64faca8

File tree

7 files changed

+154
-57
lines changed

7 files changed

+154
-57
lines changed

src/OrleanSpaces.Analyzers/OSA001/InternalUseOnlyAttributeAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace OrleanSpaces.Analyzers.OSA001;
66

77
/// <summary>
8-
/// Informs to the client that interfaces marked with this attribute are intended for internal use only.
8+
/// Reports to the client that interfaces marked with this attribute are intended for internal use only.
99
/// </summary>
1010
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1111
internal class InternalUseOnlyAttributeAnalyzer : DiagnosticAnalyzer

src/OrleanSpaces.Analyzers/OSA002/TemplateCacheOverInitAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace OrleanSpaces.Analyzers.OSA002;
66

77
/// <summary>
8-
/// Informs to create or use a '{X}TemplateCache' over initialization via 'new(...)', when all arguments are null's.
8+
/// Reports to create or use a '{X}TemplateCache' over initialization via 'new(...)', when all arguments are null's.
99
/// </summary>
1010
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1111
internal sealed class TemplateCacheOverInitAnalyzer : DiagnosticAnalyzer

src/OrleanSpaces.Analyzers/OSA003/NotSupportedTupleOrTemplateFieldTypeAnalyzer.cs renamed to src/OrleanSpaces.Analyzers/OSA003/NotSupportedFieldTypeAnalyzer.cs

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
using Microsoft.CodeAnalysis.CSharp.Syntax;
2-
using Microsoft.CodeAnalysis.Diagnostics;
1+
using Microsoft.CodeAnalysis.Diagnostics;
32
using Microsoft.CodeAnalysis.Operations;
43
using System.Collections.Immutable;
54

65
namespace OrleanSpaces.Analyzers.OSA003;
76

87
/// <summary>
9-
/// Warns when arguments passed to a 'SpaceTuple' or 'SpaceTemplate', are not supported field types.
8+
/// Reports when arguments passed to a 'SpaceTuple' or 'SpaceTemplate', are not supported field types.
109
/// </summary>
1110
[DiagnosticAnalyzer(LanguageNames.CSharp)]
12-
internal sealed class NotSupportedTupleOrTemplateFieldTypeAnalyzer : DiagnosticAnalyzer
11+
internal sealed class NotSupportedFieldTypeAnalyzer : DiagnosticAnalyzer
1312
{
1413
public static readonly DiagnosticDescriptor Diagnostic = new(
1514
id: "OSA003",
@@ -60,50 +59,35 @@ private void AnalyzeObjectCreation(OperationAnalysisContext context)
6059

6160
if (creationOperation.Type.IsOfType(context.Compilation.GetTypeByMetadataName(FullyQualifiedNames.SpaceTuple)))
6261
{
63-
foreach (var argument in creationOperation.GetArguments())
64-
{
65-
var type = creationOperation.SemanticModel?.GetTypeInfo(argument.Expression, context.CancellationToken).Type;
66-
67-
if (type.IsOfAnyClrType(simpleTypes, context.Compilation) ||
68-
type.IsOfAnyType(new List<ITypeSymbol?>()
69-
{
70-
context.Compilation.GetTypeByMetadataName("System.Int128"),
71-
context.Compilation.GetTypeByMetadataName("System.UInt128"),
72-
context.Compilation.GetTypeByMetadataName("System.Object[]")
73-
}))
74-
{
75-
continue;
76-
}
77-
78-
ReportDiagnosticFor(in context, argument, "SpaceTuple");
79-
}
62+
TryReportDiagnosticFor(in context, creationOperation, "SpaceTuple");
63+
return;
8064
}
8165

8266
if (creationOperation.Type.IsOfType(context.Compilation.GetTypeByMetadataName(FullyQualifiedNames.SpaceTemplate)))
8367
{
84-
foreach (var argument in creationOperation.GetArguments())
85-
{
86-
var type = creationOperation.SemanticModel?.GetTypeInfo(argument.Expression, context.CancellationToken).Type;
68+
TryReportDiagnosticFor(in context, creationOperation, "SpaceTemplate");
69+
return;
70+
}
71+
}
8772

88-
if (type is null || type.SpecialType == SpecialType.System_Nullable_T ||
89-
type.IsOfAnyClrType(simpleTypes, context.Compilation) ||
90-
type.IsOfClrType(typeof(Type), context.Compilation) ||
91-
type.IsOfAnyType(new List<ITypeSymbol?>()
92-
{
93-
context.Compilation.GetTypeByMetadataName("System.Int128"),
94-
context.Compilation.GetTypeByMetadataName("System.UInt128"),
95-
context.Compilation.GetTypeByMetadataName("System.Object[]")
96-
}))
97-
{
98-
continue;
99-
}
73+
private static void TryReportDiagnosticFor(
74+
in OperationAnalysisContext context, IObjectCreationOperation creationOperation, string targetTypeName)
75+
{
76+
foreach (var argument in creationOperation.GetArguments())
77+
{
78+
var type = creationOperation.SemanticModel?.GetTypeInfo(argument.Expression, context.CancellationToken).Type;
10079

101-
ReportDiagnosticFor(in context, argument, "SpaceTemplate");
80+
if (type.IsOfAnyClrType(simpleTypes, context.Compilation) ||
81+
type.IsOfAnyType(new List<ITypeSymbol?>()
82+
{
83+
context.Compilation.GetTypeByMetadataName("System.Int128"),
84+
context.Compilation.GetTypeByMetadataName("System.UInt128"),
85+
context.Compilation.GetTypeByMetadataName("System.Object[]")
86+
}))
87+
{
88+
continue;
10289
}
103-
}
10490

105-
static void ReportDiagnosticFor(in OperationAnalysisContext context, ArgumentSyntax argument, string targetTypeName)
106-
{
10791
context.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic.Create(
10892
descriptor: Diagnostic,
10993
location: argument.GetLocation(),

src/OrleanSpaces.Analyzers/OSA003/NotSupportedTupleOrTemplateFieldTypeFixer.cs renamed to src/OrleanSpaces.Analyzers/OSA003/NotSupportedFieldTypeFixer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
namespace OrleanSpaces.Analyzers.OSA003;
77

88
/// <summary>
9-
/// Code fix provider for <see cref="NotSupportedTupleOrTemplateFieldTypeAnalyzer"/>.
9+
/// Code fix provider for <see cref="NotSupportedFieldTypeAnalyzer"/>.
1010
/// </summary>
11-
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(NotSupportedTupleOrTemplateFieldTypeFixer)), Shared]
12-
internal sealed class NotSupportedTupleOrTemplateFieldTypeFixer : CodeFixProvider
11+
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(NotSupportedFieldTypeFixer)), Shared]
12+
internal sealed class NotSupportedFieldTypeFixer : CodeFixProvider
1313
{
14-
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(NotSupportedTupleOrTemplateFieldTypeAnalyzer.Diagnostic.Id);
14+
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(NotSupportedFieldTypeAnalyzer.Diagnostic.Id);
1515
public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;
1616

1717
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
@@ -30,7 +30,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
3030

3131
CodeAction action = CodeAction.Create(
3232
title: "Remove unsupported argument",
33-
equivalenceKey: NotSupportedTupleOrTemplateFieldTypeAnalyzer.Diagnostic.Id,
33+
equivalenceKey: NotSupportedFieldTypeAnalyzer.Diagnostic.Id,
3434
createChangedDocument: _ =>
3535
{
3636
var newRoot = root.RemoveNode(node, SyntaxRemoveOptions.KeepTrailingTrivia);
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using Microsoft.CodeAnalysis.Diagnostics;
2+
using Microsoft.CodeAnalysis.Operations;
3+
using System.Collections.Immutable;
4+
5+
namespace OrleanSpaces.Analyzers.OSA004;
6+
7+
/// <summary>
8+
/// Reports to prefer specialized tuples & templates over the generic verisons.
9+
/// </summary>
10+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
11+
internal sealed class PreferSpecializedOverGenericAnalyzer : DiagnosticAnalyzer
12+
{
13+
public static readonly DiagnosticDescriptor Diagnostic = new(
14+
id: "OSA004",
15+
category: Categories.Performance,
16+
defaultSeverity: DiagnosticSeverity.Warning,
17+
isEnabledByDefault: true,
18+
title: "Prefer using specialized over generic.",
19+
messageFormat: "Prefer using specialized '{0}' over generic '{1}'.",
20+
helpLinkUri: "https://github.com/ledjon-behluli/OrleanSpaces/blob/master/docs/OrleanSpaces.Analyzers/Rules/OSA004.md");
21+
22+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Diagnostic);
23+
24+
public override void Initialize(AnalysisContext context)
25+
{
26+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
27+
context.EnableConcurrentExecution();
28+
29+
context.RegisterOperationAction(AnalyzeObjectCreation, OperationKind.ObjectCreation);
30+
}
31+
32+
private void AnalyzeObjectCreation(OperationAnalysisContext context)
33+
{
34+
var creationOperation = (IObjectCreationOperation)context.Operation;
35+
36+
if (creationOperation.Type.IsOfType(context.Compilation.GetTypeByMetadataName(FullyQualifiedNames.SpaceTuple)))
37+
{
38+
TryReportDiagnosticFor(in context, creationOperation, "SpaceTuple");
39+
return;
40+
}
41+
42+
if (creationOperation.Type.IsOfType(context.Compilation.GetTypeByMetadataName(FullyQualifiedNames.SpaceTemplate)))
43+
{
44+
TryReportDiagnosticFor(in context, creationOperation, "SpaceTemplate");
45+
return;
46+
}
47+
}
48+
49+
private static void TryReportDiagnosticFor(
50+
in OperationAnalysisContext context, IObjectCreationOperation creationOperation, string genericTypeName)
51+
{
52+
var arguments = creationOperation.GetArguments();
53+
if (arguments.Count() == 0)
54+
{
55+
return;
56+
}
57+
58+
var argumentTypeSymbols = arguments.Select(arg => creationOperation.SemanticModel?.GetTypeInfo(arg.Expression).Type);
59+
if (argumentTypeSymbols == null)
60+
{
61+
return;
62+
}
63+
64+
65+
int sameTypeArgumentsCount = argumentTypeSymbols.Distinct(SymbolEqualityComparer.Default).Count();
66+
if (sameTypeArgumentsCount > 1)
67+
{
68+
return;
69+
}
70+
71+
72+
SpecialType? argumentType = argumentTypeSymbols.First()?.SpecialType;
73+
string specializedTypeName = argumentType switch
74+
{
75+
SpecialType.System_Boolean => "BoolTuple",
76+
// Continue
77+
};
78+
79+
80+
string argumentValues = string.Join(",", arguments
81+
.Select(arg => creationOperation.SemanticModel?.GetConstantValue(arg))
82+
.Select(val => val.HasValue ? val.Value.ToString() : string.Empty));
83+
84+
context.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic.Create(
85+
descriptor: Diagnostic,
86+
location: creationOperation.Syntax.GetLocation(),
87+
messageArgs: new[] { specializedTypeName, genericTypeName, argumentValues }));
88+
}
89+
90+
private static readonly List<Type> simpleTypes = new()
91+
{
92+
typeof(bool),
93+
typeof(byte),
94+
typeof(sbyte),
95+
typeof(char),
96+
typeof(double),
97+
typeof(float),
98+
typeof(short),
99+
typeof(ushort),
100+
typeof(int),
101+
typeof(uint),
102+
typeof(long),
103+
typeof(ulong),
104+
typeof(Enum),
105+
typeof(string),
106+
typeof(decimal),
107+
typeof(DateTime),
108+
typeof(DateTimeOffset),
109+
typeof(TimeSpan),
110+
typeof(Guid)
111+
};
112+
113+
}

tests/OrleanSpaces.Analyzers.Tests/OSA003/NotSupportedTupleOrTemplateFieldTypeAnalyzerTests.cs renamed to tests/OrleanSpaces.Analyzers.Tests/OSA003/NotSupportedTypeAnalyzerTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
namespace OrleanSpaces.Analyzers.Tests.OSA003;
44

5-
public class NotSupportedTupleOrTemplateFieldTypeAnalyzerTests : AnalyzerFixture
5+
public class NotSupportedTypeAnalyzerTests : AnalyzerFixture
66
{
7-
public NotSupportedTupleOrTemplateFieldTypeAnalyzerTests() : base(
8-
new NotSupportedTupleOrTemplateFieldTypeAnalyzer(),
9-
NotSupportedTupleOrTemplateFieldTypeAnalyzer.Diagnostic.Id)
7+
public NotSupportedTypeAnalyzerTests() : base(
8+
new NotSupportedFieldTypeAnalyzer(),
9+
NotSupportedFieldTypeAnalyzer.Diagnostic.Id)
1010
{
1111

1212
}
1313

1414
[Fact]
1515
public void Should_Equal()
1616
{
17-
var diagnostic = NotSupportedTupleOrTemplateFieldTypeAnalyzer.Diagnostic;
17+
var diagnostic = NotSupportedFieldTypeAnalyzer.Diagnostic;
1818

1919
Assert.Equal("OSA003", diagnostic.Id);
2020
Assert.Equal(Categories.Usage, diagnostic.Category);

tests/OrleanSpaces.Analyzers.Tests/OSA003/NotSupportedTupleOrTemplateFieldTypeFixerTests.cs renamed to tests/OrleanSpaces.Analyzers.Tests/OSA003/NotSupportedTypeFixerTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
namespace OrleanSpaces.Analyzers.Tests.OSA003;
44

5-
public class NotSupportedTupleOrTemplateFieldTypeFixerTests : FixerFixture
5+
public class NotSupportedTypeFixerTests : FixerFixture
66
{
7-
public NotSupportedTupleOrTemplateFieldTypeFixerTests() : base(
8-
new NotSupportedTupleOrTemplateFieldTypeAnalyzer(),
9-
new NotSupportedTupleOrTemplateFieldTypeFixer(),
10-
NotSupportedTupleOrTemplateFieldTypeAnalyzer.Diagnostic.Id)
7+
public NotSupportedTypeFixerTests() : base(
8+
new NotSupportedFieldTypeAnalyzer(),
9+
new NotSupportedFieldTypeFixer(),
10+
NotSupportedFieldTypeAnalyzer.Diagnostic.Id)
1111
{
1212

1313
}

0 commit comments

Comments
 (0)