Skip to content

Fix AsSelector throwing on types with only non-public constructors#9998

Merged
michaelstaib merged 2 commits into
mainfrom
mst/fix-AsSelector
Jun 29, 2026
Merged

Fix AsSelector throwing on types with only non-public constructors#9998
michaelstaib merged 2 commits into
mainfrom
mst/fix-AsSelector

Conversation

@michaelstaib

@michaelstaib michaelstaib commented Jun 29, 2026

Copy link
Copy Markdown
Member

Closes #9666

Copilot AI review requested due to automatic review settings June 29, 2026 09:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a failure in SelectionExpressionBuilder where AsSelector<T> could throw for entity types that can’t be reconstructed via public constructors / public setters (notably types with only non-public constructors), by falling back to reusing the source instance instead of throwing.

Changes:

  • Changed projection expression generation to return the source instance (context.Parent) as a last-resort fallback rather than throwing InvalidOperationException.
  • Added a regression test covering projection with AsSelector over a type that has only private constructors and private setters.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/HotChocolate/Data/test/Data.Tests/ResolveWithProjectionTests.cs Adds a regression test ensuring AsSelector works for types with only private constructors.
src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs Replaces the throw-on-unconstructable-types behavior with a safe identity/reuse fallback.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Patch coverage

73.5% of changed lines covered (1226/1669)

File Covered Changed Patch %
…/Core/src/Types/Execution/Options/NodeIdSerializerOptions.cs 0 1 0.0% 🔴
…/Core/src/Types/Types/Descriptors/UnionTypeDescriptor.cs 0 1 0.0% 🔴
src/Mocha/src/Mocha.Abstractions/MessagingModuleAttribute.cs 0 1 0.0% 🔴
…/Mocha/src/Mocha.Abstractions/MessagingModuleInfoAttribute.cs 0 3 0.0% 🔴
…/Mocha.Analyzers/Models/ImportedMediatorModuleTypesInfo.cs 0 5 0.0% 🔴
…/Mocha/src/Mocha.Analyzers/Models/ImportedModuleTypesInfo.cs 0 6 0.0% 🔴
…/Mocha.Mediator.Abstractions/MediatorModuleInfoAttribute.cs 0 2 0.0% 🔴
…/src/Mocha.Transport.Postgres/Tasks/QueueMonitoringTask.cs 0 9 0.0% 🔴
…/Mocha/src/Mocha/Configuration/MessagingSagaConfiguration.cs 0 2 0.0% 🔴
…/Mocha.Analyzers/Inspectors/ImportedModuleTypeInspector.cs 2 54 3.7% 🔴
…/Inspectors/ImportedMediatorModuleTypeInspector.cs 2 51 3.9% 🔴
…/Language/src/Language.Visitors/SyntaxWalker.Enter.cs 1 3 33.3% 🔴
…/Language/src/Language.Visitors/SyntaxWalker.Leave.cs 1 3 33.3% 🔴
…/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs 1 3 33.3% 🔴
…/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs 1 3 33.3% 🔴
src/Mocha/src/Mocha.Analyzers/KnownTypeSymbols.cs 1 3 33.3% 🔴
…/src/Mocha/Extensions/IMessageBusHostBuilderExtensions.cs 4 12 33.3% 🔴
…/Mocha.Analyzers/Inspectors/CallSiteMessageTypeInspector.cs 60 140 42.9% 🔴
src/Mocha/src/Mocha/Serialization/MessageTypeRegistry.cs 4 9 44.4% 🔴
src/Mocha/src/Mocha.Analyzers/MediatorGenerator.cs 49 109 45.0% 🔴

+65 more changed files; see the JSON below for uncovered lines.

Uncovered changed lines (JSON)
{
  "sha": "a7d6efd2367555e859476ba17329bfa8e6492079",
  "files": [
    { "path": "src/HotChocolate/Core/src/Types/Execution/Options/NodeIdSerializerOptions.cs", "ranges": [[56, 56]] },
    { "path": "src/HotChocolate/Core/src/Types/Types/Descriptors/UnionTypeDescriptor.cs", "ranges": [[95, 95]] },
    { "path": "src/Mocha/src/Mocha.Abstractions/MessagingModuleAttribute.cs", "ranges": [[31, 31]] },
    { "path": "src/Mocha/src/Mocha.Abstractions/MessagingModuleInfoAttribute.cs", "ranges": [[14, 14], [19, 19], [24, 24]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/ImportedMediatorModuleTypesInfo.cs", "ranges": [[17, 20], [23, 23]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/ImportedModuleTypesInfo.cs", "ranges": [[20, 24], [27, 27]] },
    { "path": "src/Mocha/src/Mocha.Mediator.Abstractions/MediatorModuleInfoAttribute.cs", "ranges": [[14, 14], [19, 19]] },
    { "path": "src/Mocha/src/Mocha.Transport.Postgres/Tasks/QueueMonitoringTask.cs", "ranges": [[26, 34]] },
    { "path": "src/Mocha/src/Mocha/Configuration/MessagingSagaConfiguration.cs", "ranges": [[15, 15], [20, 20]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Inspectors/ImportedModuleTypeInspector.cs", "ranges": [[47, 48], [50, 52], [55, 55], [57, 60], [64, 68], [71, 73], [75, 79], [82, 88], [90, 92], [95, 102], [104, 111], [113, 113], [115, 116]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Inspectors/ImportedMediatorModuleTypeInspector.cs", "ranges": [[48, 49], [51, 53], [56, 56], [58, 61], [65, 69], [72, 73], [75, 79], [82, 87], [89, 91], [94, 101], [103, 109], [111, 111], [113, 114]] },
    { "path": "src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Enter.cs", "ranges": [[282, 282], [287, 287]] },
    { "path": "src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker.Leave.cs", "ranges": [[283, 283], [288, 288]] },
    { "path": "src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Enter.cs", "ranges": [[284, 284], [289, 289]] },
    { "path": "src/HotChocolate/Language/src/Language.Visitors/SyntaxWalker~1.Leave.cs", "ranges": [[283, 283], [288, 288]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/KnownTypeSymbols.cs", "ranges": [[149, 149], [155, 155]] },
    { "path": "src/Mocha/src/Mocha/Extensions/IMessageBusHostBuilderExtensions.cs", "ranges": [[86, 89], [103, 106]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Inspectors/CallSiteMessageTypeInspector.cs", "ranges": [[47, 48], [55, 56], [61, 62], [73, 76], [80, 83], [86, 86], [110, 111], [113, 114], [119, 119], [125, 134], [137, 137], [142, 143], [176, 176], [180, 181], [196, 197], [199, 199], [202, 202], [205, 206], [208, 209], [211, 211], [218, 220], [223, 226], [229, 232], [235, 239], [245, 246], [248, 250], [254, 256], [259, 262], [265, 269], [277, 278]] },
    { "path": "src/Mocha/src/Mocha/Serialization/MessageTypeRegistry.cs", "ranges": [[63, 67]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/MediatorGenerator.cs", "ranges": [[122, 122], [163, 166], [169, 169], [171, 175], [177, 177], [179, 180], [280, 288], [312, 313], [347, 347], [349, 355], [358, 367], [370, 386]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/AotPublishInfo.cs", "ranges": [[12, 12]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/SagaInfo.cs", "ranges": [[11, 11]] },
    { "path": "src/Mocha/src/Mocha/Builder/MessageBusBuilder.cs", "ranges": [[89, 89], [171, 177], [225, 231], [254, 255], [257, 257], [259, 265], [459, 461]] },
    { "path": "src/HotChocolate/Core/src/Types/Internal/TypeExtensionHelper.cs", "ranges": [[29, 31]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/ContextOnlyMessageInfo.cs", "ranges": [[21, 21], [24, 24]] },
    { "path": "src/Mocha/src/Mocha/Sagas/State/Serialization/JsonSagaStateSerializerFactory.cs", "ranges": [[38, 42]] },
    { "path": "src/Mocha/src/Mocha/Serialization/JsonMessageSerializerFactory.cs", "ranges": [[40, 44]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/JsonContextSerializableTypesInfo.cs", "ranges": [[19, 19]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Inspectors/MessagingHandlerInspector.cs", "ranges": [[99, 102]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/MessagingGenerator.cs", "ranges": [[193, 194], [205, 205], [207, 207], [262, 264], [315, 318], [328, 329], [336, 337], [342, 343], [347, 348], [403, 406], [497, 502], [512, 515], [517, 526], [532, 533], [564, 566], [569, 571], [602, 604], [632, 637], [705, 707], [717, 719]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Models/CallSiteMessageTypeInfo.cs", "ranges": [[23, 23]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Generators/MessagingDependencyInjectionGenerator.cs", "ranges": [[37, 37], [74, 78], [80, 83], [85, 89], [117, 119], [132, 132], [139, 139], [200, 201]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Filters/InvocationCallSiteFilter.cs", "ranges": [[28, 28], [30, 30]] },
    { "path": "src/HotChocolate/Core/src/Execution.Projections/SelectionExpressionBuilder.cs", "ranges": [[322, 322]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/FileBuilders/MessagingDependencyInjectionFileBuilder.cs", "ranges": [[214, 219]] },
    { "path": "src/Mocha/src/Mocha.Analyzers/Inspectors/HandlerInspector.cs", "ranges": [[131, 131]] }
  ]
}

Project coverage: 52.4% (216249/412357 lines)

@michaelstaib michaelstaib merged commit c2eeaa4 into main Jun 29, 2026
147 checks passed
@michaelstaib michaelstaib deleted the mst/fix-AsSelector branch June 29, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants