Skip to content

Commit

Permalink
Merge pull request #40 from dotnet-campus/t/lindexi/TelescopeExport
Browse files Browse the repository at this point in the history
支持无特性方式导出
  • Loading branch information
walterlv authored Dec 7, 2023
2 parents cd16583 + 892d74e commit 47a8ae3
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 24 deletions.
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

0 comments on commit 47a8ae3

Please sign in to comment.