Skip to content

Commit

Permalink
feat(analzyer): add rules regarding model name suffixes
Browse files Browse the repository at this point in the history
- add four rules checking the suffixes of model names
- upgrade Roslyn to latest version since new rules require some API
- minor refactor existing codes
- add test cases for the new rules

resolve #6905
  • Loading branch information
Mingzhe Huang (from Dev Box) committed Sep 7, 2023
1 parent 115d6ab commit 988cef0
Show file tree
Hide file tree
Showing 15 changed files with 754 additions and 38 deletions.
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()
{
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

0 comments on commit 988cef0

Please sign in to comment.