diff --git a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs index b2c26017b9..2538b0a18f 100644 --- a/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs +++ b/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml.cs @@ -1,7 +1,6 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; - namespace Avalonia.NameGenerator.Sandbox.Views { /// @@ -16,7 +15,7 @@ namespace Avalonia.NameGenerator.Sandbox.Views public SignUpView() { AvaloniaXamlLoader.Load(this); - + UserNameTextBox.Text = "Joseph!"; UserNameValidation.Text = "User name is valid."; PasswordTextBox.Text = "qwerty"; diff --git a/src/Avalonia.NameGenerator.Tests/GlobPatternTests.cs b/src/Avalonia.NameGenerator.Tests/GlobPatternTests.cs new file mode 100644 index 0000000000..b21e659f30 --- /dev/null +++ b/src/Avalonia.NameGenerator.Tests/GlobPatternTests.cs @@ -0,0 +1,32 @@ +using Avalonia.NameGenerator.Generator; +using Xunit; + +namespace Avalonia.NameGenerator.Tests +{ + public class GlobPatternTests + { + [Theory] + [InlineData("*", "anything", true)] + [InlineData("", "anything", false)] + [InlineData("Views/*", "Views/SignUpView.xaml", true)] + [InlineData("Views/*", "Extensions/SignUpView.xaml", false)] + [InlineData("*SignUpView*", "Extensions/SignUpView.xaml", true)] + [InlineData("*SignUpView.paml", "Extensions/SignUpView.xaml", false)] + [InlineData("*.xaml", "Extensions/SignUpView.xaml", true)] + public void Should_Match_Glob_Expressions(string pattern, string value, bool matches) + { + Assert.Equal(matches, new GlobPattern(pattern).Matches(value)); + } + + [Theory] + [InlineData("Views/SignUpView.xaml", true, new[] { "*.xaml", "Views/*" })] + [InlineData("Views/SignUpView.paml", false, new[] { "*.xaml", "Views/*" })] + [InlineData("Extensions/SignUpView.paml", false, new[] { "*.xaml", "Views/*" })] + [InlineData("anything", true, new[] { "*", "*" })] + [InlineData("anything", false, new[] { "", "" })] + public void Should_Match_Glob_Pattern_Groups(string value, bool matches, string[] patterns) + { + Assert.Equal(matches, new GlobPatternGroup(patterns).Matches(value)); + } + } +} \ No newline at end of file diff --git a/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs b/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs index d9bd3a4353..81a54ef412 100644 --- a/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs +++ b/src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs @@ -42,6 +42,7 @@ namespace Avalonia.NameGenerator var types = new RoslynTypeSystem((CSharpCompilation)context.Compilation); var compiler = MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute); return new AvaloniaNameGenerator( + new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByPath), new XamlXViewResolver(types, compiler, true, type => ReportInvalidType(context, type)), new XamlXNameResolver(defaultFieldModifier), generator); diff --git a/src/Avalonia.NameGenerator/Domain/IGlobPattern.cs b/src/Avalonia.NameGenerator/Domain/IGlobPattern.cs new file mode 100644 index 0000000000..de75f7a197 --- /dev/null +++ b/src/Avalonia.NameGenerator/Domain/IGlobPattern.cs @@ -0,0 +1,7 @@ +namespace Avalonia.NameGenerator.Domain +{ + public interface IGlobPattern + { + bool Matches(string str); + } +} \ No newline at end of file diff --git a/src/Avalonia.NameGenerator/Generator.props b/src/Avalonia.NameGenerator/Generator.props index bef9155210..d853dedc0d 100644 --- a/src/Avalonia.NameGenerator/Generator.props +++ b/src/Avalonia.NameGenerator/Generator.props @@ -2,11 +2,13 @@ OnlyProperties internal + * + diff --git a/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs b/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs index e65a3b6f38..aaa3955c29 100644 --- a/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs +++ b/src/Avalonia.NameGenerator/Generator/AvaloniaNameGenerator.cs @@ -7,12 +7,18 @@ namespace Avalonia.NameGenerator.Generator { internal class AvaloniaNameGenerator : INameGenerator { + private readonly IGlobPattern _pathPattern; private readonly IViewResolver _classes; private readonly INameResolver _names; private readonly ICodeGenerator _code; - public AvaloniaNameGenerator(IViewResolver classes, INameResolver names, ICodeGenerator code) + public AvaloniaNameGenerator( + IGlobPattern pathPattern, + IViewResolver classes, + INameResolver names, + ICodeGenerator code) { + _pathPattern = pathPattern; _classes = classes; _names = names; _code = code; @@ -22,6 +28,7 @@ namespace Avalonia.NameGenerator.Generator { var resolveViewsQuery = from file in additionalFiles + where _pathPattern.Matches(file.Path) where file.Path.EndsWith(".xaml") || file.Path.EndsWith(".paml") || file.Path.EndsWith(".axaml") diff --git a/src/Avalonia.NameGenerator/Generator/GlobPattern.cs b/src/Avalonia.NameGenerator/Generator/GlobPattern.cs new file mode 100644 index 0000000000..6b6a0c83c7 --- /dev/null +++ b/src/Avalonia.NameGenerator/Generator/GlobPattern.cs @@ -0,0 +1,19 @@ +using System.Text.RegularExpressions; +using Avalonia.NameGenerator.Domain; + +namespace Avalonia.NameGenerator.Generator +{ + public class GlobPattern : IGlobPattern + { + private const RegexOptions GlobOptions = RegexOptions.IgnoreCase | RegexOptions.Singleline; + private readonly Regex _regex; + + public GlobPattern(string pattern) + { + var expression = "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$"; + _regex = new Regex(expression, GlobOptions); + } + + public bool Matches(string str) => _regex.IsMatch(str); + } +} \ No newline at end of file diff --git a/src/Avalonia.NameGenerator/Generator/GlobPatternGroup.cs b/src/Avalonia.NameGenerator/Generator/GlobPatternGroup.cs new file mode 100644 index 0000000000..dedc966435 --- /dev/null +++ b/src/Avalonia.NameGenerator/Generator/GlobPatternGroup.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Linq; +using Avalonia.NameGenerator.Domain; + +namespace Avalonia.NameGenerator.Generator +{ + public class GlobPatternGroup : IGlobPattern + { + private readonly GlobPattern[] _patterns; + + public GlobPatternGroup(IEnumerable patterns) => + _patterns = patterns + .Select(pattern => new GlobPattern(pattern)) + .ToArray(); + + public bool Matches(string str) => _patterns.All(pattern => pattern.Matches(str)); + } +} \ No newline at end of file diff --git a/src/Avalonia.NameGenerator/GeneratorOptions.cs b/src/Avalonia.NameGenerator/GeneratorOptions.cs index caba30a095..9966905aef 100644 --- a/src/Avalonia.NameGenerator/GeneratorOptions.cs +++ b/src/Avalonia.NameGenerator/GeneratorOptions.cs @@ -7,6 +7,7 @@ namespace Avalonia.NameGenerator { AvaloniaNameGeneratorBehavior = 0, AvaloniaNameGeneratorDefaultFieldModifier = 1, + AvaloniaNameGeneratorFilterByPath = 2, } public enum DefaultFieldModifier @@ -58,5 +59,19 @@ namespace Avalonia.NameGenerator return modifier; } } + + public string[] AvaloniaNameGeneratorFilterByPath + { + get + { + var propertyValue = _context.GetMSBuildProperty( + nameof(BuildProperties.AvaloniaNameGeneratorFilterByPath), + "*"); + + if (propertyValue.Contains(";")) + return propertyValue.Split(';'); + return new[] {propertyValue}; + } + } } } \ No newline at end of file