private static ClassDeclarationSyntax CreateClass( ClassDeclarationSyntax parentClass, ConstructorDeclarationSyntax constructor) { ObjectCreationExpressionSyntax CreateMoq(TypeSyntax moqType) => EGH.CreateObject( moqType, SF.Argument( EGH.MemberAccess( GH.Identifier("MockBehavior"), GH.Identifier("Strict")))); var mi = new MethodInspector(constructor); var recordBuilder = new RecordBuilder($"{mi.Name}Test") .AddModifiers(Modifiers.Public); foreach (var p in mi.Parameters) { var mockedType = GetMockedType(p.Type); var moqType = GH.GenericName("Mock", mockedType); recordBuilder.AddField(moqType, MockName(p.Name), CreateMoq(moqType)); } recordBuilder.AddMethod(GenerateCreateSut(parentClass, mi)); return(recordBuilder.Build()); }
private static MethodDeclarationSyntax GenerateCreateSut( ClassDeclarationSyntax classDeclaration, MethodInspector constructorInspector) { var methodBuilder = new MethodBuilder(GH.IdentifierToken("CreateSut")) .Modifiers(Modifiers.Private); var constructorParameters = constructorInspector .Parameters .Select(p => SF.Argument( EGH.MemberAccess( EGH.ThisMemberAccess( GH.Identifier(MockName(p.Name)) ), GH.Identifier("Object") ) ) ); methodBuilder.ArrowBody( EGH.Arrow( EGH.CreateObject( SF.IdentifierName(classDeclaration.Identifier), constructorParameters.ToArray()))); return(methodBuilder.Build()); }
private static void AddTaskUtilities( RecordBuilder recordBuilder, TypeSyntax tcsType) { var tcs = GeneratorHelper.GenericName( "TaskCompletionSource", tcsType); var initializer = ExpressionGenerationHelper.CreateObject(tcs); recordBuilder.AddField(tcs, "result", initializer); var resolveMethod = new MethodBuilder(GH.IdentifierToken("Resolve")) .Modifiers(Modifiers.Public) .AddParameter(tcsType, GH.IdentifierToken("value")) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetResult"), SF.Argument(GH.Identifier("value"))) .Build()) .Build(); var cancelMethod = new MethodBuilder(GH.IdentifierToken("Cancel")) .Modifiers(Modifiers.Public) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetCanceled")) .Build()) .Build(); var rejectMethod = new MethodBuilder(GH.IdentifierToken("Reject")) .Modifiers(Modifiers.Public) .AddParameter(GH.Identifier("Exception"), GH.IdentifierToken("exc")) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetException"), SF.Argument(GH.Identifier("exc"))) .Build()) .Build(); recordBuilder.AddMethod(resolveMethod); recordBuilder.AddMethod(cancelMethod); recordBuilder.AddMethod(rejectMethod); }
public static ArgumentSyntax ArgumentFromIdentifier(SyntaxToken identifier) => SF.Argument(SF.IdentifierName(identifier.WithoutTrivia()));
/// <summary> /// Generates switch cases for the provided grain type. /// </summary> /// <param name="grainType"> /// The grain type. /// </param> /// <param name="methodIdArgument"> /// The method id argument, which is used to select the correct switch label. /// </param> /// <param name="generateMethodHandler"> /// The function used to generate switch block statements for each method. /// </param> /// <returns> /// The switch cases for the provided grain type. /// </returns> public static SwitchSectionSyntax[] GenerateGrainInterfaceAndMethodSwitch( Type grainType, ExpressionSyntax methodIdArgument, Func <MethodInfo, StatementSyntax[]> generateMethodHandler) { var interfaces = GrainInterfaceUtils.GetRemoteInterfaces(grainType); interfaces[GrainInterfaceUtils.GetGrainInterfaceId(grainType)] = grainType; // Switch on interface id. var interfaceCases = new List <SwitchSectionSyntax>(); foreach (var @interface in interfaces) { var interfaceType = @interface.Value; var interfaceId = @interface.Key; var methods = GrainInterfaceUtils.GetMethods(interfaceType); var methodCases = new List <SwitchSectionSyntax>(); // Switch on method id. foreach (var method in methods) { // Generate switch case. var methodId = GrainInterfaceUtils.ComputeMethodId(method); var methodType = method; // Generate the switch label for this interface id. var methodIdSwitchLabel = SF.CaseSwitchLabel( SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId))); // Generate the switch body. var methodInvokeStatement = generateMethodHandler(methodType); methodCases.Add( SF.SwitchSection().AddLabels(methodIdSwitchLabel).AddStatements(methodInvokeStatement)); } // Generate the switch label for this interface id. var interfaceIdSwitchLabel = SF.CaseSwitchLabel( SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId))); // Generate the default case, which will throw a NotImplementedException. var errorMessage = SF.BinaryExpression( SyntaxKind.AddExpression, "interfaceId=".GetLiteralExpression(), SF.BinaryExpression( SyntaxKind.AddExpression, SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)), SF.BinaryExpression( SyntaxKind.AddExpression, ",methodId=".GetLiteralExpression(), methodIdArgument))); var throwStatement = SF.ThrowStatement( SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax()) .AddArgumentListArguments(SF.Argument(errorMessage))); var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement); // Generate switch statements for the methods in this interface. var methodSwitchStatements = SF.SwitchStatement(methodIdArgument).AddSections(methodCases.ToArray()).AddSections(defaultCase); // Generate the switch section for this interface. interfaceCases.Add( SF.SwitchSection().AddLabels(interfaceIdSwitchLabel).AddStatements(methodSwitchStatements)); } return(interfaceCases.ToArray()); }
public static ExpressionSyntax Call(this ExpressionSyntax expression, string instruction, IEnumerable <ExpressionSyntax> arguments) { return(SF.InvocationExpression(expression.Dot(instruction), SF.ArgumentList(SF.SeparatedList( arguments.Select(x => SF.Argument(x)))))); }
public static ExpressionSyntax Call(this ExpressionSyntax expression, SimpleNameSyntax instruction, params ExpressionSyntax[] arguments) { return(SF.InvocationExpression(expression.Dot(instruction), SF.ArgumentList(SF.SeparatedList( arguments.Select(x => SF.Argument(x)))))); }
public static ExpressionSyntax Invoke(this ExpressionSyntax expression, params ExpressionSyntax[] arguments) { return(SF.InvocationExpression(expression, SF.ArgumentList(SF.SeparatedList( arguments.Select(x => SF.Argument(x)))))); }
public ExpressionSyntax GetInput() { return(SF.ElementAccessExpression(SF.IdentifierName(inputBuffer), SF.BracketedArgumentList(SF.SingletonSeparatedList(SF.Argument(SF.IdentifierName(inputIndex)))))); }
public IEnumerable <StatementSyntax> GetYields(IEnumerable <ExpressionSyntax> yields, int numYields) { if (numYields == 0) { yield break; } if (numYields > BufferSize) { throw new NotImplementedException(); } yield return(SF.IfStatement(SF.BinaryExpression(SyntaxKind.GreaterThanExpression, SF.IdentifierName(outputIndex), SH.Literal(BufferSize - numYields)), SF.Block( SF.ExpressionStatement(SF.IdentifierName(outputParameter).Dot("Write").Invoke(SF.IdentifierName(outputBuffer), SH.Literal(0), SF.IdentifierName(outputIndex))), SH.Assignment(SF.IdentifierName(outputIndex), SH.Literal(0))))); int index = 0; foreach (var yieldSyntax in yields) { yield return(SH.Assignment(SF.ElementAccessExpression(SF.IdentifierName(outputBuffer), SF.BracketedArgumentList(SF.SingletonSeparatedList(SF.Argument( SF.BinaryExpression(SyntaxKind.AddExpression, SF.IdentifierName(outputIndex), SH.Literal(index)))))), yieldSyntax)); ++index; } yield return(SH.Assignment(SF.IdentifierName(outputIndex), SH.Literal(numYields), SyntaxKind.AddAssignmentExpression)); }
public async Task Test2() { // Arrange var text = @" using System; using System.Threading.Tasks; namespace RefactorClasses.Analysis.Test { [StateMachine(ContextType = typeof(ContextBase), StateType = typeof(StateBase), TriggerType = (typeof(TriggerBase)))] public class StateMachineImpl { public void DoSomething( int a, Test1 testClass, string fdeee) { } public async Task<int> TaskMethodReturningSomething(int a, float b) { return 10; } public System.Threading.Tasks.Task AsyncOperationsSupport(int a, float b) { return Task.CompletedTask; } public async Task TaskMethod(int a, float b) { return; } public async Task TaskMethodWithArrays(int[] a, float[] b) { return; } public async Task TaskMethodWithTuples((int, float) a, float[] b) { return; } private void PrintSomething() {} } public class TriggerBase { } [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class StateMachineAttribute : Attribute { public Type StateType { get; set; } public Type TriggerType { get; set; } public Type ContextType { get; set; } } }"; var tree = CSharpSyntaxTree.ParseText(text); var compilation = TestHelpers.CreateCompilation(tree); var semanticModel = compilation.GetSemanticModel(tree); var classDeclaration = TestHelpers.FindFirstClassDeclaration(await tree.GetRootAsync()); var classInspector = new ClassInspector(classDeclaration); var semanticInspector = classInspector.CreateSemanticQuery(semanticModel); bool foundAttribute = semanticInspector.TryFindFirstAttributeMatching( "StateMachineAttribute", out var atData); var triggerType = atData ?.NamedArguments .FirstOrDefault(kvp => kvp.Key.Equals("TriggerType")); if (triggerType == null) { return; } var methods = classInspector.FindMatchingMethods( mi => mi.Check(m => m.IsPublic() && !m.IsStatic()).Passed); foreach (var method in methods) { var msq = method.CreateSemanticQuery(semanticModel); var returnType = msq.GetReturnType(); var isTaskReturn = IsTask(returnType.Symbol); var parameters = method.Parameters.Select(par => par.Type).ToList(); // TODO: will throw if array var triggerTypeName = triggerType.Value.Value.Value as INamedTypeSymbol; if (triggerTypeName == null) { return; } var recordBuilder = new RecordBuilder(method.Name) .AddModifiers(Modifiers.Public) .AddBaseTypes(GeneratorHelper.Identifier(triggerTypeName.Name)) .AddProperties( method.Parameters .Select(p => (p.Type, p.Name)).ToArray()); if (isTaskReturn.Value.IsTask()) { var boolTcs = GeneratorHelper.GenericName( "TaskCompletionSource", Types.Bool); var initializer = ExpressionGenerationHelper.CreateObject(boolTcs); recordBuilder.AddField(boolTcs, "result", initializer); var resolveMethod = new MethodBuilder(GH.IdentifierToken("Resolve")) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetResult"), SF.Argument(GH.Identifier("true"))) .Build()) .Build(); var cancelMethod = new MethodBuilder(GH.IdentifierToken("Cancel")) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetCanceled")) .Build()) .Build(); var rejectMethod = new MethodBuilder(GH.IdentifierToken("Cancel")) .AddParameter(GH.Identifier("Exception"), GH.IdentifierToken("exc")) .Body(new BodyBuilder() .AddVoidMemberInvocation( GH.Identifier("result"), GH.Identifier("TrySetException"), SF.Argument(GH.Identifier("exc"))) .Build()) .Build(); recordBuilder.AddMethod(resolveMethod); recordBuilder.AddMethod(cancelMethod); recordBuilder.AddMethod(rejectMethod); int ddddd = 0; } else if (isTaskReturn.Value.IsTypedTask(out var taskType)) { var typedTcs = GeneratorHelper.GenericName( "TaskCompletionSource", GeneratorHelper.Identifier(taskType.Name)); var initializer = ExpressionGenerationHelper.CreateObject(typedTcs); recordBuilder.AddField(typedTcs, "result", initializer); } var record = recordBuilder.Build(); // TODO: if task is returned -> generate TaskCompletionSource // and matching methods var rs = record.ToString(); int a = 10; } // Act // Assert IsTaskResult?IsTask(ISymbol symbol) { var namedSymbol = symbol as INamedTypeSymbol; if (namedSymbol == null) { return(null); } if (namedSymbol.Name == "Task" && namedSymbol?.ContainingNamespace?.ToString() == "System.Threading.Tasks") { var firstTypeArg = namedSymbol.TypeArguments.FirstOrDefault(); if (firstTypeArg != null) { return(IsTaskResult.TypedTask(firstTypeArg)); } else { return(IsTaskResult.Task()); } } return(IsTaskResult.NotATask()); } //var tcs = new TaskCompletionSource<int>(); //tcs.TrySetException() }