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

支持无特性方式导出 #40

Merged
merged 9 commits into from
Dec 7, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ class ExportedTypesCodeTextGenerator
{
public string Generate(ImmutableArray<MarkClassParseResult> markClassCollection, CancellationToken token)
{
if (markClassCollection.Length == 0)
{
// 如果没有任何需要导出的类型,那就不要创建任何代码
return string.Empty;
}

// 导出的接口
var exportedInterfaces = new List<string>();
// 导出的方法
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ namespace {@namespace}
{{");
}

var generatedCodeAttributeSource = AssemblyInfo.GeneratedCodeAttribute;
// 不要带上 System.CodeDom.Compiler.GeneratedCodeAttribute 特性,因为一个类型如果是分部类型,可能有多个逻辑都在生成在不同的文件,如果这些文件同时都加上 GeneratedCodeAttribute 特性,将会导致 error CS0579: “global::System.CodeDom.Compiler.GeneratedCode”特性重复
//var generatedCodeAttributeSource = AssemblyInfo.GeneratedCodeAttribute;

// Add the core implementation for the derived context class.
string partialContextImplementation = $@"
{generatedCodeAttributeSource}
{declarationList[0]}
{{
{IndentSource(memberCode, Math.Max(1, declarationCount - 1))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,32 @@ public string GenerateSourceCode(ExportMethodReturnTypeCollectionResult exportMe
foreach (var namedTypeSymbol in list)
{
token.ThrowIfCancellationRequested();
// yield return (typeof(CurrentFoo), new F1Attribute(), () => new CurrentFoo());

var attribute = namedTypeSymbol.GetAttributes().First(t =>
SymbolEqualityComparer.Default.Equals(t.AttributeClass,
exportMethodReturnTypeCollectionResult
.ExpectedClassAttributeType));
var attributeCreatedCode = AttributeCodeReWriter.GetAttributeCreatedCode(attribute);

var typeName = TypeSymbolHelper.TypeSymbolToFullName(namedTypeSymbol);
methodCode.AppendLine(SourceCodeGeneratorHelper.IndentSource(
$" yield return (typeof({typeName}), {attributeCreatedCode}, () => new {typeName}());",
numIndentations: 1));

if (exportMethodReturnTypeCollectionResult.ExpectedClassAttributeType is null)
{
// 这是不带 Attribute 的收集
// 以下生成格式大概如下的代码
// yield return (typeof(CurrentFoo), () => new CurrentFoo());
var typeName = TypeSymbolHelper.TypeSymbolToFullName(namedTypeSymbol);
methodCode.AppendLine(SourceCodeGeneratorHelper.IndentSource(
$" yield return (typeof({typeName}), () => new {typeName}());",
numIndentations: 1));
}
else
{
// 以下生成格式大概如下的代码
// yield return (typeof(CurrentFoo), new F1Attribute(), () => new CurrentFoo());
var attribute = namedTypeSymbol.GetAttributes().First(t =>
SymbolEqualityComparer.Default.Equals(t.AttributeClass,
exportMethodReturnTypeCollectionResult
.ExpectedClassAttributeType));
var attributeCreatedCode = AttributeCodeReWriter.GetAttributeCreatedCode(attribute);

var typeName = TypeSymbolHelper.TypeSymbolToFullName(namedTypeSymbol);
methodCode.AppendLine(SourceCodeGeneratorHelper.IndentSource(
$" yield return (typeof({typeName}), {attributeCreatedCode}, () => new {typeName}());",
numIndentations: 1));
}
}

var methodSource = SourceCodeGeneratorHelper.GeneratePartialMethodCode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers;
/// <summary>
/// 从标记的方法导出类型
/// </summary>
// 形如 private static partial IEnumerable<(Type type, FooAttribute attribute, Func<FooBase> creator)> ExportFooEnumerable();
[Generator(LanguageNames.CSharp)]
public class TelescopeExportTypeToMethodIncrementalGenerator : IIncrementalGenerator
{
Expand Down Expand Up @@ -144,6 +145,30 @@ namedTypeSymbol.TypeArguments[0] is INamedTypeSymbol tupleType && tupleType.IsTu
return new ExportMethodReturnTypeCollectionResult(expectedClassBaseType, expectedClassAttributeType,
exportTypeCollectionResult, ExportMethodReturnType.EnumerableValueTupleWithTypeAttributeCreator);
}
else if (tupleType.TupleElements.Length == 2)
{
// 判断是否 `partial IEnumerable<(Type type, Func<FooBase> creator)> ExportFooEnumerable();` 的情况,没有中间的 Attribute 约束,也就是只需要导出所有继承了 FooBase 的类型即可
if (TypeSymbolHelper.TypeSymbolToFullName(tupleType.TupleElements[0].Type) != "global::System.Type")
{
// 如果首个不是 Type 类型,这就是错误的
return ReturnTypeError(nameof(Tes001_Message_EnumerableValueTupleWithTypeAttributeCreator));
}

// Func<Base>
var funcTypeSymbol = (INamedTypeSymbol) tupleType.TupleElements[1].Type;
if (!funcTypeSymbol.IsGenericType || TypeSymbolHelper.TypeSymbolToFullName(funcTypeSymbol) != "global::System.Func")
{
// 不是 Func 的
return ReturnTypeError(nameof(Tes001_Message_EnumerableValueTupleWithTypeAttributeCreator));
}

// 准备导出的类型的基类型
var expectedClassBaseType = funcTypeSymbol.TypeArguments[0];
return new ExportMethodReturnTypeCollectionResult(expectedClassBaseType,
// 没有预期的特性类型
expectedClassAttributeType: null,
exportTypeCollectionResult, ExportMethodReturnType.EnumerableValueTupleWithTypeAttributeCreator);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
context.RegisterSourceOutput(generatedCodeProvider,
(sourceProductionContext, generatedCode) =>
{
sourceProductionContext.AddSource("__AttributedTypesExport__", generatedCode);
if(!string.IsNullOrEmpty(generatedCode))
{
sourceProductionContext.AddSource("__AttributedTypesExport__", generatedCode);
}
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/TelescopeSourceGenerator/Demo/DemoLib3/F3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib3;
[F1]
public class F3 : F1
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib1;

namespace dotnetCampus.Telescope.SourceGeneratorAnalyzers.DemoLib3;

public class FooWithAttribute : F1
{
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using dotnetCampus.Telescope;
using dotnetCampus.Telescope.SourceGeneratorAnalyzers.Demo;

[assembly: MarkExport(typeof(Base), typeof(FooAttribute))]
//[assembly: MarkExport(typeof(Base), typeof(FooAttribute))]
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@ static void Main(string[] args)
{
}

var attributedTypesExport = new __AttributedTypesExport__();
ICompileTimeAttributedTypesExporter<Base, FooAttribute> exporter = attributedTypesExport;
foreach (var exportedTypeMetadata in exporter.ExportAttributeTypes())
{
// 输出导出的类型
Console.WriteLine(exportedTypeMetadata.RealType.FullName);
}
//var attributedTypesExport = new __AttributedTypesExport__();
//ICompileTimeAttributedTypesExporter<Base, FooAttribute> exporter = attributedTypesExport;
//foreach (var exportedTypeMetadata in exporter.ExportAttributeTypes())
//{
// // 输出导出的类型
// Console.WriteLine(exportedTypeMetadata.RealType.FullName);
//}
}

[dotnetCampus.Telescope.TelescopeExportAttribute(IncludeReferences = true)]
private static partial IEnumerable<(Type, F1Attribute xx, Func<DemoLib1.F1> xxx)> ExportFooEnumerable();

[dotnetCampus.Telescope.TelescopeExportAttribute(IncludeReferences = true)]
private partial IEnumerable<(Type, Func<DemoLib1.F1> xxx)> ExportF1Enumerable();
}

[F1]
Expand Down