Add initial support for global configuration.

This commit is contained in:
Mohammadreza Taikandi 2020-12-31 10:01:27 +00:00
parent f13f8783c3
commit 09d09430ef
9 changed files with 74 additions and 28 deletions

View File

@ -0,0 +1,9 @@
namespace MapTo.Configuration
{
internal enum AccessModifier
{
Public,
Internal,
Private
}
}

View File

@ -0,0 +1,26 @@
using System;
using Microsoft.CodeAnalysis;
namespace MapTo.Configuration
{
internal sealed class MapToConfigurations
{
private MapToConfigurations(AccessModifier constructorAccessModifier)
{
ConstructorAccessModifier = constructorAccessModifier;
}
internal AccessModifier ConstructorAccessModifier { get; }
internal static MapToConfigurations From(GeneratorExecutionContext context)
{
var constructorAccessModifier =
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.MapTo_ConstructorAccessModifier", out var ctorModifierValue) &&
Enum.TryParse<AccessModifier>(ctorModifierValue, out var ctorModifier) ? ctorModifier : AccessModifier.Public;
return new MapToConfigurations(
constructorAccessModifier
);
}
}
}

View File

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>9</LangVersion>
<AssemblyName>MapTo</AssemblyName>
<Description>An object to object mapping generator using Roslyn source generator.</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@ -25,7 +25,7 @@
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2">
<PrivateAssets>all</PrivateAssets>
@ -34,12 +34,10 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.8.0" />
</ItemGroup>
<ItemGroup>
<None Remove="bin\Debug\netstandard2.0\MapTo.dll" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" Visible="false" />
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="MapTo.props" Pack="true" PackagePath="build" Visible="false" />
</ItemGroup>
</Project>

5
src/MapTo/MapTo.props Normal file
View File

@ -0,0 +1,5 @@
<Project>
<ItemGroup>
<CompilerVisibleProperty Include="MapTo_ConstructorAccessModifier" />
</ItemGroup>
</Project>

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using MapTo.Configuration;
using MapTo.Extensions;
using MapTo.Models;
using Microsoft.CodeAnalysis;
@ -31,15 +32,19 @@ namespace MapTo
private static void AddGeneratedMappingsClasses(GeneratorExecutionContext context, IEnumerable<ClassDeclarationSyntax> candidateClasses)
{
var configs = MapToConfigurations.From(context);
foreach (var classSyntax in candidateClasses)
{
var model = CreateModel(context, classSyntax);
var model = CreateModel(context, classSyntax, configs);
if (model is null)
{
continue;
}
var (source, hintName) = SourceBuilder.GenerateSource(model);
context.AddSource(hintName, source);
context.ReportDiagnostic(Diagnostics.ClassMappingsGenerated(classSyntax.GetLocation(), model.ClassName));
}
@ -58,8 +63,8 @@ namespace MapTo
return sourceTypeExpressionSyntax is not null ? model.GetTypeInfo(sourceTypeExpressionSyntax.Type).Type as INamedTypeSymbol : null;
}
private static MapModel? CreateModel(GeneratorExecutionContext context, ClassDeclarationSyntax classSyntax)
private static MapModel? CreateModel(GeneratorExecutionContext context, ClassDeclarationSyntax classSyntax, MapToConfigurations configs)
{
var root = classSyntax.GetCompilationUnit();
var classSemanticModel = context.Compilation.GetSemanticModel(classSyntax.SyntaxTree);
@ -86,7 +91,7 @@ namespace MapTo
context.ReportDiagnostic(Diagnostics.NoMatchingPropertyFoundError(classSyntax.GetLocation(), className, sourceClassName));
return null;
}
return new MapModel(
root.GetNamespace(),
classSyntax.Modifiers,
@ -94,7 +99,8 @@ namespace MapTo
sourceTypeSymbol.ContainingNamespace.ToString(),
sourceClassName,
sourceTypeSymbol.ToString(),
mappedProperties);
mappedProperties,
configs.ConstructorAccessModifier);
}
private static ImmutableArray<string> GetMappedProperties(ITypeSymbol classSymbol, ITypeSymbol sourceTypeSymbol)

View File

@ -1,9 +1,10 @@
using System.Collections.Immutable;
using MapTo.Configuration;
using Microsoft.CodeAnalysis;
namespace MapTo.Models
{
public class MapModel
internal class MapModel
{
internal MapModel(
string? ns,
@ -12,7 +13,8 @@ namespace MapTo.Models
string sourceNamespace,
string sourceClassName,
string sourceClassFullName,
ImmutableArray<string> mappedProperties)
ImmutableArray<string> mappedProperties,
AccessModifier constructorAccessModifier)
{
Namespace = ns;
ClassModifiers = classModifiers;
@ -21,6 +23,7 @@ namespace MapTo.Models
SourceClassName = sourceClassName;
SourceClassFullName = sourceClassFullName;
MappedProperties = mappedProperties;
ConstructorAccessModifier = constructorAccessModifier;
}
public string? Namespace { get; }
@ -36,5 +39,7 @@ namespace MapTo.Models
public string SourceClassFullName { get; }
public ImmutableArray<string> MappedProperties { get; }
public AccessModifier ConstructorAccessModifier { get; }
}
}

View File

@ -132,7 +132,7 @@ namespace MapTo
.PadLeft(Indent2).AppendFormat("/// using the property values from the specified <paramref name=\"{0}\"/>.", sourceClassParameterName).AppendLine()
.PadLeft(Indent2).AppendLine("/// </summary>")
.PadLeft(Indent2).AppendFormat("/// <exception cref=\"ArgumentNullException\">{0} is null</exception>", sourceClassParameterName).AppendLine()
.PadLeft(Indent2).AppendFormat("public {0}({1} {2})", model.ClassName, model.SourceClassFullName, sourceClassParameterName)
.PadLeft(Indent2).AppendFormat("{0} {1}({2} {3})", model.ConstructorAccessModifier.ToString().ToLower(), model.ClassName, model.SourceClassFullName, sourceClassParameterName)
.AppendOpeningBracket(Indent2)
.PadLeft(Indent3).AppendFormat("if ({0} == null) throw new ArgumentNullException(nameof({0}));", sourceClassParameterName).AppendLine()
.AppendLine();

View File

@ -1,13 +1,5 @@
using TestConsoleApp.ViewModels;
using VM = TestConsoleApp.ViewModels;
using Data = TestConsoleApp.Data.Models;
namespace TestConsoleApp
{
internal class Program
{
private static void Main(string[] args)
{
var userViewModel = User.From(new Data.Models.User());
var userViewModel2 = UserViewModel.From(new Data.Models.User());
}
}
}
var userViewModel = VM.User.From(new Data.User());
var userViewModel2 = VM.UserViewModel.From(new Data.User());

View File

@ -6,6 +6,11 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MapTo\MapTo.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\src\MapTo\MapTo.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
<Import Project="..\..\src\MapTo\MapTo.props"/>
<PropertyGroup>
<MapTo_ConstructorAccessModifier>Internal</MapTo_ConstructorAccessModifier>
</PropertyGroup>
</Project>