You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# We additionally restore during the build because the Microsoft.DotNet.Build.Tasks.Feed package only restores when we pass `-publish`. See https://github.com/dotnet/arcade/blob/37ccfd66358af6a37a0ec385ec31d1d71bdd8723/src/Microsoft.DotNet.Arcade.Sdk/tools/Tools.proj#L61-L66
Copy file name to clipboardExpand all lines: src/roslyn/docs/contributing/Localization In Compiler Tests.md
+32-17Lines changed: 32 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,25 +3,25 @@ Localization in Compiler Tests
3
3
4
4
The compiler tests are structured such that they can be run on a machine using any locale. This
5
5
both serves as a tool to ensure the compiler does not have any localization errors but also to
6
-
ensure that developers from any locale can contribute to the project. The ability to build and
6
+
ensure that developers from any locale can contribute to the project. The ability to build and
7
7
execute tests should not be limited to English speaking developers.
8
8
9
-
Our infrastructure runs the compiler test suite on `es-ES` machines for both .NET Core and .NET
10
-
Framework. This helps us ensure that compiler tests can be authored and executed on non-English
9
+
Our infrastructure runs the compiler test suite on `es-ES` machines for both .NET Core and .NET
10
+
Framework. This helps us ensure that compiler tests can be authored and executed on non-English
11
11
machines without issues.
12
12
13
13
## How it works
14
-
To ensure that our tests run on any locale there is a general approach that is followed in the vast
15
-
majority of our tests.
14
+
To ensure that our tests run on any locale there is a general approach that is followed in the vast
15
+
majority of our tests.
16
16
17
17
1. All expected baselines are expressed in invariant culture. That means that say `decimal` values are expressed using `.` separators not `,`.
18
18
2. All generated baselines, usually via `Console.Writeline` inside `CompileAndVerify`, must be generated such that they produce output in invariant culture.
19
-
3. Diagnostic tests use the `VerifyDiagnostics` helpers using `en-US` values for the messages. The implementation of `VerifyDiagnostics` will request the diagnostic message in the `en-US` culture.
19
+
3. Diagnostic tests use the `VerifyDiagnostics` helpers using `en-US` values for the messages. The implementation of `VerifyDiagnostics` will request the diagnostic message in the `en-US` culture.
20
20
This helps ensure the compiler has no localization product issues by forcing a consistent culture no matter the current culture of the system.
21
21
22
-
The largest source of friction that developers encounter when authoring tests is passing values to
23
-
`Console.WriteLine` that have locale dependent representations. For example `double` and `decimal`
24
-
values.
22
+
The largest source of friction that developers encounter when authoring tests is passing values to
23
+
`Console.WriteLine` that have locale dependent representations. For example `double` and `decimal`
There are a few cases where it is very difficult to avoid locale dependent values. These include:
44
+
There are a few cases where it is very difficult to avoid locale dependent values. These include:
45
45
46
-
1. When a diagnostic includes a message from a thrown exception.
46
+
1. When a diagnostic includes a message from a thrown exception.
47
47
2. When a diagnostic includes a message from the underlying OS.
48
-
3. When a message is generated by a tool such as `msbuild`.
48
+
3. When a message is generated by a tool such as `msbuild`.
49
49
50
-
In those cases the message is likely to be locale dependent. Tests that have these values should be
50
+
In those cases the message is likely to be locale dependent. Tests that have these values should be
51
51
marked is `[ConditionalFact(typeof(IsEnglishLocal))]` so they run on `en-US` machines only.
52
52
53
53
## Infrastructure
54
-
The Spanish machines used in our infrastructure execute with `CurrentCulture` set to `es-ES` but
55
-
`CurrentUICulture` set to `en-US`. This configuration means that roughly string formatting happens
56
-
with `es-ES` but resource lookups happen with `en-US`. This setup doesn't fully test our code base
54
+
### Windows
55
+
The Spanish Windows machines used in our infrastructure execute with `CurrentCulture` set to `es-ES` but
56
+
`CurrentUICulture` set to `en-US`. This configuration means that roughly string formatting happens
57
+
with `es-ES` but resource lookups happen with `en-US`. This setup doesn't fully test our code base
57
58
so our test infrastructure will force the `CurrentUICulture` to be `CurrentCulture` when the two
58
59
differ.
60
+
61
+
This is done in the `TestBase` constructor, which all compiler test classes inherit from. When `CurrentUICulture` does not equal `CurrentCulture`, the constructor saves the original `CurrentUICulture`
62
+
and sets `CurrentUICulture` to `CurrentCulture`. The original value is restored in `Dispose` so the
63
+
change is scoped to the lifetime of each test instance. This ensures that on a Windows machine configured
64
+
with `CurrentCulture = es-ES` and `CurrentUICulture = en-US`, resource string lookups also happen in
65
+
`es-ES`, fully exercising the localization paths.
66
+
67
+
### Linux
68
+
The Spanish Linux machines used in our infrastructure run on Ubuntu with the `LC_ALL` environment
69
+
variable set to `es_ES.UTF-8`. On .NET running on Linux, `LC_ALL` determines both `CurrentCulture`
70
+
and `CurrentUICulture`. This means that unlike the Windows configuration, both string formatting and
71
+
resource lookups will use `es-ES`. Because both culture values are already
72
+
the same, the test infrastructure does not need to force `CurrentUICulture` to `CurrentCulture` on
This document describes how consumers should acquire the **Microsoft.CodeAnalysis.* (Roslyn) analyzer packages** over time, and why the acquisition model changes across major versions.
4
+
5
+
## Goals
6
+
7
+
1.**Reliable analyzer execution**: analyzers should run on a compiler/host that they are compatible with.
8
+
2.**Lower maintenance cost**: reduce long-term burden of supporting extremely old compiler hosts.
9
+
3.**Simpler acquisition**: move from “add NuGet packages” toward “enable via MSBuild properties”, where possible.
10
+
4.**Version alignment**: analyzers should be **version-matched to the compiler** that executes them.
11
+
12
+
---
13
+
14
+
## Recommended guidance
15
+
16
+
### If you need maximum host compatibility
17
+
- Prefer **<= 3.11.0** analyzer packages built from `dotnet/roslyn-analyzer`, especially when builds must run on older compilers/hosts.
18
+
19
+
### If you are on modern SDKs and want the newest analyzer line
20
+
- Use **5.0+** analyzer packages, ensuring your build uses the **.NET 9 SDK or higher**.
21
+
22
+
### Plan for the SDK-based future
23
+
- Expect a transition from `PackageReference`-based acquisition to **SDK-provided analyzers** enabled by configuration properties.
24
+
- Prefer central configuration (for example, `Directory.Build.props`) to ease future migration.
25
+
26
+
---
27
+
28
+
## Background and timeline
29
+
30
+
### Analyzer packages <= 3.11.0
31
+
32
+
For package versions **less than or equal to 3.11.0**:
33
+
34
+
- The analyzer packages were built from the **`dotnet/roslyn-analyzer`** repository.
35
+
- These versions were designed to support running on **very old Roslyn compilers and compiler hosts** (for example, older Visual Studio / older SDK toolsets).
36
+
- This required significant **backwards-compatibility code and testing**, increasing maintenance overhead.
37
+
38
+
**Implication for consumers:** these packages were broadly compatible with older toolchains, making them a good choice when analyzer execution had to work across older environments.
39
+
40
+
---
41
+
42
+
### Analyzer packages 5.0+ (post-merge into dotnet/roslyn)
43
+
44
+
The **`dotnet/roslyn-analyzer`** repository was merged into **`dotnet/roslyn`**. As part of that consolidation:
45
+
46
+
- A large amount of the special-case compatibility logic for very old hosts was **removed** to reduce maintenance burden.
47
+
- The newer packages adopt a compatibility posture aligned with modern SDK/compiler shipping.
48
+
49
+
For the new **5.0** packages:
50
+
51
+
- They **require the compiler from Visual Studio 17.12/.NET 9 SDK or higher**.
52
+
53
+
**Implication for consumers:** using 5.0 analyzers assumes your build uses a sufficiently new compiler/SDK. If your build environment is older, these analyzers are not a supported choice.
54
+
55
+
---
56
+
57
+
## Current acquisition model (today)
58
+
59
+
Today, acquisition is typically done via **NuGet PackageReference**, for example:
60
+
61
+
- Add analyzer packages to a project (`.csproj`) or centrally in `Directory.Build.props`.
62
+
- Ensure the build environment uses a compiler/SDK new enough to run that analyzer version (notably for 5.0+).
63
+
64
+
This model works but has downsides:
65
+
66
+
- Consumers must discover and choose package versions.
67
+
- Version skew can happen: analyzers may be newer/older than the compiler executing them.
68
+
- Upgrading analyzers can implicitly require upgrading the SDK/compiler host.
69
+
70
+
---
71
+
72
+
## Future direction: ship analyzers in the .NET SDK
73
+
74
+
The long-term goal is to ship these analyzer packages **in the .NET SDK**. Currently Roslyn ships their CodeStyle analyzers in the SDK. Consumers opt-in to using them via the `EnforceCodeStyleInBuild` property.
75
+
76
+
### Why this is better
77
+
78
+
When analyzers ship in the SDK:
79
+
80
+
- The analyzers can be **version-matched to the compiler** automatically.
81
+
- The acquisition experience becomes simpler:
82
+
- instead of adding `PackageReference`, you enable analyzers by setting **MSBuild properties** in your `.csproj` or `Directory.Build.props`.
83
+
- The SDK can ensure the analyzer/compiler pairing is known-good, reducing compatibility surprises.
84
+
85
+
### What this will look like for consumers
86
+
87
+
Conceptually, consumers will move from:
88
+
89
+
- “Add analyzer packages via NuGet”
90
+
91
+
to:
92
+
93
+
- “Enable analyzers via properties”
94
+
95
+
configured in one of:
96
+
97
+
- a project file (`.csproj`)
98
+
-`Directory.Build.props` (recommended for repository-wide policy)
99
+
100
+
*(Exact property names and final UX may evolve as the SDK integration is finalized.)*
0 commit comments