C
C#•2d ago
HeavenVR

Roslyn Incremental CodeGen from text files not working

I wrote this codegen dll for internal use in the project, but i cannot reference the generated source code in the "CodeGen" project Referencing it from "Common" project:
<Project Sdk="Microsoft.NET.Sdk.Web">
...

<ItemGroup>
<ProjectReference Include="..\CodeGen\CodeGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk.Web">
...

<ItemGroup>
<ProjectReference Include="..\CodeGen\CodeGen.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
The "CodeGen" csproj:
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../Shared.props" />

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="../cloudflare-ips-v4.txt" />
<AdditionalFiles Include="../cloudflare-ips-v6.txt" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../Shared.props" />

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="../cloudflare-ips-v4.txt" />
<AdditionalFiles Include="../cloudflare-ips-v6.txt" />
</ItemGroup>
</Project>
The codegen source:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

namespace OpenShock.CodeGen;

[Generator]
internal class CloudflareProxiesGenerator : IIncrementalGenerator
{
private const string IpV4Name = "cloudflare-ips-v4.txt";
private const string IpV6Name = "cloudflare-ips-v6.txt";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var additionalFiles = context.AdditionalTextsProvider
.Where(file => file.Path.EndsWith(IpV4Name) || file.Path.EndsWith(IpV6Name))
.Collect();

context.RegisterSourceOutput(additionalFiles, (ctx, files) =>
{
var ipv4Lines = files.FirstOrDefault(f => f.Path.EndsWith(IpV4Name))?.GetText()?.Lines.Select(l => l.ToString().Trim()).Where(l => !string.IsNullOrEmpty(l)) ?? [];
var ipv6Lines = files.FirstOrDefault(f => f.Path.EndsWith(IpV6Name))?.GetText()?.Lines.Select(l => l.ToString().Trim()).Where(l => !string.IsNullOrEmpty(l)) ?? [];

var sourceBuilder = new StringBuilder();
sourceBuilder.AppendLine("using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;");
sourceBuilder.AppendLine();
sourceBuilder.AppendLine("namespace OpenShock;");
sourceBuilder.AppendLine();
sourceBuilder.AppendLine("public static class CloudflareProxies");
sourceBuilder.AppendLine("{");
sourceBuilder.AppendLine(" public static readonly IPNetwork[] PrefetchedCloudflareProxies = [");

sourceBuilder.AppendLine(" // IPv4");
foreach (var line in ipv4Lines)
sourceBuilder.AppendLine($" IPNetwork.Parse(\"{line}\"),");

sourceBuilder.AppendLine("\n // IPv6");
foreach (var line in ipv6Lines)
sourceBuilder.AppendLine($" IPNetwork.Parse(\"{line}\"),");

sourceBuilder.AppendLine(" ];");
sourceBuilder.AppendLine("}");

ctx.AddSource("CloudflareProxies.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
});
}
}
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

namespace OpenShock.CodeGen;

[Generator]
internal class CloudflareProxiesGenerator : IIncrementalGenerator
{
private const string IpV4Name = "cloudflare-ips-v4.txt";
private const string IpV6Name = "cloudflare-ips-v6.txt";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var additionalFiles = context.AdditionalTextsProvider
.Where(file => file.Path.EndsWith(IpV4Name) || file.Path.EndsWith(IpV6Name))
.Collect();

context.RegisterSourceOutput(additionalFiles, (ctx, files) =>
{
var ipv4Lines = files.FirstOrDefault(f => f.Path.EndsWith(IpV4Name))?.GetText()?.Lines.Select(l => l.ToString().Trim()).Where(l => !string.IsNullOrEmpty(l)) ?? [];
var ipv6Lines = files.FirstOrDefault(f => f.Path.EndsWith(IpV6Name))?.GetText()?.Lines.Select(l => l.ToString().Trim()).Where(l => !string.IsNullOrEmpty(l)) ?? [];

var sourceBuilder = new StringBuilder();
sourceBuilder.AppendLine("using IPNetwork = Microsoft.AspNetCore.HttpOverrides.IPNetwork;");
sourceBuilder.AppendLine();
sourceBuilder.AppendLine("namespace OpenShock;");
sourceBuilder.AppendLine();
sourceBuilder.AppendLine("public static class CloudflareProxies");
sourceBuilder.AppendLine("{");
sourceBuilder.AppendLine(" public static readonly IPNetwork[] PrefetchedCloudflareProxies = [");

sourceBuilder.AppendLine(" // IPv4");
foreach (var line in ipv4Lines)
sourceBuilder.AppendLine($" IPNetwork.Parse(\"{line}\"),");

sourceBuilder.AppendLine("\n // IPv6");
foreach (var line in ipv6Lines)
sourceBuilder.AppendLine($" IPNetwork.Parse(\"{line}\"),");

sourceBuilder.AppendLine(" ];");
sourceBuilder.AppendLine("}");

ctx.AddSource("CloudflareProxies.g.cs", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
});
}
}
15 Replies
Thinker
Thinker•2d ago
What exactly is it you cannot reference in the generator project?
HeavenVR
HeavenVROP•2d ago
not in the generator project, in Common project
No description
Thinker
Thinker•2d ago
Right, so it works as intended. You can't reference generated code inside the generator which generates that code.
HeavenVR
HeavenVROP•2d ago
but shouldnt it generate the code in the common project and not internally? the generator is supposed to generate the file and add it to the common projects references i dont want to use it in the codegen project, that doesnt make sense
Thinker
Thinker•2d ago
yes it should
HeavenVR
HeavenVROP•2d ago
then why doesnt it work? :catthinking:
Thinker
Thinker•2d ago
Does it compile if you build it from the comnand line?
HeavenVR
HeavenVROP•2d ago
i have never built from command line it builds from IDE and if i make the generator output invalid syntax the common project fails to build so thats a good sign wait it builds my ide just doesnt want to work properly intellisens is confused no nevermind im not sure if it works
Thinker
Thinker•2d ago
This is pretty common with SGs You can try restarting VS and clearing the cache
HeavenVR
HeavenVROP•2d ago
didnt work but i dont think the compilation works properly either
HeavenVR
HeavenVROP•2d ago
tried putting this in the list of ips
No description
HeavenVR
HeavenVROP•2d ago
and added this
No description
HeavenVR
HeavenVROP•2d ago
compilation still succeeds
333fred
333fred•22h ago
Your additional files needs to be in the consuming project, not the generator project
HeavenVR
HeavenVROP•6h ago
Which I did 🤔

Did you find this page helpful?