Source Generator-添加诊断(五)

诊断的含义

通过自己的逻辑代码判断动态编译的代码是否有问题,有问题时需要告诉编译器有警告或者错误,让编译器返回来向我们展示我们期望的诊断信息。
因为动态编译时编译器无法得知我们写入是否有问题,从而产生很多奇奇怪怪的错误提示。

使用场景

当代码写好了,准备编译生成时,我们无法判断动态生成的代码是否存在问题(非少了分号那种),例如xml中不包含标签,但代码中是通过获得标签来获得的代码;又例如我们以为动态文件是一个cs类。如何在编译时就能让编译器知道我们可能弄错了文件的内容或者格式,此时context.ReportDiagnostic()方法可以帮助我们。

代码实现

  1. 创建一个类库(DiagnosticsGeneratorMethod)

  2. 添加Microsoft.CodeAnalysis.CSharp和Microsoft.CodeAnalysis.Analyzers引用

      <ItemGroup>
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
        <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3">
          <PrivateAssets>all</PrivateAssets>
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
      </ItemGroup>
    
  3. 在项目(DiagnosticsGeneratorMethod)中新建一个类(DiagnosticsGenerator.cs),添加如下代码

    using Microsoft.CodeAnalysis;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml;
    
    namespace DiagnosticsGeneratorMethod
    {
        [Generator]
        public class DiagnosticsGenerator: ISourceGenerator
        {
            //声明的诊断,例如编译器错误或警告
            // 该实例中声明的是警告
            private static readonly DiagnosticDescriptor InvalidXmlWarning = new DiagnosticDescriptor(id: "XMLGEN001",
                                            title: "Couldn't parse XML file",
                                            messageFormat: "无法解析xml文件 '{0}'.",
                                            category: "DiagnosticsGenerator",
                                            DiagnosticSeverity.Warning,
                                            isEnabledByDefault: true);
    
            public void Execute(GeneratorExecutionContext context)
            {
                // 获得所有的xml文件(也可以是其他文件,都是要动态生成的并且有且只有一种标准)
                IEnumerable<AdditionalText> xmlFiles = context.AdditionalFiles.Where(at => at.Path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase));
                foreach (AdditionalText xmlFile in xmlFiles)
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    string text = xmlFile.GetText(context.CancellationToken).ToString();
                    try
                    {
                        // 该诊断的标准是所有xml文件都能转换为xml格式的文件
                        xmlDoc.LoadXml(text);
                    }
                    catch (XmlException)
                    {
                        // 发现错误,并将诊断添加到编译器中
                        context.ReportDiagnostic(Diagnostic.Create(InvalidXmlWarning, Location.None, xmlFile.Path));
                        continue;
                    }
    
                }
            }
    
            public void Initialize(GeneratorInitializationContext context)
            {
            }
        }
    }
    
    
  4. SourceGeneratorConsole项目中引用DiagnosticsGeneratorMethod项目,并添加两个属性

    <ItemGroup>
    	<ProjectReference Include="..\DiagnosticsGenerator\DiagnosticsGeneratorMethod.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
    </ItemGroup>
    
  5. SourceGeneratorConsole项目中已添加了file.xml,可使用该文件

  6. 测试结果

    • 当file.xml文件存在root根标签时,不会报错可正常编译

    • 当file.xml文件只有cs代码时,主项目会提示警告

posted @ 2023-03-20 17:47  摧残一生  阅读(91)  评论(0编辑  收藏  举报