private void OnMethodDeclaration(SyntaxNodeAnalysisContext context) { var method = (IMethodSymbol)context.ContainingSymbol; if (!method.IsMappingMethod()) { return; } var methodDeclarationSyntax = (MethodDeclarationSyntax)context.Node; var mappingMethodAttributeSyntax = MappingMethodDetection .GetMappingMethodAttributeSyntax(methodDeclarationSyntax, context.SemanticModel); var location = mappingMethodAttributeSyntax?.GetLocation() ?? methodDeclarationSyntax.Identifier.GetLocation(); var mappingTargetType = method.GetMappingTargetType(context.Compilation); if (mappingTargetType == null) { context.ReportDiagnostic(Diagnostic.Create(Diagnostics.MissingMappingTargetType, location)); return; } var mappingTargetProperties = mappingTargetType.GetMappingTargetProperties(); var mappedProperties = new HashSet <IPropertySymbol>(); foreach (var assignment in context.Node.DescendantNodes().OfType <AssignmentExpressionSyntax>()) { var assignmentTarget = context.SemanticModel.GetSymbolInfo(assignment.Left); if (assignmentTarget.Symbol is IPropertySymbol targetProperty) { mappedProperties.Add(targetProperty); } } var excludedPropertyNames = method.GetAttributes() .Where(a => a.AttributeClass.Name == "UnmappedPropertyAttribute") .Select(a => (string)a.ConstructorArguments[0].Value) .ToList(); excludedPropertyNames.AddRange(method.GetAttributes() .Where(a => a.AttributeClass.Name == "UnmappedPropertiesAttribute") .SelectMany(a => a.ConstructorArguments[0].Values.Select(v => (string)v.Value))); var unmappedPropertyNames = mappingTargetProperties .Except(mappedProperties, new RootPropertyEqualityComparer()) .Select(p => p.Name) .Except(excludedPropertyNames) .OrderBy(n => n); foreach (var unmappedPropertyName in unmappedPropertyNames) { var diagnostic = Diagnostic.Create(Diagnostics.UnmappedProperty, location, unmappedPropertyName); context.ReportDiagnostic(diagnostic); } }
public void GetMappingMethodAttributeSyntax_NoAttribute_ReturnsNull() { var(method, semanticModel) = GetMapMethodDeclaration(@" public class TestClass { public object Map() => new object(); } "); var attributeSyntax = MappingMethodDetection.GetMappingMethodAttributeSyntax(method, semanticModel); Assert.That(attributeSyntax, Is.Null); }
public void GetMappingMethodAttributeSyntax_FullyQualifiedAttributeUsage_ReturnsSyntaxNode() { var(method, semanticModel) = GetMapMethodDeclaration(@" public class TestClass { [global::ManualMappingGuard.MappingMethodAttribute()] public object Map() => new object(); } "); var attributeSyntax = MappingMethodDetection.GetMappingMethodAttributeSyntax(method, semanticModel); Assert.That(attributeSyntax !.GetLocation().SourceSpan, Is.EqualTo(new TextSpan(56, 51))); }
public void GetMappingMethodAttributeSyntax_RegularAttributeUsage_ReturnsSyntaxNode() { var(method, semanticModel) = GetMapMethodDeclaration(@" using ManualMappingGuard; public class TestClass { [MappingMethod] public object Map() => new object(); } "); var attributeSyntax = MappingMethodDetection.GetMappingMethodAttributeSyntax(method, semanticModel); Assert.That(attributeSyntax !.GetLocation().SourceSpan, Is.EqualTo(new TextSpan(93, 13))); }