【踩坑】Roslyn 5与VS2022——不散的红色浪线

本文地址https://www.cnblogs.com/oberon-zjt0806/p/19429665
同步更新至知乎

首先祝大家2026新年快乐!🎉🐴

先说本文的结论——

Visual Studio 2022的IntelliSense似乎不能和Roslyn 5.0良好配合,导致MSBuild无法加载到生成器构建的代码
如果想在Visual Studio 2022中使用代码分析服务,请确保引用的Nuget包Microsoft.CodeAnalysis的版本为4.x
MSDN文档列举了Roslyn版本与具体IDE的兼容情况,详见这里
另外,如果目标项目的CS0103或者CS0246没有立即褪去,那么你需要关闭报错的文件,清理并重新生成解决方案。

前请提要

昨天想接触一下传说中的源代码生成器(Source Generator),于是就查了一堆资料照猫画虎写了一个——

/// 生成器程序集 SourceGeneratorDemo.Generators
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

namespace SourceGeneratorDemo.Generators;

[Generator]
public class HelloWorldGenerator : IIncrementalGenerator
{
	public void Initialize(IncrementalGeneratorInitializationContext context)
	{
		// A simple pipeline that always produces a single string
		var helloSource = context.AnalyzerConfigOptionsProvider
			.Select((_, _) => @"
namespace SourceGeneratorDemo.Generated
{
	public class GeneratedProgram
	{
		public static void HelloWorld()
		{
			Console.WriteLine(""Hello from incremental generator!"");
		}
	}
}
");

		context.RegisterSourceOutput(helloSource, (spc, source) =>
		{
			spc.AddSource("GeneratedProgram.g.cs", SourceText.From(source, Encoding.UTF8));
		});
	}
}

显然这个生成器预期产生下面这段代码,一个简单的Hello World类——

namespace SourceGenerator.Generated
{
	public class GeneratedProgram
	{
		public static void HelloWorld()
		{
			Console.WriteLine(""Hello from incremental generator!"");
		}
	}
}

然后安装了Roslyn,也就是Microsoft.CodeAnalysis包。按照项目配置了

<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>

然后在目标项目(此时是空的)中引用生成的代码。首先将生成器项目引入——

<!-- 目标项目 SourceGeneratorDemo.csproj -->
<ItemGroup>
	<ProjectReference Include="..\SourceGeneratorDemo.HelloWorldGenerator\SourceGeneratorDemo.Generators.csproj" 
					  OutputItemType="Analyzer" 
					  ReferenceOutputAssembly="false" />
</ItemGroup>

我们生成的代码在SourceGenerator.Generated命名空间下,包含一个类GeneratedProgram,带有一个方法void HelloWorld();

// 目标项目 Program.cs
using static System.Console;
using SourceGenerator.Generated;

GeneratedProgram.HelloWorld(); // 直接使用了顶级语句

当写完上面这部分的时候在生成之前,SourceGenerator.GeneratedGeneratedProgram是会标红色波浪线的(前者为CS0246,后者为CS0103),这是正常的,因为生成的代码还没有通过编译器加载到目标项目。所以自然是找不到生成的这些元素的。

按照预期,只要我生成运行整个解决方案,那么Roslyn会调用生成器SourceGeneratorDemo.Generators.HelloWorldGenerator 生成出预期的代码,然后将这段生成的代码加入到目标项目中来。只要我重新打开Program.cs,IntelliSense就应该正确解析SourceGenerator.GeneratedGeneratedProgram这两个符号。

有趣的部分

然而,有趣的部分来了,虽然在生成解决方案之后目标项目被正确构建并且弹出了控制台输出了

Hello World

但是Program.cs中的红色波浪线依然没有消失!也就是说编辑器还在提示我CS0103和CS0246,也就是IntelliSense还是找不到SourceGeneratorDemo.GeneratedGeneratedProgram。按下F12也不能导航到生成代码下。

在多次重启IDE、清理重新构建项目、删除.vs缓存之后问题仍然存在,在网上搜了半天,没找到有效的解决方法(可能也是我想尽办法也没有描述清楚),于是就开始问Copilot。

Good End

与 Copilot battle了半天(查看需要T子),期间尝试过找茬<ProjectReference>namespace以及<EnforceExtendedAnalyzerRules>等诸多要素。最终确定,问题出在生成器项目的项目文件——

<ItemGroup>
	<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" PrivateAssets="all" />
</ItemGroup>

VS2022在安装时自动选择了5.0版本,虽然能正确生成和运行项目,但是与VS2022 IDE使用的Roslyn版本不匹配(Copilot是如此声称的)。

最终我们发现只要把Version改为4.14.0,清理并重新生成解决方案,重新打开Program.cs就不再有问题了。

posted @ 2026-01-01 09:39  Oberon  阅读(10)  评论(0)    收藏  举报