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); }
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)); }
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); }
public MoqStub(StubbedCall originalMsStub, InvocationExpressionSyntax newNode) { OriginalMsStub = originalMsStub; NewNode = newNode; }