static CompleterResult GenerateProperties(SemanticModel model, INamedTypeSymbol type, InvocationExpressionSyntax[] chain)
        {
            var last = (MemberAccessExpressionSyntax)chain.Last().Expression;
            var ownerTypeSyntax = ((GenericNameSyntax)last.Expression).TypeArgumentList.Arguments.Single();
            var ownerType = model.GetTypeInfo(ownerTypeSyntax).Type;
            if(ownerType != type)
                return new CompleterError(ownerTypeSyntax, Messages.DependecyProperty_IncorrectOwnerType).YieldToImmutable();
            var properties = chain
                .Take(chain.Length - 1)
                .Select(property => {
                    var memberAccess = (MemberAccessExpressionSyntax)property.Expression;
                    var methodName = memberAccess.Name.Identifier.ValueText;
                    if(!methodName.StartsWith("Register"))
                        return null;
                    var readOnly = methodName == "RegisterReadOnly" || methodName == "RegisterAttachedReadOnly";
                    var attached = methodName == "RegisterAttached" || methodName == "RegisterAttachedReadOnly";

                    var arguments = property.ArgumentList.Arguments;

                    var propertySignature = (memberAccess.Name as GenericNameSyntax)?.TypeArgumentList.Arguments.Select(x => x.ToString()).ToArray();
                    if(propertySignature == null) {
                        var defaultValueArgument = arguments[readOnly ? 3 : 2].Expression;
                        var defaultExpressionTypeInfo = model.GetTypeInfo(defaultValueArgument);
                        propertySignature = defaultExpressionTypeInfo.Type?.DisplayString(model, defaultValueArgument.GetLocation()).With(propertyType =>
                            !attached
                                ? new string[] { propertyType }
                                : (arguments[0].Expression as ParenthesizedLambdaExpressionSyntax).With(x => new string[] { x.ParameterList.Parameters.Single().Type.ToString(), propertyType })
                        );
                    }
                    if(propertySignature == null) {
                        var span = memberAccess.Name.LineSpan();
                        return new CompleterError(memberAccess.SyntaxTree, Messages.DependecyProperty_PropertyTypeMissed, new FileLinePositionSpan(string.Empty, span.EndLinePosition, span.EndLinePosition));
                    }

                    var propertyName = GetPropertyName(arguments, attached, readOnly, memberAccess.Name.SyntaxTree);

                    return propertyName.Select(name => {
                        var overridedPropertyVisibility = GetOverridedPropertyVisibility(type, name);
                        return GenerateFields(name, readOnly, overridedPropertyVisibility == null) + (attached
                        ? GenerateAttachedProperty(propertySignature[0], propertySignature[1], name, readOnly, overridedPropertyVisibility)
                        : GenerateProperty(propertySignature.Single(), name, readOnly, overridedPropertyVisibility));
                    });
                })
                .Where(x => x != null)
                .Reverse()
                .ToArray();
            return properties
                .AggregateEither(errors => errors.ToImmutableArray(), values => values.ConcatStringsWithNewLines());
        }