diff --git a/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs b/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs index 7bb609a..f9cc208 100644 --- a/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs +++ b/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs @@ -60,6 +60,7 @@ namespace System.Extensions var attributeSymbol = compilation.GetTypeByMetadataName($"{AttributeNamespace}.{AttributeName}"); if (attributeSymbol is null) { + context.ReportDiagnostic(Diagnostics.MissingAttributeDiagnostic(AttributeName, AttributeNamespace)); return; } @@ -79,16 +80,21 @@ namespace System.Extensions foreach (var group in fieldSymbols.GroupBy(f => f.ContainingType, SymbolEqualityComparer.IncludeNullability)) { - var classSource = ProcessClass((INamedTypeSymbol)group.Key, attributeSymbol, group.ToList()); + var classSource = ProcessClass((INamedTypeSymbol)group.Key, attributeSymbol, group.ToList(), context); + context.ReportDiagnostic(Diagnostics.GeneratedSymbolsForClassDiagnostic(group.Key.Name)); context.AddSource($"{group.Key.Name}.DependencyPropertyGenerator.g.cs", classSource); } } - private static string ProcessClass(INamedTypeSymbol classSymbol, INamedTypeSymbol attributeSymbol, List fields) + private static string ProcessClass(INamedTypeSymbol classSymbol, INamedTypeSymbol attributeSymbol, List fields, GeneratorExecutionContext generatorExecutionContext) { if (!classSymbol.ContainingSymbol.Equals(classSymbol.ContainingNamespace, SymbolEqualityComparer.Default)) { - return null; //TODO: issue a diagnostic that it must be top level + var syntaxTree = classSymbol.DeclaringSyntaxReferences.First().SyntaxTree; + var textSpan = classSymbol.DeclaringSyntaxReferences.First().Span; + generatorExecutionContext.ReportDiagnostic( + Diagnostics.ClassNotTopLevelDiagnostic(classSymbol.Name, classSymbol.ContainingSymbol.Name, syntaxTree, textSpan)); + return null; } var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); @@ -127,11 +133,6 @@ namespace System.Extensions var fieldType = fieldSymbol.Type; string propertyName = GenerateName(fieldName); - if (propertyName.Length == 0 || propertyName == fieldName) - { - //TODO: issue a diagnostic that we can't process this field - return; - } var attributeData = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default)); var initialValueOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "InitialValue").Value; diff --git a/WpfExtended.SourceGeneration/Diagnostics.cs b/WpfExtended.SourceGeneration/Diagnostics.cs new file mode 100644 index 0000000..08e16a9 --- /dev/null +++ b/WpfExtended.SourceGeneration/Diagnostics.cs @@ -0,0 +1,51 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace System.Extensions +{ + internal static class Diagnostics + { + public const string DependencyPropertyGenerator_NoAttributeFound = "DGD 0001"; + public const string DependencyPropertyGenerator_ClassMustBeTopLevel = "DGD 1001"; + public const string DependencyPropertyGenerator_Success = "DGD 3001"; + + public static Diagnostic MissingAttributeDiagnostic(string attributeName, string attributeNamespace) => Diagnostic.Create( + new DiagnosticDescriptor( + DependencyPropertyGenerator_NoAttributeFound, + $"{attributeNamespace}.{attributeName} not found", + "Could not find attribute with name {0} in namespace {1}.", + "WpfExtended.SourceGeneration", + DiagnosticSeverity.Error, + true, + $"This error occurs when the attribute generated by the {nameof(DependencyPropertyGenerator)} is not found", + null), + Location.None, + attributeName, attributeNamespace); + + public static Diagnostic ClassNotTopLevelDiagnostic(string className, string containingSymbol, SyntaxTree syntaxTree, TextSpan textSpan) => Diagnostic.Create( + new DiagnosticDescriptor( + DependencyPropertyGenerator_ClassMustBeTopLevel, + $"{className} must be top level", + "Class {0} must be top level. It is currently declared under {1}.", + "WpfExtended.SourceGeneration", + DiagnosticSeverity.Error, + true, + null, + null), + Location.Create(syntaxTree, textSpan), + className, containingSymbol); + + public static Diagnostic GeneratedSymbolsForClassDiagnostic(string className) => Diagnostic.Create( + new DiagnosticDescriptor( + DependencyPropertyGenerator_Success, + $"{className} created dependency properties", + "DependencyPropertyGenerator successfully created implementations for properties in {0}", + "WpfExtended.SourceGeneration", + DiagnosticSeverity.Info, + true, + null, + null), + Location.None, + className); + } +} diff --git a/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj b/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj index 4aa4469..2c23fd3 100644 --- a/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj +++ b/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj @@ -7,7 +7,7 @@ Alexandru Macocian Source generator library. LICENSE - 0.1 + 0.1.1 latest true @@ -25,5 +25,10 @@ - + + + + + +