private async Task <SyntaxNode> GetDefaultExpression(ITypeSymbol type, MappingContext mappingContext, MappingPath mappingPath)
        {
            if (mappingPath.AddToMapped(type) == false)
            {
                return(syntaxGenerator.DefaultExpression(type)
                       .WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */")));
            }

            if (SymbolHelper.IsNullable(type, out var underlyingType))
            {
                type = underlyingType;
            }


            if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol)
            {
                var enumOption = namedTypeSymbol.MemberNames.Where(x => x != "value__" && x != ".ctor").OrderBy(x => x).FirstOrDefault();
                if (enumOption != null)
                {
                    return(SyntaxFactoryExtensions.CreateMemberAccessExpression(SyntaxFactory.IdentifierName(namedTypeSymbol.Name), false, enumOption));
                }
                return(syntaxGenerator.DefaultExpression(type));
            }

            if (type.SpecialType == SpecialType.None)
            {
                ObjectCreationExpressionSyntax objectCreationExpression = null;

                if (MappingHelper.IsCollection(type))
                {
                    var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type);

                    if (type is IArrayTypeSymbol)
                    {
                        objectCreationExpression = CreateObject(type);
                    }
                    else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection)
                    {
                        if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
                        {
                            var typeArgumentListSyntax = SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(namedType.TypeArguments.Select(x => syntaxGenerator.TypeExpression(x))));
                            var newType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("List"), typeArgumentListSyntax);
                            objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
                        }
                        else
                        {
                            var newType = SyntaxFactory.ParseTypeName("ArrayList");
                            objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
                        }
                    }
                    objectCreationExpression ??= CreateObject(type, Array.Empty <ArgumentSyntax>());

                    var subType = MappingHelper.GetElementType(type);
                    var initializationBlockExpressions = new SeparatedSyntaxList <ExpressionSyntax>();
                    var subTypeDefault = (ExpressionSyntax)(await GetDefaultExpression(subType.Type, mappingContext, mappingPath.Clone()).ConfigureAwait(false));
                    if (subTypeDefault != null)
                    {
                        initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault);
                    }

                    var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, initializationBlockExpressions).FixInitializerExpressionFormatting(objectCreationExpression);
                    return(objectCreationExpression
                           .WithInitializer(initializerExpressionSyntax)
                           .WrapInReadonlyCollectionIfNecessary(isReadonlyCollection, syntaxGenerator));
                }

                {
                    var nt = type as INamedTypeSymbol;
                    if (nt == null)
                    {
                        var genericTypeConstraints = type.UnwrapGeneric().ToList();
                        if (genericTypeConstraints.Any() == false)
                        {
                            return(GetDefaultForUnknown(type, ObjectType));
                        }
                        nt = genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Class) as INamedTypeSymbol ??
                             genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Interface) as INamedTypeSymbol;
                    }

                    if (nt == null)
                    {
                        return(GetDefaultForUnknownType(type));
                    }

                    if (nt.TypeKind == TypeKind.Interface)
                    {
                        var implementations = await SymbolFinder.FindImplementationsAsync(type, _document.Project.Solution).ConfigureAwait(false);

                        var firstImplementation = implementations.FirstOrDefault();
                        if (firstImplementation is INamedTypeSymbol == false)
                        {
                            return(GetDefaultForUnknownType(type));
                        }

                        nt = firstImplementation as INamedTypeSymbol;
                        objectCreationExpression = CreateObject(nt);
                    }
                    else if (nt.TypeKind == TypeKind.Class && nt.IsAbstract)
                    {
                        var allDerived = await SymbolFinder.FindDerivedClassesAsync(nt, _document.Project.Solution).ConfigureAwait(false);

                        var randomDerived = allDerived.FirstOrDefault(x => x.IsAbstract == false);

                        if (randomDerived != null)
                        {
                            nt = randomDerived;
                            objectCreationExpression = CreateObject(nt);
                        }
                    }
                    else
                    {
                        var publicConstructors    = nt.Constructors.Where(x => mappingContext.AccessibilityHelper.IsSymbolAccessible(x, nt)).ToList();
                        var hasDefaultConstructor = publicConstructors.Any(x => x.Parameters.Length == 0);
                        if (hasDefaultConstructor == false && publicConstructors.Count > 0)
                        {
                            var randomConstructor    = publicConstructors.First();
                            var constructorArguments = await GetConstructorArguments(mappingContext, mappingPath, randomConstructor).ConfigureAwait(false);

                            objectCreationExpression = CreateObject(nt, constructorArguments);
                        }
                    }

                    var fields      = mappingTargetHelper.GetFieldsThaCanBeSetPublicly(nt, mappingContext);
                    var assignments = new List <AssignmentExpressionSyntax>(fields.Count);
                    foreach (var x in fields)
                    {
                        var identifier    = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name));
                        var mappingSource = await this.FindMappingSource(x.Type, mappingContext, mappingPath.Clone()).ConfigureAwait(false);

                        assignments.Add(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, identifier, mappingSource.Expression));
                    }

                    if (objectCreationExpression == null)
                    {
                        objectCreationExpression = CreateObject(type);
                    }

                    return(SyntaxFactoryExtensions.WithMembersInitialization(objectCreationExpression, assignments));
                }
            }
        internal SyntaxNode GetDefaultExpression(ITypeSymbol type, MappingPath mappingPath)
        {
            if (mappingPath.AddToMapped(type) == false)
            {
                return(syntaxGenerator.DefaultExpression(type)
                       .WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */")));
            }

            if (SymbolHelper.IsNullable(type, out var underlyingType))
            {
                type = underlyingType;
            }


            if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol)
            {
                var enumOptions = namedTypeSymbol.MemberNames.Where(x => x != "value__" && x != ".ctor").ToList();
                if (enumOptions.Count > 0)
                {
                    return(syntaxGenerator.MemberAccessExpression(syntaxGenerator.IdentifierName(namedTypeSymbol.Name), syntaxGenerator.IdentifierName(enumOptions[0])));
                }
                return(syntaxGenerator.DefaultExpression(type));
            }

            if (type.SpecialType == SpecialType.None)
            {
                var objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(type);


                if (MappingHelper.IsCollection(type))
                {
                    var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type);

                    if (type is IArrayTypeSymbol)
                    {
                        objectCreationExpression = SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type));
                    }
                    else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection)
                    {
                        var namedType = type as INamedTypeSymbol;
                        if (namedType.IsGenericType)
                        {
                            var typeArgumentListSyntax = SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(namedType.TypeArguments.Select(x => syntaxGenerator.TypeExpression(x))));
                            var newType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("List"), typeArgumentListSyntax);
                            objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
                        }
                        else
                        {
                            var newType = SyntaxFactory.ParseTypeName("ArrayList");
                            objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
                        }
                    }
                    var subType = MappingHelper.GetElementType(type);
                    var initializationBlockExpressions = new SeparatedSyntaxList <ExpressionSyntax>();
                    var subTypeDefault = (ExpressionSyntax)GetDefaultExpression(subType, mappingPath.Clone());
                    if (subTypeDefault != null)
                    {
                        initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault);
                    }

                    var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, initializationBlockExpressions).FixInitializerExpressionFormatting(objectCreationExpression);
                    return(objectCreationExpression
                           .WithInitializer(initializerExpressionSyntax)
                           .WrapInReadonlyCollectionIfNecessary(isReadonlyCollection, syntaxGenerator));
                }

                {
                    var nt = type as INamedTypeSymbol;

                    if (nt == null)
                    {
                        var genericTypeConstraints = type.UnwrapGeneric().ToList();
                        if (genericTypeConstraints.Any() == false)
                        {
                            return(GetDefaultForUnknown(type, SyntaxFactory.ParseTypeName("object")));
                        }
                        nt = genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Class) as INamedTypeSymbol ??
                             genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Interface) as INamedTypeSymbol;
                    }

                    if (nt == null)
                    {
                        return(GetDefaultForUnknownType(type));
                    }

                    if (nt.TypeKind == TypeKind.Interface)
                    {
                        var implementations     = SymbolFinder.FindImplementationsAsync(type, this._document.Project.Solution).Result;
                        var firstImplementation = implementations.FirstOrDefault();
                        if (firstImplementation is INamedTypeSymbol == false)
                        {
                            return(GetDefaultForUnknownType(type));
                        }

                        nt = firstImplementation as INamedTypeSymbol;
                        objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt);
                    }
                    else if (nt.TypeKind == TypeKind.Class && nt.IsAbstract)
                    {
                        var randomDerived = SymbolFinder.FindDerivedClassesAsync(nt, this._document.Project.Solution).Result
                                            .FirstOrDefault(x => x.IsAbstract == false);

                        if (randomDerived != null)
                        {
                            nt = randomDerived;
                            objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt);
                        }
                    }

                    var publicConstructors = nt.Constructors.Where(x =>
                                                                   x.DeclaredAccessibility == Accessibility.Public ||
                                                                   (x.DeclaredAccessibility == Accessibility.Internal &&
                                                                    x.ContainingAssembly.IsSameAssemblyOrHasFriendAccessTo(_contextAssembly))).ToList();


                    var hasDefaultConstructor = publicConstructors.Any(x => x.Parameters.Length == 0);
                    if (hasDefaultConstructor == false && publicConstructors.Count > 0)
                    {
                        var randomConstructor    = publicConstructors.First();
                        var constructorArguments = randomConstructor.Parameters.Select(p => GetDefaultExpression(p.Type, mappingPath.Clone())).ToList();
                        objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt, constructorArguments);
                    }

                    var fields      = ObjectHelper.GetFieldsThaCanBeSetPublicly(nt, _contextAssembly);
                    var assignments = fields.Select(x =>
                    {
                        var identifier = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name));
                        return((ExpressionSyntax)syntaxGenerator.AssignmentStatement(identifier, this.FindMappingSource(x.Type, mappingPath.Clone()).Expression));
                    }).ToList();

                    if (assignments.Count == 0)
                    {
                        return(objectCreationExpression);
                    }
                    var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, new SeparatedSyntaxList <ExpressionSyntax>().AddRange(assignments)).FixInitializerExpressionFormatting(objectCreationExpression);
                    return(objectCreationExpression.WithInitializer(initializerExpressionSyntax));
                }
            }


            return(GetDefaultForSpecialType(type));
        }