Skip to content

Commit a402d5c

Browse files
committed
- Implement generating interface file.
1 parent c3f30a6 commit a402d5c

4 files changed

Lines changed: 56 additions & 14 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// <auto-generated/>
2+
#nullable restore
3+
4+
namespace TestLibrary;
5+
6+
internal interface IOrchestrator
7+
{
8+
public Task<int> Execute();
9+
}

AsyncTaskOrchestratorGenerator.UnitTests/Tests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public void Setup() {
1919
[Test]
2020
public async Task OneInterface() {
2121
var source = await ReadCSharpFile<OrchestratorSpec>(true);
22-
var generated = await ReadCSharpFile<Orchestrator>(false);
22+
var generatedClass = await ReadCSharpFile<Orchestrator>(false);
23+
var generatedInterface = await ReadCSharpFile<IOrchestrator>(false);
2324

2425
await new VerifyCS.Test
2526
{
@@ -35,7 +36,8 @@ public async Task OneInterface() {
3536
Sources = { source },
3637
GeneratedSources =
3738
{
38-
(typeof(Main), "Orchestrator.generated.cs", SourceText.From(generated, Encoding.UTF8, SourceHashAlgorithm.Sha256)),
39+
(typeof(Main), "Orchestrator.generated.cs", SourceText.From(generatedClass, Encoding.UTF8, SourceHashAlgorithm.Sha256)),
40+
(typeof(Main), "IOrchestrator.generated.cs", SourceText.From(generatedInterface, Encoding.UTF8, SourceHashAlgorithm.Sha256)),
3941
},
4042
},
4143
}.RunAsync();

AsyncTaskOrchestratorGenerator/Main.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CSharp.Syntax;
33
using Microsoft.CodeAnalysis.Text;
4-
using System;
5-
using System.Collections.Generic;
6-
using System.Linq;
74
using System.Text;
85
using System.Threading;
96

@@ -32,9 +29,11 @@ private static (INamedTypeSymbol, SemanticModel) GetSemanticTargetForGeneration(
3229
}
3330

3431
private static void Execute(SourceProductionContext context, (INamedTypeSymbol typeSymbol, SemanticModel semanticModel) typeInfo) {
35-
var (source, className) = OutputGenerator.GenerateOutputs(typeInfo);
32+
var (classSource, className) = OutputGenerator.GenerateClassOutputs(typeInfo);
33+
var (interfaceSource, interfaceName) = OutputGenerator.GenerateInterfaceOutputs(typeInfo.typeSymbol);
3634

37-
context.AddSource($"{className}.generated.cs", SourceText.From(source, Encoding.UTF8, SourceHashAlgorithm.Sha256));
35+
context.AddSource($"{className}.generated.cs", SourceText.From(classSource, Encoding.UTF8, SourceHashAlgorithm.Sha256));
36+
context.AddSource($"{interfaceName}.generated.cs", SourceText.From(interfaceSource, Encoding.UTF8, SourceHashAlgorithm.Sha256));
3837
}
3938
}
4039
}

AsyncTaskOrchestratorGenerator/OutputGenerator.cs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ namespace AsyncTaskOrchestratorGenerator
88
{
99
internal static class OutputGenerator
1010
{
11-
public static (string source, string className) GenerateOutputs((INamedTypeSymbol typeSymbol, SemanticModel semanticModel) typeInfo) {
11+
public static (string source, string className) GenerateClassOutputs((INamedTypeSymbol typeSymbol, SemanticModel semanticModel) typeInfo) {
1212
var type = typeInfo.typeSymbol;
1313
var semanticModel = typeInfo.semanticModel;
14-
15-
var constructorArguments = type.GetAttributes().First((a) => a.AttributeClass.Name == nameof(AsyncTaskOrchestratorAttribute)).ConstructorArguments;
14+
var constructorArguments = GetAttributeConstructorArguments(type);
1615
var className = constructorArguments.First().Value.ToString();
1716
var executeMethodName = constructorArguments.ElementAt(1).Value.ToString();
1817

@@ -50,11 +49,37 @@ namespace {type.ContainingNamespace.ToDisplayString()};
5049
return (source, className);
5150
}
5251

52+
private static System.Collections.Immutable.ImmutableArray<TypedConstant> GetAttributeConstructorArguments(INamedTypeSymbol type) {
53+
return type.GetAttributes().First((a) => a.AttributeClass.Name == nameof(AsyncTaskOrchestratorAttribute)).ConstructorArguments;
54+
}
55+
56+
public static (string source, string interfaceName) GenerateInterfaceOutputs(INamedTypeSymbol type) {
57+
var constructorArguments = GetAttributeConstructorArguments(type);
58+
var className = constructorArguments.First().Value.ToString();
59+
var executeMethodName = constructorArguments.ElementAt(1).Value.ToString();
60+
var interfaceName = $"I{className}";
61+
62+
var accessModifier = type.DeclaredAccessibility.ToString().ToLower();
63+
var executeMethod = GetExecuteMethod(type);
64+
var executeMethodAccessibility = executeMethod.DeclaredAccessibility.ToString().ToLower();
65+
var formattedExecuteMethod = $"{executeMethodAccessibility} {executeMethod.ReturnType} {executeMethodName}();";
66+
67+
var source =
68+
$@"// <auto-generated/>
69+
#nullable restore
70+
71+
namespace {type.ContainingNamespace.ToDisplayString()};
72+
73+
{accessModifier} interface {interfaceName}
74+
{{
75+
{formattedExecuteMethod}
76+
}}
77+
";
78+
return (source, interfaceName);
79+
}
80+
5381
private static (ExecuteMethodSignatureData, Dictionary<string, TaskData>, TaskData) CreateExecuteMethodData(INamedTypeSymbol type, IEnumerable<IFieldSymbol> fields, string executeMethodName) {
54-
var executeMethod = type
55-
.GetMembers()
56-
.Where(m => m is IMethodSymbol)
57-
.First(m => (m as IMethodSymbol).MethodKind == MethodKind.Ordinary) as IMethodSymbol;
82+
var executeMethod = GetExecuteMethod(type);
5883
var statements = (executeMethod.DeclaringSyntaxReferences.First().GetSyntax() as MethodDeclarationSyntax).Body.Statements;
5984
var variableStatements = statements.Remove(statements.Last());
6085

@@ -110,6 +135,13 @@ private static (ExecuteMethodSignatureData, Dictionary<string, TaskData>, TaskDa
110135
}, variableData.ToDictionary(taskData => taskData.OutputName), finalTaskData);
111136
}
112137

138+
private static IMethodSymbol GetExecuteMethod(INamedTypeSymbol type) {
139+
return type
140+
.GetMembers()
141+
.Where(m => m is IMethodSymbol)
142+
.First(m => (m as IMethodSymbol).MethodKind == MethodKind.Ordinary) as IMethodSymbol;
143+
}
144+
113145
private static string FormatExecuteMethod(ExecuteMethodSignatureData signatureData, Dictionary<string, TaskData> data, TaskData finalTaskData) {
114146
var formattedTaskDeclarations = data.Select(keyValue => {
115147
var item = keyValue.Value;

0 commit comments

Comments
 (0)