public void TryParseOrchestration() { // Arrange var model = Calculator.Semantic; var method = Calculator.MultiplyMethod; // Act var result = DurableFunction.TryParse(model, method, out DurableFunction function); // Assert Assert.True(result); Assert.Equal("WebJobs.Extensions.DurableTask.CodeGen.Example.Calculator.Multiply", function.FullTypeName); Assert.Equal(2, function.RequiredNamespaces.Count); var requiredNamespaceList = function.RequiredNamespaces.ToList(); Assert.Equal("System.Threading.Tasks", requiredNamespaceList[0]); Assert.Equal("Microsoft.Azure.WebJobs.Extensions.DurableTask", requiredNamespaceList[1]); Assert.Equal("Multiply", function.Name); Assert.Equal(DurableFunctionKind.Orchestration, function.Kind); Assert.Equal(2, function.Parameters.Count); Assert.Equal("int", function.Parameters[0].Type.ToString()); Assert.Equal("int", function.Parameters[1].Type.ToString()); Assert.Equal("num1", function.Parameters[0].Name); Assert.Equal("num2", function.Parameters[1].Name); Assert.Equal("Task<int>", function.ReturnType); Assert.Equal("<int>", function.CallGenerics); }
public void OnVisitSyntaxNode(GeneratorSyntaxContext context) { try { // Only search on one visit, because we just need need to find the DurableTask types // once and then hold a reference of them to use later. if (!Searched) { Searched = true; Initialized = true; Initialized &= DurableFunctionUtility.TryFindDurableOrchestrationContextType(context.SemanticModel, out var durableOrchestrationContextTypeSymbol); Initialized &= DurableFunctionUtility.TryFindDurableClientType(context.SemanticModel, out var durableClientTypeSymbol); DurableOrchestrationContextTypeSymbol = durableOrchestrationContextTypeSymbol; DurableClientTypeSymbol = durableClientTypeSymbol; } // Must have found DurableTask types in order to find DurableFunctions if (!Initialized) { return; } // Looking for things that are methods if (!(context.Node is MethodDeclarationSyntax method)) { return; } if (!DurableFunction.TryParse(context.SemanticModel, method, out DurableFunction function)) { return; } Debug.WriteLine($"Adding function '{function.Name}'"); DurableFunctions.Add(function); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } }
protected MethodDeclarationSyntax GenerateStartMethod( DurableFunction function ) { const string instanceParameterName = "instance"; var methodName = $"Start{function.Name}"; var leadingTrivia = AsCrefSummary(function.FullTypeName); var parameterList = AsParameterList() .AddParameters(function.Parameters.Select(p => AsParameter(p.Type.ToString(), p.Name)).ToArray()) .AddParameters(AsParameter("string", instanceParameterName).WithDefault(SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)))); return(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("Task<string>"), methodName) .WithLeadingTrivia(leadingTrivia) .WithParameterList(parameterList) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))); }
private MethodDeclarationSyntax GenerateCallerMethod( DurableFunction function, bool withRetry ) { var parameters = function.Parameters; var methodName = $"{function.Name}{(withRetry ? "WithRetry" : string.Empty)}"; var leadingTrivia = AsCrefSummary(function.FullTypeName); var parameterList = AsParameterList() .AddParameters(withRetry ? AsParameter("RetryOptions", "options") : null) .AddParameters(function.Parameters.Select(p => AsParameter(p.Type.ToString(), p.Name)).ToArray()); return(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName(function.ReturnType), methodName) .WithLeadingTrivia(leadingTrivia) .WithParameterList(parameterList) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))); }
private MethodDeclarationSyntax GenerateCallerMethod( DurableFunction function, bool withRetry ) { var parameters = function.Parameters; var methodName = $"{function.Name}{(withRetry ? "WithRetry" : string.Empty)}"; var leadingTrivia = AsCrefSummary(function.FullTypeName); var modifiers = AsModifierList(SyntaxKind.PublicKeyword); var parameterList = AsParameterList() .AddParameters(withRetry ? AsParameter("RetryOptions", "options") : null) .AddParameters(function.Parameters.Select(p => AsParameter(p.Type.ToString(), p.Name)).ToArray()); var callMethodName = (function.Kind == DurableFunctionKind.Orchestration) ? $"CallSubOrchestrator{((withRetry) ? "WithRetry" : string.Empty)}Async" : $"CallActivity{((withRetry) ? "WithRetry" : string.Empty)}Async"; var callGenerics = function.CallGenerics; var functionNameParameter = $"\"{function.Name}\""; var callRetryParameter = withRetry ? ", options" : string.Empty; var callContextParameters = (parameters.Count == 0) ? ", null" : (parameters.Count == 1) ? $", {parameters[0].Name}" : $", ({string.Join(",", parameters.Select(p => p.Name))})"; var callParameters = $"{functionNameParameter}{callRetryParameter}{callContextParameters}"; var bodyText = $"return _context.{callMethodName}{callGenerics}({callParameters});"; var returnStatement = SyntaxFactory.ParseStatement(bodyText); var bodyBlock = SyntaxFactory.Block(returnStatement); return(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName(function.ReturnType), methodName) .WithModifiers(modifiers) .WithLeadingTrivia(leadingTrivia) .WithParameterList(parameterList) .WithBody(bodyBlock)); }
protected MethodDeclarationSyntax GenerateStartMethod( DurableFunction function ) { const string instanceParameterName = "instance"; var parameters = function.Parameters; var methodName = $"Start{function.Name}"; var modifiers = AsModifierList(SyntaxKind.PublicKeyword); var leadingTrivia = AsCrefSummary(function.FullTypeName); var parameterList = AsParameterList() .AddParameters(function.Parameters.Select(p => AsParameter(p.Type.ToString(), p.Name)).ToArray()) .AddParameters(AsParameter("string", instanceParameterName).WithDefault(SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)))); // Add body var callMethodName = "StartNewAsync"; var functionNameParameter = $"\"{function.Name}\""; var callContextParameters = (parameters.Count == 0) ? $", {instanceParameterName}" : (parameters.Count == 1) ? $", {instanceParameterName}, {parameters[0].Name}" : $", {instanceParameterName}, ({string.Join(",", parameters.Select(p => p.Name))})"; var callParameters = $"{functionNameParameter}{callContextParameters}"; var bodyText = $"return _client.{callMethodName}({callParameters});"; var returnStatement = SyntaxFactory.ParseStatement(bodyText); var bodyBlock = SyntaxFactory.Block(returnStatement); return(SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("Task<string>"), methodName) .WithModifiers(modifiers) .WithLeadingTrivia(leadingTrivia) .WithParameterList(parameterList) .WithBody(bodyBlock)); }
protected MethodDeclarationSyntax GenerateCallMethodWithoutRetry(DurableFunction function) { return(GenerateCallerMethod(function, withRetry: false)); }