From 9d7ce59e14d2b454d886573dd4f944359c262581 Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Thu, 11 Apr 2024 11:59:00 +0200 Subject: [PATCH] Use compilation units Use filescoped namespaces where supported --- .../DependencyPropertyGenerator.cs | 45 ++++++++------ .../NotifyPropertyChangedGenerator.cs | 62 +++++++++++-------- .../WpfExtended.SourceGeneration.csproj | 4 +- 3 files changed, 65 insertions(+), 46 deletions(-) diff --git a/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs b/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs index ec7f98c..823fd0e 100644 --- a/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs +++ b/WpfExtended.SourceGeneration/DependencyPropertyGenerator.cs @@ -1,14 +1,9 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using Sybil; -using System.Collections.Generic; using System.Collections.Immutable; -using System.ComponentModel; -using System.Diagnostics; using System.Linq; -using System.Text; namespace System.Extensions; #nullable enable @@ -32,8 +27,11 @@ public class DependencyPropertyGenerator : IIncrementalGenerator { context.RegisterPostInitializationOutput(context => { - var attributeNamespaceBuilder = SyntaxBuilder.CreateNamespace(AttributeNamespace) - .WithUsing("System.ComponentModel") + var compilationUnitBuilder = + SyntaxBuilder.CreateCompilationUnit() + .WithUsing("System.ComponentModel") + .WithNamespace( + SyntaxBuilder.CreateNamespace(AttributeNamespace) .WithClass(SyntaxBuilder.CreateClass(AttributeName) .WithModifier(Public) .WithConstructor(SyntaxBuilder.CreateConstructor(AttributeName) @@ -46,9 +44,9 @@ public class DependencyPropertyGenerator : IIncrementalGenerator .WithProperty(SyntaxBuilder.CreateProperty("object", InitialValue) .WithModifier(Public) .WithAccessor(SyntaxBuilder.CreateGetter()) - .WithAccessor(SyntaxBuilder.CreateSetter()))); - var attributeSyntax = attributeNamespaceBuilder.Build(); - var source = attributeSyntax.ToFullString(); + .WithAccessor(SyntaxBuilder.CreateSetter())))); + var compilationUnitSyntax = compilationUnitBuilder.Build(); + var source = compilationUnitSyntax.ToFullString(); context.AddSource($"{AttributeName}.g", source); }); @@ -74,13 +72,20 @@ public class DependencyPropertyGenerator : IIncrementalGenerator return default; } - private static void Execute(Compilation _, ImmutableArray classes, SourceProductionContext sourceProductionContext) + private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext sourceProductionContext) { if (classes.IsDefaultOrEmpty) { return; } + var maybeLanguageVersion = (compilation.SyntaxTrees.FirstOrDefault()?.Options as CSharpParseOptions)?.LanguageVersion; + if (!maybeLanguageVersion.HasValue) + { + return; + } + + var languageVersion = maybeLanguageVersion.Value; var distinctClasses = classes.Distinct(); foreach (var c in distinctClasses.OfType()) { @@ -100,13 +105,17 @@ public class DependencyPropertyGenerator : IIncrementalGenerator var generatedClassBuilder = SyntaxBuilder.CreateClass(className) .WithModifiers(string.Join(" ", c.Modifiers.Select(m => m.ToFullString()))); - var generatedNamespaceBuilder = SyntaxBuilder.CreateNamespace(originalNamespaceSyntax.Name.ToFullString()) - .WithClass(generatedClassBuilder); + var generatedCompilationUnit = SyntaxBuilder.CreateCompilationUnit() + .WithNamespace( + (languageVersion >= LanguageVersion.CSharp10 ? + SyntaxBuilder.CreateFileScopedNamespace(originalNamespaceSyntax.Name.ToFullString()) : + SyntaxBuilder.CreateNamespace(originalNamespaceSyntax.Name.ToFullString())) + .WithClass(generatedClassBuilder)); if (originalNamespaceSyntax.Usings.OfType().Any(u => u.Name?.ToString() == DependencyPropertyNamespace) is false && (originalNamespaceSyntax.Parent as CompilationUnitSyntax)?.Usings.Any(u => u.Name?.ToString() == DependencyPropertyNamespace) is false) { - generatedNamespaceBuilder.WithUsing(DependencyPropertyNamespace); + generatedCompilationUnit.WithUsing(DependencyPropertyNamespace); } foreach (var field in c.DescendantNodes().OfType()) @@ -144,20 +153,20 @@ public class DependencyPropertyGenerator : IIncrementalGenerator .WithField(dependencyPropertyFieldBuilder); } - var generatedNamespace = generatedNamespaceBuilder.Build(); + var generatedSyntax = generatedCompilationUnit.Build(); if (originalNamespaceSyntax.Usings.Count != 0) { - generatedNamespace = generatedNamespace.AddUsings([.. originalNamespaceSyntax.Usings]); + generatedSyntax = generatedSyntax.AddUsings([.. originalNamespaceSyntax.Usings]); } else { if (originalNamespaceSyntax.Parent is CompilationUnitSyntax compilationUnit) { - generatedNamespace = generatedNamespace.AddUsings([.. compilationUnit.Usings]); + generatedSyntax = generatedSyntax.AddUsings([.. compilationUnit.Usings]); } } - var fileSource = generatedNamespace.ToFullString(); + var fileSource = generatedSyntax.ToFullString(); sourceProductionContext.AddSource($"{className}.g", fileSource); } } diff --git a/WpfExtended.SourceGeneration/NotifyPropertyChangedGenerator.cs b/WpfExtended.SourceGeneration/NotifyPropertyChangedGenerator.cs index 0f60c23..1ff1ae8 100644 --- a/WpfExtended.SourceGeneration/NotifyPropertyChangedGenerator.cs +++ b/WpfExtended.SourceGeneration/NotifyPropertyChangedGenerator.cs @@ -3,6 +3,8 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Sybil; using System.Linq; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CSharp; +using System.Diagnostics; namespace System.Extensions; #nullable enable @@ -22,8 +24,9 @@ public class NotifyPropertyChangedGenerator : IIncrementalGenerator { context.RegisterPostInitializationOutput(context => { - var attributeNamespaceBuilder = SyntaxBuilder.CreateNamespace(AttributeNamespace) - .WithUsing("System.ComponentModel") + var compilationUnitBuilder = SyntaxBuilder.CreateCompilationUnit() + .WithNamespace( + SyntaxBuilder.CreateNamespace(AttributeNamespace) .WithClass(SyntaxBuilder.CreateClass(AttributeName) .WithModifier(Public) .WithConstructor(SyntaxBuilder.CreateConstructor(AttributeName) @@ -32,9 +35,9 @@ public class NotifyPropertyChangedGenerator : IIncrementalGenerator .WithArgument(AttributeTargets.Field) .WithArgument("Inherited", false) .WithArgument("AllowMultiple", false)) - .WithBaseClass(nameof(Attribute))); - var attributeSyntax = attributeNamespaceBuilder.Build(); - var source = attributeSyntax.ToFullString(); + .WithBaseClass(nameof(Attribute)))); + var compilationUnitSyntax = compilationUnitBuilder.Build(); + var source = compilationUnitSyntax.ToFullString(); context.AddSource($"{AttributeName}.g", source); }); @@ -60,13 +63,20 @@ public class NotifyPropertyChangedGenerator : IIncrementalGenerator return default; } - private static void Execute(Compilation _, ImmutableArray classes, SourceProductionContext sourceProductionContext) + private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext sourceProductionContext) { if (classes.IsDefaultOrEmpty) { return; } + var maybeLanguageVersion = (compilation.SyntaxTrees.FirstOrDefault()?.Options as CSharpParseOptions)?.LanguageVersion; + if (!maybeLanguageVersion.HasValue) + { + return; + } + + var languageVersion = maybeLanguageVersion.Value; var distinctClasses = classes.Distinct(); foreach (var c in distinctClasses.OfType()) { @@ -98,25 +108,12 @@ public class NotifyPropertyChangedGenerator : IIncrementalGenerator var generatedClassBuilder = SyntaxBuilder.CreateClass(className) .WithModifiers(string.Join(" ", c.Modifiers.Select(m => m.ToFullString()))); - var generatedNamespaceBuilder = SyntaxBuilder.CreateNamespace(originalNamespaceSyntax.Name.ToFullString()) - .WithClass(generatedClassBuilder); - if (originalNamespaceSyntax.Usings.Count != 0) - { - foreach (var u in originalNamespaceSyntax.Usings.OfType()) - { - generatedNamespaceBuilder.WithUsing(u.Name?.ToString()); - } - } - else - { - if (originalNamespaceSyntax.Parent is CompilationUnitSyntax compilationUnit) - { - foreach(var u in compilationUnit.Usings.OfType()) - { - generatedNamespaceBuilder.WithUsing(u.Name?.ToString()); - } - } - } + var compilationUnitBuilder = SyntaxBuilder.CreateCompilationUnit() + .WithNamespace( + (languageVersion >= LanguageVersion.CSharp10 ? + SyntaxBuilder.CreateFileScopedNamespace(originalNamespaceSyntax.Name.ToFullString()) : + SyntaxBuilder.CreateNamespace(originalNamespaceSyntax.Name.ToFullString())) + .WithClass(generatedClassBuilder)); foreach (var field in c.DescendantNodes().OfType()) { @@ -141,7 +138,20 @@ public class NotifyPropertyChangedGenerator : IIncrementalGenerator generatedClassBuilder.WithProperty(propertyBuilder); } - var fileSource = generatedNamespaceBuilder.Build().ToFullString(); + var generatedSyntax = compilationUnitBuilder.Build(); + if (originalNamespaceSyntax.Usings.Count != 0) + { + generatedSyntax = generatedSyntax.AddUsings([.. originalNamespaceSyntax.Usings]); + } + else + { + if (originalNamespaceSyntax.Parent is CompilationUnitSyntax compilationUnit) + { + generatedSyntax = generatedSyntax.AddUsings([.. compilationUnit.Usings]); + } + } + + var fileSource = generatedSyntax.ToFullString(); sourceProductionContext.AddSource($"{className}.g", fileSource); } } diff --git a/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj b/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj index c279ed6..5b40ee8 100644 --- a/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj +++ b/WpfExtended.SourceGeneration/WpfExtended.SourceGeneration.csproj @@ -7,7 +7,7 @@ Alexandru Macocian Source generator library. LICENSE - 0.2.0 + 0.3.0 latest true true @@ -20,7 +20,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - +