using System; using System.Collections.Immutable; using MapTo.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; namespace MapTo { internal enum AccessModifier { Public, Internal, Private } internal enum NullStaticAnalysisState { Default, Enabled, Disabled } internal record SourceCode(string Text, string HintName); internal record MappedMember( string Name, string FullyQualifiedType, string Type, string? TypeConverter, ImmutableArray TypeConverterParameters, string SourcePropertyName, string? MappedSourcePropertyTypeName, string? EnumerableTypeArgument, ISymbol ActualSymbol, INamedTypeSymbol? NamedTypeSymbol, bool isEnumerable, bool isReadOnly) { public bool IsEnumerable => EnumerableTypeArgument is not null; } internal record MappedSourceType ( string SourceNamespace, string SourceTypeIdentifierName, string SourceTypeFullName, ImmutableArray SourceProperties, ImmutableArray SourceFields, ImmutableArray TypeProperties, ImmutableArray TypeFields, bool GenerateSecondaryConstructor ) { public string SourceType => SourceTypeFullName; } internal record MappingModel( SourceGenerationOptions Options, string? Namespace, SyntaxTokenList Modifiers, string Type, string TypeIdentifierName, bool IsTypeUpdatable, bool IsJsonExtension, ImmutableArray MappedSourceTypes, bool HasMappedBaseClass, ImmutableArray Usings ); internal record EfMethodsModel( SourceGenerationOptions Options, string Namespace, string PropertyName, string ContextTypeName, string ContestFullType, string EntityTypeFullName, string EntityTypeIdentifierName, string CreateTypeFullName, string CreateTypeIdentifierName, string ReadTypeFullName, string ReadTypeIdentifierName, ImmutableArray Usings ); internal record SourceGenerationOptions( AccessModifier ConstructorAccessModifier, AccessModifier GeneratedMethodsAccessModifier, bool GenerateXmlDocument, bool SupportNullableReferenceTypes, bool SupportNullableStaticAnalysis) { internal static SourceGenerationOptions From(GeneratorExecutionContext context) { const string allowNullAttributeName = "System.Diagnostics.CodeAnalysis.AllowNullAttribute"; var supportNullableStaticAnalysis = context.GetBuildGlobalOption(propertyName: nameof(SupportNullableStaticAnalysis), NullStaticAnalysisState.Default); var supportNullableReferenceTypes = context.Compilation.Options.NullableContextOptions is NullableContextOptions.Warnings or NullableContextOptions.Enable; return new( ConstructorAccessModifier: context.GetBuildGlobalOption(propertyName: nameof(ConstructorAccessModifier), AccessModifier.Public), GeneratedMethodsAccessModifier: context.GetBuildGlobalOption(propertyName: nameof(GeneratedMethodsAccessModifier), AccessModifier.Public), GenerateXmlDocument: context.GetBuildGlobalOption(propertyName: nameof(GenerateXmlDocument), true), SupportNullableReferenceTypes: supportNullableReferenceTypes, SupportNullableStaticAnalysis: supportNullableStaticAnalysis switch { NullStaticAnalysisState.Enabled => true, NullStaticAnalysisState.Disabled => false, _ => context.Compilation is CSharpCompilation { LanguageVersion: >= LanguageVersion.CSharp8 } cs && cs.TypeByMetadataNameExists(allowNullAttributeName) } ); } public string NullableReferenceSyntax => SupportNullableReferenceTypes ? "?" : string.Empty; } }