Roslyn 分析器 读取 csproj 项目文件的 AdditionalFiles Item 的 Metadata 配置

news/2024/10/12 7:17:50

在上一篇博客告诉大家如何在 IIncrementalGenerator 增量 Source Generator 里读取 csproj 项目文件的属性配置,详细请看:
IIncrementalGenerator 增量 Source Generator 生成代码入门 读取 csproj 项目文件的属性配置

在上一篇博客里面,核心是通过配置了 CompilerVisibleProperty 让属性可见,如下面代码所示

  <PropertyGroup><MyCustomProperty>lindexi is doubi</MyCustomProperty></PropertyGroup><ItemGroup><CompilerVisibleProperty Include="MyCustomProperty" /></ItemGroup>

在分析器里面获取属性内容的核心代码如下

            context.RegisterImplementationSourceOutput(context.AnalyzerConfigOptionsProvider,(productionContext, provider) =>{var text = string.Empty;// 通过 csproj 等 PropertyGroup 里面获取// 需要将可见的,放入到 CompilerVisibleProperty 里面// 需要加上 `build_property.` 前缀if (provider.GlobalOptions.TryGetValue("build_property.MyCustomProperty", out var myCustomProperty)){text += " " + myCustomProperty;}});

本文将告诉大家如何获取引用文件的 ItemGroup 里面的 Item 的 Metadata 内容如何获取到。如下面项目文件的代码,定义了名为 PaintStateDiagramMarkdownFile 的 Item 项,此项里面包含了 Link 这个 Metadata 内容

  <ItemGroup><PaintStateDiagramMarkdownFile Include="..\KereqeewahaihibayNohelqiji\*.txt" Link="Assets\StateDiagrams\%(RecursiveDir)%(Filename)%(Extension)" /></ItemGroup>

如期望让其 PaintStateDiagramMarkdownFile 项在分析器可见,需要将其添加到 AdditionalFiles 里面,如下面代码

  <ItemGroup><AdditionalFiles Include="@(PaintStateDiagramMarkdownFile)"/></ItemGroup>

为了让 Link 这个 Metadata 内容同样被分析器可见,需要在将 PaintStateDiagramMarkdownFile 添加到 AdditionalFiles 时,附带将 Link 带上,更新之后的代码如下

  <ItemGroup><AdditionalFiles Include="@(PaintStateDiagramMarkdownFile)" Link="%(Link)"/></ItemGroup>

再使用 CompilerVisibleItemMetadata 设置 AdditionalFiles 的 Link 也是对分析器可见,代码如下

  <ItemGroup><CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="Link" /></ItemGroup>

如此即可在后续分析器里面里面使用 AnalyzerConfigOptionsProvider 的 GetOptions 方法获取到 Metadata 信息

以上编辑之后的 csproj 项目文件内容如下

  <ItemGroup><PaintStateDiagramMarkdownFile Include="..\KereqeewahaihibayNohelqiji\*.txt" Link="Assets\StateDiagrams\%(RecursiveDir)%(Filename)%(Extension)" /><AdditionalFiles Include="@(PaintStateDiagramMarkdownFile)" Link="%(Link)"/><CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="Link" /></ItemGroup>

当然了,在真正的 NuGet 打包项目上,常常会将 AdditionalFiles 和 CompilerVisibleItemMetadata 写到 target 或 props 文件里面,而不是放在 csproj 里面。详细请参阅我的 博客导航 获取分析器入门知识

在分析器里面里面,可先收集或用其他方式获取到 AdditionalFiles 内容,将其传入给到 AnalyzerConfigOptionsProvider 的 GetOptions 方法,即可获取到 AnalyzerConfigOptions 对象。再对 AnalyzerConfigOptions 调用 TryGetValue 方法,传入字符串格式是 build_metadata.AdditionalFiles.[MetadataName] 即可获取到 Metadata 信息。以上字符串格式的 [MetadataName] 还请替换为实际需要获取的值,如本文以上例子里面期望获取到 Link 这个 Metadata 内容,可使用如下代码

AnalyzerConfigOptionsProvider analyzerConfigOptionsProvider = ...
AdditionalText additionalText = ...AnalyzerConfigOptions analyzerConfigOptions = analyzerConfigOptionsProvider.GetOptions(additionalText);if (analyzerConfigOptions.TryGetValue("build_metadata.AdditionalFiles.Link", out var link)){}

为了更好的说明使用方法,我创建了两个项目,其中一个项目是分析器项目,另一个是控制台项目。我将演示如何获取控制台项目所配置的 PaintStateDiagramMarkdownFile 项的 Link 信息。本文内容里面只给出关键代码片段,如需要全部的项目文件,可到本文末尾找到本文所有代码的下载方法

以下是控制台项目 CujelcijallChearjawjuja 的 csproj 文件的代码

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><PaintStateDiagramMarkdownFile Include="..\KereqeewahaihibayNohelqiji\*.txt" Link="Assets\StateDiagrams\%(RecursiveDir)%(Filename)%(Extension)" /><None Include="@(PaintStateDiagramMarkdownFile)"></None><AdditionalFiles Include="@(PaintStateDiagramMarkdownFile)" Link="%(Link)"/><CompilerVisibleItemMetadata Include="AdditionalFiles" MetadataName="Link" /></ItemGroup><ItemGroup><ProjectReference Include="..\KereqeewahaihibayNohelqiji\KereqeewahaihibayNohelqiji.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /></ItemGroup></Project>

可以看到写了 PaintStateDiagramMarkdownFile 项,且将其添加到 AdditionalFiles 里面,添加的过程中还将 PaintStateDiagramMarkdownFile 的 Link 赋值给到 AdditionalFiles 的 Link 里

最后配置 CompilerVisibleItemMetadata 让 AdditionalFiles 的 Link 信息被分析器可见

中间添加的 <None Include="@(PaintStateDiagramMarkdownFile)"></None> 只是一个简单的调试代码,用于让我可以在 VisualStudio 项目里面看到文件而已,和本文实际的演示没有关系

添加分析器 KereqeewahaihibayNohelqiji 项目,分析器项目的 csproj 项目文件的代码如下

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>netstandard2.0</TargetFramework><EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" /><PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" PrivateAssets="all" /></ItemGroup></Project>

以上代码的 EnforceExtendedAnalyzerRules 属性含义请参阅 Roslyn 分析器 EnforceExtendedAnalyzerRules 属性的作用

在 KereqeewahaihibayNohelqiji 项目放入 TextFile.txt 文件用于给 CujelcijallChearjawjuja 项目引用

在 KereqeewahaihibayNohelqiji 编写名为 YelgahainaljinalBehoballdewur 的 IIncrementalGenerator 增量 Source Generator 生成器,代码如下

namespace KereqeewahaihibayNohelqiji
{[Generator(LanguageNames.CSharp)]internal class YelgahainaljinalBehoballdewur : IIncrementalGenerator{public void Initialize(IncrementalGeneratorInitializationContext context){// 在这里编写代码context.RegisterImplementationSourceOutput(context.AdditionalTextsProvider.Collect().Combine(context.AnalyzerConfigOptionsProvider),(productionContext, provider) =>{// 这里的代码只有当配置初始化或变更时才会被执行var additionalTextArray = provider.Left;AnalyzerConfigOptionsProvider analyzerConfigOptionsProvider = provider.Right;var stringBuilder = new StringBuilder();for (int i = 0; i < 3; i++){stringBuilder.Append('"');}stringBuilder.AppendLine();foreach (AdditionalText additionalText in additionalTextArray){AnalyzerConfigOptions analyzerConfigOptions = analyzerConfigOptionsProvider.GetOptions(additionalText);if (analyzerConfigOptions.TryGetValue("build_metadata.AdditionalFiles.Link", out var link)){stringBuilder.AppendLine($"File={additionalText.Path}");stringBuilder.AppendLine($"Link={link}");}}for (int i = 0; i < 3; i++){stringBuilder.Append('"');}var code = @"using System;
namespace CujelcijallChearjawjuja
{public static class Foo{public static void F1(){Console.WriteLine(" + stringBuilder.ToString() + @");}}
}";productionContext.AddSource("Foo.cs", code);});}}
}

如此期望能够将控制台项目里面的 PaintStateDiagramMarkdownFile 作为 Foo 类型的 F1 方法输出控制台信息的内容

编辑控制台项目 CujelcijallChearjawjuja 的 Program.cs 文件,添加如下代码

using CujelcijallChearjawjuja;Foo.F1();

运行控制台项目,大概可以看到如下输出内容。如此可以证明此方法可以获取 Item 项里面配置的 Metadata 信息

File=C:\lindexi\Workbench\CujelcijallChearjawjuja\..\KereqeewahaihibayNohelqiji\TextFile.txt
Link=Assets\StateDiagrams\TextFile.txt

本文代码放在 github 和 gitee 上,可以使用如下命令行拉取代码。我整个代码仓库比较庞大,使用以下命令行可以进行部分拉取,拉取速度比较快

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin eb119d9e64e387cea847aee79f4509744c349018

以上使用的是国内的 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码。如果依然拉取不到代码,可以发邮件向我要代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin eb119d9e64e387cea847aee79f4509744c349018

获取代码之后,进入 Workbench/CujelcijallChearjawjuja 文件夹,即可获取到源代码

更多分析器和源代码生成博客,请参阅 博客导航

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70509.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

读数据工程之道:设计和构建健壮的数据系统06底层设计(下)

底层设计1. 数据问责制 1.1. 数据问责制意味着分配一个人来管理一部分数据1.1.1. 负责人协调其他利益相关者的治理活动1.1.2. 如果没有人对相关数据负责,那么管理数据质量就会很困难1.1.3. 负责数据的人不一定是数据工程师1.1.4. 负责人可能由软件工程师、产品经理或其他角色担…

CSP2024 前集训:多校A层冲刺NOIP2024模拟赛05

前言一次模拟赛四个计数,后三道一个 trick,yl 他妈都能被气活: T2、T3、T4 全是正难则反的 trick,T3、T4 都需要回退背包,T1 也可以背包。 T2 没想到正难则反一直死磕心态炸了,其实要试看看 T3 搞不好还想出来了。 以后再想不到正难则反记得抽死我谢谢。 T1 好数 可以直接…

【文化课学习笔记】【物理】恒定电流

高中物理学习笔记:恒定电流【物理】恒定电流 电流 基本概念 恒定电流:大小和方向都不变的电流。 直流电:方向不变的电流。 交流电:方向改变的电流。 电流相关 形成:电荷的定向移动。 方向:正电荷移动的方向,即负电荷的反方向,与电子运动方向相反。 定义:单位时间内通过…

数据结构 - 链表

本文介绍了链表的基本概念、节点和头指针的定义,链表的分类及实现方式。通过自申请内存空间和维护,实现了单链表的操作,包括初始化、插入、查找、更新、移除和销毁等操作,并提供了代码示例。今天我们将开始第二个数据类型-链表的学习,同样我们还是用最原始的方式,自己申请…

Design Compiler多时钟约束

这里的资料来源于《Synopsys Timing Constraints and Optimization User Guide, Version P-2019.03-SP4, September 2019》 下面图中这几种情况都是我在实际项目中碰到过的,因此有必要单独做个说明。 第一个是同步派生时钟,即CK2是通过CK1的分频来产生的,我们之前的一个实际…

uniapp创建小程序

uniapp创建小程序https://www.dcloud.io/一、安装Hbuilder和对应基本操作 ​ 安装Hbuilder这里就不在赘述。 (一)、插件安装: ​ 如果考虑到后续需要使用Scss,可以前往插件市场进行搜索安装,浏览器会提示我们是否需要打开对应的HbuilderX,然后进入应用进行安装。(二)…

labelme使用方法

labelme是一款在实例分割、语义分割、目标检测等任务中的一个常用工具,本文将介绍如何使用labelme。 labelme有各种版本,包括ubuntu、windows、macOS等。关于windows版本,也可以下载其相关的exe文件https://github.com/wkentaro/labelme/releases来使用标注 一、安装labelme…