Skip to content

Commit 0b0b9d0

Browse files
authored
Merge branch 'main' into update-xunit
2 parents c4c54ed + 56bc6b5 commit 0b0b9d0

37 files changed

+296
-61
lines changed

.github/workflows/build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ on:
88

99
env:
1010
DOTNET_NOLOGO: 1
11+
# This is for some reason set to 'all' on CI which means
12+
# we get warnings for transitive dependencies (e.g. from Messerli.CodeStyle -> StyleCop)
13+
NuGetAuditMode: direct
1114

1215
jobs:
1316
build:
@@ -23,6 +26,10 @@ jobs:
2326
- uses: actions/checkout@v4
2427
- uses: actions/setup-dotnet@v4
2528
name: Install Current .NET SDK
29+
- uses: actions/setup-dotnet@v4
30+
name: 'Install .NET SDK 8.0'
31+
with:
32+
dotnet-version: '8.0.x'
2633
- uses: actions/setup-dotnet@v4
2734
name: 'Install .NET SDK 7.0'
2835
with:

Directory.Build.props

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
2424
<EmbedUntrackedSources>true</EmbedUntrackedSources>
2525
</PropertyGroup>
26-
<ItemGroup Label="Deterministic Builds and Source Link">
27-
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All"/>
28-
</ItemGroup>
2926
<PropertyGroup>
3027
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
3128
</PropertyGroup>

Directory.Packages.props

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
<PackageVersion Include="System.Linq.Async" Version="[5.0.0, 7)" />
1313
</ItemGroup>
1414
<ItemGroup Label="Build Dependencies">
15-
<PackageVersion Include="PolySharp" Version="1.14.0" />
15+
<PackageVersion Include="PolySharp" Version="1.15.0" />
1616
<PackageVersion Include="Messerli.CodeStyle" Version="2.3.0" />
1717
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.3" />
18-
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
1918
</ItemGroup>
2019
<ItemGroup Label="Test Dependencies">
2120
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />

FrameworkFeatureConstants.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@
1818
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
1919
<DefineConstants>$(DefineConstants);RANDOM_SHUFFLE;UTF8_SPAN_PARSABLE</DefineConstants>
2020
</PropertyGroup>
21+
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">
22+
<DefineConstants>$(DefineConstants);REFLECTION_ASSEMBLY_NAME_INFO;REFLECTION_TYPE_NAME</DefineConstants>
23+
</PropertyGroup>
2124
</Project>

Funcky.Analyzers/Funcky.Analyzers.Test/Funcky.Analyzers.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFramework>net9.0</TargetFramework>
55

66
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
77
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using Microsoft.CodeAnalysis.Testing;
2+
using Xunit;
3+
using VerifyCS = Funcky.Analyzers.Test.CSharpAnalyzerVerifier<Funcky.Analyzers.NonDefaultableAnalyzer>;
4+
5+
namespace Funcky.Analyzers.Test;
6+
7+
public sealed class NonDefaultableTest
8+
{
9+
private const string AttributeSource =
10+
"""
11+
namespace Funcky.CodeAnalysis
12+
{
13+
[System.AttributeUsage(System.AttributeTargets.Struct)]
14+
internal sealed class NonDefaultableAttribute : System.Attribute { }
15+
}
16+
""";
17+
18+
[Fact]
19+
public async Task DefaultInstantiationsOfRegularStructsGetNoDiagnostic()
20+
{
21+
const string inputCode =
22+
"""
23+
class Test
24+
{
25+
private void Usage()
26+
{
27+
_ = default(Foo);
28+
}
29+
}
30+
31+
struct Foo { }
32+
""";
33+
await VerifyCS.VerifyAnalyzerAsync(inputCode + AttributeSource);
34+
}
35+
36+
[Fact]
37+
public async Task DefaultInstantiationsOfAnnotatedStructsGetError()
38+
{
39+
const string inputCode =
40+
"""
41+
using Funcky.CodeAnalysis;
42+
43+
class Test
44+
{
45+
private void Usage()
46+
{
47+
_ = default(Foo);
48+
_ = default(Funcky.Generic<int>);
49+
}
50+
}
51+
52+
[NonDefaultable]
53+
struct Foo { }
54+
55+
namespace Funcky
56+
{
57+
[NonDefaultable]
58+
struct Generic<T> { }
59+
}
60+
""";
61+
62+
DiagnosticResult[] expectedDiagnostics =
63+
[
64+
VerifyCS.Diagnostic().WithSpan(7, 13, 7, 25).WithArguments("Foo"),
65+
VerifyCS.Diagnostic().WithSpan(8, 13, 8, 41).WithArguments("Generic<int>"),
66+
];
67+
68+
await VerifyCS.VerifyAnalyzerAsync(inputCode + AttributeSource, expectedDiagnostics);
69+
}
70+
}

Funcky.Analyzers/Funcky.Analyzers/AnalyzerReleases.Unshipped.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
### New Rules
55
Rule ID | Category | Severity | Notes
66
--------|----------|----------|-------
7+
λ1009 | Funcky | Error | NonDefaultableAnalyzer
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System.Collections.Immutable;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.Diagnostics;
4+
using Microsoft.CodeAnalysis.Operations;
5+
6+
namespace Funcky.Analyzers;
7+
8+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
9+
public sealed class NonDefaultableAnalyzer : DiagnosticAnalyzer
10+
{
11+
public static readonly DiagnosticDescriptor DoNotUseDefault = new DiagnosticDescriptor(
12+
id: $"{DiagnosticName.Prefix}{DiagnosticName.Usage}09",
13+
title: "Do not use default to instantiate this type",
14+
messageFormat: "Do not use default(...) to instantiate '{0}'",
15+
category: nameof(Funcky),
16+
DiagnosticSeverity.Error,
17+
isEnabledByDefault: true,
18+
description: "Values instantiated with default are in an invalid state; any member may throw an exception.");
19+
20+
private const string AttributeFullName = "Funcky.CodeAnalysis.NonDefaultableAttribute";
21+
22+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DoNotUseDefault);
23+
24+
public override void Initialize(AnalysisContext context)
25+
{
26+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
27+
context.EnableConcurrentExecution();
28+
context.RegisterCompilationStartAction(OnCompilationStart);
29+
}
30+
31+
private static void OnCompilationStart(CompilationStartAnalysisContext context)
32+
{
33+
if (context.Compilation.GetTypeByMetadataName(AttributeFullName) is { } nonDefaultableAttribute)
34+
{
35+
context.RegisterOperationAction(AnalyzeDefaultValueOperation(nonDefaultableAttribute), OperationKind.DefaultValue);
36+
}
37+
}
38+
39+
private static Action<OperationAnalysisContext> AnalyzeDefaultValueOperation(INamedTypeSymbol nonDefaultableAttribute)
40+
=> context =>
41+
{
42+
var operation = (IDefaultValueOperation)context.Operation;
43+
if (operation.Type is { } type && type.GetAttributes().Any(IsAttribute(nonDefaultableAttribute)))
44+
{
45+
context.ReportDiagnostic(Diagnostic.Create(
46+
DoNotUseDefault,
47+
operation.Syntax.GetLocation(),
48+
messageArgs: type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)));
49+
}
50+
};
51+
52+
private static Func<AttributeData, bool> IsAttribute(INamedTypeSymbol attributeClass)
53+
=> attribute => SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, attributeClass);
54+
}

Funcky.Async.Test/Funcky.Async.Test.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFrameworks>net8.0;net7.0</TargetFrameworks>
3+
<TargetFrameworks>net9.0;net8.0;net7.0</TargetFrameworks>
44
<LangVersion>preview</LangVersion>
55
<Nullable>enable</Nullable>
66
<IsPackable>false</IsPackable>

Funcky.Async/Extensions/AsyncEnumerableExtensions/Merge.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static async IAsyncEnumerable<TSource> Merge<TSource>(this IEnumerable<IA
6161

6262
try
6363
{
64-
await foreach (var element in MergeEnumerators(enumerators.RemoveRange(await enumerators.ToAsyncEnumerable().WhereAwait(async f => await HasMoreElements(f).ConfigureAwait(false)).ToListAsync().ConfigureAwait(false)), GetMergeComparer(comparer)))
64+
await foreach (var element in MergeEnumerators(enumerators.RemoveRange(await enumerators.ToAsyncEnumerable().WhereAwait(async f => await HasMoreElements(f).ConfigureAwait(false)).ToListAsync().ConfigureAwait(false)), GetMergeComparer(comparer)).ConfigureAwait(false))
6565
{
6666
yield return element;
6767
}

0 commit comments

Comments
 (0)