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

功能更新 #1

Merged
merged 5 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions src/.idea/.idea.MT.Generators/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/.idea/.idea.MT.Generators/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/.idea/.idea.MT.Generators/.idea/indexLayout.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/.idea/.idea.MT.Generators/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

239 changes: 175 additions & 64 deletions src/AutoInject.Roslyn/AutoInjectContextGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,74 +17,158 @@ public class AutoInjectContextGenerator : IIncrementalGenerator
const string AutoInjectContext = "AutoInjectGenerator.AutoInjectContextAttribute";
const string AutoInjectConfiguration = "AutoInjectGenerator.AutoInjectConfiguration";
const string AutoInject = "AutoInjectGenerator.AutoInjectAttribute";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var source = context.SyntaxProvider.ForAttributeWithMetadataName(
AutoInjectContext
, static (node, _) => node is ClassDeclarationSyntax
, static (ctx, _) => ctx);
context.RegisterSourceOutput(source, (context, source) =>
// var source = context.SyntaxProvider.ForAttributeWithMetadataName(
// AutoInjectContext
// , static (node, _) => node is ClassDeclarationSyntax
// , static (ctx, _) => ctx);
context.RegisterSourceOutput(context.CompilationProvider, static (context, source) =>
{
var compilcation = source.SemanticModel.Compilation;
var used = compilcation.GetUsedAssemblyReferences();
var all = GetAllSymbols(compilcation.GlobalNamespace);
var classSymbol = (INamedTypeSymbol)source.TargetSymbol;
var className = classSymbol.MetadataName;
if (classSymbol.GetMembers().FirstOrDefault(m => m is IMethodSymbol { IsPartialDefinition: true, IsStatic: true }) is not IMethodSymbol methodSymbol)
// var compilcation = source.SemanticModel.Compilation;
// var used = compilcation.GetUsedAssemblyReferences();
// var all = compilcation.GetAllSymbols(AutoInject);
// var classSymbol = (INamedTypeSymbol)source.TargetSymbol;
// var className = classSymbol.MetadataName;
// if (classSymbol.GetMembers().FirstOrDefault(m => m is IMethodSymbol
// {
// IsPartialDefinition: true, IsStatic: true
// }) is not IMethodSymbol methodSymbol)
// {
// context.ReportDiagnostic(DiagnosticDefinitions.AIG00001(source.TargetNode.GetLocation()));
// return;
// }
//
// // 获取 IServiceCollection 参数的名称
// var serviceName = methodSymbol.Parameters.First(p =>
// p.Type.ToDisplayString()
// .Contains("Microsoft.Extensions.DependencyInjection.IServiceCollection"))
// .Name;
//
// var allConfig = methodSymbol.GetAttributes(AutoInjectConfiguration).Select(c =>
// {
// var i = c.GetNamedValue("Include")?.ToString() ?? "";
// var e = c.GetNamedValue("Exclude")?.ToString() ?? "";
// return (i, e);
// }).ToArray();
//
// var includes = allConfig.Select(t => t.i).Where(s => !string.IsNullOrEmpty(s)).ToArray();
// var excludes = allConfig.Select(t => t.e).Where(s => !string.IsNullOrEmpty(s)).ToArray();
//
// if (includes.Intersect(excludes).Any())
// {
// context.ReportDiagnostic(DiagnosticDefinitions.AIG00002(source.TargetNode.GetLocation()));
// return;
// }
//
// var injectStatements = CreateInjectStatements(all, serviceName, includes, excludes);
// var cm = MethodBuilder.Default.MethodName(methodSymbol.Name)
// .Modifiers("public static partial")
// .AddParameter([
// .. methodSymbol.Parameters.Select((p, i) =>
// $"{(i == 0 && methodSymbol.IsExtensionMethod ? "this " : "")}{p.Type.ToDisplayString()} {p.Name}")
// ])
// .AddBody([.. injectStatements]);
//
// var gclass = ClassBuilder.Default.ClassName(className)
// .Modifiers("static partial")
// .AddMembers(cm);
// var gn = NamespaceBuilder.Default.Namespace(source.TargetSymbol.ContainingNamespace.ToDisplayString())
// .AddMembers(gclass);
//
// var file = CodeFile.New($"{className}.AutoInject.g.cs")
// .AddMembers(gn)
// .AddUsings(source.GetTargetUsings());
//
// context.AddSource(file);

var allContext = source.GetAllSymbols(AutoInjectContext).ToArray();
if (allContext.Length == 0)
{
context.ReportDiagnostic(DiagnosticDefinitions.AIG00001(source.TargetNode.GetLocation()));
return;
}
// 获取 IServiceCollection 参数的名称
var serviceName = methodSymbol.Parameters.First(p => p.Type.ToDisplayString().Contains("Microsoft.Extensions.DependencyInjection.IServiceCollection")).Name;

var allConfig = methodSymbol.GetAttributes(AutoInjectConfiguration).Select(c =>
foreach (var item in allContext)
{
var i = c.GetNamedValue("Include")?.ToString() ?? "";
var e = c.GetNamedValue("Exclude")?.ToString() ?? "";
return (i, e);
});

var includes = allConfig.Select(t => t.i).Where(s => !string.IsNullOrEmpty(s)).ToArray();
var excludes = allConfig.Select(t => t.e).Where(s => !string.IsNullOrEmpty(s)).ToArray();
Debugger.Launch();

if (includes.Intersect(excludes).Any())
{
context.ReportDiagnostic(DiagnosticDefinitions.AIG00002(source.TargetNode.GetLocation()));
return;
if (!EqualityComparer<IAssemblySymbol>.Default.Equals(item.ContainingAssembly, source.SourceModule.ContainingAssembly))
{
continue;
}
var all = source.GetAllSymbols(AutoInject);
CreateContextFile(context, item, all);
}
});
}

var injectStatements = CreateInjectStatements(all, serviceName, includes, excludes);
var cm = MethodBuilder.Default.MethodName(methodSymbol.Name)
.Modifiers("public static partial")
.AddParameter([.. methodSymbol.Parameters.Select((p, i) => $"{(i == 0 && methodSymbol.IsExtensionMethod ? "this " : "")}{p.Type.ToDisplayString()} {p.Name}")])
.AddBody([.. injectStatements]);
private static void CreateContextFile(SourceProductionContext context, INamedTypeSymbol classSymbol,
IEnumerable<INamedTypeSymbol> all)
{
var className = classSymbol.MetadataName;
var methodSymbol = classSymbol.GetMembers().FirstOrDefault(m => m is IMethodSymbol
{
IsPartialDefinition: true, IsStatic: true
}) as IMethodSymbol;
if (methodSymbol == null)
{
context.ReportDiagnostic(DiagnosticDefinitions.AIG00001(Location.None));
return;
}

var gclass = ClassBuilder.Default.ClassName(className)
.Modifiers("static partial")
.AddMembers(cm);
var gn = NamespaceBuilder.Default.Namespace(source.TargetSymbol.ContainingNamespace.ToDisplayString())
.AddMembers(gclass);
// 获取 IServiceCollection 参数的名称
var serviceName = methodSymbol.Parameters.First(p =>
p.Type.ToDisplayString().Contains("Microsoft.Extensions.DependencyInjection.IServiceCollection")).Name;

var file = CodeFile.New($"{className}.AutoInject.g.cs")
.AddMembers(gn)
.AddUsings(source.GetTargetUsings());
var allConfig = methodSymbol.GetAttributes(AutoInjectConfiguration).Select(c =>
{
var i = c.GetNamedValue("Include")?.ToString() ?? "";
var e = c.GetNamedValue("Exclude")?.ToString() ?? "";
return (i, e);
}).ToArray();

context.AddSource(file);
});
var includes = allConfig.Select(t => t.i).Where(s => !string.IsNullOrEmpty(s)).ToArray();
var excludes = allConfig.Select(t => t.e).Where(s => !string.IsNullOrEmpty(s)).ToArray();

if (includes.Intersect(excludes).Any())
{
context.ReportDiagnostic(DiagnosticDefinitions.AIG00002(Location.None));
return;
}

var injectStatements = CreateInjectStatements(all, serviceName, includes, excludes);
var cm = MethodBuilder.Default.MethodName(methodSymbol.Name)
.Modifiers("public static partial")
.AddParameter([
.. methodSymbol.Parameters.Select((p, i) =>
$"{(i == 0 && methodSymbol.IsExtensionMethod ? "this " : "")}{p.Type.ToDisplayString()} {p.Name}")
])
.AddBody([.. injectStatements]);

var gclass = ClassBuilder.Default.ClassName(className)
.Modifiers("static partial")
.AddMembers(cm);
var gn = NamespaceBuilder.Default.Namespace(classSymbol.ContainingNamespace.ToDisplayString())
.AddMembers(gclass);

var file = CodeFile.New($"{className}.AutoInject.g.cs")
.AddMembers(gn);

context.AddSource(file);
}

private static IEnumerable<Statement> CreateInjectStatements(IEnumerable<INamedTypeSymbol> all
, string serviceName
, string[] includes
, string[] excludes)
, IReadOnlyCollection<string> includes
, IReadOnlyCollection<string> excludes)
{
foreach (var c in all)
{
foreach (var a in c.GetAttributes(AutoInject))
{
// 没有配置规则,全部注入
if (includes.Length > 0 || excludes.Length > 0)
if (includes.Count > 0 || excludes.Count > 0)
{
if (a.GetNamedValue("Group", out var group))
{
Expand All @@ -99,6 +183,7 @@ private static IEnumerable<Statement> CreateInjectStatements(IEnumerable<INamedT
}
}
}

var implType = c.ToDisplayString();
var serviceType = "";
if (a.GetNamedValue("ServiceType", out var t) && t is INamedTypeSymbol type)
Expand All @@ -120,6 +205,7 @@ private static IEnumerable<Statement> CreateInjectStatements(IEnumerable<INamedT
// AutoInjectGenerator.InjectLifeTime
injectType = 1;
}

if (serviceType == implType)
{
yield return $"{serviceName}.Add{FormatInjectType(injectType)}<{implType}>()";
Expand All @@ -142,25 +228,50 @@ private static string FormatInjectType(object? t)
_ => "Scoped"
};
}

private static IEnumerable<INamedTypeSymbol> GetAllSymbols(INamespaceSymbol global)
{
foreach (var symbol in global.GetMembers())
{
if (symbol is INamespaceSymbol s)
{
foreach (var item in GetAllSymbols(s))
{
//if (item.HasAttribute(AutoInject))
yield return item;
}
}
else if (symbol is INamedTypeSymbol target && !target.IsImplicitlyDeclared)
{
if (target.HasAttribute(AutoInject))
yield return target;
}
}
}
}
}

//namespace AutoInjectGenerator
//{
// [Generator(LanguageNames.CSharp)]
// public class AutoInjectContextGenerator : IIncrementalGenerator
// {
// const string AutoInjectContext = "AutoInjectGenerator.AutoInjectContextAttribute";
// const string AutoInjectConfiguration = "AutoInjectGenerator.AutoInjectConfiguration";
// const string AutoInject = "AutoInjectGenerator.AutoInjectAttribute";
// public void Initialize(IncrementalGeneratorInitializationContext context)
// {
// var source = context.SyntaxProvider.ForAttributeWithMetadataName(
// AutoInjectContext
// , static (node, _) => node is ClassDeclarationSyntax
// , static (ctx, _) => ctx);
// context.RegisterSourceOutput(source, (context, source) =>
// {
// //var compilcation = source.SemanticModel.Compilation;
// //var used = compilcation.GetUsedAssemblyReferences();

// //var allContext = source.GetAllSymbols(AutoInjectContext);
// //if (allContext.Any() == false)
// //{
// // return;
// //}

// //foreach (var item in allContext)
// //{
// // if (!EqualityComparer<IAssemblySymbol>.Default.Equals(item.ContainingAssembly, source.SourceModule.ContainingAssembly))
// // {
// // continue;
// // }
// // var all = source.GetAllSymbols(AutoInject);
// // CreateContextFile(context, item, all);
// //}

// var all = source.SemanticModel.Compilation.GetAllSymbols(AutoInject);
// CreateContextFile(context, (INamedTypeSymbol)source.TargetSymbol, all);

// });
// }


// }
//}
1 change: 1 addition & 0 deletions src/AutoInjectGenerator/AutoInjectGenerator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<Version>0.0.1</Version>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>readme.md</PackageReadmeFile>
<RootNamespace>AutoInjectGenerator</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading