Commit 6ed2bb2
[MEVD] Fix VectorStoreKeyAttribute.IsAutoGenerated to be usable as a compile-time attribute argument (#13698)
### Motivation and Context
`VectorStoreKeyAttribute.IsAutoGenerated` was typed as `bool?`, which C#
does not permit as a compile-time attribute argument. This made the
following valid-looking code fail to compile:
```csharp
[VectorStoreKey(StorageName = "name", IsAutoGenerated = true)]
public Guid Key { get; set; }
```
### Description
- **`VectorStoreKeyAttribute.IsAutoGenerated`**: Changed from `public
bool?` to a `public bool` property. Its setter stores the value into a
new `internal bool? IsAutoGeneratedNullable` backing property. The
getter returns `IsAutoGeneratedNullable.GetValueOrDefault()` rather than
throwing; an inline comment explains this is a workaround for the C#
compiler restriction that prevents `Nullable<bool>` from being used as a
compile-time attribute argument. The `bool?` backing preserves the "not
explicitly set" vs. "explicitly set" distinction the framework relies
on.
- **`CollectionModelBuilder`**: Updated to read
`keyAttribute.IsAutoGeneratedNullable` (the `bool?` backing) instead of
the former `bool?` public property, keeping the existing `??
SupportsKeyAutoGeneration(...)` fallback behaviour intact.
- **`KernelFunctionFromMethod`**: Fixed a pre-existing operator
precedence bug in a pattern match expression (`value is not JsonElement
or JsonDocument or JsonNode`) that caused CS9336 redundant-pattern
errors on the .NET 10 compiler. Added parentheses to correctly express
the intended negation of all three types: `value is not (JsonElement or
JsonDocument or JsonNode)`.
- **`CollectionModelBuilderTests`**: Added four new unit tests covering
all `IsAutoGenerated` attribute scenarios: explicitly set to `true`,
explicitly set to `false`, omitted on a `Guid` key (fallback to
`SupportsKeyAutoGeneration` returns `true`), and omitted on an `int` key
(fallback returns `false`).
```csharp
// Now compiles and works correctly
[VectorStoreKey(IsAutoGenerated = true)]
public Guid Key { get; set; }
[VectorStoreKey(IsAutoGenerated = false)]
public Guid Key { get; set; }
[VectorStoreKey] // IsAutoGeneratedNullable remains null, fallback to SupportsKeyAutoGeneration()
public Guid Key { get; set; }
```
### Contribution Checklist
- [x] The code builds clean without any errors or warnings
- [ ] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>[MEVD] Can't set IsAutoGenerated property of
VectorStoreKeyAttribute at compile time</issue_title>
> <issue_description>The following code fails to compile:
>
> ```csharp
> [VectorStoreKey(StorageName = "name", IsAutoGenerated = true)]
> public Guid Key { get; set; }
> ```
>
> Because the `IsAutoGenerated` is `bool?`:
>
>
https://github.com/microsoft/semantic-kernel/blob/082e28e52ec2b45ad8cf287176d844150617e8b5/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs#L30
>
> Which in C# maps to `System.Nullable<bool>` (a struct) and can't be
set at compile time.
>
> Could we make it just a `bool` like what it's mapped to at the end?
>
>
https://github.com/microsoft/semantic-kernel/blob/082e28e52ec2b45ad8cf287176d844150617e8b5/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/KeyPropertyModel.cs#L18
>
> Context:
https://github.com/dotnet/extensions/pull/7423/changes#r2974567816
>
> cc @roji </issue_description>
>
> <agent_instructions>1. Make
[this](https://github.com/microsoft/semantic-kernel/blob/082e28e52ec2b45ad8cf287176d844150617e8b5/dotnet/src/VectorData/VectorData.Abstractions/RecordAttributes/VectorStoreKeyAttribute.cs#L30)
property be a `bool` rather than `bool?` property.
> 2. Implement the getter and setter for it.
> 3. The setter should set an internal `bool?` property that should be
used instead of the public property everywhere in the repo.
[Example]https://github.com/microsoft/semantic-kernel/blob/082e28e52ec2b45ad8cf287176d844150617e8b5/dotnet/src/VectorData/VectorData.Abstractions/ProviderServices/CollectionModelBuilder.cs#L162)
> 3. Proof of concept code that I've used to verify it's going to get us
what we need:
>
> ```csharp
> using System.Reflection;
>
> namespace ConsoleApp15
> {
> public class Program
> {
> static void Main()
> {
> TestAttribute setToTrue =
typeof(Program).GetMethod(nameof(SetToTrue))!.GetCustomAttribute<TestAttribute>()!;
> Console.WriteLine($"IsAutoGenerated_Core for [Test(IsAutoGenerated =
true)]: {setToTrue.IsAutoGenerated_Core}");
>
> TestAttribute setToFalse =
typeof(Program).GetMethod(nameof(SetToFalse))!.GetCustomAttribute<TestAttribute>()!;
> Console.WriteLine($"IsAutoGenerated_Core for [Test(IsAutoGenerated =
false)]: {setToFalse.IsAutoGenerated_Core}");
>
> TestAttribute notSet =
typeof(Program).GetMethod(nameof(NotSet))!.GetCustomAttribute<TestAttribute>()!;
> Console.WriteLine($"IsAutoGenerated_Core for [Test]:
{notSet.IsAutoGenerated_Core}");
> }
>
> [Test(IsAutoGenerated = true)]
> public static void SetToTrue() { }
>
> [Test(IsAutoGenerated = false)]
> public static void SetToFalse() { }
>
> [Test]
> public static void NotSet() { }
> }
>
> [AttributeUsage(AttributeTargets.All)]
> public class TestAttribute : Attribute
> {
> public bool IsAutoGenerated
> {
> get => throw new InvalidOperationException(); // provided to satisfy
compiler requirements
> set => IsAutoGenerated_Core = value;
> }
>
> internal bool? IsAutoGenerated_Core { get; set; }
> }
> }
> ```</agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #13697
<!-- START COPILOT CODING AGENT TIPS -->
---
💬 Send tasks to Copilot coding agent from
[Slack](https://gh.io/cca-slack-docs) and
[Teams](https://gh.io/cca-teams-docs) to turn conversations into code.
Copilot posts an update in your thread when it's finished.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>1 parent 082e28e commit 6ed2bb2
4 files changed
Lines changed: 103 additions & 3 deletions
File tree
- dotnet
- src
- SemanticKernel.Core/Functions
- VectorData/VectorData.Abstractions
- ProviderServices
- RecordAttributes
- test/VectorData/VectorData.UnitTests
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
720 | 720 | | |
721 | 721 | | |
722 | 722 | | |
723 | | - | |
| 723 | + | |
724 | 724 | | |
725 | 725 | | |
726 | 726 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
| 162 | + | |
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| |||
Lines changed: 16 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
29 | 33 | | |
30 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
31 | 46 | | |
Lines changed: 85 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
423 | 423 | | |
424 | 424 | | |
425 | 425 | | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
426 | 511 | | |
427 | 512 | | |
428 | 513 | | |
| |||
0 commit comments