diff --git a/analyzers/its/expected/Ember-MM/Ember.Plugins-{9496C697-5AFD-4813-AEDC-AF33FACEADF0}-S2094.json b/analyzers/its/expected/Ember-MM/Ember.Plugins-{9496C697-5AFD-4813-AEDC-AF33FACEADF0}-S2094.json index 0ac2683eee3..45dbbc1ebc5 100644 --- a/analyzers/its/expected/Ember-MM/Ember.Plugins-{9496C697-5AFD-4813-AEDC-AF33FACEADF0}-S2094.json +++ b/analyzers/its/expected/Ember-MM/Ember.Plugins-{9496C697-5AFD-4813-AEDC-AF33FACEADF0}-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Ember-MM\Ember.Plugins\PluginActionContext.cs", "region": { diff --git a/analyzers/its/expected/Net5/Net5--net5.0-S2094.json b/analyzers/its/expected/Net5/Net5--net5.0-S2094.json index 808fb732c6d..6410000afd1 100644 --- a/analyzers/its/expected/Net5/Net5--net5.0-S2094.json +++ b/analyzers/its/expected/Net5/Net5--net5.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\ModuleInitializers.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\ParameterValidation.cs", "region": { @@ -28,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\S2330.cs", "region": { @@ -41,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\S3240.cs", "region": { @@ -54,7 +54,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\S3247.cs", "region": { @@ -67,7 +67,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\S3453.cs", "region": { @@ -80,7 +80,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net5\Net5\StaticLambdas.cs", "region": { diff --git a/analyzers/its/expected/Net7/Net7--net7.0-S2094.json b/analyzers/its/expected/Net7/Net7--net7.0-S2094.json index 289b4af880f..9315f036e86 100644 --- a/analyzers/its/expected/Net7/Net7--net7.0-S2094.json +++ b/analyzers/its/expected/Net7/Net7--net7.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\Net7\Net7\features\WarningWave7.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka--netstandard2.0-S2094.json index 6370b12ad44..b8fd5dbc010 100644 --- a/analyzers/its/expected/akka.net/Akka--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka--netstandard2.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Actor\ActorSelection.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Actor\FSM.cs", "region": { @@ -28,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Event\LoggerInitialized.cs", "region": { @@ -41,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Event\Logging.cs", "region": { @@ -54,7 +54,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Dns.cs", "region": { @@ -67,7 +67,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Inet.cs", "region": { @@ -80,7 +80,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Tcp.cs", "region": { @@ -93,7 +93,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Tcp.cs", "region": { @@ -106,7 +106,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Tcp.cs", "region": { @@ -119,7 +119,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Udp.cs", "region": { @@ -132,7 +132,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\Udp.cs", "region": { @@ -145,7 +145,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\IO\UdpConnected.cs", "region": { @@ -158,7 +158,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Pattern\BackoffOptions.cs", "region": { @@ -171,7 +171,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Routing\Listeners.cs", "region": { @@ -184,7 +184,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka\Routing\RouterMsg.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.Benchmarks--netcoreapp3.1-S2094.json b/analyzers/its/expected/akka.net/Akka.Benchmarks--netcoreapp3.1-S2094.json index 025ab6cbded..77c88c4e851 100644 --- a/analyzers/its/expected/akka.net/Akka.Benchmarks--netcoreapp3.1-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.Benchmarks--netcoreapp3.1-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\benchmark\Akka.Benchmarks\IO\TcpOperationsBenchmarks.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\benchmark\Akka.Benchmarks\IO\TcpOperationsBenchmarks.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.Cluster--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka.Cluster--netstandard2.0-S2094.json index 7e3af656072..aac4b747412 100644 --- a/analyzers/its/expected/akka.net/Akka.Cluster--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.Cluster--netstandard2.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Cluster\ClusterDaemon.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Cluster\ClusterHeartbeat.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.DI.TestKit--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka.DI.TestKit--netstandard2.0-S2094.json index 8bbc0bb2e33..f0fd59ab4d8 100644 --- a/analyzers/its/expected/akka.net/Akka.DI.TestKit--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.DI.TestKit--netstandard2.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\contrib\dependencyinjection\Akka.DI.TestKit\DiResolverSpec.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\contrib\dependencyinjection\Akka.DI.TestKit\DiResolverSpec.cs", "region": { @@ -28,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\contrib\dependencyinjection\Akka.DI.TestKit\DiResolverSpec.cs", "region": { @@ -41,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\contrib\dependencyinjection\Akka.DI.TestKit\DiResolverSpec.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net471-S2094.json b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net471-S2094.json index 3c7716e2695..cc98d74023d 100644 --- a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net471-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net471-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net5.0-S2094.json b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net5.0-S2094.json index 3c7716e2695..cc98d74023d 100644 --- a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net5.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--net5.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--netcoreapp3.1-S2094.json b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--netcoreapp3.1-S2094.json index 3c7716e2695..cc98d74023d 100644 --- a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--netcoreapp3.1-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner--netcoreapp3.1-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner.Shared--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner.Shared--netstandard2.0-S2094.json index 42a6a955478..8ebac24a9d7 100644 --- a/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner.Shared--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.MultiNodeTestRunner.Shared--netstandard2.0-S2094.json @@ -2,20 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", -"location": { -"uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\CompilerErrorCollection.cs", -"region": { -"startLine": 14, -"startColumn": 18, -"endLine": 14, -"endColumn": 41 -} -} -}, -{ -"id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Reporting\TestRunCoordinator.cs", "region": { @@ -28,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\Messages.cs", "region": { @@ -41,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\MessageSinkActor.cs", "region": { @@ -54,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\SinkCoordinator.cs", "region": { @@ -67,7 +54,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\SinkCoordinator.cs", "region": { @@ -80,7 +67,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\SinkCoordinator.cs", "region": { @@ -93,7 +80,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\TimelineLogCollectorActor.cs", "region": { @@ -106,7 +93,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.MultiNodeTestRunner.Shared\Sinks\TimelineLogCollectorActor.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.Remote--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka.Remote--netstandard2.0-S2094.json index 5ecaa3af7c5..627fcfd752e 100644 --- a/analyzers/its/expected/akka.net/Akka.Remote--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.Remote--netstandard2.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Endpoint.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Endpoint.cs", "region": { @@ -28,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\EndpointManager.cs", "region": { @@ -41,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\EndpointManager.cs", "region": { @@ -54,7 +54,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\AkkaPduCodec.cs", "region": { @@ -67,7 +67,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\AkkaProtocolTransport.cs", "region": { @@ -80,7 +80,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\AkkaProtocolTransport.cs", "region": { @@ -93,7 +93,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\AkkaProtocolTransport.cs", "region": { @@ -106,7 +106,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\AkkaProtocolTransport.cs", "region": { @@ -119,7 +119,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\TestTransport.cs", "region": { @@ -132,7 +132,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote\Transport\ThrottleTransportAdapter.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.Remote.Tests.Performance--netcoreapp3.1-S2094.json b/analyzers/its/expected/akka.net/Akka.Remote.Tests.Performance--netcoreapp3.1-S2094.json index 76790ed6bfc..f4479e9850a 100644 --- a/analyzers/its/expected/akka.net/Akka.Remote.Tests.Performance--netcoreapp3.1-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.Remote.Tests.Performance--netcoreapp3.1-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Remote.Tests.Performance\Transports\RemoteMessagingThroughputSpecBase.cs", "region": { diff --git a/analyzers/its/expected/akka.net/Akka.Streams--netstandard2.0-S2094.json b/analyzers/its/expected/akka.net/Akka.Streams--netstandard2.0-S2094.json index cea40b0ba52..1aed34bc8d5 100644 --- a/analyzers/its/expected/akka.net/Akka.Streams--netstandard2.0-S2094.json +++ b/analyzers/its/expected/akka.net/Akka.Streams--netstandard2.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Streams\Attributes.cs", "region": { @@ -15,7 +15,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Streams\Attributes.cs", "region": { @@ -28,7 +28,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Streams\Attributes.cs", "region": { @@ -41,7 +41,7 @@ }, { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\core\Akka.Streams\Stage\Context.cs", "region": { diff --git a/analyzers/its/expected/akka.net/RemotePingPong--net471-S2094.json b/analyzers/its/expected/akka.net/RemotePingPong--net471-S2094.json index 19fa046d379..c626699ce26 100644 --- a/analyzers/its/expected/akka.net/RemotePingPong--net471-S2094.json +++ b/analyzers/its/expected/akka.net/RemotePingPong--net471-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\benchmark\RemotePingPong\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/RemotePingPong--net5.0-S2094.json b/analyzers/its/expected/akka.net/RemotePingPong--net5.0-S2094.json index 19fa046d379..c626699ce26 100644 --- a/analyzers/its/expected/akka.net/RemotePingPong--net5.0-S2094.json +++ b/analyzers/its/expected/akka.net/RemotePingPong--net5.0-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\benchmark\RemotePingPong\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/RemotePingPong--netcoreapp3.1-S2094.json b/analyzers/its/expected/akka.net/RemotePingPong--netcoreapp3.1-S2094.json index 19fa046d379..c626699ce26 100644 --- a/analyzers/its/expected/akka.net/RemotePingPong--netcoreapp3.1-S2094.json +++ b/analyzers/its/expected/akka.net/RemotePingPong--netcoreapp3.1-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\benchmark\RemotePingPong\Program.cs", "region": { diff --git a/analyzers/its/expected/akka.net/TcpEchoService.Server--netcoreapp3.1-S2094.json b/analyzers/its/expected/akka.net/TcpEchoService.Server--netcoreapp3.1-S2094.json index 0c7c2328513..6b95eb1b717 100644 --- a/analyzers/its/expected/akka.net/TcpEchoService.Server--netcoreapp3.1-S2094.json +++ b/analyzers/its/expected/akka.net/TcpEchoService.Server--netcoreapp3.1-S2094.json @@ -2,7 +2,7 @@ "issues": [ { "id": "S2094", -"message": "Remove this empty class, or add members to it.", +"message": "Remove this empty class, write its code or make it an "interface".", "location": { "uri": "sources\akka.net\src\examples\TcpEchoService.Server\Actors.cs", "region": { diff --git a/analyzers/rspec/cs/S2094_c#.html b/analyzers/rspec/cs/S2094_c#.html index 369f2453587..dcee0efaa5c 100644 --- a/analyzers/rspec/cs/S2094_c#.html +++ b/analyzers/rspec/cs/S2094_c#.html @@ -14,9 +14,10 @@
Partial classes are ignored entirely, as they are often used with Source Generators. Subclasses of System.Exception are be ignored, as even an -empty Exception class can provide useful information by its type name alone. Subclasses of certain framework types - like the PageModel class used in -ASP.NET Core Razor Pages - are also be ignored.
+Partial classes are ignored entirely, as they are often used with Source Generators. Subclasses of System.Exception are ignored, as even an empty +Exception class can provide useful information by its type name alone. Subclasses of System.Attribute are ignored, as well as classes which are +annotated with attributes. Subclasses of generic classes are ignored, as even when empty they can be used for type specialization. Subclasses of +certain framework types - like the PageModel class used in ASP.NET Core Razor Pages - are also ignored.
using Microsoft.AspNetCore.Mvc.RazorPages; diff --git a/analyzers/rspec/vbnet/S2094_vb.net.html b/analyzers/rspec/vbnet/S2094_vb.net.html index dd073431b49..7f83fc3a456 100644 --- a/analyzers/rspec/vbnet/S2094_vb.net.html +++ b/analyzers/rspec/vbnet/S2094_vb.net.html @@ -14,9 +14,10 @@Compliant Solution
End Interface
Partial classes are ignored entirely, as they are often used with Source Generators. Subclasses of System.Exception will be ignored, as even an -empty Exception class can provide useful information by its type name alone. Subclasses of certain framework types - like the PageModel class used in -ASP.NET Core Razor Pages - will also be ignored.
+Partial classes are ignored entirely, as they are often used with Source Generators. Subclasses of System.Exception are ignored, as even an empty +Exception class can provide useful information by its type name alone. Subclasses of System.Attribute are ignored, as well as classes which are +annotated with attributes. Subclasses of generic classes are ignored, as even when empty they can be used for type specialization. Subclasses of +certain framework types - like the PageModel class used in ASP.NET Core Razor Pages - are also ignored.
Imports Microsoft.AspNetCore.Mvc.RazorPages diff --git a/analyzers/src/SonarAnalyzer.CSharp/Rules/ClassShouldNotBeEmpty.cs b/analyzers/src/SonarAnalyzer.CSharp/Rules/ClassShouldNotBeEmpty.cs index 1dae0adc1d4..70fe3c4b6d6 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/Rules/ClassShouldNotBeEmpty.cs +++ b/analyzers/src/SonarAnalyzer.CSharp/Rules/ClassShouldNotBeEmpty.cs @@ -21,7 +21,7 @@ namespace SonarAnalyzer.Rules.CSharp; [DiagnosticAnalyzer(LanguageNames.CSharp)] -public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase+public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase { protected override ILanguageFacade Language => CSharpFacade.Instance; @@ -30,9 +30,26 @@ public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase x.IsKind(SyntaxKind.PartialKeyword)) && (node is ClassDeclarationSyntax || IsParameterlessRecord(node)); - protected override bool IsClassWithDeclaredBaseClass(SyntaxNode node) => node is ClassDeclarationSyntax { BaseList: not null }; + protected override BaseTypeDeclarationSyntax GetIfHasDeclaredBaseClass(SyntaxNode node) => + node is ClassDeclarationSyntax { BaseList: not null } declaration + ? declaration + : null; - protected override string DeclarationTypeKeyword(SyntaxNode node) => ((TypeDeclarationSyntax)node).Keyword.ValueText; + protected override bool HasGenericBaseClassOrInterface(BaseTypeDeclarationSyntax declaration) => + declaration.BaseList.Types.Any(x => x.Type is GenericNameSyntax); + + protected override bool HasAnyAttribute(SyntaxNode node) => + node is TypeDeclarationSyntax { AttributeLists.Count: > 0 }; + + protected override string DeclarationTypeKeyword(SyntaxNode node) => + ((TypeDeclarationSyntax)node).Keyword.ValueText; + + protected override bool HasConditionalCompilationDirectives(SyntaxNode node) => + node.DescendantNodes(descendIntoTrivia: true).Any(x => x.IsAnyKind( + SyntaxKind.IfDirectiveTrivia, + SyntaxKind.ElifDirectiveTrivia, + SyntaxKind.ElseDirectiveTrivia, + SyntaxKind.EndIfDirectiveTrivia)); private bool IsParameterlessRecord(SyntaxNode node) => RecordDeclarationSyntaxWrapper.IsInstance(node) diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs index b0b254a4c2a..7a34af784c7 100644 --- a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs +++ b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs @@ -60,6 +60,7 @@ public sealed partial class KnownType public static readonly KnownType Microsoft_AspNetCore_Mvc_ControllerAttribute = new("Microsoft.AspNetCore.Mvc.ControllerAttribute"); public static readonly KnownType Microsoft_AspNetCore_Mvc_DisableRequestSizeLimitAttribute = new("Microsoft.AspNetCore.Mvc.DisableRequestSizeLimitAttribute"); public static readonly KnownType Microsoft_AspNetCore_Mvc_FromServicesAttribute = new("Microsoft.AspNetCore.Mvc.FromServicesAttribute"); + public static readonly KnownType Microsoft_AspNetCore_Mvc_IActionResult = new("Microsoft.AspNetCore.Mvc.IActionResult"); public static readonly KnownType Microsoft_AspNetCore_Mvc_IgnoreAntiforgeryTokenAttribute = new("Microsoft.AspNetCore.Mvc.IgnoreAntiforgeryTokenAttribute"); public static readonly KnownType Microsoft_AspNetCore_Mvc_NonActionAttribute = new("Microsoft.AspNetCore.Mvc.NonActionAttribute"); public static readonly KnownType Microsoft_AspNetCore_Mvc_NonControllerAttribute = new("Microsoft.AspNetCore.Mvc.NonControllerAttribute"); diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/ClassShouldNotBeEmptyBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/ClassShouldNotBeEmptyBase.cs index 95de276a89d..aba8dd35454 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/ClassShouldNotBeEmptyBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/ClassShouldNotBeEmptyBase.cs @@ -20,20 +20,28 @@ namespace SonarAnalyzer.Rules; -public abstract class ClassShouldNotBeEmptyBase : SonarDiagnosticAnalyzer +public abstract class ClassShouldNotBeEmptyBase : SonarDiagnosticAnalyzer where TSyntaxKind : struct + where TDeclarationSyntax: SyntaxNode { private const string DiagnosticId = "S2094"; private static readonly ImmutableArray BaseClassesToIgnore = ImmutableArray.Create( KnownType.Microsoft_AspNetCore_Mvc_RazorPages_PageModel, + KnownType.System_Attribute, KnownType.System_Exception); + private static readonly ImmutableArray InterfacesToIgnore = ImmutableArray.Create( + KnownType.Microsoft_AspNetCore_Mvc_IActionResult); + protected abstract bool IsEmptyAndNotPartial(SyntaxNode node); - protected abstract bool IsClassWithDeclaredBaseClass(SyntaxNode node); + protected abstract TDeclarationSyntax GetIfHasDeclaredBaseClass(SyntaxNode node); + protected abstract bool HasGenericBaseClassOrInterface(TDeclarationSyntax declaration); + protected abstract bool HasAnyAttribute(SyntaxNode node); protected abstract string DeclarationTypeKeyword(SyntaxNode node); + protected abstract bool HasConditionalCompilationDirectives(SyntaxNode node); - protected override string MessageFormat => "Remove this empty {0}, or add members to it."; + protected override string MessageFormat => "Remove this empty {0}, write its code or make it an \"interface\"."; protected ClassShouldNotBeEmptyBase() : base(DiagnosticId) { } @@ -44,15 +52,22 @@ public abstract class ClassShouldNotBeEmptyBase : SonarDiagnosticAn { if (Language.Syntax.NodeIdentifier(c.Node) is { IsMissing: false } identifier && IsEmptyAndNotPartial(c.Node) - && !ShouldIgnoreBecauseOfBaseClass(c.Node, c.SemanticModel)) + && !HasAnyAttribute(c.Node) + && !HasConditionalCompilationDirectives(c.Node) + && !ShouldIgnoreBecauseOfBaseClassOrInterface(c.Node, c.SemanticModel)) { c.ReportIssue(Diagnostic.Create(Rule, identifier.GetLocation(), DeclarationTypeKeyword(c.Node))); } }, Language.SyntaxKind.ClassAndRecordClassDeclarations); - private bool ShouldIgnoreBecauseOfBaseClass(SyntaxNode node, SemanticModel model) => - IsClassWithDeclaredBaseClass(node) - && model.GetDeclaredSymbol(node) is INamedTypeSymbol classSymbol - && (classSymbol.BaseType is { IsAbstract: true } || classSymbol.DerivesFromAny(BaseClassesToIgnore)); + private bool ShouldIgnoreBecauseOfBaseClassOrInterface(SyntaxNode node, SemanticModel model) => + GetIfHasDeclaredBaseClass(node) is { } declaration + && (HasGenericBaseClassOrInterface(declaration) || ShouldIgnoreType(declaration, model)); + + private static bool ShouldIgnoreType(TDeclarationSyntax node, SemanticModel model) => + model.GetDeclaredSymbol(node) is INamedTypeSymbol classSymbol + && (classSymbol.BaseType is { IsAbstract: true } + || classSymbol.DerivesFromAny(BaseClassesToIgnore) + || classSymbol.ImplementsAny(InterfacesToIgnore)); } diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/ClassShouldNotBeEmpty.cs b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/ClassShouldNotBeEmpty.cs index 931ae271056..1bff2c9f1bb 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/Rules/ClassShouldNotBeEmpty.cs +++ b/analyzers/src/SonarAnalyzer.VisualBasic/Rules/ClassShouldNotBeEmpty.cs @@ -21,7 +21,7 @@ namespace SonarAnalyzer.Rules.VisualBasic; [DiagnosticAnalyzer(LanguageNames.VisualBasic)] -public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase +public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase { protected override ILanguageFacade Language => VisualBasicFacade.Instance; @@ -29,7 +29,24 @@ public sealed class ClassShouldNotBeEmpty : ClassShouldNotBeEmptyBase x.IsKind(SyntaxKind.PartialKeyword)); - protected override bool IsClassWithDeclaredBaseClass(SyntaxNode node) => node is ClassBlockSyntax { Inherits.Count: > 0 }; + protected override TypeBlockSyntax GetIfHasDeclaredBaseClass(SyntaxNode node) => + node is ClassBlockSyntax { Inherits.Count: > 0 } classBlock + ? classBlock + : null; - protected override string DeclarationTypeKeyword(SyntaxNode node) => ((TypeBlockSyntax)node).BlockStatement.DeclarationKeyword.ValueText.ToLower(); + protected override bool HasGenericBaseClassOrInterface(TypeBlockSyntax declaration) => + declaration.Inherits.Any(x => x.Types.Any(t => t is GenericNameSyntax)); + + protected override bool HasAnyAttribute(SyntaxNode node) => + node is ClassBlockSyntax { ClassStatement.AttributeLists.Count: > 0 }; + + protected override bool HasConditionalCompilationDirectives(SyntaxNode node) => + node.DescendantNodes(descendIntoTrivia: true).Any(x => x.IsAnyKind( + SyntaxKind.IfDirectiveTrivia, + SyntaxKind.ElseIfDirectiveTrivia, + SyntaxKind.ElseDirectiveTrivia, + SyntaxKind.EndIfDirectiveTrivia)); + + protected override string DeclarationTypeKeyword(SyntaxNode node) => + ((TypeBlockSyntax)node).BlockStatement.DeclarationKeyword.ValueText.ToLower(); } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/ClassShouldNotBeEmptyTest.cs b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/ClassShouldNotBeEmptyTest.cs index e5c2643502a..fb7699daef8 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/Rules/ClassShouldNotBeEmptyTest.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/Rules/ClassShouldNotBeEmptyTest.cs @@ -45,7 +45,9 @@ public class ClassShouldNotBeEmptyTest private static readonly MetadataReference[] AdditionalReferences = new[] { - AspNetCoreMetadataReference.MicrosoftAspNetCoreRazorPages + AspNetCoreMetadataReference.MicrosoftAspNetCoreMvcAbstractions, + AspNetCoreMetadataReference.MicrosoftAspNetCoreMvcCore, + AspNetCoreMetadataReference.MicrosoftAspNetCoreRazorPages, }; [TestMethod] diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp10.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp10.cs index 1f2342b1612..02fd205d0ae 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp10.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp10.cs @@ -1,5 +1,5 @@ -record class EmptyRecordClass1(); // Noncompliant {{Remove this empty record, or add members to it.}} +record class EmptyRecordClass1(); // Noncompliant {{Remove this empty record, write its code or make it an "interface".}} // ^^^^^^^^^^^^^^^^^ record class EmptyRecordClass2() { }; // Noncompliant diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp9.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp9.cs index dbdd5228c73..7383f176f20 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp9.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.CSharp9.cs @@ -1,6 +1,6 @@ using System; -record EmptyRecord1(); // Noncompliant {{Remove this empty record, or add members to it.}} +record EmptyRecord1(); // Noncompliant {{Remove this empty record, write its code or make it an "interface".}} // ^^^^^^^^^^^^ record EmptyRecord2() { }; // Noncompliant diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.cs index c1753d38de1..3896e880e1a 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; using System; class BaseClass @@ -18,6 +19,9 @@ abstract class AbstractBaseWithoutAbstractMethods class NoImplementation: AbstractBaseWithAbstractMethods { } // Error - abstract methods should be implemented class DefaultImplementation: AbstractBaseWithoutAbstractMethods { } // Compliant - the class will use the default implementation of DefaultMethod -class EmptyPageModel: PageModel { } // Compliant - an empty PageModel can be fully functional, the C# code can be in the cshtml file class CustomException: Exception { } // Compliant - empty exception classes are allowed, the name of the class already provides information +class CustomAttribute: Attribute { } // Compliant - empty attribute classes are allowed, the name of the class already provides information + +class EmptyPageModel: PageModel { } // Compliant - an empty PageModel can be fully functional, the C# code can be in the cshtml file +class CustomActionResult: ActionResult { } // Compliant - an empty action result can still provide information by its name diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.vb index 60cf17b6482..c28782f9c07 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.vb +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.Inheritance.vb @@ -1,4 +1,5 @@ -Imports Microsoft.AspNetCore.Mvc.RazorPages +Imports Microsoft.AspNetCore.Mvc +Imports Microsoft.AspNetCore.Mvc.RazorPages Imports System Public Class BaseClass @@ -9,7 +10,7 @@ Public Class BaseClass End Property End Class -Public Class SubClass ' Noncompliant - not derived from any special base class +Public Class SubClass ' Noncompliant - not derived from any special base class Inherits BaseClass End Class @@ -22,18 +23,26 @@ MustInherit Class AbstractBaseWithoutAbstractMethods End Sub End Class -Class NoImplementation ' Error - abstract methods should be implemented +Class NoImplementation ' Error - abstract methods should be implemented Inherits AbstractBaseWithAbstractMethods End Class -Class DefaultImplementation ' Compliant - the class will use the default implementation of DefaultMethod +Class DefaultImplementation ' Compliant - the class will use the default implementation of DefaultMethod Inherits AbstractBaseWithoutAbstractMethods End Class -Public Class EmptyPageModel ' Compliant - an empty PageModel can be fully functional, the VB code can be in the vbhtml file - Inherits PageModel +Public Class CustomException ' Compliant - empty exception classes are allowed, the name of the class already provides information + Inherits Exception End Class -Public Class CustomException ' Compliant - empty exception classes are allowed, the name of the class already provides information +Public Class CustomAttribute ' Compliant - empty attribute classes are allowed, the name of the class already provides information Inherits Exception End Class + +Public Class EmptyPageModel ' Compliant - an empty PageModel can be fully functional, the VB code can be in the vbhtml file + Inherits PageModel +End Class + +Public Class CustomActionResult ' Compliant - an empty action result can still provide information by its name + Inherits ActionResult +End Class diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.cs index 493dbc28ec3..c842c307146 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; -class Empty { } // Noncompliant {{Remove this empty class, or add members to it.}} +class Empty { } // Noncompliant {{Remove this empty class, write its code or make it an "interface".}} // ^^^^^ public class PublicEmpty { } // Noncompliant @@ -73,6 +75,19 @@ class GenericNotEmptyWithConstraints void Method(T arg) { } } +class IntegerList: List { } // Compliant - creates a more specific type without adding new members to it (similar to using the typedef keyword in C/C++) +class StringLookup : Dictionary { } +interface IIntegerSet : ISet { } + +[ComVisible(true)] +class ClassWithAttribute { } // Compliant - types with attributes are ignored + +[ComVisible(true), Obsolete] +class ClassWithMultipleAttributes { } + +[] // Error +class AttributeError { } + static class StaticEmpty { } // Noncompliant abstract class AbstractEmpty { } // Noncompliant @@ -90,5 +105,15 @@ struct EmptyStruct { } // Compliant - this rule only deals enum EmptyEnum { } // Compliant - this rule only deals with classes +class Conditional // Compliant - it's not empty when the given symbol is defined +{ +#if NOTDEFINED + public override string ToString() + { + return "Debug Text"; + } +#endif +} + class { } // Error diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.vb index d6221105cf5..6a7845a4431 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.vb +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/ClassShouldNotBeEmpty.vb @@ -1,6 +1,8 @@ Imports System +Imports System.Collections.Generic +Imports System.Runtime.InteropServices -Class Empty ' Noncompliant {{Remove this empty class, or add members to it.}} +Class Empty ' Noncompliant {{Remove this empty class, write its code or make it an "interface".}} ' ^^^^^ End Class @@ -97,6 +99,30 @@ Class GenericNotEmptyWithConstraints(Of T As Class) End Sub End Class +Class IntegerList ' Compliant - creates a more specific type without adding new members to it (similar to using the typedef keyword in C/C++) + Inherits List(Of Integer) +End Class + +Class StringLookup(Of T) + Inherits Dictionary(Of String, T) +End Class + +Interface IIntegerSet(Of T) + Inherits ISet(Of Integer) +End Interface + + +Class ClassWithAttribute ' Compliant - types with attributes are ignored +End Class + + +Class ClassWithMultipleAttributes +End Class + +<> ' Error +Class AttributeError ' Noncompliant +End Class + MustInherit Class AbstractEmpty ' Noncompliant End Class @@ -117,5 +143,13 @@ End Interface Structure EmptyStruct ' Compliant - this rule only deals with classes End Structure +Class Conditional ' Compliant - it's not empty when the given symbol is defined +#If NOTDEFINED Then + Public Overrides Function ToString() As String + Return "Debug Text" + End Function +#End If +End Class + Class ' Error -End Class +End Class