Skip to content

Commit

Permalink
Merge pull request #39 from dotnet-campus/t/lindexi/TelescopeExport
Browse files Browse the repository at this point in the history
源代码生成类型的方法导出功能
  • Loading branch information
lindexi authored Sep 2, 2023
2 parents 1957721 + dde5876 commit cd16583
Show file tree
Hide file tree
Showing 41 changed files with 1,883 additions and 39 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/nuget publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
run: dotnet build --configuration Release -v n
shell: pwsh

- name: Pack with dotnet
run: dotnet pack --configuration Release --no-build

- name: Install Nuget
uses: nuget/setup-nuget@v1
with:
Expand Down
21 changes: 21 additions & 0 deletions SourceFusion.sln
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Actions", "GitHub Ac
..\Ipc\.github\workflows\nuget-tag-publish.yml = ..\Ipc\.github\workflows\nuget-tag-publish.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib1", "src\TelescopeSourceGenerator\Demo\DemoLib1\dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib1.csproj", "{D9EA5A56-A4E4-4994-B634-8C1B1256D393}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib2", "src\TelescopeSourceGenerator\Demo\DemoLib2\dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib2.csproj", "{804D6902-6885-42A7-9EC3-BB0E09AAD3F2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib3", "src\TelescopeSourceGenerator\Demo\DemoLib3\dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib3.csproj", "{F1E050D2-E840-4793-8E97-024FBAD8908A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -98,6 +104,18 @@ Global
{F1E2D63D-A05A-4647-ADB3-750A9F651D22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1E2D63D-A05A-4647-ADB3-750A9F651D22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1E2D63D-A05A-4647-ADB3-750A9F651D22}.Release|Any CPU.Build.0 = Release|Any CPU
{D9EA5A56-A4E4-4994-B634-8C1B1256D393}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9EA5A56-A4E4-4994-B634-8C1B1256D393}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9EA5A56-A4E4-4994-B634-8C1B1256D393}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9EA5A56-A4E4-4994-B634-8C1B1256D393}.Release|Any CPU.Build.0 = Release|Any CPU
{804D6902-6885-42A7-9EC3-BB0E09AAD3F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{804D6902-6885-42A7-9EC3-BB0E09AAD3F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{804D6902-6885-42A7-9EC3-BB0E09AAD3F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{804D6902-6885-42A7-9EC3-BB0E09AAD3F2}.Release|Any CPU.Build.0 = Release|Any CPU
{F1E050D2-E840-4793-8E97-024FBAD8908A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1E050D2-E840-4793-8E97-024FBAD8908A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1E050D2-E840-4793-8E97-024FBAD8908A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1E050D2-E840-4793-8E97-024FBAD8908A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -108,6 +126,9 @@ Global
{C8BB3F7F-344C-40B4-BF00-005575C8C91A} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
{350C2DAF-7AD8-4285-9C8F-737D4D078B65} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
{F1E2D63D-A05A-4647-ADB3-750A9F651D22} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
{D9EA5A56-A4E4-4994-B634-8C1B1256D393} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
{804D6902-6885-42A7-9EC3-BB0E09AAD3F2} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
{F1E050D2-E840-4793-8E97-024FBAD8908A} = {A9879CB9-D164-4A0F-9F7A-D4B86C66BD68}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {22702A10-22E1-4670-8FCA-9581202E6CAB}
Expand Down
18 changes: 18 additions & 0 deletions src/TelescopeSourceGenerator/Analyzers/Core/AccessibilityHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Microsoft.CodeAnalysis;
using System;

namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.Core;

static class AccessibilityHelper
{
public static string ToCSharpCode(this Accessibility accessibility)
=> accessibility switch
{
Accessibility.Public => "public",
Accessibility.Private => "private",
Accessibility.Internal => "internal",
Accessibility.Protected => "protected",
Accessibility.ProtectedAndInternal => "private protected",
_ => string.Empty
};
}
36 changes: 36 additions & 0 deletions src/TelescopeSourceGenerator/Analyzers/Core/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;

namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.Core;

internal static class AssemblyInfo
{
public static string ToolName =>
Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyProductAttribute>().Product;

public static string ToolVersion =>
Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()
.InformationalVersion;

/// <summary>
/// 如果需要为类加上 <see cref="System.CodeDom.Compiler.GeneratedCodeAttribute"/>,则使用此字符串。
/// </summary>
public static string GeneratedCodeAttribute =>
$@"[global::System.CodeDom.Compiler.GeneratedCode(""{ToolName}"", ""{ToolVersion}"")]";

/// <summary>
/// 获取可以为每一个生成的文件都增加的文件头。
/// </summary>
public const string GeneratedCodeComment =
$@"//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
#define GENERATED_CODE
";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Microsoft.CodeAnalysis;

using System.Collections.Generic;

namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.Core;

static class AssemblySymbolHelper
{
/// <summary>
/// 获取当前程序集里面的所有类型
/// </summary>
/// <param name="assemblySymbol"></param>
/// <returns></returns>
public static IEnumerable<INamedTypeSymbol> GetAllTypeSymbols(IAssemblySymbol assemblySymbol) => GetAllTypeSymbols(assemblySymbol.GlobalNamespace);

public static IEnumerable<INamedTypeSymbol> GetAllTypeSymbols(INamespaceSymbol namespaceSymbol)
{
var typeMemberList = namespaceSymbol.GetTypeMembers();

foreach (var typeSymbol in typeMemberList)
{
yield return typeSymbol;
}

foreach (var namespaceMember in namespaceSymbol.GetNamespaceMembers())
{
foreach (var typeSymbol in GetAllTypeSymbols(namespaceMember))
{
yield return typeSymbol;
}
}
}

public static bool IsReference(IAssemblySymbol currentAssemblySymbol, IAssemblySymbol requiredAssemblySymbol)
{
var visited = new Dictionary<IAssemblySymbol, bool /*是否引用*/>(SymbolEqualityComparer.Default);
return IsReference(currentAssemblySymbol, requiredAssemblySymbol, visited);
}

public static bool IsReference(IAssemblySymbol currentAssemblySymbol, IAssemblySymbol requiredAssemblySymbol,
Dictionary<IAssemblySymbol, bool /*是否引用*/> visited)
{
if (SymbolEqualityComparer.Default.Equals(currentAssemblySymbol, requiredAssemblySymbol))
{
// 这个就看业务了,如果两个程序集是相同的,是否判断为引用关系
return true;
}

foreach (var moduleSymbol in currentAssemblySymbol.Modules)
{
foreach (var referencedAssemblySymbol in moduleSymbol.ReferencedAssemblySymbols)
{
if (SymbolEqualityComparer.Default.Equals(referencedAssemblySymbol, requiredAssemblySymbol))
{
// 记录当前程序集存在引用关系
visited[currentAssemblySymbol] = true;
return true;
}
else if (SymbolEqualityComparer.Default.Equals(referencedAssemblySymbol, currentAssemblySymbol))
{
// 循环引用,跳过
continue;
}
else
{
if (visited.TryGetValue(referencedAssemblySymbol, out var isReference))
{
// 这个是访问过的,那就从字典获取缓存,不需要再访问一次
// 同时也能解决程序集循环引用问题
}
else
{
// 进入递归之前,先将自身设置到字典,先设置为没有引用。防止循环引用炸掉
visited[referencedAssemblySymbol] = false;

// 没有访问过的,获取引用的程序集是否存在引用关系
isReference = IsReference(referencedAssemblySymbol, requiredAssemblySymbol, visited);
visited[referencedAssemblySymbol] = isReference;
}

if (isReference)
{
// 如果这个程序集有引用,那也算上
return true;
}
}
}
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ public static string GetAttributeCreatedCode(AttributeData attributeData)
$@"new {TypeSymbolHelper.TypeSymbolToFullName(attributeData.AttributeClass!)}({string.Join(",", constructorArgumentCodeList)})
{{
{string.Join(@",
", namedArgumentCodeList.Select(x => $"{x.propertyName} = {x.valueCode}"))}
", namedArgumentCodeList.Select(x => $"{x.propertyName} = {x.valueCode}"))}
}}";

static string TypedConstantToCodeString(TypedConstant typedConstant)
{
var constructorArgumentType = typedConstant.Type;
var constructorArgumentValue = typedConstant.Value;

string constructorArgumentCode;
Expand All @@ -69,6 +68,27 @@ static string TypedConstantToCodeString(TypedConstant typedConstant)

break;
}
case TypedConstantKind.Primitive:
{
if (typedConstant.Value is string text)
{
constructorArgumentCode = "\"" + text + "\"";
}
else if (typedConstant.Value is true)
{
constructorArgumentCode = "true";
}
else if (typedConstant.Value is false)
{
constructorArgumentCode = "false";
}
else
{
constructorArgumentCode = typedConstant.Value?.ToString() ?? "null";
}

break;
}
default:
{
constructorArgumentCode = typedConstant.Value?.ToString() ?? "null";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.CodeAnalysis;

namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.Core;

static class IncrementalValuesProviderHelper
{
/// <summary>
/// 过滤掉空的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="provider"></param>
/// <returns></returns>
public static IncrementalValuesProvider<T> ExcludeNulls<T>(this IncrementalValuesProvider<T?> provider)
{
return provider.Where(static t => t != null).Select(static (t, _) => t!);
}
}
Loading

0 comments on commit cd16583

Please sign in to comment.