Skip to content

TextColorToGenerator generates code referencing internal types from Microsoft.Maui.Controls, causing CS0122 #3160

@jfversluis

Description

@jfversluis

Description

The TextColorToGenerator source generator does not account for type accessibility when scanning the Microsoft.Maui.Controls assembly. This causes it to generate extension methods for internal (non-public) types, which results in CS0122 ("type is inaccessible due to its protection level") compile errors in consuming projects.

Root Cause

In TextColorToGenerator.cs, the GetMauiInterfaceImplementors method scans all namespace-level types in the Maui Controls assembly that implement ITextStyle and IAnimatable:

static IEnumerable<INamedTypeSymbol> GetMauiInterfaceImplementors(...)
{
    return mauiControlsAssemblySymbolProvider.GlobalNamespace.GetNamedTypeSymbols()
        .Where(x => x.AllInterfaces.Contains(itextStyleSymbol, SymbolEqualityComparer.Default)
            && x.AllInterfaces.Contains(iAnimatableSymbol, SymbolEqualityComparer.Default));
}

This does not filter by DeclaredAccessibility, so it picks up internal types too.

The GenerateMetadata method does set the generated extension class access modifier to internal for Maui types, but the generated code still references the original type by its fully qualified name (e.g., global::Microsoft.Maui.Controls.ContentLabel) in the method signature and body. Since that type is internal to the Maui Controls assembly, the generated code in the consuming project cannot compile.

Additionally, the GetClassAccessModifier helper only handles Public and Internal — it does not handle other accessibility levels and does not contribute to filtering out types that should not have code generated for them.

Steps to Reproduce

  1. Have a type with internal accessibility in the Microsoft.Maui.Controls namespace that implements both ITextStyle and IAnimatable (e.g., internal class ContentLabel : Label)
  2. Use CommunityToolkit.Maui in a project
  3. Build → CS0122 errors referencing the internal type in the generated TextColorTo extension

This was triggered by dotnet/maui#31940 which added an internal class ContentLabel : Label to Microsoft.Maui.Controls. See dotnet/maui#34512 for the original user report.

Suggested Fix

The GetMauiInterfaceImplementors method should filter out types that are not publicly accessible:

static IEnumerable<INamedTypeSymbol> GetMauiInterfaceImplementors(...)
{
    return mauiControlsAssemblySymbolProvider.GlobalNamespace.GetNamedTypeSymbols()
        .Where(x => x.DeclaredAccessibility == Accessibility.Public
            && x.AllInterfaces.Contains(itextStyleSymbol, SymbolEqualityComparer.Default)
            && x.AllInterfaces.Contains(iAnimatableSymbol, SymbolEqualityComparer.Default));
}

Workaround

A workaround was merged on the .NET MAUI side in dotnet/maui#34514, which moved ContentLabel from a top-level internal class to a nested (private) class so it is no longer visible to namespace-level scans. However, this is a workaround — the source generator should be resilient to non-public types in referenced assemblies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions