Skip to content

BRO1312: Namespace names should begin with an upper-case letter

Every part of a namespace name is PascalCase: MyCompany.Billing, not myCompany.billing. Replaces StyleCop SA1300 for namespaces (BRO1309 covers the other elements). Off by default: renaming a namespace renames every type in it.

Example

root = true

[*.cs]
dotnet_diagnostic.BRO1312.severity = warning

Before

namespace myCompany.billing
{
    internal class Invoice
    {
    }
}

namespace myCompany.web
{
    using myCompany.billing;

    internal class InvoicePage
    {
        public Invoice Current { get; } = new Invoice();
    }
}

After

namespace MyCompany.Billing
{
    internal class Invoice
    {
    }
}

namespace MyCompany.Web
{
    using MyCompany.Billing;

    internal class InvoicePage
    {
        public Invoice Current { get; } = new Invoice();
    }
}

Why

Namespaces are PascalCase everywhere in .NET, and a lower-case part stands out in every using directive.

How the fix works

Like StyleCop, each part of every namespace declaration is reported. The fix renames the part everywhere in the solution at once: every declaration (block and file-scoped), using directives of every kind (global using, using static, aliases), qualified names (global:: included) and crefs. It's all or nothing: when one place can't be renamed safely, nothing is.

Renaming a namespace changes the full name of every type in it. That's a breaking change for code outside the solution, and for anything that stored a type name: Type.GetType("myCompany.billing.Invoice"), Json.NET's $type, configuration files that name types. The fix leaves the namespace alone when a string in the solution or an additional file (Razor, XAML) contains its name, but it can't see stored data or other repositories. Files and folders aren't renamed (dotnet format only changes file contents).

Configuration

[*.cs]
# Parts that keep their casing, like StyleCop's allowedNamespaceComponents.
stylebro_allowed_namespace_components = eBay, iOS

stylebro_rename_public_api = true also renames names other assemblies see (default false, see Not reported; the owner's decision in decisions.md).

Not reported

  • Where IDE1006 is suppressed: after #pragma warning disable IDE1006 (up to its restore), or with [SuppressMessage("Style", "IDE1006")] on the declaration, its member or type, or a global one targeting them. Code that opts out of the SDK's naming rules (a file copied from another project) keeps its names.
  • A new name your SDK naming rule rejects: when the first dotnet_naming_rule that covers the symbol is enforced (IDE1006, or the rule's own severity, at suggestion or above) and asks for another style, like _camelCase for private properties, the name stays (renaming it would only trade this warning for IDE1006).
  • Public API (unless stylebro_rename_public_api = true): Namespaces that hold such a type (directly or in a namespace inside them) that other assemblies see, that is public, protected or protected internal in types that are visible too. Renaming them breaks code outside the solution. Internal code is renamed, also with InternalsVisibleTo.
  • Allowed components (stylebro_allowed_namespace_components): brand names like iText, iOS, eBay.
  • The project's root namespace or a part of it (RootNamespace, by default the project name). Embedded resource names start with the root namespace, not with the declared one, so GetManifestResourceStream(typeof(T).Namespace + ".data.json") would stop finding its resource, and new files and regenerated designer files would get the old casing again. Rename the project (or set RootNamespace) first; the declarations then follow on the next run.
  • A namespace another assembly also declares, inside it included (a package's myCompany.common next to your myCompany.data): the other assembly keeps its name. A namespace that two projects of the solution share is reported in the project that doesn't see the other's part, and the fix renames both.
  • A namespace declared in generated code (.designer.cs, .g.cs, <auto-generated>): the generator writes it again.
  • The new name already exists in the containing namespace (MyCompany next to myCompany, or a type named Billing).

Reported but not fixed

If dotnet format leaves a finding, StyleBro kept it on purpose. The fix looks at the whole solution, other projects included, which the analyzer can't see, and leaves a change that would break something there: the name in a string or a nameof (reflection, serialization), a member that would hide it, a use in generated code. It offers no code action for such a finding, and stylebro-migrate format lists each one with its reason (Findings kept on purpose); its --verify-no-changes doesn't fail on them. Change it by hand only after checking those uses, or suppress it or record it in the baseline.

  • The full name appears in a string anywhere in the solution, or in an additional file.
  • The part appears in disabled #if code.
  • A reference is in generated code, like a Razor component's @using.
  • Another project gets part of the namespace from a library outside the solution.
  • The new name already means something: in another project's containing namespace, where a reference looks the part up by its simple name, or for code inside the containing namespace that uses the new name for a type or alias (it would find the renamed namespace first).

Rename these by hand, or suppress the warning.

Compared with StyleCop

Same positions as StyleCop, minus the cases under "Not reported" (StyleCop has no such skips; its allowedNamespaceComponents is stylebro_allowed_namespace_components, and stylebro-migrate carries it over). StyleCop's fix renames only the one declaration it's on, which leaves every other file's declarations and using directives behind (the code doesn't compile until all are renamed).