private MemberDeclarationSyntax ExplicitInterfaceMember() { var decoratedValueTypeSyntax = ValueTypeSyntax; if (Symbol.ReturnsByRef) { decoratedValueTypeSyntax = F.RefType(decoratedValueTypeSyntax); } else if (Symbol.ReturnsByRefReadonly) { decoratedValueTypeSyntax = F.RefType(decoratedValueTypeSyntax).WithReadOnlyKeyword(F.Token(SyntaxKind.ReadOnlyKeyword)); } var mockedProperty = F.PropertyDeclaration(decoratedValueTypeSyntax, Symbol.Name) .WithExplicitInterfaceSpecifier(F.ExplicitInterfaceSpecifier(TypesForSymbols.ParseName(InterfaceSymbol))); if (Symbol.IsReadOnly) { ExpressionSyntax elementAccess = F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(MemberMockName), F.IdentifierName("Value")); if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly) { elementAccess = TypesForSymbols.WrapByRef(elementAccess, ValueTypeSyntax); } mockedProperty = mockedProperty.WithExpressionBody(F.ArrowExpressionClause(elementAccess)) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)); } else { if (!Symbol.IsWriteOnly) { mockedProperty = mockedProperty.AddAccessorListAccessors(F.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithExpressionBody(F.ArrowExpressionClause(F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(MemberMockName), F.IdentifierName("Value")))) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)) ); } if (!Symbol.IsReadOnly) { mockedProperty = mockedProperty.AddAccessorListAccessors(F.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .WithExpressionBody( F.ArrowExpressionClause( F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(MemberMockName), F.IdentifierName("Value")), F.IdentifierName("value")))) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)) ); } } return(mockedProperty); }
private MemberDeclarationSyntax ExplicitInterfaceMember() { var decoratedValueTypeSyntax = ValueTypeSyntax; if (Symbol.ReturnsByRef) { decoratedValueTypeSyntax = F.RefType(decoratedValueTypeSyntax); } else if (Symbol.ReturnsByRefReadonly) { decoratedValueTypeSyntax = F.RefType(decoratedValueTypeSyntax).WithReadOnlyKeyword(F.Token(SyntaxKind.ReadOnlyKeyword)); } var mockedIndexer = F.IndexerDeclaration(decoratedValueTypeSyntax) .WithParameterList(KeyType.BuildParameterList()) .WithExplicitInterfaceSpecifier(F.ExplicitInterfaceSpecifier(TypesForSymbols.ParseName(InterfaceSymbol))); var arguments = KeyType.BuildArgumentList(); if (Symbol.IsReadOnly) { ExpressionSyntax elementAccess = F.ElementAccessExpression(F.IdentifierName(MemberMockName)) .WithExpressionsAsArgumentList(arguments); if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly) { elementAccess = TypesForSymbols.WrapByRef(elementAccess, ValueTypeSyntax); } mockedIndexer = mockedIndexer.WithExpressionBody(F.ArrowExpressionClause(elementAccess)) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)); } else { if (!Symbol.IsWriteOnly) { mockedIndexer = mockedIndexer.AddAccessorListAccessors(F.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithExpressionBody(F.ArrowExpressionClause(F.ElementAccessExpression(F.IdentifierName(MemberMockName)) .WithExpressionsAsArgumentList(arguments))) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)) ); } if (!Symbol.IsReadOnly) { mockedIndexer = mockedIndexer.AddAccessorListAccessors(F.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .WithExpressionBody(F.ArrowExpressionClause( F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, F.ElementAccessExpression(F.IdentifierName(MemberMockName)).WithExpressionsAsArgumentList(arguments), F.IdentifierName("value")))) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken))); } } return(mockedIndexer); }
protected MemberDeclarationSyntax ExplicitInterfaceMember() { var baseReturnType = Symbol.ReturnsVoid ? F.PredefinedType(F.Token(SyntaxKind.VoidKeyword)) : TypesForSymbols.ParseTypeName(Symbol.ReturnType, Symbol.ReturnTypeIsNullableOrOblivious()); var returnType = baseReturnType; if (Symbol.ReturnsByRef) { returnType = F.RefType(returnType); } else if (Symbol.ReturnsByRefReadonly) { returnType = F.RefType(returnType).WithReadOnlyKeyword(F.Token(SyntaxKind.ReadOnlyKeyword)); } var mockedMethod = ExplicitInterfaceMemberMethodDeclaration(returnType); var memberMockInstance = ExplicitInterfaceMemberMemberMockInstance(); ExpressionSyntax invocation = F.InvocationExpression( F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, memberMockInstance, F.IdentifierName("Call"))) .WithExpressionsAsArgumentList(ParametersType.BuildArgumentListWithOriginalNames()); // look at the return parameters. If we don't have any we can just make the call. // if we only have one and that's the return value, we can just return it. if (ReturnValuesType.Count == 0 || ReturnValuesType.Count == 1 && ReturnValuesType[0].IsReturnValue) { if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly) { invocation = TypesForSymbols.WrapByRef(invocation, baseReturnType); } mockedMethod = mockedMethod.WithExpressionBody(F.ArrowExpressionClause(invocation)) .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken)); } // if we only have one and that's not a return value, we can just assign it to the out or ref parameter it corresponds to. else if (ReturnValuesType.Count == 1) { mockedMethod = mockedMethod.WithBody(F.Block(F.ExpressionStatement(F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, F.IdentifierName(ReturnValuesType[0].OriginalName), invocation)))); } else { // if we have more than one, put it in a temporary variable. (consider name clashes with method parameter names) var x = new Uniquifier(Symbol.Parameters.Select(m => m.Name)); string tmp = x.GetUniqueName("tmp"); var statements = new List <StatementSyntax> { F.LocalDeclarationStatement(F.VariableDeclaration(F.IdentifierName("var")).WithVariables( F.SingletonSeparatedList(F.VariableDeclarator(F.Identifier(tmp)).WithInitializer(F.EqualsValueClause(invocation))))) }; // then for any out or ref parameters, set their values from the temporary variable. foreach (var rv in ReturnValuesType.Where(a => !a.IsReturnValue)) { statements.Add(F.ExpressionStatement(F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, F.IdentifierName(rv.OriginalName), F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(tmp), F.IdentifierName(rv.TupleSafeName))))); } // finally, if there is a 'proper' return type, return the corresponding value from the temporary variable. foreach (var rv in ReturnValuesType.Where(a => a.IsReturnValue)) { ExpressionSyntax memberAccess = F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(tmp), F.IdentifierName(rv.TupleSafeName)); if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly) { memberAccess = TypesForSymbols.WrapByRef(memberAccess, baseReturnType); } statements.Add(F.ReturnStatement(memberAccess)); } mockedMethod = mockedMethod.WithBody(F.Block(statements)); } return(mockedMethod); }