Separated context verification and model creation.
This commit is contained in:
parent
2a671a9dd4
commit
804a0c4eb3
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MapTo.Extensions
|
||||||
|
{
|
||||||
|
internal static class EnumerableExtensions
|
||||||
|
{
|
||||||
|
internal static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
|
||||||
|
{
|
||||||
|
foreach (var item in enumerable)
|
||||||
|
{
|
||||||
|
action(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MapTo.Extensions;
|
||||||
using MapTo.Models;
|
using MapTo.Models;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
@ -28,19 +29,25 @@ namespace MapTo
|
||||||
|
|
||||||
private static void AddGeneratedMappingsClasses(GeneratorExecutionContext context, IEnumerable<ClassDeclarationSyntax> candidateClasses)
|
private static void AddGeneratedMappingsClasses(GeneratorExecutionContext context, IEnumerable<ClassDeclarationSyntax> candidateClasses)
|
||||||
{
|
{
|
||||||
foreach (var classDeclarationSyntax in candidateClasses)
|
foreach (var classSyntax in candidateClasses)
|
||||||
{
|
{
|
||||||
var (model, diagnostic) = MapModel.Create(context.Compilation, classDeclarationSyntax);
|
var root = classSyntax.GetCompilationUnit();
|
||||||
if (model is null)
|
var classSemanticModel = context.Compilation.GetSemanticModel(classSyntax.SyntaxTree);
|
||||||
|
var classSymbol = classSemanticModel.GetDeclaredSymbol(classSyntax) as INamedTypeSymbol;
|
||||||
|
var sourceTypeSymbol = GetSourceTypeSymbol(classSyntax, classSemanticModel);
|
||||||
|
|
||||||
|
var (isValid, diagnostics) = Verify(root, classSyntax, classSemanticModel, classSymbol, sourceTypeSymbol);
|
||||||
|
if (!isValid)
|
||||||
{
|
{
|
||||||
context.ReportDiagnostic(diagnostic!);
|
diagnostics.ForEach(context.ReportDiagnostic);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var model = new MapModel(root, classSyntax, classSymbol!, sourceTypeSymbol!);
|
||||||
|
|
||||||
var (source, hintName) = SourceBuilder.GenerateSource(model);
|
var (source, hintName) = SourceBuilder.GenerateSource(model);
|
||||||
|
|
||||||
context.AddSource(hintName, source);
|
context.AddSource(hintName, source);
|
||||||
context.ReportDiagnostic(Diagnostics.ClassMappingsGenerated(classDeclarationSyntax.GetLocation(), model.ClassName));
|
context.ReportDiagnostic(Diagnostics.ClassMappingsGenerated(classSyntax.GetLocation(), model.ClassName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,5 +56,33 @@ namespace MapTo
|
||||||
var (source, hintName) = SourceBuilder.GenerateMapFromAttribute();
|
var (source, hintName) = SourceBuilder.GenerateMapFromAttribute();
|
||||||
context.AddSource(hintName, source);
|
context.AddSource(hintName, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static INamedTypeSymbol? GetSourceTypeSymbol(ClassDeclarationSyntax classSyntax, SemanticModel model)
|
||||||
|
{
|
||||||
|
var sourceTypeExpressionSyntax = classSyntax
|
||||||
|
.GetAttribute(SourceBuilder.MapFromAttributeName)
|
||||||
|
?.DescendantNodes()
|
||||||
|
.OfType<TypeOfExpressionSyntax>()
|
||||||
|
.SingleOrDefault();
|
||||||
|
|
||||||
|
return sourceTypeExpressionSyntax is not null ? model.GetTypeInfo(sourceTypeExpressionSyntax.Type).Type as INamedTypeSymbol : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (bool isValid, IEnumerable<Diagnostic> diagnostics) Verify(CompilationUnitSyntax root, ClassDeclarationSyntax classSyntax, SemanticModel classSemanticModel, INamedTypeSymbol? classSymbol, INamedTypeSymbol? sourceTypeSymbol)
|
||||||
|
{
|
||||||
|
var diagnostics = new List<Diagnostic>();
|
||||||
|
|
||||||
|
if (classSymbol is null)
|
||||||
|
{
|
||||||
|
diagnostics.Add(Diagnostics.SymbolNotFound(classSyntax.GetLocation(), classSyntax.Identifier.ValueText));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceTypeSymbol is null)
|
||||||
|
{
|
||||||
|
diagnostics.Add(Diagnostics.SymbolNotFound(classSyntax.GetLocation(), classSyntax.Identifier.ValueText));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!diagnostics.Any(), diagnostics);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using MapTo.Extensions;
|
using MapTo.Extensions;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
@ -28,6 +27,17 @@ namespace MapTo.Models
|
||||||
SourceTypeProperties = sourceTypeProperties;
|
SourceTypeProperties = sourceTypeProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal MapModel(CompilationUnitSyntax root, ClassDeclarationSyntax classSyntax, ITypeSymbol classSymbol, ITypeSymbol sourceTypeSymbol)
|
||||||
|
: this(
|
||||||
|
root.GetNamespace(),
|
||||||
|
classSyntax.Modifiers,
|
||||||
|
classSyntax.GetClassName(),
|
||||||
|
classSymbol.GetAllMembersOfType<IPropertySymbol>(),
|
||||||
|
sourceTypeSymbol.ContainingNamespace.ToString(),
|
||||||
|
sourceTypeSymbol.Name,
|
||||||
|
sourceTypeSymbol.ToString(),
|
||||||
|
sourceTypeSymbol.GetAllMembersOfType<IPropertySymbol>()) { }
|
||||||
|
|
||||||
public string? Namespace { get; }
|
public string? Namespace { get; }
|
||||||
|
|
||||||
public SyntaxTokenList ClassModifiers { get; }
|
public SyntaxTokenList ClassModifiers { get; }
|
||||||
|
@ -43,45 +53,5 @@ namespace MapTo.Models
|
||||||
public string SourceClassFullName { get; }
|
public string SourceClassFullName { get; }
|
||||||
|
|
||||||
public IEnumerable<IPropertySymbol> SourceTypeProperties { get; }
|
public IEnumerable<IPropertySymbol> SourceTypeProperties { get; }
|
||||||
|
|
||||||
internal static (MapModel? model, Diagnostic? diagnostic) Create(Compilation compilation, ClassDeclarationSyntax classSyntax)
|
|
||||||
{
|
|
||||||
var root = classSyntax.GetCompilationUnit();
|
|
||||||
var classSemanticModel = compilation.GetSemanticModel(classSyntax.SyntaxTree);
|
|
||||||
|
|
||||||
if (!(classSemanticModel.GetDeclaredSymbol(classSyntax) is INamedTypeSymbol classSymbol))
|
|
||||||
{
|
|
||||||
return (default, Diagnostics.SymbolNotFound(classSyntax.GetLocation(), classSyntax.Identifier.ValueText));
|
|
||||||
}
|
|
||||||
|
|
||||||
var sourceTypeSymbol = GetSourceTypeSymbol(classSyntax, classSemanticModel);
|
|
||||||
if (sourceTypeSymbol is null)
|
|
||||||
{
|
|
||||||
return (default, Diagnostics.SymbolNotFound(classSyntax.GetLocation(), classSyntax.Identifier.ValueText));
|
|
||||||
}
|
|
||||||
|
|
||||||
var model = new MapModel(
|
|
||||||
root.GetNamespace(),
|
|
||||||
classSyntax.Modifiers,
|
|
||||||
classSyntax.GetClassName(),
|
|
||||||
classSymbol.GetAllMembersOfType<IPropertySymbol>(),
|
|
||||||
sourceTypeSymbol.ContainingNamespace.ToString(),
|
|
||||||
sourceTypeSymbol.Name,
|
|
||||||
sourceTypeSymbol.ToString(),
|
|
||||||
sourceTypeSymbol.GetAllMembersOfType<IPropertySymbol>());
|
|
||||||
|
|
||||||
return (model, default);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ITypeSymbol? GetSourceTypeSymbol(ClassDeclarationSyntax classSyntax, SemanticModel model)
|
|
||||||
{
|
|
||||||
var sourceTypeExpressionSyntax = classSyntax
|
|
||||||
.GetAttribute(SourceBuilder.MapFromAttributeName)
|
|
||||||
?.DescendantNodes()
|
|
||||||
.OfType<TypeOfExpressionSyntax>()
|
|
||||||
.SingleOrDefault();
|
|
||||||
|
|
||||||
return sourceTypeExpressionSyntax is not null ? model.GetTypeInfo(sourceTypeExpressionSyntax.Type).Type : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue