Skip to content
Merged
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
11 changes: 7 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,22 @@ dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = fie

# StyleCop Field Naming Rules

# All constant fields must be PascalCase
# All non-private constant fields must be PascalCase. Private constants are owned by
# 'private_static_fields_group' below - a field must be covered by exactly one rule, otherwise the
# same violation is reported once per matching rule.
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = non_private_static_field_style
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const

# All static readonly fields must be PascalCase
# All non-private static readonly fields must be PascalCase. Private static readonly fields are
# owned by 'private_static_fields_group' below (see the note on the constant rule above).
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = non_private_static_field_style
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly

Expand Down
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ Version detection logging is disabled by default. Set `VersionDetectionLogEnable
| `NamespacePrefix` | *(required)* | Root namespace prefix, e.g. `Acme`. Results in `Acme.MyProject`. |
| `DisableNamespacePrefixCheck` | `false` | Set to `true` to suppress the build error for missing `NamespacePrefix`. |
| `DisablePurviewStylePolicyValidation` | `false` | Set to `true` to stop the build failing (`PRSGD0006`-`PRSGD0009`) when the repository `.editorconfig` overrides the modifier policy, hides `IDE0040`/`IDE1006`, disables the Style category in bulk, weakens the `_camelCase` field-naming rule, or adds the accessibility rules to `NoWarn`. |
| `PurviewTestContextNoWarn` | `CA1002;CA1012;CA1034;CA1047;CA1050;CA1051;CA1062;CA1064;CA1515;CA1707` | Semicolon-fenced rule set exempted in test and shared-testing projects, so test classes stay public, `Method_Scenario_Expectation` names keep their underscores, and helpers need no null guards. Override before the SDK import to narrow or extend it. |
| `DisablePurviewTestContextRuleSet` | `false` | Set to `true` to make test and shared-testing projects enforce the production API-surface rules as well (the strict style contract applies either way). |
| `PurviewSharedTestingOutputType` | `Library` | Output type forced on `IsSharedTestingProject` projects. `Library` (default) keeps them helper libraries - with `IsTestProject`/`IsTestingPlatformApplication` cleared - which also keeps their fixtures out of `CA1515`'s Exe-only scope. Set to `Exe` before the SDK import to keep the test packages' executable/test-host shape instead. |
| `TargetFramework` | `net10.0` | Override the default TFM per-project or globally. Defaults to `netstandard2.0` for projects declaring `IsRoslynComponent=true`. |
| `IsRoslynComponent` | `false` | When explicitly `true`, applies source-generator defaults: a single `netstandard2.0` target, `LangVersion=latest`, `Nullable=enable`, `TreatWarningsAsErrors=true`, `Deterministic=true`, extended analyzer rules, SourceLink with `EmbedUntrackedSources=true`, compiler-generated output under the intermediate directory, no dependency file, telemetry exclusion, and package build output. Pack-time validation (`ValidateRoslynComponentCompilerSettings`) fails the pack if the compiler defaults are missing unless `DisableRoslynCompilerDefaultsValidation=true`. Roslyn development dependencies (`Microsoft.CodeAnalysis.*`, `Microsoft.CodeAnalysis.Analyzers`) default to `PrivateAssets="all"`. |
| `IsRoslynComponentOnly` | `true` for Roslyn components | Produces an analyzer-only package: `IncludeBuildOutput=false`, `IncludeSymbols=false`, and the analyzer assembly and portable PDB are packed under `analyzers/dotnet/cs/`. Set to `false` for a dual-role Roslyn component that uses normal library symbol packaging. |
Expand Down Expand Up @@ -542,13 +545,26 @@ deliberately not silenceable:
matches the language default (`private` inside a type, `internal` at namespace scope, `public` inside
an interface) is reported by `IDE0040` and must be **removed**. Omit the default modifier instead.
- Private instance fields must be `_camelCase`, never `camelCase` or `PascalCase`: the `_` prefix keeps
field access unambiguous, so the noisy `this.` qualifier is never needed. Constants and `static
readonly` fields stay PascalCase, and local constants stay camelCase.
field access unambiguous, so the noisy `this.` qualifier is never needed. Private constants and private
`static readonly` fields are type-level state and stay PascalCase; non-private constants and
`static readonly` fields follow the same PascalCase rule, and local constants stay camelCase.
- `CA1515` (public type in an application/test assembly) ships at **warning**, `CA1852` (seal internal
types) is no longer suppressed for internals exposed through `InternalsVisibleTo`, and `CA1034` is no
longer disabled for `Extensions/` files.
- Test projects are executables, so test classes must be non-public (`sealed class MyTests`, which is
`internal` by default) instead of `CA1515`/`CA1707`/`CA1062` being hidden through `NoWarn`.
longer disabled for `Extensions/` files. Project shapes whose public surface is mandated by a
framework are exempt by the SDK itself: Aspire hosts and CLI apps keep their nested public options
types, and test projects use the test-context rule set below.
- Test and shared-testing projects get a **test-context rule set** (`PurviewTestContextNoWarn`) that
exempts the production API-surface rules (`CA1002`, `CA1012`, `CA1034`, `CA1047`, `CA1050`, `CA1051`,
`CA1062`, `CA1064`, `CA1515`, `CA1707`), because test classes and fixtures are legitimately public,
test names use `Method_Scenario_Expectation`, helpers expose fields and take fixture parameters
without null guards, and abstract test bases have public constructors. Everything stylistic still
applies to tests (`IDE0040`, field naming, formatting, the `IDE1006` naming rules). Set
`DisablePurviewTestContextRuleSet=true` to enforce the production rules in tests as well, or override
`PurviewTestContextNoWarn` with your own semicolon-fenced list before the SDK import.
- Shared testing projects stay **libraries** even though their test packages request the test-host shape,
so their fixtures remain legitimate public API and `CA1515` does not apply to them at all. Use
`<PurviewSharedTestingOutputType>Exe</PurviewSharedTestingOutputType>` to opt back into the
package-driven executable.

`ValidatePurviewStylePolicy` runs before every C# compile and fails the build when a repository neuters
the policy:
Expand All @@ -557,7 +573,7 @@ the policy:
| -- | -- |
| `PRSGD0006` | `dotnet_style_require_accessibility_modifiers` is overridden with anything other than `omit_if_default`. |
| `PRSGD0007` | A policy rule (`IDE0040`, `CA1515`, `CA1852`, `CA1034`) is downgraded below warning, any policy rule is set to `none`/`silent`, or the `Style` category is disabled in bulk without an explicit `IDE0040` severity. |
| `PRSGD0008` | `IDE0040`, `CA1515`, `CA1852`, `CA1034`, `CA1012`, `CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, or `CA1707` is added to `NoWarn`. |
| `PRSGD0008` | `IDE0040`, `CA1515`, `CA1852`, `CA1034`, `CA1012`, `CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, or `CA1707` is added to `NoWarn` by the repository. Entries the SDK injects itself (the test-context rule set for test/shared-testing projects and `CA1515` for Aspire hosts and CLI apps) are ignored so the SDK's own context-aware defaults stay usable. |
| `PRSGD0009` | `IDE1006` is hidden, the private instance field rule is downgraded below warning, or the `_` prefix is removed from the field naming style. |

The validator walks the same `.editorconfig` chain as the compiler (nearest file wins, later entries
Expand Down
25 changes: 19 additions & 6 deletions docs/wiki/Analyzers.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,32 @@ The SDK ships the modifier/visibility **and field-naming** policy in `.editorcon
matches the language default (`private` inside a type, `internal` at namespace scope, `public` inside
an interface) is reported by `IDE0040` and must be removed.
- Private instance fields must be `_camelCase` (`_name`, never `name`): the `_` prefix keeps field
access unambiguous, so the noisy `this.` qualifier is never needed. Constants and `static readonly`
fields stay PascalCase, and local constants stay camelCase.
access unambiguous, so the noisy `this.` qualifier is never needed. Private constants and private
`static readonly` fields are type-level state and stay PascalCase; non-private constants and
`static readonly` fields follow the same rule, and local constants stay camelCase.
- `CA1515` (public type in an application/test assembly) ships at warning; `CA1852` (seal internal
types) is not suppressed for types exposed through `InternalsVisibleTo`; `CA1034` is not disabled for
`Extensions/` files; the API-surface rules `CA1062`/`CA1707` are not pre-suppressed for test projects.
- Test projects are executables, so their test classes must be non-public (`sealed class MyTests`,
`internal` by default) rather than the rules being hidden through `NoWarn`.
`Extensions/` files; the API-surface rules `CA1062`/`CA1707` are not pre-suppressed for repositories.
Where the public surface is framework-mandated the SDK exempts itself: Aspire hosts and CLI apps keep
their nested public options types (Spectre.Console settings, `[ZodSchema]` resource-kit options), and
test projects use the test-context rule set below. Both exemptions are recorded so `PRSGD0008`
accepts them while still rejecting repository-authored silencing.
- Test and shared-testing projects are **context aware**: they enforce the same strict style contract as
the rest of the repository (`IDE0040`, field naming, formatting, the `IDE1006` naming rules) but not
the production API-surface rules. `PurviewTestContextNoWarn` exempts `CA1002`, `CA1012`, `CA1034`,
`CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, `CA1515` and `CA1707`, because test classes and
fixtures are legitimately public, test names use `Method_Scenario_Expectation`, helpers expose fields
and take fixture parameters without null guards, and abstract test bases have public constructors.
`DisablePurviewTestContextRuleSet=true` opts a repository into the production rules for tests too.
- Shared testing projects are helper **libraries** (their test packages request the test-host shape, and
the SDK reasserts `OutputType=Library` after package props). Their fixtures stay public API, which is
also why `CA1515` does not apply to them; `PurviewSharedTestingOutputType=Exe` opts back in.

| Code | Reported when |
| -- | -- |
| `PRSGD0006` | `dotnet_style_require_accessibility_modifiers` is set to anything other than `omit_if_default`. |
| `PRSGD0007` | A policy rule is downgraded below warning (`IDE0040`, `CA1515`, `CA1852`, `CA1034`), any policy rule is set to `none`/`silent`, or the `Style` category is disabled in bulk without an explicit `IDE0040` severity. |
| `PRSGD0008` | One of the accessibility rules (`IDE0040`, `CA1515`, `CA1852`, `CA1034`, `CA1012`, `CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, `CA1707`) is added to `NoWarn`. |
| `PRSGD0008` | One of the accessibility rules (`IDE0040`, `CA1515`, `CA1852`, `CA1034`, `CA1012`, `CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, `CA1707`) is added to `NoWarn` by the repository. Entries the SDK injects itself (the test-context rule set, `CA1515` for Aspire hosts and CLI apps) are ignored. |
| `PRSGD0009` | `IDE1006` is hidden, the private instance field naming rule is downgraded below warning, or the `_` prefix is removed from the field naming style. |

Opt out with `<DisablePurviewStylePolicyValidation>true</DisablePurviewStylePolicyValidation>`. A stale
Expand Down
7 changes: 5 additions & 2 deletions docs/wiki/Configuration-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ See [Version Detection](Version-Detection.md) for the full resolution rules.
| -- | -- | -- |
| `NamespacePrefix` | *(required)* | Root namespace prefix, e.g. `Acme`. Results in `Acme.MyProject`. |
| `DisableNamespacePrefixCheck` | `false` | Set to `true` to suppress the build error for missing `NamespacePrefix`. |
| `DisablePurviewStylePolicyValidation` | `false` | Set to `true` to stop `ValidatePurviewStylePolicy` failing the build (`PRSGD0006`-`PRSGD0009`) when the repository `.editorconfig` overrides `dotnet_style_require_accessibility_modifiers`, hides `IDE0040`/`IDE1006`, disables the Style category in bulk, weakens the `_camelCase` private instance field rule, or adds the accessibility rules to `NoWarn`. See [Style policy](Analyzers.md#style-policy). |
| `DisablePurviewStylePolicyValidation` | `false` | Set to `true` to stop `ValidatePurviewStylePolicy` failing the build (`PRSGD0006`-`PRSGD0009`) when the repository `.editorconfig` overrides `dotnet_style_require_accessibility_modifiers`, hides `IDE0040`/`IDE1006`, disables the Style category in bulk, weakens the `_camelCase` private instance field rule, or adds the accessibility rules to `NoWarn`. Entries the SDK injects itself (the test-context rule set, `CA1515` for Aspire hosts and CLI apps) are ignored. See [Style policy](Analyzers.md#style-policy). |
| `PurviewTestContextNoWarn` | `CA1002;CA1012;CA1034;CA1047;CA1050;CA1051;CA1062;CA1064;CA1515;CA1707` | Production API-surface rules exempted in test and shared-testing projects (they keep the strict style contract). Override before the SDK import to narrow or extend the list. |
| `DisablePurviewTestContextRuleSet` | `false` | Set to `true` to make test and shared-testing projects enforce the production API-surface rules as well. |
| `PurviewSharedTestingOutputType` | `Library` | Output type forced on `IsSharedTestingProject` projects; `Library` also clears `IsTestProject`/`IsTestingPlatformApplication`. Set to `Exe` before the SDK import to keep the test packages' executable/test-host shape. |
| `TargetFramework` | `net10.0` | Override the default TFM per-project or globally. Defaults to `netstandard2.0` for projects declaring `IsRoslynComponent=true`. |
| `IsRoslynComponent` | `false` | When explicitly `true`, applies source-generator defaults: a single `netstandard2.0` target, `LangVersion=latest`, `Nullable=enable`, `TreatWarningsAsErrors=true`, `Deterministic=true`, extended analyzer rules, SourceLink with `EmbedUntrackedSources=true`, compiler-generated output under the intermediate directory, no dependency file, symbol packaging (`IncludeSymbols=false` by default), telemetry exclusion, and package build output. Packable Roslyn components automatically pack the built analyzer assembly and its PDB into `analyzers/dotnet/cs/` (`PurviewPackAnalyzerPdb=true`; set `false` only when symbols are delivered another way — NuGet's `.snupkg` cannot host `analyzers/dotnet/cs` symbols). Pack-time validation (`ValidateRoslynComponentCompilerSettings`) fails the pack if the compiler defaults are missing unless `DisableRoslynCompilerDefaultsValidation=true`. Roslyn development dependencies (`Microsoft.CodeAnalysis.*`, `Microsoft.CodeAnalysis.Analyzers`) default to `PrivateAssets="all"`. |
| `PackProjectReferencedSourceGenerators` | `true` | Automatically packs analyzer `ProjectReference` outputs and their runtime dependencies under `analyzers/dotnet/cs/`. Set to `false` to opt out; set `Pack="false"` on an individual reference to exclude only that generator. |
Expand Down Expand Up @@ -154,7 +157,7 @@ read them through `build_property.<PropertyName>`:
| `AutoIncludeUsings` | Controls SDK-added global usings. |
| `IsCSharpProject` | True when the project is a `.csproj`. |
| `IsTestProject` | True when project name ends with a supported test suffix. |
| `IsSharedTestingProject` | True for known shared testing helper project names. |
| `IsSharedTestingProject` | True for known shared testing helper project names; the project is forced to `OutputType=Library` (see `PurviewSharedTestingOutputType`). |
| `TestingType` | Detected test category suffix from project name. |
| `TargetProjectName` | Inferred target project name for test projects. |
| `IsContainerProject` | True when Dockerfile markers indicate container defaults. |
Expand Down
8 changes: 8 additions & 0 deletions docs/wiki/Project-Type-Detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ targets.
### Test projects (`IsTestProject=true`)

- `OutputType=Exe` when the testing framework is not `None`.
- A **test-context rule set** (`PurviewTestContextNoWarn`): the production API-surface rules
(`CA1002`, `CA1012`, `CA1034`, `CA1047`, `CA1050`, `CA1051`, `CA1062`, `CA1064`, `CA1515`, `CA1707`)
are exempt, while the strict style contract (`IDE0040`, field naming, formatting, `IDE1006` naming
rules) still applies. `DisablePurviewTestContextRuleSet=true` enforces the production rules instead.
- `CollectCoverage=true` with coverage exclusions for framework and mocking packages.
- `IsPackable=false`, `IsPublishable=false`, `MaxCpuCount=0`.
- Disabled native instrumentation by default.
Expand All @@ -44,6 +48,10 @@ targets.
- Test package references, but not the test runner or coverage settings.
- A `[Skip]` attribute (TUnit) so the shared assembly is never executed directly.
- `TUnit.Core` instead of the full `TUnit` package.
- `OutputType=Library` with `IsTestProject`/`IsTestingPlatformApplication` cleared, reasserted after the
package props (which otherwise flip the project into an executable test host). The fixtures are consumed
by the test assemblies, so staying a library avoids `CA1515` (which only targets executables). Set
`PurviewSharedTestingOutputType=Exe` before the SDK import to keep the package-driven test-host shape.

### Shared projects (`IsSharedProject=true`)

Expand Down
Loading
Loading