Browse Source

feature: Generate this.AttachDevTools() if Avalonia.Diagnostics is nearby (#35)

pull/10407/head
Artyom V. Gorchakov 5 years ago
committed by GitHub
parent
commit
6e621e553a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Avalonia.NameGenerator.Tests/Avalonia.NameGenerator.Tests.csproj
  2. 26
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/AttachedProps.txt
  3. 30
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/CustomControls.txt
  4. 28
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/DataTemplates.txt
  5. 34
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/DevToolsCode.cs
  6. 36
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/FieldModifier.txt
  7. 26
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NamedControl.txt
  8. 30
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NamedControls.txt
  9. 26
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NoNamedControls.txt
  10. 42
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/SignUpView.txt
  11. 26
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/xNamedControl.txt
  12. 30
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/xNamedControls.txt
  13. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/AttachedProps.txt
  14. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/CustomControls.txt
  15. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/DataTemplates.txt
  16. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/FieldModifier.txt
  17. 6
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/InitializeComponentCode.cs
  18. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NamedControl.txt
  19. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NamedControls.txt
  20. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NoNamedControls.txt
  21. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/SignUpView.txt
  22. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/xNamedControl.txt
  23. 0
      src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/xNamedControls.txt
  24. 51
      src/Avalonia.NameGenerator.Tests/InitializeComponent/InitializeComponentTests.cs
  25. 6
      src/Avalonia.NameGenerator.Tests/Views/View.cs
  26. 37
      src/Avalonia.NameGenerator/Compiler/RoslynTypeSystem.cs
  27. 12
      src/Avalonia.NameGenerator/Domain/INameGenerator.cs
  28. 14
      src/Avalonia.NameGenerator/Domain/INameResolver.cs
  29. 14
      src/Avalonia.NameGenerator/Domain/IViewResolver.cs
  30. 5
      src/Avalonia.NameGenerator/Domain/IsExternalInit.cs
  31. 4
      src/Avalonia.NameGenerator/Generator.cs
  32. 27
      src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs
  33. 1
      src/Directory.Build.props

4
src/Avalonia.NameGenerator.Tests/Avalonia.NameGenerator.Tests.csproj

@ -8,6 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="xunit" Version="2.4.1" />
@ -17,7 +18,8 @@
<ItemGroup>
<EmbeddedResource Include="Views\*.xml" />
<EmbeddedResource Include="OnlyProperties\GeneratedCode\*.txt" />
<EmbeddedResource Include="InitializeComponent\GeneratedCode\*.txt" />
<EmbeddedResource Include="InitializeComponent\GeneratedInitializeComponent\*.txt" />
<EmbeddedResource Include="InitializeComponent\GeneratedDevTools\*.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.NameGenerator\Avalonia.NameGenerator.csproj" />

26
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/AttachedProps.txt

@ -0,0 +1,26 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
}
}
}

30
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/CustomControls.txt

@ -0,0 +1,30 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.ReactiveUI.RoutedViewHost ClrNamespaceRoutedViewHost { get; set; }
internal global::Avalonia.ReactiveUI.RoutedViewHost UriRoutedViewHost { get; set; }
internal global::Controls.CustomTextBox UserNameTextBox { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
ClrNamespaceRoutedViewHost = this.FindControl<global::Avalonia.ReactiveUI.RoutedViewHost>("ClrNamespaceRoutedViewHost");
UriRoutedViewHost = this.FindControl<global::Avalonia.ReactiveUI.RoutedViewHost>("UriRoutedViewHost");
UserNameTextBox = this.FindControl<global::Controls.CustomTextBox>("UserNameTextBox");
}
}
}

28
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/DataTemplates.txt

@ -0,0 +1,28 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
internal global::Avalonia.Controls.ListBox NamedListBox { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
NamedListBox = this.FindControl<global::Avalonia.Controls.ListBox>("NamedListBox");
}
}
}

34
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/DevToolsCode.cs

@ -0,0 +1,34 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedDevTools
{
public static class DevToolsCode
{
public const string NamedControl = "NamedControl.txt";
public const string NamedControls = "NamedControls.txt";
public const string XNamedControl = "xNamedControl.txt";
public const string XNamedControls = "xNamedControls.txt";
public const string NoNamedControls = "NoNamedControls.txt";
public const string CustomControls = "CustomControls.txt";
public const string DataTemplates = "DataTemplates.txt";
public const string SignUpView = "SignUpView.txt";
public const string AttachedProps = "AttachedProps.txt";
public const string FieldModifier = "FieldModifier.txt";
public static async Task<string> Load(string generatedCodeResourceName)
{
var assembly = typeof(XamlXNameResolverTests).Assembly;
var fullResourceName = assembly
.GetManifestResourceNames()
.First(name => name.Contains("InitializeComponent") &&
name.Contains("GeneratedDevTools") &&
name.EndsWith(generatedCodeResourceName));
await using var stream = assembly.GetManifestResourceStream(fullResourceName);
using var reader = new StreamReader(stream!);
return await reader.ReadToEndAsync();
}
}
}

36
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/FieldModifier.txt

@ -0,0 +1,36 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
public global::Avalonia.Controls.TextBox FirstNameTextBox { get; set; }
public global::Avalonia.Controls.TextBox LastNameTextBox { get; set; }
protected global::Avalonia.Controls.TextBox PasswordTextBox { get; set; }
private global::Avalonia.Controls.TextBox ConfirmPasswordTextBox { get; set; }
internal global::Avalonia.Controls.Button SignUpButton { get; set; }
internal global::Avalonia.Controls.Button RegisterButton { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
FirstNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("FirstNameTextBox");
LastNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("LastNameTextBox");
PasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
ConfirmPasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("ConfirmPasswordTextBox");
SignUpButton = this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
RegisterButton = this.FindControl<global::Avalonia.Controls.Button>("RegisterButton");
}
}
}

26
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NamedControl.txt

@ -0,0 +1,26 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
}
}
}

30
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NamedControls.txt

@ -0,0 +1,30 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
internal global::Avalonia.Controls.TextBox PasswordTextBox { get; set; }
internal global::Avalonia.Controls.Button SignUpButton { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
PasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
SignUpButton = this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
}
}
}

26
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/NoNamedControls.txt

@ -0,0 +1,26 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
}
}
}

42
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/SignUpView.txt

@ -0,0 +1,42 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Controls.CustomTextBox UserNameTextBox { get; set; }
internal global::Avalonia.Controls.TextBlock UserNameValidation { get; set; }
internal global::Avalonia.Controls.TextBox PasswordTextBox { get; set; }
internal global::Avalonia.Controls.TextBlock PasswordValidation { get; set; }
internal global::Avalonia.Controls.ListBox AwesomeListView { get; set; }
internal global::Avalonia.Controls.TextBox ConfirmPasswordTextBox { get; set; }
internal global::Avalonia.Controls.TextBlock ConfirmPasswordValidation { get; set; }
internal global::Avalonia.Controls.Button SignUpButton { get; set; }
internal global::Avalonia.Controls.TextBlock CompoundValidation { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Controls.CustomTextBox>("UserNameTextBox");
UserNameValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("UserNameValidation");
PasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
PasswordValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("PasswordValidation");
AwesomeListView = this.FindControl<global::Avalonia.Controls.ListBox>("AwesomeListView");
ConfirmPasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("ConfirmPasswordTextBox");
ConfirmPasswordValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("ConfirmPasswordValidation");
SignUpButton = this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
CompoundValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("CompoundValidation");
}
}
}

26
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/xNamedControl.txt

@ -0,0 +1,26 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
}
}
}

30
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedDevTools/xNamedControls.txt

@ -0,0 +1,30 @@
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.Controls.TextBox UserNameTextBox { get; set; }
internal global::Avalonia.Controls.TextBox PasswordTextBox { get; set; }
internal global::Avalonia.Controls.Button SignUpButton { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
#if DEBUG
this.AttachDevTools();
#endif
UserNameTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("UserNameTextBox");
PasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
SignUpButton = this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
}
}
}

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/AttachedProps.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/AttachedProps.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/CustomControls.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/CustomControls.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/DataTemplates.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/DataTemplates.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/FieldModifier.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/FieldModifier.txt

6
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/InitializeComponentCode.cs → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/InitializeComponentCode.cs

@ -2,7 +2,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedCode
namespace Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedInitializeComponent
{
public static class InitializeComponentCode
{
@ -22,7 +22,9 @@ namespace Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedCode
var assembly = typeof(XamlXNameResolverTests).Assembly;
var fullResourceName = assembly
.GetManifestResourceNames()
.First(name => name.Contains("InitializeComponent") && name.EndsWith(generatedCodeResourceName));
.First(name => name.Contains("InitializeComponent") &&
name.Contains("GeneratedInitializeComponent") &&
name.EndsWith(generatedCodeResourceName));
await using var stream = assembly.GetManifestResourceStream(fullResourceName);
using var reader = new StreamReader(stream!);

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/NamedControl.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NamedControl.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/NamedControls.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NamedControls.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/NoNamedControls.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/NoNamedControls.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/SignUpView.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/SignUpView.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/xNamedControl.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/xNamedControl.txt

0
src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedCode/xNamedControls.txt → src/Avalonia.NameGenerator.Tests/InitializeComponent/GeneratedInitializeComponent/xNamedControls.txt

51
src/Avalonia.NameGenerator.Tests/InitializeComponent/InitializeComponentTests.cs

@ -1,7 +1,8 @@
using System.Threading.Tasks;
using Avalonia.NameGenerator.Compiler;
using Avalonia.NameGenerator.Generator;
using Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedCode;
using Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedDevTools;
using Avalonia.NameGenerator.Tests.InitializeComponent.GeneratedInitializeComponent;
using Avalonia.NameGenerator.Tests.OnlyProperties.GeneratedCode;
using Avalonia.NameGenerator.Tests.Views;
using Microsoft.CodeAnalysis.CSharp;
@ -12,24 +13,39 @@ namespace Avalonia.NameGenerator.Tests.InitializeComponent
public class InitializeComponentTests
{
[Theory]
[InlineData(InitializeComponentCode.NamedControl, View.NamedControl)]
[InlineData(InitializeComponentCode.NamedControls, View.NamedControls)]
[InlineData(InitializeComponentCode.XNamedControl, View.XNamedControl)]
[InlineData(InitializeComponentCode.XNamedControls, View.XNamedControls)]
[InlineData(InitializeComponentCode.NoNamedControls, View.NoNamedControls)]
[InlineData(InitializeComponentCode.CustomControls, View.CustomControls)]
[InlineData(InitializeComponentCode.DataTemplates, View.DataTemplates)]
[InlineData(InitializeComponentCode.SignUpView, View.SignUpView)]
[InlineData(InitializeComponentCode.AttachedProps, View.AttachedProps)]
[InlineData(InitializeComponentCode.FieldModifier, View.FieldModifier)]
public async Task Should_Generate_FindControl_Refs_From_Avalonia_Markup_File(string expectation, string markup)
[InlineData(InitializeComponentCode.NamedControl, View.NamedControl, false)]
[InlineData(InitializeComponentCode.NamedControls, View.NamedControls, false)]
[InlineData(InitializeComponentCode.XNamedControl, View.XNamedControl, false)]
[InlineData(InitializeComponentCode.XNamedControls, View.XNamedControls, false)]
[InlineData(InitializeComponentCode.NoNamedControls, View.NoNamedControls, false)]
[InlineData(InitializeComponentCode.CustomControls, View.CustomControls, false)]
[InlineData(InitializeComponentCode.DataTemplates, View.DataTemplates, false)]
[InlineData(InitializeComponentCode.SignUpView, View.SignUpView, false)]
[InlineData(InitializeComponentCode.AttachedProps, View.AttachedProps, false)]
[InlineData(InitializeComponentCode.FieldModifier, View.FieldModifier, false)]
[InlineData(DevToolsCode.NamedControl, View.NamedControl, true)]
[InlineData(DevToolsCode.NamedControls, View.NamedControls, true)]
[InlineData(DevToolsCode.XNamedControl, View.XNamedControl, true)]
[InlineData(DevToolsCode.XNamedControls, View.XNamedControls, true)]
[InlineData(DevToolsCode.NoNamedControls, View.NoNamedControls, true)]
[InlineData(DevToolsCode.CustomControls, View.CustomControls, true)]
[InlineData(DevToolsCode.DataTemplates, View.DataTemplates, true)]
[InlineData(DevToolsCode.SignUpView, View.SignUpView, true)]
[InlineData(DevToolsCode.AttachedProps, View.AttachedProps, true)]
[InlineData(DevToolsCode.FieldModifier, View.FieldModifier, true)]
public async Task Should_Generate_FindControl_Refs_From_Avalonia_Markup_File(
string expectation,
string markup,
bool devToolsMode)
{
var excluded = devToolsMode ? null : "Avalonia.Diagnostics";
var compilation =
View.CreateAvaloniaCompilation()
View.CreateAvaloniaCompilation(excluded)
.WithCustomTextBox();
var types = new RoslynTypeSystem(compilation);
var classResolver = new XamlXViewResolver(
new RoslynTypeSystem(compilation),
types,
MiniCompiler.CreateDefault(
new RoslynTypeSystem(compilation),
MiniCompiler.AvaloniaXmlnsDefinitionAttribute));
@ -39,12 +55,15 @@ namespace Avalonia.NameGenerator.Tests.InitializeComponent
var nameResolver = new XamlXNameResolver();
var names = nameResolver.ResolveNames(classInfo.Xaml);
var generator = new InitializeComponentCodeGenerator();
var generator = new InitializeComponentCodeGenerator(types);
var code = generator
.GenerateCode("SampleView", "Sample.App", names)
.Replace("\r", string.Empty);
var expected = await InitializeComponentCode.Load(expectation);
var expected = devToolsMode
? await DevToolsCode.Load(expectation)
: await InitializeComponentCode.Load(expectation);
CSharpSyntaxTree.ParseText(code);
Assert.Equal(expected.Replace("\r", string.Empty), code);
}

6
src/Avalonia.NameGenerator.Tests/Views/View.cs

@ -34,7 +34,7 @@ namespace Avalonia.NameGenerator.Tests.Views
return await reader.ReadToEndAsync();
}
public static CSharpCompilation CreateAvaloniaCompilation()
public static CSharpCompilation CreateAvaloniaCompilation(string excludedPattern = null)
{
var compilation = CSharpCompilation
.Create("AvaloniaLib", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
@ -48,7 +48,9 @@ namespace Avalonia.NameGenerator.Tests.Views
var avaloniaAssemblyDirectory = Path.GetDirectoryName(avaloniaAssemblyLocation);
var avaloniaAssemblyReferences = Directory
.EnumerateFiles(avaloniaAssemblyDirectory!)
.Where(file => file.EndsWith(".dll") && file.Contains("Avalonia"))
.Where(file => file.EndsWith(".dll") &&
file.Contains("Avalonia") &&
(string.IsNullOrWhiteSpace(excludedPattern) || !file.Contains(excludedPattern)))
.Select(file => MetadataReference.CreateFromFile(file))
.ToList();

37
src/Avalonia.NameGenerator/Compiler/RoslynTypeSystem.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@ -26,31 +27,19 @@ namespace Avalonia.NameGenerator.Compiler
public IReadOnlyList<IXamlAssembly> Assemblies => _assemblies;
public IXamlAssembly FindAssembly(string substring) => _assemblies[0];
public IXamlAssembly FindAssembly(string name) =>
Assemblies
.FirstOrDefault(a => string.Equals(a.Name, name, StringComparison.OrdinalIgnoreCase));
public IXamlType FindType(string name)
{
foreach (var assembly in _assemblies)
{
var type = assembly.FindType(name);
if (type != null)
return type;
}
return null;
}
public IXamlType FindType(string name) =>
_assemblies
.Select(assembly => assembly.FindType(name))
.FirstOrDefault(type => type != null);
public IXamlType FindType(string name, string assembly)
{
foreach (var assemblyInstance in _assemblies)
{
var type = assemblyInstance.FindType(name);
if (type != null)
return type;
}
return null;
}
public IXamlType FindType(string name, string assembly) =>
_assemblies
.Select(assemblyInstance => assemblyInstance.FindType(name))
.FirstOrDefault(type => type != null);
}
public class RoslynAssembly : IXamlAssembly

12
src/Avalonia.NameGenerator/Domain/INameGenerator.cs

@ -8,15 +8,5 @@ namespace Avalonia.NameGenerator.Domain
IReadOnlyList<GeneratedPartialClass> GenerateNameReferences(IEnumerable<AdditionalText> additionalFiles);
}
internal record GeneratedPartialClass
{
public string FileName { get; }
public string Content { get; }
public GeneratedPartialClass(string fileName, string content)
{
FileName = fileName;
Content = content;
}
}
internal record GeneratedPartialClass(string FileName, string Content);
}

14
src/Avalonia.NameGenerator/Domain/INameResolver.cs

@ -8,17 +8,5 @@ namespace Avalonia.NameGenerator.Domain
IReadOnlyList<ResolvedName> ResolveNames(XamlDocument xaml);
}
internal record ResolvedName
{
public string TypeName { get; }
public string Name { get; }
public string FieldModifier { get; }
public ResolvedName(string typeName, string name, string fieldModifier)
{
TypeName = typeName;
Name = name;
FieldModifier = fieldModifier;
}
}
internal record ResolvedName(string TypeName, string Name, string FieldModifier);
}

14
src/Avalonia.NameGenerator/Domain/IViewResolver.cs

@ -7,17 +7,5 @@ namespace Avalonia.NameGenerator.Domain
ResolvedView ResolveView(string xaml);
}
internal record ResolvedView
{
public XamlDocument Xaml { get; }
public string ClassName { get; }
public string Namespace { get; }
public ResolvedView(string className, string nameSpace, XamlDocument xaml)
{
ClassName = className;
Namespace = nameSpace;
Xaml = xaml;
}
}
internal record ResolvedView(string ClassName, string Namespace, XamlDocument Xaml);
}

5
src/Avalonia.NameGenerator/Domain/IsExternalInit.cs

@ -0,0 +1,5 @@
// ReSharper disable once CheckNamespace
namespace System.Runtime.CompilerServices
{
internal static class IsExternalInit { }
}

4
src/Avalonia.NameGenerator/AvaloniaNameSourceGenerator.cs → src/Avalonia.NameGenerator/Generator.cs

@ -32,14 +32,14 @@ namespace Avalonia.NameGenerator
private static INameGenerator CreateNameGenerator(GeneratorExecutionContext context)
{
var options = new GeneratorOptions(context);
var types = new RoslynTypeSystem((CSharpCompilation)context.Compilation);
var defaultFieldModifier = options.AvaloniaNameGeneratorDefaultFieldModifier.ToString().ToLowerInvariant();
ICodeGenerator generator = options.AvaloniaNameGeneratorBehavior switch {
Behavior.OnlyProperties => new OnlyPropertiesCodeGenerator(),
Behavior.InitializeComponent => new InitializeComponentCodeGenerator(),
Behavior.InitializeComponent => new InitializeComponentCodeGenerator(types),
_ => throw new ArgumentOutOfRangeException()
};
var types = new RoslynTypeSystem((CSharpCompilation)context.Compilation);
var compiler = MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute);
return new AvaloniaNameGenerator(
new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByPath),

27
src/Avalonia.NameGenerator/Generator/InitializeComponentCodeGenerator.cs

@ -1,21 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using Avalonia.NameGenerator.Domain;
using XamlX.TypeSystem;
namespace Avalonia.NameGenerator.Generator
{
internal class InitializeComponentCodeGenerator: ICodeGenerator
{
public string GenerateCode(string className, string nameSpace, IEnumerable<ResolvedName> names)
private readonly bool _attachDevTools;
private const string AttachDevToolsCodeBlock = @"
#if DEBUG
this.AttachDevTools();
#endif
";
public InitializeComponentCodeGenerator(IXamlTypeSystem types)
{
_attachDevTools = types.FindAssembly("Avalonia.Diagnostics") != null;
}
public string GenerateCode(string className, string nameSpace, IEnumerable<ResolvedName> names)
{
var properties = new List<string>();
var initializations = new List<string>();
foreach (var info in names)
foreach (var (typeName, name, fieldModifier) in names)
{
properties.Add($" {info.FieldModifier} global::{info.TypeName} {info.Name} {{ get; set; }}");
initializations.Add($" {info.Name} = this.FindControl<global::{info.TypeName}>(\"{info.Name}\");");
properties.Add($" {fieldModifier} global::{typeName} {name} {{ get; set; }}");
initializations.Add($" {name} = this.FindControl<global::{typeName}>(\"{name}\");");
}
var devToolsBlock = _attachDevTools ? AttachDevToolsCodeBlock : string.Empty;
return $@"// <auto-generated />
using Avalonia.Controls;
@ -33,7 +46,7 @@ namespace {nameSpace}
{{
AvaloniaXamlLoader.Load(this);
}}
{devToolsBlock}
{string.Join("\n", initializations)}
}}
}}

1
src/Directory.Build.props

@ -21,6 +21,7 @@
<PackageReference Include="Avalonia" Version="0.10.999-cibuild0012810-beta" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.999-cibuild0012810-beta" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.999-cibuild0012810-beta" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.999-cibuild0012810-beta" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)..\LICENSE" Pack="true" PackagePath="LICENSE" />

Loading…
Cancel
Save