Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(analyzer): add rules regarding model name suffixes #6916

Merged
merged 21 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
23 changes: 23 additions & 0 deletions src/dotnet/Azure.ClientSdk.Analyzers/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# The warnings below are found after upgrading to Roslyn 4.7.0
# It should be able to fix them all. Suppressing them is just a temporary work-around.

[*.cs]

# CS0618: 'IOperation.Children' is obsolete: 'This API has performance penalties, please use ChildOperations instead.
dotnet_diagnostic.CS0618.severity = none

# RS1031: The diagnostic title should not contain a period, nor any line return character, nor any leading or trailing whitespaces
dotnet_diagnostic.RS1031.severity = none

# RS1032: The diagnostic message should not contain any line return character nor any leading or trailing whitespaces and should either be a single sentence without a trailing period or a multi-sentences with a trailing period
dotnet_diagnostic.RS1032.severity = none

# RS2008: Enable analyzer release tracking for the analyzer project containing rule 'XXX'
dotnet_diagnostic.RS2008.severity = none

# RS1024: Use 'SymbolEqualityComparer' when comparing symbols
dotnet_diagnostic.RS1024.severity = none

# RS1037: Add "CompilationEnd" custom tag to the diagnostic descriptor used to initialize field 'AZC0011' as it is used to report a compilation end diagnostic
dotnet_diagnostic.RS1037.severity = none

Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeRefactoring.Testing.XUnit" Version="1.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />

<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Reflection.Metadata" Version="1.8.0" />
<PackageReference Include="System.Reflection.Metadata" Version="7.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="3.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.7.0" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net'))">
<PackageReference Include="System.Interactive.Async" Version="4.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Threading.Tasks;
using Azure.ClientSdk.Analyzers.ModelName;
using Xunit;

using VerifyCS = Azure.ClientSdk.Analyzers.Tests.AzureAnalyzerVerifier<
Azure.ClientSdk.Analyzers.ModelName.GeneralSuffixAnalyzer>;

namespace Azure.ClientSdk.Analyzers.Test.ModelName
{
public class AZC0030Tests
{
[Fact]
public async Task ClassNotUnderModelsNamespaceIsNotChecked()
archerzz marked this conversation as resolved.
Show resolved Hide resolved
{
var test = @"namespace Azure.ResourceManager;

class MonitorResult
{
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task OnlyModelsNamespaceIsChecked()
{
var test = @"namespace Azure.ResourceManager.AModels;

class MonitorResult
{
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task EnumIsNotChecked()
{
var test = @"namespace Azure.ResourceManager.Models;

enum MonitorResult
{
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task GoodSuffix()
{
var test = @"namespace Azure.ResourceManager.Models;

class MonitorContent
{
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task ParametersSuffix()
{
var test = @"namespace Azure.ResourceManager.Models
{
public class ResponseParameters
{
}
}";
var expected = VerifyCS.Diagnostic(GeneralSuffixAnalyzer.DiagnosticId).WithSpan(3, 18, 3, 36).WithArguments("ResponseParameters", "Parameters", "'ResponseContent' or 'ResponsePatch'");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[Fact]
public async Task ResultSuffix()
{
var test = @"namespace Azure.ResourceManager.Models
{
public class NetworkRequest
{
}
}";
var expected = VerifyCS.Diagnostic(GeneralSuffixAnalyzer.DiagnosticId).WithSpan(3, 18, 3, 32).WithArguments("NetworkRequest", "Request", "'NetworkContent'");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[Fact]
public async Task OptionSuffixWithNestedNameSpace()
{
var test = @"namespace Azure.ResourceManager.Models
{
namespace SubTest
{
public class DiskOption
{
}
}
}";
var expected = VerifyCS.Diagnostic(GeneralSuffixAnalyzer.DiagnosticId).WithSpan(5, 22, 5, 32).WithArguments("DiskOption", "Option", "'DiskConfig'");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[Fact]
public async Task ResponsesSuffix()
{
var test = @"namespace Azure.ResourceManager.Models
{
namespace SubTest
{
public class CreationResponses
{
}
}
}";
var expected = VerifyCS.Diagnostic(GeneralSuffixAnalyzer.DiagnosticId).WithSpan(5, 22, 5, 39).WithArguments("CreationResponses", "Responses", "'CreationResults'");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Threading.Tasks;
using Azure.ClientSdk.Analyzers.ModelName;
using Xunit;

using VerifyCS = Azure.ClientSdk.Analyzers.Tests.AzureAnalyzerVerifier<
Azure.ClientSdk.Analyzers.ModelName.DefinitionSuffixAnalyzer>;

namespace Azure.ClientSdk.Analyzers.Tests.ModelName
{
public class AZC0031Tests
{
[Fact]
public async Task ModelWithDefinitionSuffix()
{
var test = @"
namespace Azure.ResourceManager.Network.Models
{
public partial class AadAuthenticationDefinition
{
}
}";
var expected = VerifyCS.Diagnostic(DefinitionSuffixAnalyzer.DiagnosticId).WithSpan(4, 26, 4, 53).WithArguments("AadAuthenticationDefinition", "Definition");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[Fact]
public async Task ArmResourceIsNotChecked()
{
var test = @"
using Azure.ResourceManager;
namespace Azure.ResourceManager
{
public class ArmResource {
}
}
namespace Azure.ResourceManager.Network.Models
{
public partial class AadAuthenticationDefinition: ArmResource
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task NotCheckIfRemovingSuffixIsAnotherType()
{
var test = @"
using Azure.ResourceManager;
namespace Azure.ResourceManager.Network.Models
{
public class AadAuthentication {
}

public partial class AadAuthenticationDefinition
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System.Threading.Tasks;
using Xunit;

using VerifyCS = Azure.ClientSdk.Analyzers.Tests.AzureAnalyzerVerifier<
Azure.ClientSdk.Analyzers.ModelName.DataSuffixAnalyzer>;
using Azure.ClientSdk.Analyzers.ModelName;

namespace Azure.ClientSdk.Analyzers.Tests.ModelName
{
public class AZC0032Tests
{
[Fact]
public async Task ClassUnderNonModelsNamespaceIsNotChecked()
{
var test = @"
namespace Azure.ResourceManager.Network.Temp
{
public partial class AadAuthenticationData
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task ModelClassWithDataSuffix()
{
var test = @"
namespace Azure.ResourceManager.Network.Models
{
public partial class AadAuthenticationData
{
}
}";
var expected = VerifyCS.Diagnostic(DataSuffixAnalyzer.DiagnosticId).WithSpan(4, 26, 4, 47).WithArguments("AadAuthenticationData", "Data");
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[Fact]
public async Task ResourceDataClassesAreNotChecked()
{
var test = @"
using Azure.ResourceManager.Models;
namespace Azure.ResourceManager.Models
{
public class ResourceData {
}
}
namespace Azure.ResourceManager.Network.Models
{
public partial class AadAuthenticationData: ResourceData
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task TrackedResourceDataClassesAreNotChecked()
{
var test = @"
using Azure.ResourceManager.Models;
namespace Azure.ResourceManager.Models
{
public class TrackedResourceData {
}
}
namespace Azure.ResourceManager.Network.Models
{
public partial class AadAuthenticationData: TrackedResourceData
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Threading.Tasks;
using Azure.ClientSdk.Analyzers.ModelName;
using Microsoft.CodeAnalysis.Testing;
using Xunit;

using VerifyCS = Azure.ClientSdk.Analyzers.Tests.AzureAnalyzerVerifier<
Azure.ClientSdk.Analyzers.ModelName.OperationSuffixAnalyzer>;

namespace Azure.ClientSdk.Analyzers.Test.ModelName
{
public class AZC0033Tests
{
[Fact]
public async Task OperationClassIsNotChecked()
{
var test = @"
using Azure;
using Azure.ResourceManager;
namespace Azure
{
public class Operation
{
}
public class Operation<T>
{
}
}
namespace Azure.ResourceManager
{
public class ArmOperation : Operation
{
}
public class ArmOperation<T> : Operation<T>
{
}
}
namespace Azure.ResourceManager.Network.Models
{
internal class DnsOperation : Operation
{
}
internal class DnsArmOperation : ArmOperation
{
}
internal class DnsOperation<T> : Operation<T>
{
}
internal class DnsArmOperation<T> : ArmOperation<T>
{
}
}";
await VerifyCS.VerifyAnalyzerAsync(test);
}

[Fact]
public async Task OperationSuffix()
{
var test = @"
namespace Azure.ResourceManager.Network.Models
{
public class DnsOperation
{
}
public class DnsArmOperation<T>
{
}
}";
DiagnosticResult[] expected = {
VerifyCS.Diagnostic(OperationSuffixAnalyzer.DiagnosticId).WithSpan(4, 18, 4, 30).WithArguments("DnsOperation", "Operation", "DnsData", "DnsInfo"),
VerifyCS.Diagnostic(OperationSuffixAnalyzer.DiagnosticId).WithSpan(7, 18, 7, 33).WithArguments("DnsArmOperation", "Operation", "DnsArmData", "DnsArmInfo")
};
await VerifyCS.VerifyAnalyzerAsync(test, expected);
}
}
}

Loading