Skip to content

RMG012 emitted for getter-only target properties when queryable projection exists #2226

Description

@Demivan

Please do the checklist before filing an issue:

  • I have read the documentation, including the FAQ
  • I can reproduce the bug using the latest prerelease version
  • I have searched existing discussion and issue to avoid duplicates

Describe the bug

When a mapper class contains both a queryable projection method (IQueryable<A> -> IQueryable<B>) and a regular mapping method (A -> B) targeting a type with getter-only properties (expression-bodied or { get; } without a setter), Mapperly incorrectly emits RMG012 for those read-only properties on the regular mapping method.

Without the queryable projection method, no diagnostic is emitted (correct behavior). The presence of the projection triggers the false positive.

Repro
A link to a repro Gist or GitHub repository or a link to a Mapperly fork with a failing test.

Declaration code

public class A
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class B
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    // Computed property - no setter, cannot be mapped to
    public string FullName => $"{FirstName} {LastName}";
}

[Mapper]
public static partial class MyMapper
{
    // Having this projection method triggers the bug
    public static partial IQueryable<B> ProjectToB(this IQueryable<A> q);

    // RMG012: The member FullName on the mapping target type B
    // was not found on the mapping source type A
    public static partial B MapToB(this A source);
}

Removing the ProjectToB projection method eliminates the false RMG012 diagnostic on MapToB.

Actual relevant generated code

// The generated mapping code is correct (FullName is not assigned),
// but a spurious RMG012 warning is emitted for FullName.
public static partial B MapToB(this A source)
{
    var target = new B();
    target.FirstName = source.FirstName;
    target.LastName = source.LastName;
    return target;
}

Expected relevant generated code

// Same generated code, but without the RMG012 diagnostic for FullName.
public static partial B MapToB(this A source)
{
    var target = new B();
    target.FirstName = source.FirstName;
    target.LastName = source.LastName;
    return target;
}

Reported relevant diagnostics

  • RMG012: The member FullName on the mapping target type B was not found on the mapping source type A

Environment (please complete the following information):

  • Mapperly Version: 5.0.0-next.4 (also reproducible on current main)
  • Nullable reference types: enabled
  • .NET Version: .NET 10.0
  • Target Framework: net10.0

Additional context
I will create a fix PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions