예제 #1
0
        public static ValidationErrors IsWritableReferenceType(Expression e)
        {
            if (IsReferenceType(e) is ValidationErrors r)
            {
                return(r);
            }

            var err = e switch {
                Expression.AddressOfCase a => ValidationErrors.Create($"AddresOf expression returns read-only reference").Nest("AddressOf"),
                Expression.ArrayIndexCase a => null,
                Expression.BlockCase b => IsWritableReferenceType(b.Item.Result).Nest("result").Nest("Block"),
                Expression.BreakableCase b => null, // we don't know in this case :/ ; TODO: analyze more in-depth?
                Expression.ConditionalCase c => ValidationErrors.Join(
                    IsWritableReferenceType(c.Item.IfTrue).Nest("ifTrue"),
                    IsWritableReferenceType(c.Item.IfFalse).Nest("ifFalse")
                    ).Nest("Conditional"),
                Expression.FieldAccessCase f =>
                null,
                // uh oh, even readonly fields can be assigned from the constructor ;(
                //f.Item.Field.Signature.IsReadonly ? ValidationErrors.CreateField(new [] { "FieldAccess", "field", "signature", "isReadonly" }, $"Field {f.Item.Field} is readonly") : null,
                Expression.InvokeCase _ => null,     // we don't know if method return readonly ref...
                Expression.MethodCallCase _ => null, // we don't know if method return readonly ref...
                Expression.LetInCase l => IsWritableReferenceType(l.Item.Target).Nest("target").Nest("LetIn"),
                Expression.VariableReferenceCase v => !v.Item.Variable.Mutable ? ValidationErrors.CreateField(new [] { "VariableReference", "variable", "mutable" }, $"Variable {v.Item.Variable} is not mutable") : null,
                Expression.ParameterCase p => null, // can't track mutability of variables :/
                var x =>
#if DEBUG
                throw new NotSupportedException($"Expression {x} was supposed not to return reference")
#else
                null
#endif
            };

            return(err);
        }
예제 #2
0
파일: DataSchema.cs 프로젝트: exyi/coberec
        public static ValidationErrors Validate(ImmutableArray <Entity> entities, ImmutableArray <TypeDef> types)
        {
            // IEnumerable<string> getReferencedTypes(TypeRef t) =>
            //     t.Match(
            //         actual: x => new [] { x.TypeName },
            //         nullable: x => getReferencedTypes(x.Type),
            //         list: x => getReferencedTypes(x.Type)
            //     )
            // IEnumerable<string> getReferencedTypes(TypeDefCore t) =>
            //     t.Match(
            //         primitive: x => new string[0],
            //         union: x => x.Options.SelectMany(getReferencedTypes),
            //         @interface: x => x.Fields.SelectMany(f => getReferencedTypes(f.Type)),
            //         composite: x => x.Fields.SelectMany(f => getReferencedTypes(

            var declaredTypes = types.Select((a, index) => (a, index)).ToLookup(t => t.a.Name);
            var result        = new List <ValidationErrors>();

            // Type names must be unique
            foreach (var d in declaredTypes)
            {
                if (d.Count() > 1)
                {
                    foreach (var(type, index) in d)
                    {
                        result.Add(ValidationErrors.CreateField(new [] { "types", index.ToString(), "name" }, $"Name of this type is not unique."));
                    }
                }
            }

            foreach (var(index, type) in types.Select((a, i) => (i, a)))
            {
                result.Add(ValidateName(type.Name).Nest("name").Nest(index.ToString()).Nest("types"));
                if (type.Core is TypeDefCore.CompositeCase composite)
                {
                    result.Add(ValidateFields(composite.Fields).Nest("core").Nest(index.ToString()).Nest("types"));
                }
                else if (type.Core is TypeDefCore.InterfaceCase ifc)
                {
                    result.Add(ValidateFields(ifc.Fields).Nest("core").Nest(index.ToString()).Nest("types"));
                }
                else if (type.Core is TypeDefCore.UnionCase union)
                {
                    result.Add(ValidationErrors.Join(
                                   union.Options.Select((o, i) =>
                                                        (o is TypeRef.ActualTypeCase actO ?
                                                         ValidateName(actO.TypeName) :
                                                         ValidationErrors.Create("Union case can't have any modifiers (list, non-null)."))
                                                        .Nest(i.ToString()).Nest("options").Nest("core").Nest(index.ToString()).Nest("types")
                                                        )
                                   .ToArray()
                                   ));
                }
            }

            return(ValidationErrors.Join(result.ToArray()));
        }
예제 #3
0
파일: DataSchema.cs 프로젝트: exyi/coberec
 static ValidationErrors ValidateFields(ImmutableArray <TypeField> fields)
 {
     return(ValidationErrors.Join(
                fields
                .GroupBy(f => f.Name)
                .Where(g => g.Count() > 1)
                .SelectMany(g => g)
                .Select(field =>
                        ValidationErrors.CreateField(new [] { fields.IndexOf(field).ToString(), "name" }, $"Non-unique field name: {field.Name}")
                        )
                .Concat(fields.Select((f, i) =>
                                      ValidationErrors.Join(
                                          ValidateName(f.Name).Nest("name"),
                                          ValidateDirectives(f.Directives)
                                          ).Nest(i.ToString())
                                      ))
                .ToArray())
            .Nest("fields"));
 }
예제 #4
0
        private static IEnumerable <ValidatorUsage> AnalyzeDirectives(IEnumerable <Directive> directives, Func <string, string[]> getValidatorArgs, string fieldName = null, int?fieldIndex = null)
        {
            var defaultFields = fieldName == null ? ImmutableArray <string> .Empty : ImmutableArray.Create(fieldName);
            var fieldPrefix   = fieldName == null ? "" : fieldName + ".";

            return(from xx in directives.Select((d, i) => (i, d))
                   let d = xx.d
                           let dindex = xx.i
                                        where d.Name.StartsWith("validate") && d.Name.Length > "validate".Length
                                        let validatorName = char.ToLower(d.Name["validate".Length]) + d.Name.Substring("validate".Length + 1)

                                                            let args = getValidatorArgs(validatorName) ??
                                                                       throw new ValidationErrorException(ValidationErrors.CreateField(
                                                                                                              (fieldIndex == null ? Array.Empty <string>() : new[] { "fields", fieldIndex.ToString() }).Concat(new [] { "directives", dindex.ToString(), "name" }).ToArray(),
                                                                                                              $"Validator {validatorName} could not be found"
                                                                                                              ))

                                                                       let forFields = d.Args["forFields"] == null || args.Contains("forFields") ?
                                                                                       defaultFields :
                                                                                       d.Args["forFields"].Values <string>().Select(a => fieldPrefix + a).ToImmutableArray()

                                                                                       let argValues = args.Select(a => (a, val: d.Args[a]))
                                                                                                       .Where(a => a.val != null)
                                                                                                       .ToDictionary(a => a.a, a => a.val)

                                                                                                       select new ValidatorUsage(validatorName, argValues, forFields, dindex, fieldIndex));
        }