private static ClassDeclarationSyntax CreateClass( SemanticModel semanticModel, MethodDeclarationSyntax method) { var mi = new MethodInspector(method); var semanticQuery = mi.CreateSemanticQuery(semanticModel); var isTaskReturn = SymbolSemanticQuery.IsTask( semanticQuery.GetReturnType().Symbol); var parameters = mi.Parameters.Select(par => par.Type).ToList(); var recordBuilder = new RecordBuilder($"{mi.Name}Command") .AddModifiers(Modifiers.Public) .AddProperties( mi.Parameters .Select(p => (p.Type, p.Name)).ToArray()); if (isTaskReturn.IsTask()) { AddTaskUtilities(recordBuilder, Types.Bool); } else if (isTaskReturn.IsTypedTask(out var typeSymbol)) { AddTaskUtilities( recordBuilder, GH.Identifier(SymbolSemanticQuery.GetName(typeSymbol))); } 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 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 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 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() }