Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Documentation/src/analyzer-rules/analyzer-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ contains a rule.
| [λ0004](./λ0004.md) | Error | The `default` literal is wrapped by an implicit conversion |
| [λ0005](./λ0005.md) | Error | A `null` literal is passed to `Option`, `Result` or `Either` |
| [λ1009](./λ1009.md) | Error | Do not use `default` to instantiate this type (moved from `Funcky.Analyzers` in 3.7.0) |
| [λ1010](./λ1010.md) | Error | An option has either zero or one elements (needs Roslyn 4.4, i.e. the .NET 7 SDK or newer) |
| [λ1010](./λ1010.md) | Error | An option has either zero or one elements |

## Funcky.Analyzers

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AnalyzerRoslynVersion>4.4.0</AnalyzerRoslynVersion>
<AnalyzerRoslynVersion>4.14.0</AnalyzerRoslynVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Funcky.Analyzers\Funcky.Analyzers.csproj" PrivateAssets="all" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>
<PropertyGroup Label="NuGet Metadata">
<PackageId>Funcky.Analyzers</PackageId>
<VersionPrefix>2.1.0</VersionPrefix>
<VersionPrefix>3.0.0</VersionPrefix>
<Description>Analyzers to guide to the correct usage of Funcky.</Description>
<PackageTags>funcky, analyzers, roslyn</PackageTags>
<DevelopmentDependency>true</DevelopmentDependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Condition="'$(SupportsRoslynComponentVersioning)' != 'true'"
AfterTargets="ResolvePackageDependenciesForBuild;ResolveNuGetPackageAssets">
<Warning Code="λ.BUILD.0001"
Text="Funcky.Analyzers requires at least Roslyn 4.4 i.e. Visual Studio 2022 17.4 / .NET SDK 7.0" />
Text="Funcky.Analyzers requires at least Roslyn 4.14 i.e. Visual Studio 2022 17.14 / .NET SDK 9.0.300" />
<ItemGroup>
<Analyzer Remove="@(Analyzer->WithMetadataValue('NuGetPackageId', 'Funcky.Analyzers'))" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static bool HasStaticMember(INamedTypeSymbol type, string name)
.OfType<IMethodSymbol>()
.Any(method => method.IsStatic && !method.IsExtensionMethod);

/// <summary>The static class an extension member or classic extension method is declared in. Roslyn 4.4 has no notion of
/// <summary>The static class an extension member or classic extension method is declared in. Roslyn 4.14 has no notion of
/// an extension block, so any type nested in a static class is taken for one.</summary>
public static INamedTypeSymbol? DeclaringClass(ISymbol? symbol)
=> symbol is IMethodSymbol method && (method.ReducedFrom ?? method).ContainingType is { } containingType
Expand Down
2 changes: 1 addition & 1 deletion Funcky.Analyzers/Funcky.Analyzers/Funcky.Analyzers.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AnalyzerRoslynVersion>4.4.0</AnalyzerRoslynVersion>
<AnalyzerRoslynVersion>4.14.0</AnalyzerRoslynVersion>
</PropertyGroup>
<Import Project="Funcky.Analyzers.targets" />
</Project>
10 changes: 0 additions & 10 deletions Funcky.Analyzers/Funcky.Analyzers/Funcky.Analyzers.targets
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,5 @@
<ItemGroup>
<EmbeddedResource Update="Resources.resx" Generator="ResXFileCodeGenerator" LastGenOutput="Resources.Designer.cs" />
</ItemGroup>
<PropertyGroup Condition="'$(DisableAnalyzerReleaseTracking)' == 'true'">
<!-- RS2008: Enable analyzer release tracking -->
<NoWarn>$(NoWarn);RS2008</NoWarn>
</PropertyGroup>
<Target Name="_FunckyRemoveAnalyzerReleasesFiles" BeforeTargets="CoreCompile" Condition="'$(DisableAnalyzerReleaseTracking)' == 'true'">
<ItemGroup>
<AdditionalFiles Remove="AnalyzerReleases.Shipped.md" />
<AdditionalFiles Remove="AnalyzerReleases.Unshipped.md" />
</ItemGroup>
</Target>
<Import Project="..\Funcky.Analyzers.Package\Packing.targets" />
</Project>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AnalyzerRoslynVersion>4.4.0</AnalyzerRoslynVersion>
<AnalyzerRoslynVersion>4.14.0</AnalyzerRoslynVersion>
</PropertyGroup>
<ItemGroup>
<None Include="Funcky.BuiltinAnalyzers.CodeFixes.Roslyn3.7.csproj" />
</ItemGroup>
<Import Project="Funcky.BuiltinAnalyzers.CodeFixes.targets" />
</Project>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AnalyzerRoslynVersion>4.4.0</AnalyzerRoslynVersion>
<DefineConstants>$(DefineConstants);ROSLYN_4_4_0</DefineConstants>
<AnalyzerRoslynVersion>4.14.0</AnalyzerRoslynVersion>
</PropertyGroup>
<ItemGroup>
<None Include="Funcky.BuiltinAnalyzers.Roslyn3.7.csproj" />
</ItemGroup>
<Import Project="Funcky.BuiltinAnalyzers.targets" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,5 @@
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" VersionOverride="$(AnalyzerRoslynVersion)" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup Condition="'$(DisableAnalyzerReleaseTracking)' == 'true'">
<!-- RS2008: Enable analyzer release tracking -->
<NoWarn>$(NoWarn);RS2008</NoWarn>
</PropertyGroup>
<Target Name="_FunckyRemoveAnalyzerReleasesFiles" BeforeTargets="CoreCompile" Condition="'$(DisableAnalyzerReleaseTracking)' == 'true'">
<ItemGroup>
<AdditionalFiles Remove="AnalyzerReleases.Shipped.md" />
<AdditionalFiles Remove="AnalyzerReleases.Unshipped.md" />
</ItemGroup>
</Target>
<Import Project="..\Funcky.Analyzers.Package\Packing.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if ROSLYN_4_4_0
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
Expand Down Expand Up @@ -51,4 +50,3 @@ private static Action<OperationAnalysisContext> AnalyzeListPattern(INamedTypeSym
}
};
}
#endif
25 changes: 14 additions & 11 deletions Funcky.Analyzers/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ where a rule was born: `λ00xx` built-in, `λ10xx` `Funcky.Analyzers`, `λ11xx`
the documentation is the authority on where a rule lives.

### Built-in Analyzers and Roslyn Versions
The built-in analyzers have to load on every SDK that can consume `Funcky`, so their baseline is Roslyn 3.7
(`Funcky.BuiltinAnalyzers.Roslyn3.7.csproj`). Rules that need newer compiler APIs are guarded with `#if ROSLYN_4_4_0` and
only ship in the `roslyn4.4` asset (`Funcky.BuiltinAnalyzers.csproj`); the `Funcky` package packs both assets with the
same `GetAnalyzerPackFiles` mechanism as `Funcky.Analyzers.Package`, and `Funcky/build/Funcky.targets` removes the
`roslyn4.4` asset on SDKs without analyzer versioning and honours `FunckyDisableBuiltinAnalyzers`.
The built-in analyzers share the Roslyn 4.14 baseline of `Funcky.Analyzers` since Funcky 4.0.0 (up to 3.8.0 they also
shipped a `roslyn3.7` asset for the SDKs before .NET 7, with the newer rules behind `#if ROSLYN_4_4_0`). The `Funcky`
package packs the asset with the same `GetAnalyzerPackFiles` mechanism as `Funcky.Analyzers.Package`, and
`Funcky/build/Funcky.targets` removes the analyzers on SDKs without analyzer versioning (which would otherwise load
them and fail) and honours `FunckyDisableBuiltinAnalyzers`. Unlike `Funcky.Analyzers`, the library package does not
warn about an old SDK: the analyzers are an extra, the library itself keeps working.

## Roslyn Multi-Targeting
In order to support newer C# features (which in turn requires an upgrade of the `Microsoft.CodeAnalysis.*` packages)
Expand All @@ -49,16 +50,18 @@ can be shipped side by side:
```
╰─ analyzers
╰─ dotnet
╰─ roslyn4.4
╰─ roslyn4.14
╰─ cs
├─ Funcky.Analyzers.dll
╰─ ...
```

From the different versions, the highest compatible version is picked. Funcky.Analyzers currently ships a
single asset for Roslyn 4.4 (Visual Studio 2022 17.4, .NET SDK 7.0.100), the oldest version the analyzers
need. Up to Funcky.Analyzers 1.4.2 there was a second, untested `roslyn4.0` asset for Visual Studio 2022
17.0; Funcky.Analyzers 2.0.0 dropped it, as that version is out of support. To add an asset for another Roslyn
single asset for Roslyn 4.14 (Visual Studio 2022 17.14, .NET SDK 9.0.300), the compiler the .NET 10 SDK era
starts from. Funcky.Analyzers 2.x shipped a `roslyn4.4` asset (Visual Studio 2022 17.4, .NET SDK 7.0.100); 3.0.0
raised the baseline together with Funcky 4.0.0, which no longer supports SDKs before .NET 10. Up to
Funcky.Analyzers 1.4.2 there was a second, untested `roslyn4.0` asset for Visual Studio 2022 17.0; Funcky.Analyzers
2.0.0 dropped it, as that version is out of support. To add an asset for another Roslyn
version, add a second project file next to `Funcky.Analyzers.csproj` with a different `AnalyzerRoslynVersion`, reference it
from the package project with `PackAsAnalyzer`, and guard the sources that need the newer API with a define.

Expand All @@ -68,9 +71,9 @@ from the package project with `PackAsAnalyzer`, and guard the sources that need
* The `System.Text.Json` package fixes this by shipping a `.targets` file with their packages that
catches this case by checking for the `SupportsRoslynComponentVersioning` property
and manually removing discovered analyzers that are incompatible.
* Our analyzers require at least Roslyn 4.4; SDKs without multi-targeting support (before Roslyn 4.0 / .NET 6.0)
* Our analyzers require at least Roslyn 4.14; SDKs without multi-targeting support (before Roslyn 4.0 / .NET 6.0)
would load them anyway, so we ship a `.targets` file that removes all our analyzers and warns the user.
* An SDK that supports multi-targeting but is older than Roslyn 4.4 finds no compatible directory and loads
* An SDK that supports multi-targeting but is older than Roslyn 4.14 finds no compatible directory and loads
nothing, without a warning; that cannot be detected from MSBuild.
* SDKs versions that support multi-targeting also load analyzers
that are not in a `roslyn*` directory, so to avoid loading analyzers twice
Expand Down
2 changes: 1 addition & 1 deletion Funcky.SourceGenerator/Funcky.SourceGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" VersionOverride="4.12.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" VersionOverride="4.14.0" />
<PackageReference Include="PolySharp" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
Expand Down
2 changes: 0 additions & 2 deletions Funcky.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
<Project Path="Funcky.Analyzers/Funcky.Analyzers.Test/Funcky.Analyzers.Test.csproj" />
<Project Path="Funcky.Analyzers/Funcky.Analyzers.Vsix/Funcky.Analyzers.Vsix.csproj" />
<Project Path="Funcky.Analyzers/Funcky.Analyzers/Funcky.Analyzers.csproj" />
<Project Path="Funcky.Analyzers/Funcky.BuiltinAnalyzers.CodeFixes/Funcky.BuiltinAnalyzers.CodeFixes.Roslyn3.7.csproj" />
<Project Path="Funcky.Analyzers/Funcky.BuiltinAnalyzers.CodeFixes/Funcky.BuiltinAnalyzers.CodeFixes.csproj" />
<Project Path="Funcky.Analyzers/Funcky.BuiltinAnalyzers/Funcky.BuiltinAnalyzers.Roslyn3.7.csproj" />
<Project Path="Funcky.Analyzers/Funcky.BuiltinAnalyzers/Funcky.BuiltinAnalyzers.csproj" />
</Folder>
<Folder Name="/Build Config/">
Expand Down
7 changes: 2 additions & 5 deletions Funcky/Funcky.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,13 @@
<Import Project="..\GlobalUsings.props" />
<Import Project="..\FrameworkFeatureConstants.props" />
<Import Project="..\PublicApiAnalyzers.targets" />
<!-- The built-in analyzers ship inside this package, one assembly per supported Roslyn version
(analyzers/dotnet/roslyn3.7/cs and analyzers/dotnet/roslyn4.4/cs). Analyzers.props already references
the Roslyn 4.4 projects so that they run on Funcky itself; here they are additionally marked for packing. -->
<!-- The built-in analyzers ship inside this package (analyzers/dotnet/roslyn4.14/cs). Analyzers.props already
references the projects so that they run on Funcky itself; here they are additionally marked for packing. -->
<ItemGroup Label="Built-in analyzers packed into the Funcky package">
<ProjectReference Update="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers\Funcky.BuiltinAnalyzers.csproj" PackAsAnalyzer="true" />
<ProjectReference Update="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers.CodeFixes\Funcky.BuiltinAnalyzers.CodeFixes.csproj" PackAsAnalyzer="true" />
<ProjectReference Include="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers\Funcky.BuiltinAnalyzers.csproj" Condition="'$(FunckyDisableAnalyzers)' == 'true'" ReferenceOutputAssembly="false" PrivateAssets="all" PackAsAnalyzer="true" />
<ProjectReference Include="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers.CodeFixes\Funcky.BuiltinAnalyzers.CodeFixes.csproj" Condition="'$(FunckyDisableAnalyzers)' == 'true'" ReferenceOutputAssembly="false" PrivateAssets="all" PackAsAnalyzer="true" />
<ProjectReference Include="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers\Funcky.BuiltinAnalyzers.Roslyn3.7.csproj" ReferenceOutputAssembly="false" PrivateAssets="all" PackAsAnalyzer="true" />
<ProjectReference Include="..\Funcky.Analyzers\Funcky.BuiltinAnalyzers.CodeFixes\Funcky.BuiltinAnalyzers.CodeFixes.Roslyn3.7.csproj" ReferenceOutputAssembly="false" PrivateAssets="all" PackAsAnalyzer="true" />
</ItemGroup>
<!-- Adapted from https://github.com/dotnet/runtime/blob/4bd597ffde128555b4ff017e87c60adc2fedd178/eng/packaging.targets#L136,
the same mechanism Funcky.Analyzers.Package uses. -->
Expand Down
14 changes: 7 additions & 7 deletions Funcky/build/Funcky.targets
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@
</ItemGroup>

<!-- Built-in analyzers.
The Funcky package ships its analyzers once per supported Roslyn version (analyzers/dotnet/roslyn3.7/cs and
analyzers/dotnet/roslyn4.4/cs). SDKs that support analyzer versioning (.NET 6 and newer) pick the newest
compatible directory on their own. Older SDKs load every analyzer they find, so the targets below keep only
the Roslyn 3.7 assets there. Adapted from the targets that System.Text.Json ships. -->
The Funcky package ships its analyzers in analyzers/dotnet/roslyn4.14/cs. SDKs that support analyzer
versioning (.NET 6 and newer) load the directory only when their compiler is at least Roslyn 4.14
(Visual Studio 2022 17.14, .NET SDK 9.0.300). Older SDKs load every analyzer they find, so the target
below removes the assets there instead of letting the compiler fail to load them. Adapted from the
targets that System.Text.Json ships. -->
<Target Name="_Funcky_GatherBuiltinAnalyzers">
<ItemGroup>
<_FunckyBuiltinAnalyzer Include="@(Analyzer)" Condition="'%(Analyzer.NuGetPackageId)' == 'Funcky'" />
</ItemGroup>
</Target>

<Target Name="_Funcky_BuiltinAnalyzerMultiTargeting"
<Target Name="_Funcky_RemoveBuiltinAnalyzersWithoutVersioning"
Condition="'$(SupportsRoslynComponentVersioning)' != 'true'"
AfterTargets="ResolvePackageDependenciesForBuild;ResolveNuGetPackageAssets"
DependsOnTargets="_Funcky_GatherBuiltinAnalyzers">
<ItemGroup>
<Analyzer Remove="@(_FunckyBuiltinAnalyzer)"
Condition="$([System.String]::Copy('%(_FunckyBuiltinAnalyzer.Identity)').IndexOf('roslyn4')) &gt;= 0" />
<Analyzer Remove="@(_FunckyBuiltinAnalyzer)" />
</ItemGroup>
</Target>

Expand Down
8 changes: 8 additions & 0 deletions SupportPolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ We support the all the actively supported modern Frameworks, .NET Standard 2.1,

* We only remove support for target frameworks on major version changes, to avoid breaking changes for the consumers.

## What SDKs do we support?

The analyzers built into Funcky and the Funcky.Analyzers package are compiled against a fixed Roslyn version. Funcky 4
targets Roslyn 4.14, the compiler of Visual Studio 2022 17.14 and the .NET SDK 9.0.300, so every .NET 10 SDK and newer
loads them. Older SDKs skip the analyzers; the library itself has no SDK requirement beyond its target frameworks.

* We only raise the Roslyn baseline on major version changes.

## Testing

Testing with old frameworks which are not supported anymore is getting painful, we therefore only test with frameworks which are still in active support.
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ Funcky adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
* The `net11.0` asset also wraps the search overloads .NET 11 adds to `string`: `IndexOfOrNone` and `LastIndexOfOrNone`
for a `char` with a `StringComparison` and a start index or count, and both for a `Rune` in every shape the `char`
overloads come in.
* Breaking: the built-in analyzers and Funcky.Analyzers 3.0.0 are built against Roslyn 4.14 and ship a single
`roslyn4.14` asset. They load on Visual Studio 2022 17.14 and the .NET SDK 9.0.300 or newer, which covers every
.NET 10 SDK. The `roslyn3.7` asset of the built-in analyzers and the `roslyn4.4` asset of Funcky.Analyzers are gone;
an older SDK that supports analyzer versioning finds no compatible asset and silently skips the analyzers, and the
package targets remove them on SDKs without analyzer versioning (before .NET 6). The library itself keeps working on
those SDKs. `λ1010` no longer needs a separate note, it is part of the one asset.

## Funcky 3.8.0 | Funcky.Async 1.6.0 | Funcky.Xunit 2.3.0 | Funcky.Xunit.v3 1.1.0 | Funcky.Analyzers 2.1.0

Expand Down
Loading