Skip to content

Commit

Permalink
Do not warn when invoking APIs that has SupportedOSPlatformGuard attr…
Browse files Browse the repository at this point in the history
…ibute (#7326)

* Do not warn when invoking APIs that has SupportedOSPlatformGuard attribute

* dotnet build /t:pack update

* Add more scenarios in the test

* Again doc updated
  • Loading branch information
buyaa-n committed Jun 14, 2024
1 parent 4d5fd9d commit 52913b2
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1407,14 +1407,18 @@ void CheckOperationAttributes(ISymbol symbol, bool checkParents)
platformSpecificOperations.TryAdd(new KeyValuePair<IOperation, ISymbol>(operation, symbol), (notSuppressedAttributes, callSiteAttributes.Platforms));
}
}
else if (TryCopyAttributesNotSuppressedByMsBuild(operationAttributes.Platforms!, msBuildPlatforms, out var copiedAttributes))
else if (!OperationHasOnlyAssemblyAttributesAndCalledFromSameAssembly(operationAttributes, symbol, containingSymbol) &&
TryCopyAttributesNotSuppressedByMsBuild(operationAttributes.Platforms!, msBuildPlatforms, out var copiedAttributes))
{
platformSpecificOperations.TryAdd(new KeyValuePair<IOperation, ISymbol>(operation, symbol), (copiedAttributes, null));
}
}
}
}

private static bool OperationHasOnlyAssemblyAttributesAndCalledFromSameAssembly(PlatformAttributes operationAttributes, ISymbol symbol, ISymbol containingSymbol) =>
operationAttributes.IsAssemblyAttribute && containingSymbol.ContainingAssembly == symbol.ContainingAssembly;

private static bool UsedInCreatingNotSupportedException(IArgumentOperation operation, ITypeSymbol? notSupportedExceptionType)
{
if (operation.Parent is IObjectCreationOperation creation &&
Expand Down Expand Up @@ -1799,11 +1803,7 @@ static void MergePlatformAttributes(ImmutableArray<AttributeData> immediateAttri

if (attribute.AttributeClass.Name is SupportedOSPlatformGuardAttribute or UnsupportedOSPlatformGuardAttribute)
{
if (!parentAttributes.IsAssemblyAttribute)
{
parentAttributes = new PlatformAttributes();
}

parentAttributes = new PlatformAttributes(); // The API is for guard, clear parent attributes
return;
}

Expand Down
3 changes: 1 addition & 2 deletions src/NetAnalyzers/RulesMissingDocumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

Rule ID | Missing Help Link | Title |
--------|-------------------|-------|
CA1871 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1871> | Do not pass a nullable struct to 'ArgumentNullException.ThrowIfNull' |
CA2022 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2022> | Avoid inexact read with 'Stream.Read' |
CA2264 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2264> | Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull' |
CA2265 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2265> | Do not compare Span\<T> to 'null' or 'default' |
CA5360 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5360> | Do Not Call Dangerous Methods In Deserialization |
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;

Expand Down Expand Up @@ -1216,6 +1217,91 @@ static void M1()
await VerifyAnalyzerCSAsync(csSource);
}

[Fact]
public async Task CallGuardFromPlatformSpecificAssembly()
{
string csDependencyCode = @"
public class Library
{
static bool s_isWindowsOrLinux = false;
[System.Runtime.Versioning.SupportedOSPlatformGuard(""windows"")]
[System.Runtime.Versioning.SupportedOSPlatformGuard(""linux"")]
public static bool IsSupported => s_isWindowsOrLinux;
[System.Runtime.Versioning.UnsupportedOSPlatformGuard(""windows"")]
[System.Runtime.Versioning.UnsupportedOSPlatformGuard(""linux"")]
public static bool IsNotSupported => false;
public static void AMethod() { }
}";
csDependencyCode = @$"[assembly: System.Runtime.Versioning.SupportedOSPlatform(""windows"")]
[assembly: System.Runtime.Versioning.SupportedOSPlatform(""linux"")]
{csDependencyCode}";

string csCurrentAssemblyCode = @"
using System;
public class Program
{
public void ProgramMethod()
{
[|Library.AMethod()|]; // Not guarded, warns
if (Library.IsSupported)
{
Library.AMethod();
}
if (Library.IsNotSupported)
{
[|Library.AMethod()|]; // warn because guarded by unsupported
}
else
{
Library.AMethod(); // guarded
}
}
}";
var test = SetupDependencyAndTestCSWithOneSourceFile(csCurrentAssemblyCode, csDependencyCode);
test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", $@"root = true
[*]
build_property.TargetFramework = net5
"));
await test.RunAsync();
}

private static VerifyCS.Test SetupDependencyAndTestCSWithOneSourceFile(string csInput, string csDependencyCode)
{
return new VerifyCS.Test
{
ReferenceAssemblies = ReferenceAssemblies.Net.Net80,
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
MarkupOptions = MarkupOptions.UseFirstDescriptor,
TestState =
{
Sources =
{
csInput
},
AdditionalProjects =
{
["PreviewAssembly"] =
{
Sources =
{
("/PreviewAssembly/AssemblyInfo.cs", csDependencyCode)
},
},
},
AdditionalProjectReferences =
{
"PreviewAssembly",
},
},
};
}

[Fact]
public async Task GuardedWith_RuntimeInformation_IsOSPlatform_SimpleIfElseAsync()
{
Expand Down Expand Up @@ -4181,7 +4267,7 @@ public async Task GuardCallingCachedValue_CallSiteHasAssemblyAttributeAsync()
[assembly: SupportedOSPlatform(""ios10.0"")]
class Test
{
static bool s_isiOS11OrNewer => false;
static bool s_isiOS11OrNewer = false;
[SupportedOSPlatformGuard(""ios11.0"")]
private bool IsIos11Supported() => s_isiOS11OrNewer; // should not warn
Expand Down

0 comments on commit 52913b2

Please sign in to comment.