コード例 #1
0
ファイル: MsTestStub2Moq.cs プロジェクト: molinch/kickmstest
        public ExpressionStatementSyntax TryReplaceAssignmentExpressionWithMethodCall(ExpressionStatementSyntax node, INamedTypeSymbol typeSymbol = null)
        {
            // There are 2 cases to consider
            // Either we stub a method/property by setting a property; set value being the stub lambda
            // Or by invoking a method having a single argument; method argument being the stub lambda

            StubbedCall msStub = null;

            var assignment = node.ChildNodes().OfType <AssignmentExpressionSyntax>().FirstOrDefault();

            if (assignment != null)
            {
                var member = assignment.ChildNodes().FirstOrDefault() as MemberAccessExpressionSyntax;
                if (member == null)
                {
                    return(null);
                }

                var resultExpression = assignment.Right;

                msStub = StubMsTestMethodOrPropertyCall(assignment, member, resultExpression, typeSymbol);
            }
            else
            {
                var invocation = node.ChildNodes().OfType <InvocationExpressionSyntax>().FirstOrDefault();
                if (invocation == null)
                {
                    return(null);
                }

                var member = invocation.ChildNodes().FirstOrDefault() as MemberAccessExpressionSyntax;
                if (member == null)
                {
                    return(null);
                }

                var argument = invocation.ArgumentList.ChildNodes().FirstOrDefault() as ArgumentSyntax;
                if (argument == null)
                {
                    return(null);
                }

                msStub = StubMsTestMethodOrPropertyCall(invocation, member, argument.Expression, typeSymbol);
            }

            if (msStub != null)
            {
                var moqStub = MockMethodOrPropertyCall(msStub);

                var stubDefinition = SyntaxFactory.ExpressionStatement(moqStub.NewNode)
                                     .WithLeadingTrivia(node.GetLeadingTrivia())
                                     .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);

                return(stubDefinition);
            }

            return(null);
        }
コード例 #2
0
ファイル: MsTestStub2Moq.cs プロジェクト: molinch/kickmstest
        private MoqStub MockMethodOrPropertyCall(StubbedCall msStub)
        {
            var trivia = new List <SyntaxTrivia>()
            {
                SyntaxFactory.CarriageReturnLineFeed
            };

            trivia.AddRange(msStub.OriginalLeadingTrivia);
            trivia.Add(SyntaxFactory.Tab);

            var stubIdentifier = MoqStub.GetStubDefinitionIdentifierName(msStub.Identifier.Identifier.ValueText)
                                 .WithTrailingTrivia(trivia);
            var setup        = SyntaxFactory.IdentifierName("Setup");
            var memberAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, stubIdentifier, setup);

            var stubArguments = new List <ArgumentSyntax>();
            var arguments     = msStub.Stubbed.Arguments.ToList();

            foreach (var arg in msStub.Stubbed.Arguments)
            {
                var typeName = arg.ToDisplayString();

                var it                 = SyntaxFactory.IdentifierName("It");
                var isAny              = IdentifierNameHelper.CreateGenericName("IsAny", typeName);
                var anyValue           = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, it, isAny);
                var anyValueInvocation = SyntaxFactory.InvocationExpression(anyValue);

                var stubArgument = SyntaxFactory.Argument(anyValueInvocation);
                stubArguments.Add(stubArgument);
            }
            var argumentList = SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(stubArguments));

            var typeArguments    = (msStub.Stubbed.MethodOrPropertySymbol as IMethodSymbol)?.TypeArguments.Select(a => a.ToDisplayString());
            var stubLambdaAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("c"),
                                                                        IdentifierNameHelper.CreateName(msStub.Stubbed.MethodOrPropertySymbol.Name, typeArguments));
            var stubLambdaParam = SyntaxFactory.Parameter(SyntaxFactory.Identifier("c"));
            SimpleLambdaExpressionSyntax stubLambda;

            if (msStub.Stubbed.MethodOrPropertySymbol.Kind == SymbolKind.Property)
            {
                stubLambda = SyntaxFactory.SimpleLambdaExpression(stubLambdaParam, stubLambdaAccess).NormalizeWhitespace();
            }
            else
            {
                var stubLambdaBody = SyntaxFactory.InvocationExpression(stubLambdaAccess, argumentList);
                stubLambda = SyntaxFactory.SimpleLambdaExpression(stubLambdaParam, stubLambdaBody).NormalizeWhitespace();
            }

            var stubCall = SyntaxFactory
                           .InvocationExpression(memberAccess, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(stubLambda) })))
                           .WithTrailingTrivia(trivia);

            SimpleNameSyntax ret;

            if (msStub.Stubbed.ReturnType == null)
            {
                ret = IdentifierNameHelper.CreateName("Callback", msStub.Stubbed.Arguments.Select(a => a.ToDisplayString()));
            }
            else
            {
                ret = IdentifierNameHelper.CreateName("Returns", msStub.Stubbed.Arguments.Select(a => a.ToDisplayString()));
            }

            var retArgsList = SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(msStub.StubReturn));
            var retArgs     = SyntaxFactory.ArgumentList(retArgsList);

            var fullExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, stubCall, ret);
            var fullWithArgs   = SyntaxFactory.InvocationExpression(fullExpression, retArgs);

            return(new MoqStub(msStub, fullWithArgs));
        }
コード例 #3
0
ファイル: MsTestStub2Moq.cs プロジェクト: molinch/kickmstest
        private StubbedCall StubMsTestMethodOrPropertyCall(ExpressionSyntax originalNode, MemberAccessExpressionSyntax member, ExpressionSyntax returnExpression, INamedTypeSymbol typeSymbol = null)
        {
            if (typeSymbol == null)
            {
                var identifier = member.Expression as IdentifierNameSyntax;
                if (identifier == null)
                {
                    return(null);
                }

                var symbol = semanticModel.GetSymbolInfo(identifier).Symbol;
                typeSymbol = (symbol as ILocalSymbol)?.Type as INamedTypeSymbol;

                if (typeSymbol == null)
                {
                    return(null);
                }
            }

            string typeToMock;

            if (!msTestHelper.IsStub(typeSymbol, out typeToMock))
            {
                return(null);
            }

            var variableName = member.ChildNodes().OfType <IdentifierNameSyntax>().FirstOrDefault();

            if (variableName == null)
            {
                return(null);
            }

            var methodOrPropertyCallIdentifier = member.ChildNodes().OfType <SimpleNameSyntax>().LastOrDefault();

            if (methodOrPropertyCallIdentifier == null)
            {
                return(null);
            }

            INamedTypeSymbol             fakesDelegateType;
            ImmutableArray <ITypeSymbol> methodTypeArguments;

            if (!msTestHelper.IsFakesDelegateMethodOrPropertySetter(typeSymbol, methodOrPropertyCallIdentifier.Identifier.ValueText, out fakesDelegateType, out methodTypeArguments))
            {
                return(null);
            }

            string fakeCallName = methodOrPropertyCallIdentifier.Identifier.ValueText;

            var         lambdaArguments = new List <ITypeSymbol>();
            ITypeSymbol returnType      = null;

            if (fakesDelegateType.TypeParameters.Length > 0)
            {
                IEnumerable <ITypeSymbol> typeArguments = null;
                if (fakesDelegateType.TypeParameters.Last().Name == "TResult")
                {
                    var last = fakesDelegateType.TypeArguments.Last();
                    typeArguments = fakesDelegateType.TypeArguments.Where((t, i) => i < (fakesDelegateType.TypeArguments.Length - 1));
                    returnType    = last;
                }
                else
                {
                    typeArguments = fakesDelegateType.TypeArguments;
                }

                if (typeArguments != null)
                {
                    lambdaArguments = typeArguments.ToList();
                }
            }

            var concreteLambdaArguments = lambdaArguments;
            var hashsetGenericType      = new Dictionary <ITypeSymbol, TypeSyntax>();
            var genericMemberName       = member.Name as GenericNameSyntax;

            if (genericMemberName != null)
            {
                var realTypeArguments = genericMemberName.TypeArgumentList.Arguments;
                for (int i = 0; i < realTypeArguments.Count; i++)
                {
                    var genericType = methodTypeArguments[i];
                    var realType    = realTypeArguments[i];
                    hashsetGenericType[genericType] = realType;
                }

                concreteLambdaArguments = lambdaArguments.ToList();
                for (int i = 0; i < lambdaArguments.Count; i++)
                {
                    var lambdaArgument = concreteLambdaArguments[i] as INamedTypeSymbol;
                    if (lambdaArgument != null && lambdaArgument.IsGenericType) // null check needed since ArrayType is not an INamedTypeSymbol
                    {
                        var concreteArguments = lambdaArgument.TypeArguments.Select(arg =>
                        {
                            if (arg.TypeKind != TypeKind.TypeParameter)
                            {
                                return(arg);
                            }
                            return(semanticModel.GetTypeInfo(hashsetGenericType[arg]).Type);
                        });
                        var unbound = lambdaArgument.ConstructUnboundGenericType();

                        var newLambdaArgument = lambdaArgument.ConstructedFrom.Construct(concreteArguments.ToArray());
                        concreteLambdaArguments[i] = newLambdaArgument;
                    }
                }
            }

            var originalType = typeSymbol.BaseType.TypeArguments.FirstOrDefault() as INamedTypeSymbol;

            if (originalType == null)
            {
                return(null);
            }

            var originalMethodOrPropertySymbol = msTestHelper.GetOriginalSymbolFromFakeCallName(fakeCallName, lambdaArguments, originalType, fakesDelegateType.TypeParameters);

            if (originalMethodOrPropertySymbol == null)
            {
                return(null);
            }

            var originalMethodSymbol = originalMethodOrPropertySymbol as IMethodSymbol;

            if (originalMethodSymbol != null && originalMethodSymbol.TypeArguments.Length > 0)
            {
                var typeArguments = originalMethodSymbol.TypeArguments.Select(t => {
                    var concreteType = hashsetGenericType.Where(pair => pair.Key.Name == t.Name).Select(pair => pair.Value).FirstOrDefault();
                    if (concreteType != null)
                    {
                        return(semanticModel.GetTypeInfo(concreteType).Type);
                    }
                    else
                    {
                        // can happen for stubbed methods like Find<E>(), in that case generic type E must be explicitely passed
                        // however MsTest tests may declare it this way: instance.FindOf1(() => ...), where ... has to return an instance of E
                        // in that case the type is inferred
                        var invocationExpression = originalNode as InvocationExpressionSyntax;
                        if (invocationExpression != null)
                        {
                            var expressionArgument = invocationExpression.ArgumentList.Arguments.FirstOrDefault()?.Expression;
                            if (expressionArgument != null)
                            {
                                var expressionType = semanticModel.GetTypeInfo(expressionArgument).ConvertedType as INamedTypeSymbol;
                                if (expressionType != null)
                                {
                                    return(expressionType?.TypeArguments.FirstOrDefault()); // type which is inferred
                                }
                            }
                        }

                        return(null);
                    }
                });
                originalMethodOrPropertySymbol = originalMethodSymbol.Construct(typeArguments.Where(t => t != null).ToArray());
            }

            var msStubbed = new StubbedMethodOrProperty(originalType, originalMethodOrPropertySymbol, concreteLambdaArguments, returnType);
            var msStub    = new StubbedCall(variableName, msStubbed, returnExpression, originalNode.GetLeadingTrivia(), originalNode.GetTrailingTrivia());

            return(msStub);
        }
コード例 #4
0
ファイル: MoqStub.cs プロジェクト: molinch/kickmstest
 public MoqStub(StubbedCall originalMsStub, InvocationExpressionSyntax newNode)
 {
     OriginalMsStub = originalMsStub;
     NewNode        = newNode;
 }