【C#】분석기 소스 발생기 개발의 요점
분석기원 발생기 몇 개를 개발했기 때문에 지식을 총결해 봅시다.
C# 이외의NET 언어도 마찬가지라고 생각해요. C#의 개발이니까 C#로 보도하죠.
제목 중 [A/S] 중 하나는 분석기 원본 발생기 공통이고 [A]는 분석기만 표시하며 [S]는 원본 발생기를 대상으로 하는 항목만 표시한다.
공식 창고의 쿡북[S] 보기
소스 발생기만 있고 쿡쿡이 있어서 아주 유용해요.
주문을 csproj에 [A/S]
분석기 소스 발생기는 csproj에 대해 다양한 주문을 필요로 한다.
누겟 패키지 만들기
Analyzer 소스 발생기는 NuGet 포장을 평소와 다르게 만듭니다.
그래서 다양한 주문이 있다.
<PropertyGroup>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IncludeSymbols>false</IncludeSymbols>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs</TargetsForTfmSpecificContentInPackage>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<DevelopmentDependency>true</DevelopmentDependency>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
</ItemGroup>
<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
<Target Name="PackBuildOutputs" DependsOnTargets="SatelliteDllsProjectOutputGroup;DebugSymbolsProjectOutputGroup">
<ItemGroup>
<TfmSpecificPackageFile Include="$(TargetDir)\*.dll" PackagePath="analyzers\dotnet\cs" />
<TfmSpecificPackageFile Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\*.dll" PackagePath="analyzers\dotnet\cs" />
<TfmSpecificPackageFile Include="@(SatelliteDllsProjectOutputGroupOutput->'%(FinalOutputPath)')" PackagePath="analyzers\dotnet\cs\%(SatelliteDllsProjectOutputGroupOutput.Culture)\" />
</ItemGroup>
</Target>
설정설명
IncludeBuildOutput=false
패키지에 DLL을 자동으로 추가하지 않음
IncludeSymbols=false
기호 정보 필요 없음
TargetsForTfmSpecificContentInPackage
매크로 패키지 구성
SuppressDependenciesWhenPacking=true
패키지 의존 관계 포함하지 않음
DevelopmentDependency=true
분석기로 포장하다
DevelopmentDependency
가 true
로 설정되면 NuGet에서 분석기로 처리되며 사용자가 설치할 때도 자동으로 분석기용 설정으로 설치됩니다.사용자가
<PackageReference Include="SourceExpander.Embedder" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
DevelopmentDependency
true
인 패키지를 설치한 후 위에서 설명한 대로 PrivateAssets
,IncludeAssets
가 자동으로 설정됩니다.이렇게 되면 분석기의 의존성은 사용자측의 라이브러리에 누설되지 않을 것이다.
Newtonsoft.Json 사용
Analyzer 소스 발생기가 사용하는 라이브러리에서는 NuGet의 종속성 문제를 해결할 수 없습니다.
따라서 DLL을 포함해야 합니다.
설정
설명
GetTargetPathDependsOn
종속 라이브러리 해결
GeneratePathProperty
를 true
로 설정할 때 Newtonsoft.Json
일 경우 $(PkgNewtonsoft_Json)
라는 변수 이름으로 라이브러리를 다운로드하는 경로를 얻을 수 있으며 이것도nupkg에 삽입됩니다.Newtonsoft.제이슨은 MIT 라이선스니까 제대로 표시해야 돼.
<PropertyGroup>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IncludeSymbols>false</IncludeSymbols>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs</TargetsForTfmSpecificContentInPackage>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<DevelopmentDependency>true</DevelopmentDependency>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
</ItemGroup>
<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
<Target Name="PackBuildOutputs" DependsOnTargets="SatelliteDllsProjectOutputGroup;DebugSymbolsProjectOutputGroup">
<ItemGroup>
<TfmSpecificPackageFile Include="$(TargetDir)\*.dll" PackagePath="analyzers\dotnet\cs" />
<TfmSpecificPackageFile Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\*.dll" PackagePath="analyzers\dotnet\cs" />
<TfmSpecificPackageFile Include="@(SatelliteDllsProjectOutputGroupOutput->'%(FinalOutputPath)')" PackagePath="analyzers\dotnet\cs\%(SatelliteDllsProjectOutputGroupOutput.Culture)\" />
</ItemGroup>
</Target>
취소된 [A/S] 확인
SyntaxNodeAnalysisContext
와 GeneratorExecutionContext
등이 받았다System.Threading.CancellationToken
.시끄럽지 않게
context.CancellationToken.ThrowIfCancellationRequested()
검사 취소해.Visual Studio는 백그라운드에서 분석기 소스 발생기를 실행하기 때문에 자주 취소됩니다.그러나 검사를 취소하지 않으면 분석기 원본 발생기의 실행이 완료될 때까지 기다려야 한다.
Diagnostic의 출력 [A/S]
이 점에 대해서는 취향이 다를 것 같지만
DiagnosticDescriptor
부터 제작Diagnostic
하면 DiagnosticDescriptor
하는 방법대로 제작할 수 있다.정보에 전달되는 매개 변수의 수를 고정시키고 싶으므로
Diagnostic.Create
에서 제작된 곳은 숨겨두세요.분석기라면 납품
DiagnosticDescriptor
이 필요하기 때문에 private
할 수 없지만 그 외에 사용하지 않는 것이 좋다고 생각합니다.public static Diagnostic EMBED0001_UnknownError(string message)
=> Diagnostic.Create(EMBED0001_UnknownError_Descriptor, Location.None, message);
private static readonly DiagnosticDescriptor EMBED0001_UnknownError_Descriptor = new(
"EMBED0001",
new LocalizableResourceString(
nameof(DiagnosticsResources.EMBED0001_Title),
DiagnosticsResources.ResourceManager,
typeof(DiagnosticsResources)),
new LocalizableResourceString(
nameof(DiagnosticsResources.EMBED0001_Body),
DiagnosticsResources.ResourceManager,
typeof(DiagnosticsResources)),
"Error",
DiagnosticSeverity.Warning,
true);
멀티스레드 실행 [A/S]
compilation.Options.ConcurrentBuild
에서 다중 루틴 환경에서 컴파일이 실행되었는지 확인할 수 있습니다.다선정일 때도 병행 집행을 유연하게 활용하여 고속 동작을 하도록 해야 한다.
SyntaxTree[] newTrees;
if (compilation.Options.ConcurrentBuild)
newTrees = compilation.SyntaxTrees.AsParallel().WithCancellation(cancellationToken)
.Select(Rewrited).ToArray();
else
newTrees = compilation.SyntaxTrees
.Select(Rewrited).ToArray();
분석기의 경우AnalysisContext
에서 실행context.EnableConcurrentExecution()
.
Reference
이 문제에 관하여(【C#】분석기 소스 발생기 개발의 요점), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/naminodarie/articles/32973a36fcbe99텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)