Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
SMAP0004 | Design | Warning | SourceMapperDescriptors, [Documentation](https://github.com/alekshura/SourceMapper/wiki/Diagnostics##smap0004)
SMAP0005 | Design | Warning | SourceMapperDescriptors, [Documentation](https://github.com/alekshura/SourceMapper/wiki/Diagnostics##smap0005)

### Changed Rules
Rule ID | New Category | New Severity | Old Category | Old Severity | Notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ public static class SourceMapperDescriptors
public static readonly DiagnosticDescriptor DependencyInjectionNotUsed =
new("SMAP0004", "Dependency Injection not used", "No Dependency Injection mechanism used in project. '{0}'.", "Design", DiagnosticSeverity.Warning, true,
"SourceMapper based on Dependency Injection, but no used in project.", $"{DiagnosticsDescriptorsUri}#smap0004");

public static readonly DiagnosticDescriptor FieldIsNotMapped =
new("SMAP0005", "Field is not mapped", "The field '{0}' is not mapped", "Design", DiagnosticSeverity.Warning, true,
"Source field for defined target field not found, thus field does not mapped.", $"{DiagnosticsDescriptorsUri}#smap0005");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static class AttributesMatchers
/// <param name="attributes">Attributes collection</param>
/// <param name="targetProperty">Target property to match</param>
/// <returns>Matched attribute</returns>
internal static MappingAttribute MatchTargetAttribute(this IEnumerable<MappingAttribute> attributes, IPropertyMetadata targetProperty)
internal static MappingAttribute MatchTargetAttribute(this IEnumerable<MappingAttribute> attributes, IMetadata targetProperty)
{
return attributes.FirstOrDefault(attribute => attribute?.Target == targetProperty?.Name);
}
Expand All @@ -26,7 +26,7 @@ internal static MappingAttribute MatchTargetAttribute(this IEnumerable<MappingAt
/// <param name="targetProperty"></param>
/// <param name="sourceProperty"></param>
/// <returns></returns>
internal static MappingAttribute MatchExpressionAttribute(this IEnumerable<MappingAttribute> attributes, IPropertyMetadata targetProperty, IPropertyMetadata sourceProperty)
internal static MappingAttribute MatchExpressionAttribute(this IEnumerable<MappingAttribute> attributes, IMetadata targetProperty, IMetadata sourceProperty)
{
var matchedExpressionAttribute = attributes.FirstOrDefault(attribute => attribute?.Target == targetProperty?.Name
&& attribute?.Source == sourceProperty?.Name
Expand Down
16 changes: 8 additions & 8 deletions Compentio.SourceMapper.Generator/Matchers/MembersMatchers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ namespace Compentio.SourceMapper.Matchers
internal static class MembersMatchers
{
/// <summary>
/// Method searches for source member that matches <see cref="MappingAttribute.Source"/> value. This <see cref="MappingAttribute"/> also should match the target property.
/// Method searches for source member that matches <see cref="MappingAttribute.Source"/> value. This <see cref="MappingAttribute"/> also should match the target member.
/// </summary>
/// <param name="sourceMembers">Collection of source properties</param>
/// <param name="sourceMembers">Collection of source members</param>
/// <param name="mappingAttributes">Collection of all defined mapping attributes</param>
/// <param name="targetMember">Target member</param>
/// <returns>Matched source member</returns>
internal static IPropertyMetadata MatchSourceMember(this IEnumerable<IPropertyMetadata> sourceMembers, IEnumerable<MappingAttribute> mappingAttributes, IPropertyMetadata targetMember)
internal static IMemberMetadata MatchSourceMember(this IEnumerable<IMemberMetadata> sourceMembers, IEnumerable<MappingAttribute> mappingAttributes, IMemberMetadata targetMember)
{
var matchedAttribute = mappingAttributes.MatchTargetAttribute(targetMember);
var matchedSourceMember = sourceMembers.FirstOrDefault(member => member?.Name == matchedAttribute?.Source);
Expand All @@ -27,21 +27,21 @@ internal static IPropertyMetadata MatchSourceMember(this IEnumerable<IPropertyMe
/// <summary>
/// Method searches for source member that name matches target member.
/// </summary>
/// <param name="members">Collection of source properties</param>
/// <param name="members">Collection of source members</param>
/// <param name="targetMember">Target member</param>
/// <returns>Matched source member</returns>
internal static IPropertyMetadata MatchSourceMember(this IEnumerable<IPropertyMetadata> members, IPropertyMetadata targetMember)
internal static IMemberMetadata MatchSourceMember(this IEnumerable<IMemberMetadata> members, IMemberMetadata targetMember)
{
return members.FirstOrDefault(member => member?.Name == targetMember?.Name);
}
/// <summary>
/// Method searches for target member that matches <see cref="MappingAttribute.Target"/> value. This <see cref="MappingAttribute"/> also should match the target property.
/// Method searches for target member that matches <see cref="MappingAttribute.Target"/> value. This <see cref="MappingAttribute"/> also should match the target member.
/// </summary>
/// <param name="targetMembers">Collection of target properties</param>
/// <param name="targetMembers">Collection of target members</param>
/// <param name="mappingAttributes">Collection of all defined mapping attributes</param>
/// <param name="targetMember">Target member</param>
/// <returns>Matched target member</returns>
internal static IPropertyMetadata MatchTargetMember(this IEnumerable<IPropertyMetadata> targetMembers, IEnumerable<MappingAttribute> mappingAttributes, IPropertyMetadata targetMember)
internal static IMemberMetadata MatchTargetMember(this IEnumerable<IMemberMetadata> targetMembers, IEnumerable<MappingAttribute> mappingAttributes, IMemberMetadata targetMember)
{
var matchedAttribute = mappingAttributes.MatchTargetAttribute(targetMember);
var matchedTargetMember = targetMembers.FirstOrDefault(member => member?.Name == matchedAttribute?.Target);
Expand Down
6 changes: 3 additions & 3 deletions Compentio.SourceMapper.Generator/Matchers/MethodsMatchers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ internal static class MethodsMatchers
/// Returns method data that defined in mapping corresponds to source and target types.
/// This method can be used in mappings of nested types.
/// </summary>
/// <param name="source">Source property metadata</param>
/// <param name="target">Target property metadata</param>
/// <param name="source">Source member metadata</param>
/// <param name="target">Target member metadata</param>
/// <returns>Matched method <see cref="IMethodMetadata"/></returns>
internal static IMethodMetadata MatchDefinedMethod(this IMapperMetadata mapperMetadata, IPropertyMetadata source, IPropertyMetadata target)
internal static IMethodMetadata MatchDefinedMethod(this IMapperMetadata mapperMetadata, IMemberMetadata source, IMemberMetadata target)
{
var method = mapperMetadata.MethodsMetadata.FirstOrDefault(m =>
m.ReturnType.FullName == target.FullName && m.Parameters.FirstOrDefault().FullName == source.FullName);
Expand Down
120 changes: 120 additions & 0 deletions Compentio.SourceMapper.Generator/Metadata/MemberMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using Compentio.SourceMapper.Attributes;
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Linq;

namespace Compentio.SourceMapper.Metadata
{
/// <summary>
/// Encapsulates a member that is mapped
/// </summary>
internal interface IMemberMetadata : IMetadata
{
/// <summary>
/// Indicate that member is field or property (or unknown)
/// Based od <see cref="IPropertySymbol" /> and <see cref="IFieldSymbol" />
/// </summary>
MemberType MemberType { get; }

/// <summary>
/// Full name with namespace of the member
/// </summary>
string FullName { get; }

/// <summary>
/// Indicates whether the member is user defined class or no
/// </summary>
bool IsClass { get; }

/// <summary>
/// Indicates whether the member is static
/// </summary>
bool IsStatic { get; }

/// <summary>
/// Indicate that field should be ignored during mapping generating, due to <see cref="IgnoreMappingAttribute">
/// </summary>
bool IgnoreInMapping { get; }

/// <summary>
/// List of properties. It is empty in a case when the property is not user defined class: <c>IsClass == false</c> or is a field: <c>IsField == true</c>
/// </summary>
/// <see cref="IsClass"/>
/// <see cref="IsField"/>
IEnumerable<IMemberMetadata> Properties { get; }
}

internal class MemberMetadata : IMemberMetadata
{
private readonly ISymbol _symbol;

internal MemberMetadata(ISymbol symbol)
{
_symbol = symbol;
}

public MemberType MemberType
{
get
{
if (_symbol is IFieldSymbol) return MemberType.Field;
if (_symbol is IPropertySymbol) return MemberType.Property;

return MemberType.Unknown;
}
}

public string FullName => TypeMetadata.FullName;

public bool IsClass => Type.SpecialType == SpecialType.None && Type.TypeKind == TypeKind.Class;

public bool IsStatic => _symbol.IsStatic;

public bool IgnoreInMapping
{
get
{
var attribute = _symbol.GetAttributes().FirstOrDefault(attribute => attribute is not null && attribute.AttributeClass?.Name == nameof(IgnoreMappingAttribute));
return attribute != null;
}
}

public IEnumerable<IMemberMetadata> Properties
{
get
{
if (!IsClass || MemberType != MemberType.Property)
return Enumerable.Empty<IMemberMetadata>();

return Type.GetMembers()
.Where(member => member.Kind == SymbolKind.Property && !member.IsStatic)
.Select(member => new MemberMetadata(member as IPropertySymbol));
}
}

public Location? Location => _symbol.Locations.FirstOrDefault();

public string Name => _symbol.Name;

private ITypeSymbol Type
{
get
{
if (MemberType == MemberType.Field) return ((IFieldSymbol)_symbol).Type;
else return ((IPropertySymbol)_symbol).Type;
}
}

private ITypeMetadata TypeMetadata => new TypeMetadata(Type);
}

/// <summary>
/// Types of member
/// </summary>
internal enum MemberType
{
Field,
Property,
Unknown
}
}
80 changes: 0 additions & 80 deletions Compentio.SourceMapper.Generator/Metadata/PropertyMetadata.cs

This file was deleted.

31 changes: 22 additions & 9 deletions Compentio.SourceMapper.Generator/Metadata/TypeMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ internal interface ITypeMetadata : IMetadata
string FullName { get; }

/// <summary>
/// Object lis of properties
/// Object list of properties
/// </summary>
IEnumerable<IPropertyMetadata> Properties { get; }
IEnumerable<IMemberMetadata> Properties { get; }

/// <summary>
/// Object list of fields <see cref="IMemberMetadata.IsField == true" />
/// </summary>
IEnumerable<IMemberMetadata> Fields { get; }

/// <summary>
/// Recurrent method that return flatten list of properties tree for the object
/// </summary>
/// <param name="propertyMetadata">List of properties</param>
/// <returns></returns>
IEnumerable<IPropertyMetadata> FlattenProperties(IEnumerable<IPropertyMetadata> propertyMetadata);
IEnumerable<IMemberMetadata> FlattenProperties(IEnumerable<IMemberMetadata> propertyMetadata);
}

internal class ParameterTypeMetadata : ITypeMetadata
Expand All @@ -39,13 +44,17 @@ internal ParameterTypeMetadata(IParameterSymbol parameterSymbol)
public string Name => _parameterSymbol.Name;
public string FullName => _parameterSymbol.ToDisplayString();

public IEnumerable<IPropertyMetadata> Properties => _parameterSymbol.Type.GetMembers()
public IEnumerable<IMemberMetadata> Properties => _parameterSymbol.Type.GetMembers()
.Where(member => member as IPropertySymbol is not null)
.Select(member => new PropertyMetadata(member as IPropertySymbol));
.Select(member => new MemberMetadata(member as IPropertySymbol));

public IEnumerable<IMemberMetadata> Fields => _parameterSymbol.Type.GetMembers()
.Where(member => member is IFieldSymbol && member.CanBeReferencedByName && !((IFieldSymbol)member).IsConst)
.Select(member => new MemberMetadata(member as IFieldSymbol));

public Location? Location => _parameterSymbol.Locations.FirstOrDefault();

public IEnumerable<IPropertyMetadata> FlattenProperties(IEnumerable<IPropertyMetadata> propertyMetadata) =>
public IEnumerable<IMemberMetadata> FlattenProperties(IEnumerable<IMemberMetadata> propertyMetadata) =>
propertyMetadata.SelectMany(c => FlattenProperties(c.Properties)).Concat(propertyMetadata);
}

Expand All @@ -63,13 +72,17 @@ internal TypeMetadata(ITypeSymbol typeSymbol)

public ITypeSymbol Type => _typeSymbol;

public IEnumerable<IPropertyMetadata> Properties => _typeSymbol.GetMembers()
public IEnumerable<IMemberMetadata> Properties => _typeSymbol.GetMembers()
.Where(member => member.Kind == SymbolKind.Property && !member.IsStatic)
.Select(member => new PropertyMetadata(member as IPropertySymbol));
.Select(member => new MemberMetadata(member as IPropertySymbol));

public IEnumerable<IMemberMetadata> Fields => _typeSymbol.GetMembers()
.Where(member => member.Kind == SymbolKind.Field && member.CanBeReferencedByName && !((IFieldSymbol)member).IsConst)
.Select(member => new MemberMetadata(member as IFieldSymbol));

public Location? Location => _typeSymbol.Locations.FirstOrDefault();

public IEnumerable<IPropertyMetadata> FlattenProperties(IEnumerable<IPropertyMetadata> propertyMetadata) =>
public IEnumerable<IMemberMetadata> FlattenProperties(IEnumerable<IMemberMetadata> propertyMetadata) =>
propertyMetadata.SelectMany(c => FlattenProperties(c.Properties)).Concat(propertyMetadata);
}
}
Loading