C
C#•5mo ago
bymaybe

Source Generator AdditionalFiles Batching missing metadata

Hey folks, I am working with a source generator that wraps NSwag to generate clients and servers based on OpenApi spesefications. I have each project that wants to have generated client add the following Item.
<ItemGroup>
<GeneratedApiServerContracts Include="$(OpenApiBasePath)openapi.yml" /> <-- clients
<GeneratedApiClientContracts Include="$(OpenApiBasePath)openapi.yml" /> <-- servers
</ItemGroup>
<ItemGroup>
<GeneratedApiServerContracts Include="$(OpenApiBasePath)openapi.yml" /> <-- clients
<GeneratedApiClientContracts Include="$(OpenApiBasePath)openapi.yml" /> <-- servers
</ItemGroup>
I have both of these custom items defined with the following
<ItemDefinitionGroup>
<GeneratedApiClientContracts>
<Namespace>$(RootNamespace)</Namespace>
<NSwagGenerateClient>true</NSwagGenerateClient>
</GeneratedApiClientContracts>
<GeneratedApiServerContracts>
<Namespace>$(RootNamespace)</Namespace>
<NSwagGenerateServer>true</NSwagGenerateServer>
</GeneratedApiServerContracts>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<GeneratedApiClientContracts>
<Namespace>$(RootNamespace)</Namespace>
<NSwagGenerateClient>true</NSwagGenerateClient>
</GeneratedApiClientContracts>
<GeneratedApiServerContracts>
<Namespace>$(RootNamespace)</Namespace>
<NSwagGenerateServer>true</NSwagGenerateServer>
</GeneratedApiServerContracts>
</ItemDefinitionGroup>
I then merge these two items into an AdditionalFiles item so that it could be read by the source generator.
<AdditionalFiles Include="@(GeneratedApiClientContracts)"/>
<AdditionalFiles Include="@(GeneratedApiServerContracts)"/>
<AdditionalFiles Include="@(GeneratedApiClientContracts)"/>
<AdditionalFiles Include="@(GeneratedApiServerContracts)"/>
If I were evaluate this the following would be returned, as expected dotnet msbuild -getItem:AdditionalFiles
// trimed extra metadata for brevity.
{
"Items": {
"AdditionalFiles": [
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\nswag\\openapi.nswag",
"NSwagConfig": "true"
},
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\api\\api-gateway\\openapi.yml",
"Namespace": "ApiGateway",
"NSwagGenerateClient": "true"
},
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\api\\api-gateway\\openapi.yml",
"Namespace": "ApiGateway",
"NSwagGenerateServer": "true"
}
]
}
}
// trimed extra metadata for brevity.
{
"Items": {
"AdditionalFiles": [
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\nswag\\openapi.nswag",
"NSwagConfig": "true"
},
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\api\\api-gateway\\openapi.yml",
"Namespace": "ApiGateway",
"NSwagGenerateClient": "true"
},
{
"Identity": "D:\\dev\\gdw\\cadet\\cadet.service\\api\\api-gateway\\openapi.yml",
"Namespace": "ApiGateway",
"NSwagGenerateServer": "true"
}
]
}
}
When trying to access this from the source generator only the first two elements are returned from AdditionalTextsProvider.
3 Replies
bymaybe
bymaybe•5mo ago
I would expect either all three to be returned or the second two items would have their metadata merged. In this case it just completely drops the second one since it's got the same identity. My backup option which is really ugly is to just give it a unique identity to make it unique, but that is very ugly. I was just trying to figure out if this is expected. If I was writing a custom ITask I would have access to all elements.
<AdditionalFiles Include="@(GeneratedApiClientContracts->'%(Identity)@client')"/>
<AdditionalFiles Include="@(GeneratedApiServerContracts->'%(Identity)@server')"/>
<AdditionalFiles Include="@(GeneratedApiClientContracts->'%(Identity)@client')"/>
<AdditionalFiles Include="@(GeneratedApiServerContracts->'%(Identity)@server')"/>
my ugly workaround
Thinker
Thinker•5mo ago
Try #roslyn, you'll get much better help for this there.
bymaybe
bymaybe•5mo ago
I will try out it, thank you 🙂