private static ElementAccessExpressionSyntax Bracket(ExpressionSyntax expr, Type keyType, object key)
 =>     // {expr}[{key}], key must be inlinable
 ElementAccessExpression(expr,
                         BracketedArgumentList(
                             SingletonSeparatedList(
                                 Argument(TypeInitConstructor.Construct(keyType, key))
                                 )));
Exemplo n.º 2
0
        private IEnumerable <StatementSyntax> PayloadConstructionMethodBody(ITestDataRecord tdr)
        {
            if (tdr.Payload == null)
            {
                yield return(ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)));

                yield break;
            }

            if (tdr.RecordType.IsInlineable())
            {
                yield return(ReturnStatement(TypeInitConstructor.Construct(tdr.RecordType, tdr.Payload)));

                yield break;
            }
            var ctx = new GenerationContext(_usings);

            if (tdr is AnonymousTestDataRecord anon)
            {
            }

            if (tdr.RecordType.IsEnumerable() || tdr.RecordType.IsTuple())
            {
                var coll =
                    tdr.RecordType.IsTuple()
                        ? SyntaxGeneration.Generator.ProceedTuple(_tgr, tdr.Payload.GetTupleValues(), ctx)
                    : SyntaxGeneration.Generator.ProceedCollection(_tgr, tdr.RecordType, (IEnumerable)tdr.Payload, ctx);

                foreach (var s in ctx.Declarations)
                {
                    yield return(s);
                }

                foreach (var s in ctx.LateBound)
                {
                    yield return(s);
                }

                yield return(ReturnStatement(coll));

                yield break;
            }

            var gen = _tgr.GetGeneratorFor(tdr.RecordType);

            gen.Proceed(tdr.Payload, ctx);
            foreach (var statementSyntax in ctx.Declarations)
            {
                yield return(statementSyntax);
            }

            foreach (var statementSyntax in ctx.LateBound)
            {
                yield return(statementSyntax);
            }
        }
        private ExpressionSyntax MakeAssertions(CommandBase command, AssertionCheckParameter cecp)
        {
            var value = cecp.Extractor.DynamicInvoke(command);

            var          statements = new Stack <StatementSyntax>();
            const string varName    = "x";

            statements.Push(ReturnStatement(LiteralExpression(SyntaxKind.TrueLiteralExpression)));
            if (value == null)
            {
                statements.Push(IfReturnFalse(IdentifierName(varName), LiteralExpression(SyntaxKind.NullLiteralExpression)));
            }
            else
            {
                var tp = value.GetType();
                if (tp.IsInlineable())
                {
                    var v = TypeInitConstructor.Construct(tp, value);
                    statements.Push(IfReturnFalse(IdentifierName(varName), v));
                }
                else
                {
                    var assertProps = cecp.PropertiesToAssert;
                    if (assertProps == null || assertProps.Length == 0)
                    {
                        assertProps =
                            tp.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
                    }

                    var props = assertProps
                                .Where(x => x.PropertyType.IsInlineable());
                    foreach (var propertyInfo in props)
                    {
                        var access = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                            IdentifierName(varName), IdentifierName(propertyInfo.Name));
                        var propValue    = propertyInfo.GetValue(value);
                        var inlinedValue = TypeInitConstructor.Construct(propertyInfo.PropertyType, propValue);

                        statements.Push(IfReturnFalse(access, inlinedValue));
                    }
                }
            }

            var blk = Block(List(statements));

            var lambda = SimpleLambdaExpression(Parameter(Identifier(varName)), blk);

            return(lambda);
        }
        private ExpressionSyntax ExtractFromCommand(CommandBase command, CommandExtractCheckParameter cecp)
        {
            var value = cecp.Extractor.DynamicInvoke(command);
            ExpressionSyntax result;
            if (cecp.Type.IsInlineable())
            {
                EnsureUsing(cecp.Type);
                result = TypeInitConstructor.Construct(cecp.Type, value);
            }
            else
            {
                throw new Exception($"{cecp.Type} is not inlineable into tests");
            }

            return result;
        }
        private YieldStatementSyntax ProduceYield(ITestDataRecord trd)
        {
            TypeSyntax type = null;

            if (trd.RecordType.IsAnonymousType())
            {
                type = AnonymousRecordType;
            }
            else if (trd.RecordType.IsCollection() && trd.RecordType.ElementType().IsAnonymousType())
            {
                type = AnonymousCollectionRecordType;
            }
            else
            {
                type = trd.GetType().TypeName(_usings);
            }

            var hash = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                            IdentifierName(nameof(ITestDataRecord.Hash)),
                                            TypeInitConstructor.Construct(typeof(string), trd.Hash));

            var description = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                   IdentifierName(nameof(ITestDataRecord.Description)),
                                                   TypeInitConstructor.Construct(typeof(string), trd.Description));

            //var data = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
            //    IdentifierName(nameof(ITestDataRecord<int>.Data)),
            //    InvocationExpression(IdentifierName(CurrentMethodName)));
            var invokeGetData = InvocationExpression(IdentifierName(CurrentMethodName));

            var sto = (new SyntaxNodeOrToken[]
                       { hash, Token(SyntaxKind.CommaToken), description });

            var init = ObjectCreationExpression(type)
                       .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(invokeGetData))))
                       .WithInitializer(InitializerExpression(SyntaxKind.ObjectInitializerExpression,
                                                              SeparatedList <ExpressionSyntax>(sto)));

            return(YieldStatement(SyntaxKind.YieldReturnStatement,
                                  init));
        }
        private ExpressionSyntax ExtractFromCommand(CommandBase command, CommandExtractCheckParameter cecp)
        {
            var value = cecp.Extractor.DynamicInvoke(command);

            if (value == null)
            {
                return(TypeInitConstructor.Null());
            }

            var type = value.GetType();
            ExpressionSyntax result;

            if (type.IsInlineable())
            {
                EnsureUsing(cecp.Type);
                result = TypeInitConstructor.Construct(cecp.Type, value);
            }
            else
            {
                if (type.IsDictionary())
                {
                    var(keyType, valueType) = type.GetDictionaryParameters();
                    if (keyType != null && valueType != null && keyType.IsInlineable())
                    {
                        return(MakeDictionary(value as IDictionary, keyType, valueType));
                    }
                }
                else if (type.IsCollection())
                {
                    var elementType = type.GetCollectionElementType();
                    if (elementType != null && elementType.IsInlineable())
                    {
                        return(MakeCollection(value as IEnumerable, elementType));
                    }
                }
                throw new Exception($"Can not inline {type} into tests");
            }

            return(result);
        }
Exemplo n.º 7
0
        private List <StatementSyntax> ProduceInlineableProperties(string instanceName, object instance, GenerationContext context)
        {
            List <StatementSyntax> initNodes = new List <StatementSyntax>();

            foreach (var propertyInfo in Meta.InlineProperties)
            {
                if (!Meta.IsDefault(propertyInfo, instance))
                {
                    var pName = propertyInfo.Name;
                    // "value"
                    var propValue = TypeInitConstructor.Construct(propertyInfo.PropertyType, Meta.Value(propertyInfo, instance));

                    var invocation = SafeAssignment(instanceName, pName, propValue);

                    initNodes.Add(ExpressionStatement(invocation));
                    var u = ExtractEnumUsing(propertyInfo.PropertyType);
                    context.AddUsing(u);
                }
            }

            return(initNodes);
        }
Exemplo n.º 8
0
        protected virtual ExpressionSyntax EarlyChecks(Type t, object instance, GenerationContext context)
        {
            if (t.IsDictionary())
            {
                throw new Exception("TODO: implement dictionaries support in test data capture");
            }

            if (t.IsEnumerable())
            {
                return(ProceedCollection(_tgr, t, (IEnumerable)instance, context));
            }

            if (t.IsTuple())
            {
                if (t.IsInlineable())
                {
                    return(TypeInitConstructor.Construct(t, instance));
                }
                return(ProceedTuple(_tgr, instance.GetTupleValues(), context));
            }

            return(null);
        }
        private ExpressionSyntax MakeDictionary(IDictionary dct, Type keType, Type valType)
        {
            var inits = new List <InitializerExpressionSyntax>();

            foreach (DictionaryEntry dictionaryEntry in dct)
            {
                if (dictionaryEntry.Value == null || dictionaryEntry.Value.GetType().IsInlineable())
                {
                    var keyExpression   = TypeInitConstructor.Construct(keType, dictionaryEntry.Key);
                    var valueExpression =
                        dictionaryEntry.Value == null
                            ? TypeInitConstructor.Null()
                          : TypeInitConstructor.Construct(dictionaryEntry.Value.GetType(), dictionaryEntry.Value);

                    inits.Add(InitializerExpression(
                                  SyntaxKind.ComplexElementInitializerExpression,
                                  SeparatedList <ExpressionSyntax>(
                                      new SyntaxNodeOrToken[] {
                        keyExpression,
                        Token(SyntaxKind.CommaToken),
                        valueExpression
                    })));
                }
            }

            var nt            = typeof(Dictionary <,>).MakeGenericType(keType, valType);
            var newDictionary = nt.TypeName(_usings);
            var arg           = SeparatedList <ExpressionSyntax>(inits.ComaSeparated());

            var objCreation = ObjectCreationExpression(newDictionary)
                              .WithArgumentList(ArgumentList())
                              .WithInitializer(
                InitializerExpression(
                    SyntaxKind.CollectionInitializerExpression, arg));

            return(objCreation);
        }
        private ExpressionSyntax MakeCollection(IEnumerable dct, Type elementType)
        {
            var inits = new List <ExpressionSyntax>();

            foreach (var value in dct)
            {
                if (value == null)
                {
                    inits.Add(TypeInitConstructor.Null());
                }
                else
                {
                    var tp = value.GetType();
                    if (!tp.IsInlineable())
                    {
                        throw new Exception($"Can not inline value '{value}' of type '{tp}' into tests");
                    }
                    inits.Add(TypeInitConstructor.Construct(tp, value));
                }
            }

            var arrayType = ArrayType(elementType.TypeName(_usings));
            var arg       = SeparatedList <ExpressionSyntax>(inits.ComaSeparated());

            var objCreation = ArrayCreationExpression(
                arrayType
                .WithRankSpecifiers(
                    SingletonList <ArrayRankSpecifierSyntax>(
                        ArrayRankSpecifier(
                            SingletonSeparatedList <ExpressionSyntax>(
                                OmittedArraySizeExpression())))))
                              .WithInitializer(
                InitializerExpression(
                    SyntaxKind.ArrayInitializerExpression, arg));

            return(objCreation);
        }
        private static IEnumerable <InvocationExpressionSyntax> AssertionForNotNull(AssertInstanceReference instance)
        {
            if (AssertionForBool(instance, out var expr))
            {
                yield return(expr);

                yield break;
            }

            if (instance.ActualType.IsInlineable())
            {
                var inlined = TypeInitConstructor.Construct(instance.ActualType, instance.Value, instance.Usings);
                yield return(AssertionEquals(instance.AssertionName, instance.Expression, inlined, $"{instance.Path} has invalid value"));

                yield break;
            }

            if (instance.ActualType.IsDictionary())
            {
                var dicParams = instance.ActualType.GetDictionaryParameters();
                yield return(AssertionEquals(
                                 instance.AssertionName,
                                 MemberAccessExpression(
                                     SyntaxKind.SimpleMemberAccessExpression,
                                     instance.Expression,
                                     IdentifierName(nameof(IDictionary.Count)))
                                 , LiteralExpression(SyntaxKind.NumericLiteralExpression,
                                                     Literal(instance.KeysCount())),
                                 $"{instance.Path} has invalid size"));

                if (dicParams.Item1.IsInlineable())
                {
                    foreach (var dictionaryItem in instance.Dictionary())
                    {
                        foreach (var check in AssertionFor(dictionaryItem))
                        {
                            yield return(check);
                        }
                    }
                }
                yield break;
            }

            if (instance.ActualType.IsEnumerable())
            {
                var arguments = new List <ExpressionSyntax>();
                arguments.Add((instance.Expression));
                arguments.Add((T($"{instance.Path} must be composed correctly")));

                foreach (var lValueTuple in instance.Items())
                {
                    var setOfChecks = AssertionFor(lValueTuple.Item2).ToArray();
                    arguments.Add((WrapIntoLambda(setOfChecks, lValueTuple.Item1)));
                }

                yield return(AssertForCollection(instance.AssertionName, arguments.ToArray()));

                yield break;
            }

            foreach (var property in instance.Properties())
            {
                foreach (var assrt in AssertionFor(property))
                {
                    yield return(assrt);
                }
            }
        }
        private IEnumerable <StatementSyntax> PayloadConstructionMethodBody(ITestDataRecord tdr)
        {
            if (tdr.Payload == null)
            {
                yield return(ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)));

                yield break;
            }

            if (tdr.RecordType.IsInlineable())
            {
                yield return(ReturnStatement(TypeInitConstructor.Construct(tdr.RecordType, tdr.Payload)));

                yield break;
            }

            var ctx = new GenerationContext(_usings);

            if (tdr.RecordType.IsDictionary())
            {
                var dict = Generator.ProceedDictionary(_tgr, tdr.RecordType, (IDictionary)tdr.Payload, ctx);
                foreach (var s in ctx.Declarations)
                {
                    yield return(s);
                }

                foreach (var s in ctx.LateBound)
                {
                    yield return(s);
                }

                yield return(ReturnStatement(dict));

                yield break;
            }
            else if (tdr.RecordType.IsEnumerable() || tdr.RecordType.IsTuple())
            {
                var coll =
                    tdr.RecordType.IsTuple()
                        ? SyntaxGeneration.Generator.ProceedTuple(_tgr, tdr.Payload.GetTupleValues(), ctx)
                        : SyntaxGeneration.Generator.ProceedCollection(_tgr, tdr.RecordType, (IEnumerable)tdr.Payload,
                                                                       ctx, forceArray: true);

                foreach (var s in ctx.Declarations)
                {
                    yield return(s);
                }

                foreach (var s in ctx.LateBound)
                {
                    yield return(s);
                }

                yield return(ReturnStatement(coll));

                yield break;
            }

            var gen    = _tgr.GetGeneratorFor(tdr.RecordType);
            var result = gen.New(tdr.Payload, ctx);

            while (ctx.Declarations.Count > 0)
            {
                yield return(ctx.Declarations.Dequeue());
            }
            while (ctx.LateBound.Count > 0)
            {
                yield return(ctx.LateBound.Dequeue());
            }
            yield return(ReturnStatement(result));
        }