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