Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

源代码生成类型的方法导出功能 #39

Merged
merged 51 commits into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
011ab8a
测试读取程序集里面所有其他的内容
lindexi Jun 16, 2023
70e7c50
Revert "测试读取程序集里面所有其他的内容"
lindexi Jun 16, 2023
bf051cb
加上对方法导出的定义
lindexi Jun 16, 2023
b64eaf0
Merge branch 'master' of github.com:dotnet-campus/SourceFusion into t…
lindexi Jul 1, 2023
65fbd69
收集定义的方法
lindexi Jul 1, 2023
32e9c59
完成收集项目的所有类型
lindexi Jul 1, 2023
605cdd9
判断项目里面的类型是否符合预期
lindexi Jul 2, 2023
3563746
修复判断逻辑
lindexi Jul 2, 2023
9f15fe3
Merge branch 'master' of github.com:dotnet-campus/SourceFusion into t…
lindexi Aug 21, 2023
342abc7
尝试实现导出方法
lindexi Aug 21, 2023
951d48e
合并代码
lindexi Aug 21, 2023
e9eec05
尝试修复构建
lindexi Aug 21, 2023
5ad0a3a
完成读取配置的属性
lindexi Aug 21, 2023
10977ce
定义 ValueTuple 的转换代码
lindexi Aug 22, 2023
85bba4c
尝试添加转换代码
lindexi Aug 22, 2023
cd661f9
整理文件
lindexi Aug 22, 2023
12c0a0a
拆分代码
lindexi Aug 22, 2023
956cfc0
封装辅助方法
lindexi Aug 23, 2023
bc4d8f1
支持读取整个程序集
lindexi Aug 23, 2023
fa12b86
修复取错期望继承类型
lindexi Aug 23, 2023
fd882bf
添加更多测试代码
lindexi Aug 23, 2023
423ce81
减少创建大量对象
lindexi Aug 23, 2023
a35a4d0
完成生成代码
lindexi Aug 28, 2023
e601998
修复判断
lindexi Aug 28, 2023
8ac604d
整理辅助代码
lindexi Aug 28, 2023
00f469d
修改代码格式化
lindexi Aug 28, 2023
66825b1
修复空格
lindexi Aug 28, 2023
e0e3c28
修复循环引用
lindexi Aug 28, 2023
f464e1d
修复特性丢失字符串
lindexi Aug 28, 2023
31d8a81
防止加上不可见的类型
lindexi Aug 28, 2023
fb32ef0
修复判定逻辑
lindexi Aug 28, 2023
5539984
修复布尔值
lindexi Aug 28, 2023
4499016
优化代码格式
lindexi Aug 28, 2023
4517a81
删除不使用代码
lindexi Aug 28, 2023
4013936
修改注释
lindexi Aug 28, 2023
bd81630
提供辅助方法
lindexi Aug 28, 2023
12ff430
更新打包方法
lindexi Aug 29, 2023
b015756
优化打包方法
lindexi Aug 29, 2023
9e402aa
提升 VisualStudio 性能
lindexi Aug 29, 2023
659c3f6
删除调试代码
lindexi Aug 29, 2023
3a88719
拆分代码
lindexi Aug 29, 2023
fb91d7a
拆分返回值实现方法
lindexi Aug 29, 2023
16800d8
定义源代码生成静态类
lindexi Aug 29, 2023
592aafd
支持创建单独的类型
lindexi Aug 29, 2023
30dca58
拆分代码创建
lindexi Aug 30, 2023
2db8be6
删除不使用代码
lindexi Aug 30, 2023
6aa457b
加上智能提示功能
lindexi Aug 30, 2023
61aba68
支持静态
lindexi Aug 30, 2023
b9804d1
准备发布
lindexi Aug 30, 2023
a347ab7
提升性能
lindexi Aug 30, 2023
dde5876
修改命名
lindexi Sep 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

";
}
Comment on lines +24 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

从今天开始,你可以使用 """ 来编写这种代码,对得齐多好

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
Loading