如何为C#生成类中的源代码生成错误添加位置提示?
为C#源代码生成器的编译错误添加有效位置提示
问题描述
我有一个C#源代码生成器,读取数据时遇到的配置问题会以编译错误抛出。当前实现代码如下:
DiagnosticDescriptor errorType = new DiagnosticDescriptor(...); Location? fileLocation = null; context.ReportDiagnostic(Diagnostic.Create(errorType, fileLocation, DiagnosticSeverity.Error));
这段代码能正常抛出错误,但点击或查看错误时无法定位到有效位置。我知道生成文本中需要高亮的错误区域,但此时新源代码只是一个string,无法展示错误位置。
尝试使用Location的创建方法时遇到障碍:
Create(SyntaxTree syntaxTree, TextSpan textSpan):生成的源代码要在生成器运行完毕后才会被解析,此时不存在syntaxTreeCreate(string filePath, TextSpan textSpan, LinePositionSpan lineSpan):目标是生成文件而非磁盘上的现有文件,无法获取filePath(虽然后续会写入,但当前无法获取该路径)
请问如何为源代码生成错误添加Location提示?
解决方案
方法1:定位到输入源文件(推荐)
如果配置问题来自用户提供的实际输入文件(比如带配置属性的代码、JSON配置文件等),直接复用这些现有文件的位置:
- 从输入的
SyntaxTree、AttributeData或AdditionalText中获取对应位置,用这个位置报告诊断。 - 示例:若错误源于类上的自定义属性配置错误,直接使用该属性的位置:
// 假设attr是获取到的AttributeData实例 context.ReportDiagnostic(Diagnostic.Create(errorType, attr.ApplicationSyntaxReference.GetLocation(), "配置参数格式错误"));
方法2:为生成文件创建虚拟Location
如果必须定位到生成的代码文件,可以通过虚拟路径实现:
- 生成代码时,记录错误对应的文本起始索引和长度,生成
TextSpan - 把生成的代码字符串转为
SourceText,计算出对应的行列范围LinePositionSpan - 使用生成文件的虚拟路径(格式一般为
GeneratedFiles/[生成器名称]/[文件名].cs,无需实际存在),调用Location.Create创建位置:
// 假设generatedCode是生成的代码字符串,错误起始索引start,长度length var textSpan = new TextSpan(start, length); var sourceText = SourceText.From(generatedCode); var linePositionSpan = sourceText.Lines.GetLinePositionSpan(textSpan); // 自定义虚拟路径 var virtualFilePath = $"GeneratedFiles/MyGenerator/ConfigGenerated.cs"; var location = Location.Create(virtualFilePath, textSpan, linePositionSpan); context.ReportDiagnostic(Diagnostic.Create(errorType, location, "配置项缺失"));
编译工具会识别这个虚拟路径,用户点击错误时会自动打开对应的生成文件(若生成器已输出该文件)。
方法3:定位到生成器通用位置
如果不需要精确行号,可以把错误定位到生成器程序集位置,这种方式精度最低:
var location = Location.Create(typeof(MySourceGenerator).Assembly.Location, TextSpan.Zero, LinePositionSpan.Zero); context.ReportDiagnostic(Diagnostic.Create(errorType, location, "配置读取失败"));
内容的提问来源于stack exchange,提问作者user3797758
相关产品推荐
相关产品推荐

