From b5ddad6ec36b15bcf609f2926c62a188f5000296 Mon Sep 17 00:00:00 2001 From: artyom Date: Sat, 13 Feb 2021 01:24:41 +0300 Subject: [PATCH] feature: Ability to specify default field modifier, closes #31 --- .../AvaloniaNameSourceGenerator.cs | 48 ++++++++++--------- src/Avalonia.NameGenerator/Generator.props | 2 + .../Generator/XamlXNameResolver.cs | 10 +++- .../GeneratorOptions.cs | 28 ++++++++++- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs b/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs index acfdab35f5..d9bd3a4353 100644 --- a/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs +++ b/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs @@ -17,26 +17,10 @@ namespace Avalonia.NameGenerator public void Execute(GeneratorExecutionContext context) { - var compilation = (CSharpCompilation)context.Compilation; - var types = new RoslynTypeSystem(compilation); - var compiler = MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute); - - var options = new GeneratorOptions(context); - ICodeGenerator generator = options.AvaloniaNameGeneratorBehavior switch { - Behavior.OnlyProperties => new OnlyPropertiesCodeGenerator(), - Behavior.InitializeComponent => new InitializeComponentCodeGenerator(), - _ => throw new ArgumentOutOfRangeException() - }; - - INameGenerator avaloniaNameGenerator = - new AvaloniaNameGenerator( - new XamlXViewResolver(types, compiler, true, type => ReportInvalidType(context, type)), - new XamlXNameResolver(), - generator); - + var generator = CreateNameGenerator(context); try { - var partials = avaloniaNameGenerator.GenerateNameReferences(context.AdditionalFiles); + var partials = generator.GenerateNameReferences(context.AdditionalFiles); foreach (var partial in partials) context.AddSource(partial.FileName, partial.Content); } catch (Exception exception) @@ -45,10 +29,29 @@ namespace Avalonia.NameGenerator } } + private static INameGenerator CreateNameGenerator(GeneratorExecutionContext context) + { + var options = new GeneratorOptions(context); + var defaultFieldModifier = options.AvaloniaNameGeneratorDefaultFieldModifier.ToString().ToLowerInvariant(); + ICodeGenerator generator = options.AvaloniaNameGeneratorBehavior switch { + Behavior.OnlyProperties => new OnlyPropertiesCodeGenerator(), + Behavior.InitializeComponent => new InitializeComponentCodeGenerator(), + _ => throw new ArgumentOutOfRangeException() + }; + + var types = new RoslynTypeSystem((CSharpCompilation)context.Compilation); + var compiler = MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute); + return new AvaloniaNameGenerator( + new XamlXViewResolver(types, compiler, true, type => ReportInvalidType(context, type)), + new XamlXNameResolver(defaultFieldModifier), + generator); + } + private static void ReportUnhandledError(GeneratorExecutionContext context, Exception error) { - const string message = "Unhandled exception occured while generating typed Name references. " + - "Please file an issue: https://github.com/avaloniaui/avalonia.namegenerator"; + const string message = + "Unhandled exception occured while generating typed Name references. " + + "Please file an issue: https://github.com/avaloniaui/avalonia.namegenerator"; context.ReportDiagnostic( Diagnostic.Create( new DiagnosticDescriptor( @@ -63,8 +66,9 @@ namespace Avalonia.NameGenerator private static void ReportInvalidType(GeneratorExecutionContext context, string typeName) { - var message = $"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " + - $"The type '{typeName}' does not exist in the assembly."; + var message = + $"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " + + $"The type '{typeName}' does not exist in the assembly."; context.ReportDiagnostic( Diagnostic.Create( new DiagnosticDescriptor( diff --git a/src/Avalonia.NameGenerator/Generator.props b/src/Avalonia.NameGenerator/Generator.props index 5965e7d6f6..bef9155210 100644 --- a/src/Avalonia.NameGenerator/Generator.props +++ b/src/Avalonia.NameGenerator/Generator.props @@ -1,10 +1,12 @@  OnlyProperties + internal + diff --git a/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs b/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs index a110432a78..bda9c98882 100644 --- a/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs +++ b/src/Avalonia.NameGenerator/Generator/XamlXNameResolver.cs @@ -9,6 +9,12 @@ namespace Avalonia.NameGenerator.Generator internal class XamlXNameResolver : INameResolver, IXamlAstVisitor { private readonly List _items = new(); + private readonly string _defaultFieldModifier; + + public XamlXNameResolver(string defaultFieldModifier = "internal") + { + _defaultFieldModifier = defaultFieldModifier; + } public IReadOnlyList ResolveNames(XamlDocument xaml) { @@ -55,7 +61,7 @@ namespace Avalonia.NameGenerator.Generator void IXamlAstVisitor.Pop() { } - private static string TryGetFieldModifier(XamlAstObjectNode objectNode) + private string TryGetFieldModifier(XamlAstObjectNode objectNode) { // We follow Xamarin.Forms API behavior in terms of x:FieldModifier here: // https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/field-modifiers @@ -78,7 +84,7 @@ namespace Avalonia.NameGenerator.Generator "protected" => "protected", "internal" => "internal", "notpublic" => "internal", - _ => "internal" + _ => _defaultFieldModifier }; } } diff --git a/src/Avalonia.NameGenerator/GeneratorOptions.cs b/src/Avalonia.NameGenerator/GeneratorOptions.cs index efa10b39cf..caba30a095 100644 --- a/src/Avalonia.NameGenerator/GeneratorOptions.cs +++ b/src/Avalonia.NameGenerator/GeneratorOptions.cs @@ -5,7 +5,16 @@ namespace Avalonia.NameGenerator { public enum BuildProperties { - AvaloniaNameGeneratorBehavior = 0 + AvaloniaNameGeneratorBehavior = 0, + AvaloniaNameGeneratorDefaultFieldModifier = 1, + } + + public enum DefaultFieldModifier + { + Public = 0, + Private = 1, + Internal = 2, + Protected = 3, } public enum Behavior @@ -29,10 +38,25 @@ namespace Avalonia.NameGenerator nameof(BuildProperties.AvaloniaNameGeneratorBehavior), nameof(Behavior.OnlyProperties)); - if (!Enum.TryParse(propertyValue, out Behavior behavior)) + if (!Enum.TryParse(propertyValue, true, out Behavior behavior)) return Behavior.OnlyProperties; return behavior; } } + + public DefaultFieldModifier AvaloniaNameGeneratorDefaultFieldModifier + { + get + { + var propertyValue = _context + .GetMSBuildProperty( + nameof(BuildProperties.AvaloniaNameGeneratorDefaultFieldModifier), + nameof(DefaultFieldModifier.Internal)); + + if (!Enum.TryParse(propertyValue, true, out DefaultFieldModifier modifier)) + return DefaultFieldModifier.Internal; + return modifier; + } + } } } \ No newline at end of file