Open wachulski opened 5 years ago
@genlu, @drewnoakes I had a look at the actual implementation and the code relies on operations to find banned usages. It doesn't seem that we can use operation to catch to the other cases reported in this issue. I know that Symbol actions are expensive but except for this solution and syntax based one (which then will rely on getting the symbol), I can't think of any other way to do so. Any idea?
I am not sure I understand the value add for such a change. For example, if the return type is a banned type, then the analyzer will currently flag the return value. This is sufficient to fix the code for user. I believe we should close this issue as by design.
Banned is banned. I agree with the the original expected behavior: 4 diagnostics should be reported.
I know that Symbol actions are expensive
Symbol actions are not expensive. The expensive actions are syntax actions that use symbols via GetSymbolInfo
.
Banned is banned. I agree with the the original expected behavior: 4 diagnostics should be reported
I still feel there is absolute no value add in doing this work. Current approach does not find banned type usages in signatures, but it does so in all executable code. I claim this is sufficient for the user to make their code clean.
@sharwell Oh! Thanks for that clarification!
@mavasani It might be somehow a corner case but it could happen that you are defining an interface or abstract class in some common library that you are providing to your internal devs and yet your lead dev wants to make sure you won't use some type. With the current approach the "detection" will only occur after the code is delivered and at this point that's a bit of a nightmare to do some change. At the same time, I do share your point when you say that the current implementation will cover most of the cases and so the update isn't really top priority.
I claim this is sufficient for the user to make their code clean.
We are using this analyzer to ensure IVT isolation in Roslyn will prevent partner code breaks. Failure to detect these situations would cause a partner code break for the described scenario, even if the interface is not implemented or used anywhere. Since we already must fix this for correct behavior of restricted IVTs, it doesn't seem problematic to apply it to RS0030 in addition.
@sharwell, @mavasani How do you want to proceed with this? Close? Implement? Something else?
I would like to wait on this issue until someone can provide me a real user case of when existing RS0030 violations in code were not sufficient to catch these additional usages. Until then, it just feels like an unnecessary code churn. We seem to have sufficient feedback. I'd be fine if someone wants to submit a PR here.
@mavasani I believe it may hit when the usage differs, e.g. if I want to ban ICloneable, with T:System.ICloneable, it will not find any.
So if understand correctly this is by design?
public interface IExample
{
// Does not trigger
void Test(DateTime input);
// Does not trigger
DateTime DoSomething();
void Other();
}
public class Example : IExample
{
// arg does not trigger
public void Test(DateTime input)
{
// does not trigger
var x = input;
// triggers here
x.AddDays(1);
}
// does not trigger
public DateTime DoSomething()
{
// triggers
return new DateTime(2022,9, 17);
}
public void Other()
{
// triggers
var x = new DateTime(2022, 1, 1);
// triggers
var y = DateTime.Now;
}
}
So the official statement is that any usage of the type will trigger it?
That would mean the current approach will work for any scenario except .Interface / Abstract classes in a different dll than the implementation?
The config being used is, but perhaps I need additional lines?
T:System.DateTime;Always use System.DateTimeOffset over System.DateTime
I would like to wait on this issue until someone can provide me a real user case of when existing RS0030 violations in code were not sufficient to catch these additional usages. Until then, it just feels like an unnecessary code churn.
When separating abstractions from implementations, one creates a project with (mostly) only interfaces. I cannot ban the use of certain APIs in this project, as the project doesn't "interact" with the banned APIs, but merely points to them in method signatures / return types. We have a WCF project like this where we define the contracts in a separate project. We don't want to expose any internal types through this project, so being able to ban types in this project would achieve that. However as it currently stands, no error is reported for this project.
@mavasani
To echo what other people said here, a concrete use case we faced yesterday is, we want to ban DateTime
in the benefit of DateTimeOffset
for entity objects we use with EF Core. The problem is that it is perfectly fine for someone to create an assembly with types that have DateTime
-type properties, but nobody will be able to consume it, so allowing declaration of banned types doesn't make sense.
In a context where the producer and the consumer are in the place, it's fine, but once they are lose-coupled, it just becomes a non-sense to ban only on one side.
Given we have sufficient feedback here, I am fine if someone wants to submit a PR with the fix for this one.
I'm fine to give it a try.
@mavasani
I ran build.cmd
and it worked fine, however running test.cmd
failed with the following message:
Toolset version 8.0.0-beta.23463.1 has not been restored.
Here are the SDKs I have on my machine:
2.1.302
2.2.104
3.1.301
6.0.201
6.0.416
7.0.402
8.0.100-rc.2.23502.2
Do you have any idea how to fix that ? Thank you.
NB: Here is my dotnet --info
:
dotnet --info
.NET SDK:
Version: 8.0.100-rc.2.23502.2
Commit: 0abacfc2b6
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22621
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.100-rc.2.23502.2\
.NET workloads installed:
[wasm-tools-net6]
Installation Source: VS 17.8.34205.153, VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.23479.6/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.workload.mono.toolchain.net6\8.0.0-rc.2.23479.6\WorkloadManifest.json
Install Type: Msi
[wasm-tools-net7]
Installation Source: VS 17.8.34205.153
Manifest Version: 8.0.0-rc.2.23479.6/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.workload.mono.toolchain.net7\8.0.0-rc.2.23479.6\WorkloadManifest.json
Install Type: Msi
[maui-windows]
Installation Source: VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.9373/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.maui\8.0.0-rc.2.9373\WorkloadManifest.json
Install Type: Msi
[wasm-tools]
Installation Source: VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.23479.6/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.workload.mono.toolchain.current\8.0.0-rc.2.23479.6\WorkloadManifest.json
Install Type: Msi
[maui-maccatalyst]
Installation Source: VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.9373/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.maui\8.0.0-rc.2.9373\WorkloadManifest.json
Install Type: Msi
[android]
Installation Source: VS 17.7.34202.233
Manifest Version: 34.0.0-rc.2.468/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.android\34.0.0-rc.2.468\WorkloadManifest.json
Install Type: Msi
[maccatalyst]
Installation Source: VS 17.7.34202.233
Manifest Version: 16.4.8968-net8-rc2/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.maccatalyst\16.4.8968-net8-rc2\WorkloadManifest.json
Install Type: Msi
[maui-ios]
Installation Source: VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.9373/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.maui\8.0.0-rc.2.9373\WorkloadManifest.json
Install Type: Msi
[ios]
Installation Source: VS 17.7.34202.233
Manifest Version: 16.4.8968-net8-rc2/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.ios\16.4.8968-net8-rc2\WorkloadManifest.json
Install Type: Msi
[maui-android]
Installation Source: VS 17.7.34202.233
Manifest Version: 8.0.0-rc.2.9373/8.0.100-rc.2
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100-rc.2\microsoft.net.sdk.maui\8.0.0-rc.2.9373\WorkloadManifest.json
Install Type: Msi
Host:
Version: 8.0.0-rc.2.23479.6
Architecture: x64
Commit: 0b25e38ad3
.NET SDKs installed:
2.1.302 [C:\Program Files\dotnet\sdk]
2.2.104 [C:\Program Files\dotnet\sdk]
3.1.301 [C:\Program Files\dotnet\sdk]
6.0.201 [C:\Program Files\dotnet\sdk]
6.0.416 [C:\Program Files\dotnet\sdk]
7.0.402 [C:\Program Files\dotnet\sdk]
8.0.100-rc.2.23502.2 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0-rc.2.23480.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0-rc.2.23479.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.0-rc.2.23479.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
C:\data\xxx\thirdparty\roslyn-analyzers\global.json
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
When I was working on this project, I adjusted some of these files to not reference/require vNext (in this case: 8). Not sure about the toolset, I think I also couldn't find out how to install those.
Requiring these dependencies is not great for external contributors. I would applaud a mode/configuration that allows me to contribute using just the latest GA sdk. CI would do verification testing against vNext.
@mavasani
Any help to get test.cmd
to run and work please ?
Without this, it's impossible to validate if changes made are correct or breaking.
Thanks.
@TanukiSharp I believe there are changes to global.json in https://github.com/dotnet/roslyn-analyzers/pull/6972/files that should likely address your issue once that PR is merged. Can you try restore after locally making the global.json changes from that PR?
@mavasani Thank you for your answer. The problem remains the same, some versions used are not yet available to mere mortals like me.
> dotnet restore
The command could not be loaded, possibly because:
* You intended to execute a .NET application:
The application 'restore' does not exist.
* You intended to execute a .NET SDK command:
A compatible .NET SDK was not found.
Requested SDK version: 8.0.100-rtm.23506.1
global.json file: xxx\thirdparty\roslyn-analyzers\global.json
Installed SDKs:
2.1.302 [C:\Program Files\dotnet\sdk]
2.2.104 [C:\Program Files\dotnet\sdk]
3.1.301 [C:\Program Files\dotnet\sdk]
6.0.201 [C:\Program Files\dotnet\sdk]
6.0.416 [C:\Program Files\dotnet\sdk]
7.0.402 [C:\Program Files\dotnet\sdk]
8.0.100-rc.2.23502.2 [C:\Program Files\dotnet\sdk]
Install the [8.0.100-rtm.23506.1] .NET SDK or update [xxx\thirdparty\roslyn-analyzers\global.json] to match an installed SDK.
Learn about SDK resolution:
https://aka.ms/dotnet/sdk-not-found
I've searched for *rtm*
in the dotnet repo but apparently there are no binaries available yet.
I tried to tweak the versions in global.json with other RCs, but it always fail one way or another.
Requested SDK version: 8.0.100-rtm.23506.1 global.json file: xxx\thirdparty\roslyn-analyzers\global.json
@TanukiSharp Do you still get the issue with the below contents of global.json? Nothing should be pulling onto 8.0.100-rtm.23506.1
{
"tools": {
"dotnet": "8.0.100-rc.2.23502.2",
"runtimes": {
"dotnet": [
"3.1.7",
"6.0.11"
]
},
"vs": {
"version": "17.7.0"
},
"xcopy-msbuild": "17.8.1-2"
},
"sdk": {
"version": "8.0.100-rc.2.23502.2",
"allowPrerelease": true,
"rollForward": "patch"
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.23528.2"
}
}
@mavasani Thank you for the very quick answer. With the above mentioned global.json
I get the following error on .\test.cmd
:
> .\test.cmd
Toolset version 9.0.0-beta.23528.2 has not been restored.
I just updated all my installs of VS 2022 and Preview, just in case, but it didn't help.
@mavasani Thank you for the very quick answer. With the above mentioned
global.json
I get the following error on.\test.cmd
:> .\test.cmd Toolset version 9.0.0-beta.23528.2 has not been restored.
I just updated all my installs of VS 2022 and Preview, just in case, but it didn't help.
@Evangelink @carlossanlop any suggestions here?
I just merged https://github.com/dotnet/roslyn-analyzers/pull/6972 into main, which downgrades the rtm version used in global.json to the last publicily available one, rc2.
The command .\Test.cmd
still fails with the following:
> .\Test.cmd
Toolset version 8.0.0-beta.23463.1 has not been restored.
The global.json
is still on "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23463.1"
but even if I set it to 9.0.0-beta.23528.2
, it fails with:
Toolset version 9.0.0-beta.23528.2 has not been restored.
I've run .\Restore.cmd
and .\Build.cmd
and both commands work fine with both versions of Microsoft.DotNet.Arcade.Sdk
, but the .\Test.cmd
command keeps failing.
@carlossanlop Any update ?
@TanukiSharp we will look at the Test.cmd issue and share an update. However, you can workaround for now by running the Banned API Analyzers unit tests in VS from the TestExplorer. That should be sufficient for the changes required for this Issue
Hi, just ran into this scenario, where there was a class with a DateTime property that is not picked up by the analyser.
Initially it was being set by x.CreateDate = DateTimeOffset.Now.DateTime
, which I changed to x.CreateDate = timeProvider.GetLocalNow().DateTime
, as I have another rule banning Now/UtcNow.
After that the error went away, as the .DateTime conversion is not in my code, and the property type is not being analysed. The record is written to a DB as JSON, so auto-serialised, and we don't have code that reads the property.
My expectation would be that the analyser picked up this usage of the banned type.
(And yes, I know the property name is also bad, as it is not a date; it should be x.CreateTimestamp or similar)
I encountered that issue in a POC of BannedApiAnalyzers when trying to add a 2nd example (the 1st is for DateTime.Now
) to forbid usage of IActionResult
as a controller's method return type to encourage Results<> usage. It's 1 of my 3 ideas (the 3rd being Newtosoft.Json
) so I just lost a serious percentage of "POC ammo" 😢
Analyzer package
Example: Microsoft.CodeAnalysis.BannedApiAnalyzers
Package Version
Example: v2.9.4 (Latest)
Diagnostic ID
RS0030
Repro steps
BannedSymbols.txt:
.cs:
Expected behavior
All four occurrences of
B
should be reported.Actual behavior
Only
C.B
's symbol in expression body is reported (innew B();
)