예제 #1
0
        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());
        }
예제 #2
0
        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());
        }
예제 #3
0
        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);
        }
예제 #4
0
 public static ArgumentSyntax ArgumentFromIdentifier(SyntaxToken identifier) =>
 SF.Argument(SF.IdentifierName(identifier.WithoutTrivia()));
예제 #5
0
        /// <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());
        }
예제 #6
0
 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))))));
 }
예제 #7
0
 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))))));
 }
예제 #8
0
 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))))));
 }
예제 #10
0
        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));
        }
예제 #11
0
        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()
        }