Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
8 changes: 4 additions & 4 deletions GFramework.Core/Extensions/ContextAwareServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static class ContextAwareServiceExtensions
/// <param name="contextAware">实现 IContextAware 接口的上下文感知对象</param>
/// <returns>指定类型的服务实例,如果未找到则返回 null</returns>
/// <exception cref="ArgumentNullException">当 contextAware 参数为 null 时抛出</exception>
public static TService? GetService<TService>(this IContextAware contextAware) where TService : class
public static TService GetService<TService>(this IContextAware contextAware) where TService : class
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
Expand All @@ -34,7 +34,7 @@ public static class ContextAwareServiceExtensions
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
/// <returns>指定类型的系统实例</returns>
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
public static TSystem? GetSystem<TSystem>(this IContextAware contextAware) where TSystem : class, ISystem
public static TSystem GetSystem<TSystem>(this IContextAware contextAware) where TSystem : class, ISystem
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
Expand All @@ -48,7 +48,7 @@ public static class ContextAwareServiceExtensions
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
/// <returns>指定类型的模型实例</returns>
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
public static TModel? GetModel<TModel>(this IContextAware contextAware) where TModel : class, IModel
public static TModel GetModel<TModel>(this IContextAware contextAware) where TModel : class, IModel
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
Expand All @@ -62,7 +62,7 @@ public static class ContextAwareServiceExtensions
/// <param name="contextAware">实现 IContextAware 接口的对象</param>
/// <returns>指定类型的工具实例</returns>
/// <exception cref="ArgumentNullException">当 contextAware 为 null 时抛出</exception>
public static TUtility? GetUtility<TUtility>(this IContextAware contextAware) where TUtility : class, IUtility
public static TUtility GetUtility<TUtility>(this IContextAware contextAware) where TUtility : class, IUtility
{
ArgumentNullException.ThrowIfNull(contextAware);
var context = contextAware.GetContext();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记类需要自动推断并注入上下文相关字段。
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class GetAllAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入单个模型实例。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetModelAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入模型集合。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetModelsAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入单个服务实例。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetServiceAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入服务集合。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetServicesAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入单个系统实例。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetSystemAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入系统集合。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetSystemsAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入工具集合。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetUtilitiesAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace GFramework.SourceGenerators.Abstractions.Rule;

/// <summary>
/// 标记字段需要自动注入单个工具实例。
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class GetUtilityAttribute : Attribute
{
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using GFramework.SourceGenerators.Common.Info;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace GFramework.SourceGenerators.Common.Extensions;

Expand Down Expand Up @@ -69,38 +71,50 @@ public static GenericInfo ResolveGenerics(this INamedTypeSymbol symbol)
: $"where {tp.Name} : {string.Join(", ", parts)}";
}

/// <summary>
/// 判断类型的所有声明是否均带有 partial 关键字。
/// </summary>
/// <param name="symbol">要获取完整类名的命名类型符号</param>
extension(INamedTypeSymbol symbol)
/// <returns>如果所有声明均为 partial,则返回 <c>true</c>。</returns>
public static bool AreAllDeclarationsPartial(this INamedTypeSymbol symbol)
{
/// <summary>
/// 获取命名类型符号的完整类名(包括嵌套类型名称)
/// </summary>
/// <returns>完整的类名,格式为"外层类名.内层类名.当前类名"</returns>
public string GetFullClassName()
{
var names = new Stack<string>();
var current = symbol;

// 遍历包含类型链,将所有类型名称压入栈中
while (current != null)
{
names.Push(current.Name);
current = current.ContainingType;
}
return symbol.DeclaringSyntaxReferences
.Select(static reference => reference.GetSyntax())
.OfType<ClassDeclarationSyntax>()
.All(static declaration =>
declaration.Modifiers.Any(static modifier => modifier.IsKind(SyntaxKind.PartialKeyword)));
}

// 将栈中的名称用点号连接,形成完整的类名
return string.Join(".", names);
}
/// <summary>
/// 获取命名类型符号的完整类名(包括嵌套类型名称)
/// </summary>
/// <param name="symbol">要获取完整类名的命名类型符号</param>
/// <returns>完整的类名,格式为"外层类名.内层类名.当前类名"</returns>
public static string GetFullClassName(this INamedTypeSymbol symbol)
{
var names = new Stack<string>();
var current = symbol;

/// <summary>
/// 获取命名类型符号的命名空间名称
/// </summary>
/// <returns>命名空间名称,如果是全局命名空间则返回null</returns>
public string? GetNamespace()
// 遍历包含类型链,将所有类型名称压入栈中
while (current != null)
{
return symbol.ContainingNamespace.IsGlobalNamespace
? null
: symbol.ContainingNamespace.ToDisplayString();
names.Push(current.Name);
current = current.ContainingType;
}

// 将栈中的名称用点号连接,形成完整的类名
return string.Join(".", names);
}

/// <summary>
/// 获取命名类型符号的命名空间名称
/// </summary>
/// <param name="symbol">要获取完整类名的命名类型符号</param>
/// <returns>命名空间名称,如果是全局命名空间则返回null</returns>
public static string? GetNamespace(this INamedTypeSymbol symbol)
{
return symbol.ContainingNamespace.IsGlobalNamespace
? null
: symbol.ContainingNamespace.ToDisplayString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Microsoft.CodeAnalysis;

namespace GFramework.SourceGenerators.Common.Extensions;

/// <summary>
/// 提供 <see cref="ITypeSymbol" /> 的通用符号判断扩展。
/// </summary>
public static class ITypeSymbolExtensions
{
/// <summary>
/// 判断当前类型是否等于或实现/继承目标类型。
/// </summary>
/// <param name="typeSymbol">当前类型符号。</param>
/// <param name="targetType">目标类型符号。</param>
/// <returns>若等于、实现或继承则返回 <c>true</c>。</returns>
public static bool IsAssignableTo(
this ITypeSymbol typeSymbol,
INamedTypeSymbol? targetType)
{
if (targetType is null)
return false;

if (SymbolEqualityComparer.Default.Equals(typeSymbol, targetType))
return true;

if (typeSymbol is INamedTypeSymbol namedType)
{
if (namedType.AllInterfaces.Any(i =>
SymbolEqualityComparer.Default.Equals(i, targetType)))
return true;

for (var current = namedType.BaseType; current is not null; current = current.BaseType)
if (SymbolEqualityComparer.Default.Equals(current, targetType))
return true;
}

return false;
}
}
14 changes: 14 additions & 0 deletions GFramework.SourceGenerators.Common/Info/FieldCandidateInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace GFramework.SourceGenerators.Common.Info;

/// <summary>
/// 表示字段级生成器候选成员。
/// </summary>
/// <param name="Variable">字段变量语法节点。</param>
/// <param name="FieldSymbol">字段符号。</param>
public sealed record FieldCandidateInfo(
VariableDeclaratorSyntax Variable,
IFieldSymbol FieldSymbol
);
14 changes: 14 additions & 0 deletions GFramework.SourceGenerators.Common/Info/TypeCandidateInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace GFramework.SourceGenerators.Common.Info;

/// <summary>
/// 表示类型级生成器候选成员。
/// </summary>
/// <param name="Declaration">类型声明语法节点。</param>
/// <param name="TypeSymbol">类型符号。</param>
public sealed record TypeCandidateInfo(
ClassDeclarationSyntax Declaration,
INamedTypeSymbol TypeSymbol
);
20 changes: 20 additions & 0 deletions GFramework.SourceGenerators.Common/Internals/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// IsExternalInit.cs
// This type is required to support init-only setters and record types
// when targeting netstandard2.0 or older frameworks.

#if !NET5_0_OR_GREATER
using System.ComponentModel;

// ReSharper disable CheckNamespace

namespace System.Runtime.CompilerServices;

/// <summary>
/// 提供一个占位符类型,用于支持 C# 9.0 的 init 访问器功能。
/// 该类型在 .NET 5.0 及更高版本中已内置,因此仅在较低版本的 .NET 中定义。
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal static class IsExternalInit
{
}
#endif
Loading
Loading