Beispiel #1
0
            public TypeConfig(RoslynMetadataHelper roslyn, Type contract, Type implementation, Func <INamedTypeSymbol, INamedTypeSymbol, CollectionImplementation> implementationFactory)
            {
                _contractType          = contract;
                _implementationType    = implementation;
                _implementationFactory = implementationFactory;

                _contract       = (INamedTypeSymbol)roslyn.FindTypeByFullName(contract.FullName);
                _implementation = (INamedTypeSymbol)roslyn.FindTypeByFullName(implementation.FullName);

                _contractFullName = _contract?.ConstructUnboundGenericType().ToDisplayString();
            }
        private void ResolveTypes()
        {
            var additionalTypes = _config.Entities.Safe().Concat(WellKnownTypes.Types).ToArray();

            // Augment the current compilation by adding types to compilation
            _roslynHelper = new RoslynMetadataHelper(_compilation,
                                                     _project,
                                                     additionalTypes
                                                     );

            // Change current compilation for the new one
            _compilation = _roslynHelper.Compilation;

            _serializationTypeInstance = _config.CreateInstance(_roslynHelper);

            _collections = new CollectionImplementationResolver(_roslynHelper);

            // Prepare known custom deserializers
            _knownCustomDeserializers.Add(
                (INamedTypeSymbol)_roslynHelper.GetTypeByFullName("GeneratedSerializers.JwtData`1"),
                (INamedTypeSymbol)_roslynHelper.GetTypeByFullName("GeneratedSerializers.JwtDataDeserializer`1"));

            SymbolExtensions.KnownCustomDeserializers = _knownCustomDeserializers;

            // Extract types declared by using the [assembly: JsonSerializableType(typeof(<some Type>))] attribute
            var jsonSerializableTypesFromAttributes =
                //Types in current assembly
                GetSerializableTypesFromAttribute(_compilation.Assembly)
                //Types in referenced assemblies
                .Concat(_compilation.Assembly
                        .Modules
                        .First()
                        .ReferencedAssemblySymbols
                        .SelectMany(GetSerializableTypesFromAttribute)
                        );

            // Extract types declared in the configuration file (SerializationConfig.xml) -- that's a legacy feature
            var typesFromConfig = _config
                                  .Entities
                                  .Safe()
                                  .Select(typeName =>
            {
                var type = _roslynHelper.FindTypeByFullName(typeName);

                if (type == null)
                {
                    throw new TypeAccessException("Cannot resolve type {0}.".InvariantCultureFormat(typeName));
                }

                return(type);
            });

            // Join the 2 lists into one
            var configuredTypes = typesFromConfig
                                  .Concat(jsonSerializableTypesFromAttributes)
                                  .Distinct()
                                  .ToList();

            // Unwrap Collections & Dictionaries...
            var simplifiedConfiguredTypes = configuredTypes
                                            .Select(t => t.DictionnaryOf() ?? t.EnumerableOf() ?? t.NullableOf() ?? t)
                                            .Distinct()
                                            .ToArray();

            // Find all types to generate a StaticDeserializer for (include nested types)
            var allNeededTypes = simplifiedConfiguredTypes
                                 .Concat(_serializationTypeInstance
                                         .StaticDeserializerPropertyFinder
                                         .GetNestedTypes(simplifiedConfiguredTypes)
                                         .Where(type => _nonGeneratedNameSpaces.None(ns => type.ContainingNamespace?.ToDisplayString().Equals(ns, StringComparison.OrdinalIgnoreCase) ?? false)))
                                 .ToList();

            foreach (var t in allNeededTypes.ToArray())
            {
                var attr = t.FindAttribute("Uno.ImmutableBuilderAttribute");
                if (attr == null)
                {
                    // no builder for this one
                    continue;
                }

                if (!(attr.ConstructorArguments[0].Value is ITypeSymbol builderType))
                {
                    continue;                     // That would bea weird situation.
                }

                // Add the builder to type to deserialize (neededtype + root types)
                configuredTypes.Add(builderType);
                allNeededTypes.Add(builderType);
            }

            _allNeededTypes = allNeededTypes.ToArray();

            // Check if configuration restrict the generation to configured types
            if (!GetForceGenerateCollectionSerializable(_compilation.Assembly))
            {
                var nullable = (INamedTypeSymbol)_roslynHelper.GetTypeByFullName("System.Nullable`1");

                var collectionTypes = _collections
                                      .GetUnboundedSupportedTypes()
                                      .Where(t => !_config.IsImmutablesAtRootDisabled || !t.Implementation.GetDeclarationGenericFullName().Contains("Immutable"))
                                      .Concat(new Implemtation(_roslynHelper.GetArray(_roslynHelper.GetGenericType())));

                var typesToGenerate = new List <ITypeSymbol>();

                // Add Nullable<T> version for enums
                typesToGenerate.AddRange(_allNeededTypes
                                         .SelectMany(type => type.TypeKind == TypeKind.Enum
                                                ? new[] { type, nullable.Construct(type) }
                                                : new[] { type }));

                // Add all "primitives" types (value types + string)
                typesToGenerate.AddRange(ValueTypeSerializersGenerator.Types.Select(_roslynHelper.GetTypeByFullName));

                // Add all permutations collection/type in collection<type>
                typesToGenerate.AddRange(typesToGenerate
                                         .SelectMany(type => collectionTypes
                                                     .Select(colImp => _roslynHelper.ConstructFromUnbounded(colImp.Contract, type)))
                                         .ToArray());

                // That's all
                _rootTypes = typesToGenerate.ToArray();
            }
            else
            {
                _rootTypes = configuredTypes.ToArray();
            }

            //Find all CustomDeserializer Types present (include nested types)
            _customSerializationAttributeTypes = _serializationTypeInstance
                                                 .CustomDeserializerPropertyFinder
                                                 .GetNestedCustomDeserializerTypes(simplifiedConfiguredTypes)
                                                 .Concat(simplifiedConfiguredTypes.Select(type => type.FindCustomDeserializerType()).Trim())
                                                 .Distinct()
                                                 .ToArray();
        }