private static SyntaxNode CompileFunction(SyntaxNode node, Scope scope) { var method = (MethodDeclarationSyntax)node; var concurrentClass = method.Identifier.ToString() + "__concurrent"; //create a concurrent class with the method var @class = CSharp.ClassDeclaration(concurrentClass) .AddMembers(method); //add it to the parent var document = scope.GetDocument(); document.change(node.Parent, AddFunctionClass(@class)); //create a substitute call var invocation = Templates.FunctionInvocation .Get <ExpressionStatementSyntax>( concurrentClass, method.Identifier); if (method.ParameterList.Parameters.Count > 0) { var invoke = (InvocationExpressionSyntax)invocation.Expression; var arguments = method.ParameterList .Parameters .Select(parameter => CSharp.Argument(CSharp.IdentifierName( parameter.Identifier))) .Union(invoke.ArgumentList.Arguments); invocation = invocation .WithExpression(invoke .WithArgumentList(CSharp.ArgumentList(CSharp.SeparatedList( arguments)))); } return(method .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList <AttributeSyntax>(new[] { CSharp.Attribute(CSharp.ParseName("Concurrent")) }))) .AddParameterListParameters(Templates .FunctionParameters .Parameters .ToArray()) .WithBody(CSharp.Block(invocation))); }
private static SyntaxNode CompileService(SyntaxNode node, Scope scope) { var @class = (node as ClassDeclarationSyntax) .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList(new[] { CSharp .Attribute(CSharp .ParseName("Service"), CSharp.ParseAttributeArgumentList( $"(id : \"{Guid.NewGuid()}\")")) }))); var options = new Options(); return(ConcurrentExtension.CompileClass(options)(@class, scope)); }
private static SyntaxNode Compile(SyntaxNode node, Scope scope, bool isSingleton, Options options) { Debug.Assert(node is ClassDeclarationSyntax); var @class = (node as ClassDeclarationSyntax) .AddBaseListTypes( CSharp.SimpleBaseType(CSharp.ParseTypeName( "ConcurrentObject"))); if (options.GenerateInterface) { @class = @class.AddBaseListTypes( CSharp.SimpleBaseType(CSharp.ParseTypeName( "I" + (node as ClassDeclarationSyntax).Identifier.ToString()))); } var className = @class.Identifier.ToString(); var ctx = new Class(className, scope, isSingleton); scope.set <Class>(ctx); foreach (var member in @class.Members) { if (member is PropertyDeclarationSyntax) { compileProperty(member as PropertyDeclarationSyntax, ctx, scope); } else if (member is MethodDeclarationSyntax) { var method = member as MethodDeclarationSyntax; if (compileMethod(method, ctx, scope, options, isSingleton)) { var isVoid = method.ReturnType.ToString() == "void"; var taskArgs = isVoid ? new[] { CSharp.Argument(Templates.NullCancelationToken), CSharp.Argument(Roslyn.@null), CSharp.Argument(Roslyn.@null) } : new[] { CSharp.Argument(Templates.NullCancelationToken) }; var taskCall = CSharp .InvocationExpression( CSharp.IdentifierName(method.Identifier), CSharp.ArgumentList(CSharp.SeparatedList( method .ParameterList .Parameters .Select(parameter => CSharp .Argument(CSharp.IdentifierName(parameter.Identifier))) .Union( taskArgs)))); var newMethod = method .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList(new[] { CSharp .Attribute(CSharp .ParseName("Concurrent")) }))) .WithBody(CSharp.Block() .WithStatements(CSharp.List(new[] { isVoid ? Templates .SynchVoidMethod .Get <StatementSyntax>(taskCall) : Templates .SynchReturnMethod .Get <StatementSyntax>(taskCall) }))); if (isSingleton && ctx.willReplace(method)) { //singleton methods must change into __methodName var fs = (newMethod .Body .Statements .First() as ExpressionStatementSyntax) .Expression as InvocationExpressionSyntax; var newId = "__" + method.Identifier.ToString(); newMethod = newMethod .ReplaceNode(fs, fs.WithExpression(CSharp.IdentifierName(newId))) .WithIdentifier(CSharp.ParseToken(newId)); } ctx.Replace(method, newMethod); } } } //all concurrent compilation has been done, produce @class = ctx.Update(@class); if (isSingleton) { @class = @class.AddMembers( Templates.SingletonField .Get <MemberDeclarationSyntax>(@class.Identifier), Templates.SingletonInit .Get <MemberDeclarationSyntax>(@class.Identifier)); } //generate the interface if (options.GenerateInterface) { scope.AddType(CreateInterface(@class)); } if (options.GenerateRemote) { //add a remote type, to be used with an identity server var remoteMethod = null as MethodDeclarationSyntax; createRemoteType(@class, scope, out remoteMethod); @class = @class.AddMembers(remoteMethod); } if (options.GenerateID) { @class = @class.AddMembers(Templates .ObjectId .Get <MemberDeclarationSyntax>()); } //schedule linking var document = scope.GetDocument(); return(document.change(@class, Link(ctx), null)); }
private ClassDeclarationSyntax addAttribute(ClassDeclarationSyntax @class, string attributeName, bool optional) { if (@class.AttributeLists.Any(attrList => attrList .Attributes .Any(attr => attr.Name.ToString() == attributeName))) { return(@class); } return(@class .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList(new[] { CSharp .Attribute(CSharp .ParseName(attributeName), optional ? Templates.GuidAttributeArgument(optional: true) : Templates.GuidAttributeArgument(optional: false)) })))); }