public static void Create() { var syntaxTree = CSharpSyntaxTree.ParseText("public class A { public int B { get; } }"); var typeSyntax = syntaxTree.GetRoot().DescendantNodes(_ => true).OfType <TypeDeclarationSyntax>().Single(); var references = AppDomain.CurrentDomain.GetAssemblies() .Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location)) .Select(_ => MetadataReference.CreateFromFile(_.Location)) .Concat(new[] { MetadataReference.CreateFromFile(typeof(MapGenerator).Assembly.Location) }); var compilation = CSharpCompilation.Create("generator", new SyntaxTree[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var model = compilation.GetSemanticModel(syntaxTree, true); var typeSymbol = model.GetDeclaredSymbol(typeSyntax) !; var propertySymbol = (typeSymbol.GetMembers("B")[0] as IPropertySymbol) !; var diagnostic = NoMatchDiagnostic.Create(propertySymbol, "C", typeSymbol); Assert.Multiple(() => { Assert.That(diagnostic.GetMessage(), Is.EqualTo("A match for B on the C type A could not be found.")); Assert.That(diagnostic.Descriptor.Title.ToString(CultureInfo.CurrentCulture), Is.EqualTo(NoMatchDiagnostic.Title)); Assert.That(diagnostic.Id, Is.EqualTo(NoMatchDiagnostic.Id)); Assert.That(diagnostic.Severity, Is.EqualTo(DiagnosticSeverity.Info)); Assert.That(diagnostic.Descriptor.Category, Is.EqualTo(DescriptorConstants.Usage)); }); }
private static void ValidatePairs(SyntaxNode currentNode, INamedTypeSymbol source, INamedTypeSymbol destination, Maps.Builder maps) { var key = (source, destination); if (maps.ContainsKey(key)) { var diagnostics = maps[key].diagnostics.ToList(); diagnostics.Add(DuplicatedAttributeDiagnostic.Create(currentNode, maps[key].node)); maps[key] = (diagnostics.ToImmutableArray(), maps[key].node, maps[key].maps); } else { var diagnostics = ImmutableArray.CreateBuilder <Diagnostic>(); if (!destination.Constructors.Any(_ => _.DeclaredAccessibility == Accessibility.Public && _.Parameters.Length == 0)) { diagnostics.Add(NoArgumentConstructorDiagnostic.Create(currentNode)); } var propertyMaps = ImmutableArray.CreateBuilder <string>(); var destinationProperties = destination.GetMembers().OfType <IPropertySymbol>() .Where(_ => _.SetMethod is not null && (_.SetMethod.DeclaredAccessibility == Accessibility.Public || (destination.ContainingAssembly.ExposesInternalsTo(source.ContainingAssembly) && _.SetMethod.DeclaredAccessibility == Accessibility.Friend))) .ToList(); foreach (var sourceProperty in source.GetMembers().OfType <IPropertySymbol>() .Where(_ => _.GetMethod is not null && (_.GetMethod.DeclaredAccessibility == Accessibility.Public || (source.ContainingAssembly.ExposesInternalsTo(destination.ContainingAssembly) && _.GetMethod.DeclaredAccessibility == Accessibility.Friend)))) { var destinationProperty = destinationProperties.FirstOrDefault( _ => _.Name == sourceProperty.Name && _.Type.Equals(sourceProperty.Type, SymbolEqualityComparer.Default) && (sourceProperty.NullableAnnotation != NullableAnnotation.Annotated || sourceProperty.NullableAnnotation == NullableAnnotation.Annotated && _.NullableAnnotation == NullableAnnotation.Annotated)); if (destinationProperty is not null) { propertyMaps.Add($"{destinationProperty.Name} = self.{sourceProperty.Name},"); destinationProperties.Remove(destinationProperty); } else { diagnostics.Add(NoMatchDiagnostic.Create(sourceProperty, "source", source)); } } foreach (var remainingDestinationProperty in destinationProperties) { diagnostics.Add(NoMatchDiagnostic.Create(remainingDestinationProperty, "destination", destination)); } if (propertyMaps.Count == 0) { diagnostics.Add(NoPropertyMapsFoundDiagnostic.Create(currentNode)); } maps.Add((source, destination), (diagnostics.ToImmutable(), currentNode, propertyMaps.ToImmutable())); } }