Example #1
0
 public StubbedCall(IdentifierNameSyntax identifier, StubbedMethodOrProperty stubbed, ExpressionSyntax stubReturn,
                    SyntaxTriviaList originalLeadingTrivia, SyntaxTriviaList originalTrailingTrivia)
 {
     Identifier             = identifier;
     Stubbed                = stubbed;
     StubReturn             = stubReturn;
     OriginalLeadingTrivia  = originalLeadingTrivia;
     OriginalTrailingTrivia = originalTrailingTrivia;
 }
Example #2
0
        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);
        }