Browse Source

Nullable annotations for projects using XamlX (#15796)

* Nullable annotations for projects using XamlX

* Update .NET SDK

* Update XamlX to latest master

* Use ILRepack tool instead of submodule

* Fix build

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
pull/16539/head
Julien Lebosquain 2 years ago
committed by GitHub
parent
commit
d1bd85e9b8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      .gitmodules
  2. 2
      global.json
  3. 6
      nukebuild/Build.cs
  4. 34
      nukebuild/BuildTasksPatcher.cs
  5. 4
      nukebuild/_build.csproj
  6. 1
      nukebuild/il-repack
  7. 162
      src/Avalonia.Base/Compatibility/NullableAttributes.cs
  8. 21
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  9. 2
      src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj
  10. 1
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  11. 58
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
  12. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs
  13. 8
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  14. 13
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompilerConfiguration.cs
  15. 50
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  16. 29
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
  17. 7
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/IXamlAstGroupTransformer.cs
  18. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs
  19. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlMergeResourceGroupTransformer.cs
  20. 10
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AddNameScopeRegistration.cs
  21. 5
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaBindingExtensionTransformer.cs
  22. 32
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs
  23. 12
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs
  24. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlClassesPropertyResolver.cs
  25. 24
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs
  26. 6
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs
  27. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlEnsureResourceDictionaryCapacityTransformer.cs
  28. 33
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs
  29. 35
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs
  30. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlReorderClassesPropertiesTransformer.cs
  31. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlRootObjectScopeTransformer.cs
  32. 72
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs
  33. 26
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  34. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlThemeVariantProviderTransformer.cs
  35. 14
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs
  36. 31
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  37. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Visitors/NameScopeRegistrationVisitor.cs
  38. 43
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  39. 99
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
  40. 23
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs
  41. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlPropertyInfoAccessorFactoryEmitter.cs
  42. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlTrampolineBuilder.cs
  43. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  44. 2
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  45. 3
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
  46. 6
      src/tools/Avalonia.Designer.HostApp/DesignXamlLoader.cs
  47. 12
      src/tools/Avalonia.Generators/Avalonia.Generators.csproj
  48. 2
      src/tools/Avalonia.Generators/Common/Domain/IViewResolver.cs
  49. 16
      src/tools/Avalonia.Generators/Common/XamlXViewResolver.cs
  50. 63
      src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs
  51. 2
      src/tools/Avalonia.Generators/GeneratorContextExtensions.cs
  52. 2
      src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameSourceGenerator.cs
  53. 3
      tests/Avalonia.Generators.Tests/InitializeComponent/InitializeComponentTests.cs
  54. 3
      tests/Avalonia.Generators.Tests/OnlyProperties/OnlyPropertiesTests.cs
  55. 1
      tests/Avalonia.Generators.Tests/XamlXClassResolverTests.cs
  56. 1
      tests/Avalonia.Generators.Tests/XamlXNameResolverTests.cs

3
.gitmodules

@ -4,6 +4,3 @@
[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"]
path = src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
url = https://github.com/kekekeks/XamlX.git
[submodule "nukebuild/il-repack"]
path = nukebuild/il-repack
url = https://github.com/Gillibald/il-repack

2
global.json

@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.101",
"version": "8.0.204",
"rollForward": "latestFeature"
},
"msbuild-sdks": {

6
nukebuild/Build.cs

@ -40,7 +40,8 @@ partial class Build : NukeBuild
[PackageExecutable("Microsoft.DotNet.GenAPI.Tool", "Microsoft.DotNet.GenAPI.Tool.dll", Framework = "net8.0")]
Tool ApiGenTool;
[PackageExecutable("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")]
Tool IlRepackTool;
protected override void OnBuildInitialized()
{
@ -307,7 +308,8 @@ partial class Build : NukeBuild
.Executes(() =>
{
BuildTasksPatcher.PatchBuildTasksInPackage(Parameters.NugetIntermediateRoot / "Avalonia.Build.Tasks." +
Parameters.Version + ".nupkg");
Parameters.Version + ".nupkg",
IlRepackTool);
var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
EnsureCleanDirectory(Parameters.NugetRoot);
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,

34
nukebuild/BuildTasksPatcher.cs

@ -2,9 +2,9 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using ILRepacking;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Nuke.Common.Tooling;
public class BuildTasksPatcher
{
@ -56,7 +56,7 @@ public class BuildTasksPatcher
return null;
}
public static void PatchBuildTasksInPackage(string packagePath)
public static void PatchBuildTasksInPackage(string packagePath, Tool ilRepackTool)
{
using (var archive = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.ReadWrite),
ZipArchiveMode.Update))
@ -70,7 +70,7 @@ public class BuildTasksPatcher
Directory.CreateDirectory(tempDir);
var temp = Path.Combine(tempDir, entry.Name);
var output = temp + ".output";
File.Copy(typeof(Microsoft.Build.Framework.ITask).Assembly.GetModules()[0].FullyQualifiedName,
File.Copy(GetAssemblyPath(typeof(Microsoft.Build.Framework.ITask)),
Path.Combine(tempDir, "Microsoft.Build.Framework.dll"));
var patched = new MemoryStream();
try
@ -78,22 +78,15 @@ public class BuildTasksPatcher
entry.ExtractToFile(temp, true);
// Get Original SourceLinkInfo Content
var sourceLinkInfoContent = GetSourceLinkInfo(temp);
var repack = new ILRepacking.ILRepack(new RepackOptions()
{
Internalize = true,
InputAssemblies = new[]
{
temp,
typeof(Mono.Cecil.AssemblyDefinition).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Rocks.MethodBodyRocks).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Pdb.PdbReaderProvider).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Mdb.MdbReaderProvider).Assembly.GetModules()[0].FullyQualifiedName,
},
SearchDirectories = Array.Empty<string>(),
DebugInfo = true, // Allowed read debug info
OutputFile = output
});
repack.Repack();
var cecilAsm = GetAssemblyPath(typeof(Mono.Cecil.AssemblyDefinition));
var cecilRocksAsm = GetAssemblyPath(typeof(Mono.Cecil.Rocks.MethodBodyRocks));
var cecilPdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Pdb.PdbReaderProvider));
var cecilMdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Mdb.MdbReaderProvider));
ilRepackTool.Invoke(
$"/internalize /out:\"{output}\" \"{temp}\" \"{cecilAsm}\" \"{cecilRocksAsm}\" \"{cecilPdbAsm}\" \"{cecilMdbAsm}\"",
tempDir);
// 'hurr-durr assembly with the same name is already loaded' prevention
using (var asm = AssemblyDefinition.ReadAssembly(output,
@ -161,4 +154,7 @@ public class BuildTasksPatcher
}
}
}
private static string GetAssemblyPath(Type typeInAssembly)
=> typeInAssembly.Assembly.GetModules()[0].FullyQualifiedName;
}

4
nukebuild/_build.csproj

@ -20,7 +20,6 @@
<PackageReference Include="MicroCom.CodeGenerator" Version="0.11.0" />
<!-- Keep in sync with Avalonia.Build.Tasks -->
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="Microsoft.Debugging.Tools.PdbStr" Version="20230731.1609.0" GeneratePathProperty="true" PrivateAssets="All"/>
<PackageReference Include="Microsoft.Build.Framework" Version="17.3.2" PrivateAssets="All" />
<PackageReference Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
@ -29,6 +28,7 @@
<PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[8.0.200]" />
<PackageDownload Include="Microsoft.DotNet.GenAPI.Tool" Version="[8.0.300-preview.24115.44]" />
<PackageDownload Include="dotnet-ilrepack" Version="[1.0.0]" />
</ItemGroup>
<ItemGroup>
@ -38,9 +38,7 @@
<!-- Common build related files -->
<Compile Remove="Numerge/**/*.*" />
<Compile Include="Numerge/Numerge/**/*.cs" Exclude="Numerge/Numerge/obj/**/*.cs" />
<EmbeddedResource Include="$(PkgMicrosoft_Debugging_Tools_PdbStr)/content/x86/pdbstr.exe" />
<EmbeddedResource Include="../build/avalonia.snk" />
<Compile Remove="il-repack\ILRepack\Application.cs" />
</ItemGroup>
<ItemGroup>

1
nukebuild/il-repack

@ -1 +0,0 @@
Subproject commit 892f079ea8cb0c178f0a68f53a7a7eac13acdda9

162
src/Avalonia.Base/Metadata/NullableAttributes.cs → src/Avalonia.Base/Compatibility/NullableAttributes.cs

@ -1,63 +1,30 @@
#pragma warning disable MA0048 // File name must match type name
#define INTERNAL_NULLABLE_ATTRIBUTES
// https://github.com/dotnet/corefx/blob/48363ac826ccf66fbe31a5dcb1dc2aab9a7dd768/src/Common/src/CoreLib/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
// https://raw.githubusercontent.com/dotnet/runtime/753648476b64946b8f5f4d25e1294adbabd3165b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace System.Diagnostics.CodeAnalysis
{
#if NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NET45 || NET451 || NET452 || NET6 || NET461 || NET462 || NET47 || NET471 || NET472 || NET48
#if !NET6_0_OR_GREATER
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class AllowNullAttribute : Attribute
{ }
internal sealed class AllowNullAttribute : Attribute { }
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DisallowNullAttribute : Attribute
{ }
internal sealed class DisallowNullAttribute : Attribute { }
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MaybeNullAttribute : Attribute
{ }
internal sealed class MaybeNullAttribute : Attribute { }
/// <summary>Specifies that an output will not be null even if the corresponding type allows it.</summary>
/// <summary>Specifies that an output will not be null even if the corresponding type allows it. Specifies that an input argument was not null when the call returns.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullAttribute : Attribute
{ }
internal sealed class NotNullAttribute : Attribute { }
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MaybeNullWhenAttribute : Attribute
internal sealed class MaybeNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
@ -71,12 +38,7 @@ namespace System.Diagnostics.CodeAnalysis
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullWhenAttribute : Attribute
internal sealed class NotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
@ -90,12 +52,7 @@ namespace System.Diagnostics.CodeAnalysis
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullIfNotNullAttribute : Attribute
internal sealed class NotNullIfNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with the associated parameter name.</summary>
/// <param name="parameterName">
@ -109,22 +66,11 @@ namespace System.Diagnostics.CodeAnalysis
/// <summary>Applied to a method that will never return under any circumstance.</summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DoesNotReturnAttribute : Attribute
{ }
internal sealed class DoesNotReturnAttribute : Attribute { }
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DoesNotReturnIfAttribute : Attribute
internal sealed class DoesNotReturnIfAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified parameter value.</summary>
/// <param name="parameterValue">
@ -136,82 +82,62 @@ namespace System.Diagnostics.CodeAnalysis
/// <summary>Gets the condition parameter value.</summary>
public bool ParameterValue { get; }
}
#endif // NETSTANDARD2_0 attributes
#if NETSTANDARD2_1 || NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2 || NETCOREAPP3_1 || NET45 || NET451 || NET452 || NET6 || NET461 || NET462 || NET47 || NET471 || NET472 || NET48
/// <summary>
/// Specifies that the method or property will ensure that the listed field and property members have
/// not-<see langword="null"/> values.
/// </summary>
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MemberNotNullAttribute : Attribute
internal sealed class MemberNotNullAttribute : Attribute
{
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
/// <summary>Initializes the attribute with a field or property member.</summary>
/// <param name="member">The field or property member that is promised to be not-null.</param>
public MemberNotNullAttribute(string member)
{
Members = new[] { member };
}
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullAttribute(string member) => Members = [member];
/// <summary>Initializes the attribute with the list of field and property members.</summary>
/// <param name="members">The list of field and property members that are promised to be not-null.</param>
public MemberNotNullAttribute(params string[] members)
{
Members = members;
}
}
/// <summary>
/// Specifies that the method or property will ensure that the listed field and property members have
/// non-<see langword="null"/> values when returning with the specified return value condition.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullAttribute(params string[] members) => Members = members;
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
internal sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value,
/// the associated parameter will not be <see langword="null"/>.
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
/// <param name="member">The field or property member that is promised to be not-<see langword="null"/>.</param>
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new[] { member };
Members = [member];
}
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.
/// </summary>
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value,
/// the associated parameter will not be <see langword="null"/>.
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
/// <param name="members">The list of field and property members that are promised to be not-null.</param>
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
#endif // NETSTANDARD2_1 attributes
#endif
}

21
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<BuildOutputTargetFolder>tools</BuildOutputTargetFolder>
<DefineConstants>$(DefineConstants);BUILDTASK;XAMLX_CECIL_INTERNAL;XAMLX_INTERNAL</DefineConstants>
@ -114,16 +115,18 @@
<Compile Include="../Avalonia.Base/RelativePoint.cs">
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />
<Compile Include="..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
<Compile Include="..\Avalonia.Base\Utilities\SpanHelpers.cs" Link="Utilities\SpanHelpers.cs" />
<Compile Include="..\Shared\StringCompatibilityExtensions.cs" Link="Compatibility\StringCompatibilityExtensions.cs" />
<Compile Include="..\Shared\IsExternalInit.cs" Link="Compatibility\IsExternalInit.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
<Compile Include="../Avalonia.Base/Compatibility/NullableAttributes.cs" Link="Compatibility/NullableAttributes.cs" />
<Compile Include="../Avalonia.Base/Compatibility/TrimmingAttributes.cs" Link="Compatibility/TrimmingAttributes.cs" />
<Compile Include="../Avalonia.Base/Utilities/SpanHelpers.cs" Link="Utilities/SpanHelpers.cs" />
<Compile Include="../Shared/StringCompatibilityExtensions.cs" Link="Compatibility/StringCompatibilityExtensions.cs" />
<Compile Include="../Shared/IsExternalInit.cs" Link="Compatibility/IsExternalInit.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/**/obj/**/*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/Compatibility/*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/IL/SreTypeSystem.cs" />
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup>
<Import Project="..\..\build\SourceGenerators.props" />
<Import Project="../../build/SourceGenerators.props" />
<Import Project="../../build/NullableEnable.props" />
</Project>

2
src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj

@ -4,7 +4,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />
<Compile Include="..\Avalonia.Base\Compatibility\NullableAttributes.cs" Link="NullableAttributes.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />

1
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@ -14,4 +14,5 @@
<Import Project="..\..\..\build\DevAnalyzers.props" />
<Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="..\..\..\build\SourceGenerators.props" />
<Import Project="..\..\..\build\NullableEnable.props" />
</Project>

58
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

@ -33,14 +33,14 @@ namespace Avalonia.Markup.Xaml.XamlIl
internal static class AvaloniaXamlIlRuntimeCompiler
{
#if !RUNTIME_XAML_CECIL
private static SreTypeSystem _sreTypeSystem;
private static Type _ignoresAccessChecksFromAttribute;
private static ModuleBuilder _sreBuilder;
private static IXamlType _sreContextType;
private static XamlLanguageTypeMappings _sreMappings;
private static XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> _sreEmitMappings;
private static XamlXmlnsMappings _sreXmlns;
private static AssemblyBuilder _sreAsm;
private static SreTypeSystem? _sreTypeSystem;
private static Type? _ignoresAccessChecksFromAttribute;
private static ModuleBuilder? _sreBuilder;
private static IXamlType? _sreContextType;
private static XamlLanguageTypeMappings? _sreMappings;
private static XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult>? _sreEmitMappings;
private static XamlXmlnsMappings? _sreXmlns;
private static AssemblyBuilder? _sreAsm;
private static bool _sreCanSave;
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
@ -48,7 +48,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
if (_sreBuilder == null)
return;
var saveMethod = _sreAsm.GetType().GetMethods()
var saveMethod = _sreAsm!.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "Save" && m.GetParameters().Length == 1);
if (saveMethod == null)
return;
@ -65,6 +65,13 @@ namespace Avalonia.Markup.Xaml.XamlIl
[CompilerDynamicDependencies]
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
[MemberNotNull(nameof(_sreTypeSystem))]
[MemberNotNull(nameof(_sreBuilder))]
[MemberNotNull(nameof(_sreMappings))]
[MemberNotNull(nameof(_sreEmitMappings))]
[MemberNotNull(nameof(_sreXmlns))]
[MemberNotNull(nameof(_sreContextType))]
[MemberNotNull(nameof(_ignoresAccessChecksFromAttribute))]
static void InitializeSre()
{
if (_sreTypeSystem == null)
@ -81,8 +88,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
name, (AssemblyBuilderAccess)3,
Path.GetDirectoryName(typeof(AvaloniaXamlIlRuntimeCompiler).Assembly.GetModules()[0]
.FullyQualifiedName)
});
.FullyQualifiedName)!
})!;
else
_sreCanSave = false;
}
@ -94,7 +101,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
_sreBuilder = _sreAsm.DefineDynamicModule("XamlIlLoader.ildump");
}
if (_sreMappings == null)
if (_sreMappings is null || _sreEmitMappings is null)
(_sreMappings, _sreEmitMappings) = AvaloniaXamlIlLanguage.Configure(_sreTypeSystem);
if (_sreXmlns == null)
_sreXmlns = XamlXmlnsMappings.Resolve(_sreTypeSystem, _sreMappings);
@ -108,7 +115,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
static MethodInfo GetDefineDynamicAssembly() => AppDomain.CurrentDomain.GetType().GetMethods()
static MethodInfo? GetDefineDynamicAssembly() => AppDomain.CurrentDomain.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "DefineDynamicAssembly"
&& m.GetParameters().Length == 3 &&
m.GetParameters()[2].ParameterType == typeof(string));
@ -142,12 +149,12 @@ namespace Avalonia.Markup.Xaml.XamlIl
ctorIl.Emit(OpCodes.Ret);
tb.SetCustomAttribute(new CustomAttributeBuilder(
typeof(AttributeUsageAttribute).GetConstructor(new[] { typeof(AttributeTargets) }),
typeof(AttributeUsageAttribute).GetConstructor(new[] { typeof(AttributeTargets) })!,
new object[] { AttributeTargets.Assembly },
new[] { typeof(AttributeUsageAttribute).GetProperty("AllowMultiple") },
new[] { typeof(AttributeUsageAttribute).GetProperty(nameof(AttributeUsageAttribute.AllowMultiple))! },
new object[] { true }));
return tb.CreateTypeInfo();
return tb.CreateTypeInfo()!;
}
[UnconditionalSuppressMessage("Trimming", "IL2080", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
@ -159,8 +166,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
var key = assemblyName.GetPublicKey();
if (key != null && key.Length != 0)
name += ", PublicKey=" + BitConverter.ToString(key).Replace("-", "").ToUpperInvariant();
_sreAsm.SetCustomAttribute(new CustomAttributeBuilder(
_ignoresAccessChecksFromAttribute.GetConstructors()[0],
_sreAsm!.SetCustomAttribute(new CustomAttributeBuilder(
_ignoresAccessChecksFromAttribute!.GetConstructors()[0],
new object[] { name }));
}
@ -267,7 +274,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
using (var sr = new StreamReader(document.XamlStream))
xaml = sr.ReadToEnd();
IXamlType overrideType = null;
IXamlType? overrideType = null;
if (document.RootInstance != null)
{
overrideType = _sreTypeSystem.GetType(document.RootInstance.GetType());
@ -326,13 +333,16 @@ namespace Avalonia.Markup.Xaml.XamlIl
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
static object LoadOrPopulate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type created, object rootInstance, IServiceProvider parentServiceProvider)
static object LoadOrPopulate(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type created,
object? rootInstance,
IServiceProvider? parentServiceProvider)
{
var isp = Expression.Parameter(typeof(IServiceProvider));
var epar = Expression.Parameter(typeof(object));
var populate = created.GetMethod(AvaloniaXamlIlCompiler.PopulateName);
var populate = created.GetMethod(AvaloniaXamlIlCompiler.PopulateName)!;
isp = Expression.Parameter(typeof(IServiceProvider));
var populateCb = Expression.Lambda<Action<IServiceProvider, object>>(
Expression.Call(populate, isp, Expression.Convert(epar, populate.GetParameters()[1].ParameterType)),
@ -353,7 +363,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
target => { populateCb(serviceProvider, target); }));
try
{
return Activator.CreateInstance(targetType);
return Activator.CreateInstance(targetType)!;
}
finally
{
@ -363,7 +373,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
var createCb = Expression.Lambda<Func<IServiceProvider, object>>(
Expression.Convert(Expression.Call(
created.GetMethod(AvaloniaXamlIlCompiler.BuildName), isp), typeof(object)), isp).Compile();
created.GetMethod(AvaloniaXamlIlCompiler.BuildName)!, isp), typeof(object)), isp).Compile();
return createCb(serviceProvider);
}
else
@ -394,7 +404,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
#endif
}
private static string GetSafeUriIdentifier(Uri uri)
private static string? GetSafeUriIdentifier(Uri? uri)
{
return uri?.ToString()
.Replace(":", "_")

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs

@ -28,8 +28,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
{
codeGen
.Ldloc(context.ContextLocal)
.Castclass(context.Configuration.TypeMappings.UriContextProvider)
.EmitCall(context.Configuration.TypeMappings.UriContextProvider.FindMethod(
.Castclass(context.Configuration.TypeMappings.UriContextProvider!)
.EmitCall(context.Configuration.TypeMappings.UriContextProvider!.GetMethod(
"get_BaseUri", _types.Uri, false))
.Ldstr(_text)
.Newobj(_types.FontFamilyConstructorUriName);

8
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -17,7 +17,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
class AvaloniaXamlIlCompiler : XamlILCompiler
{
private readonly IXamlType _contextType;
private readonly IXamlType _contextType = null!;
private readonly AvaloniaXamlIlDesignPropertiesTransformer _designTransformer;
private readonly AvaloniaBindingExtensionTransformer _bindingTransformer;
@ -156,7 +156,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
#if !XAMLX_CECIL_INTERNAL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
#endif
public XamlDocument Parse(string xaml, IXamlType overrideRootType)
public XamlDocument Parse(string xaml, IXamlType? overrideRootType)
{
var parsed = XDocumentXamlParser.Parse(xaml, new Dictionary<string, string>
{
@ -192,7 +192,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return parsed;
}
public void Compile(XamlDocument document, XamlDocumentTypeBuilderProvider typeBuilderProvider, string baseUri, IFileSource fileSource)
public void Compile(XamlDocument document, XamlDocumentTypeBuilderProvider typeBuilderProvider, string? baseUri, IFileSource? fileSource)
{
Compile(
document,
@ -211,7 +211,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
#if !XAMLX_CECIL_INTERNAL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
#endif
public void ParseAndCompile(string xaml, string baseUri, IFileSource fileSource, IXamlTypeBuilder<IXamlILEmitter> tb, IXamlType overrideRootType)
public void ParseAndCompile(string xaml, string? baseUri, IFileSource fileSource, IXamlTypeBuilder<IXamlILEmitter> tb, IXamlType overrideRootType)
{
var parsed = Parse(xaml, overrideRootType);

13
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompilerConfiguration.cs

@ -9,16 +9,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public XamlIlPropertyInfoAccessorFactoryEmitter AccessorFactoryEmitter { get; }
public XamlIlTrampolineBuilder TrampolineBuilder { get; }
public AvaloniaXamlIlCompilerConfiguration(IXamlTypeSystem typeSystem,
IXamlAssembly defaultAssembly,
public AvaloniaXamlIlCompilerConfiguration(
IXamlTypeSystem typeSystem,
IXamlAssembly? defaultAssembly,
XamlLanguageTypeMappings typeMappings,
XamlXmlnsMappings xmlnsMappings,
XamlValueConverter customValueConverter,
XamlXmlnsMappings? xmlnsMappings,
XamlValueConverter? customValueConverter,
XamlIlClrPropertyInfoEmitter clrPropertyEmitter,
XamlIlPropertyInfoAccessorFactoryEmitter accessorFactoryEmitter,
XamlIlTrampolineBuilder trampolineBuilder,
IXamlIdentifierGenerator identifierGenerator,
XamlDiagnosticsHandler diagnosticsHandler)
IXamlIdentifierGenerator? identifierGenerator,
XamlDiagnosticsHandler? diagnosticsHandler)
: base(typeSystem, defaultAssembly, typeMappings, xmlnsMappings, customValueConverter, identifierGenerator, diagnosticsHandler)
{
ClrPropertyEmitter = clrPropertyEmitter;

50
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlX.Ast;
@ -21,8 +22,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult> emit) Configure(IXamlTypeSystem typeSystem)
{
var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
var assignBindingAttribute = typeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
var bindingType = typeSystem.GetType("Avalonia.Data.IBinding");
var rv = new XamlLanguageTypeMappings(typeSystem)
{
SupportInitialize = typeSystem.GetType("System.ComponentModel.ISupportInitialize"),
@ -89,7 +88,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
IXamlTypeSystem typeSystem,
IXamlILContextDefinition<IXamlILEmitter> definition)
{
var nameScopeType = typeSystem.FindType("Avalonia.Controls.INameScope");
var nameScopeType = typeSystem.GetType("Avalonia.Controls.INameScope");
var field = definition.TypeBuilder.DefineField(nameScopeType,
ContextNameScopeFieldName, XamlVisibility.Public, false);
definition.ConstructorBuilder.Generator
@ -97,7 +96,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.Ldarg(1)
.Ldtype(nameScopeType)
.EmitCall(mappings.ServiceProvider.GetMethod(new FindMethodMethodSignature("GetService",
typeSystem.FindType("System.Object"), typeSystem.FindType("System.Type"))))
typeSystem.GetType("System.Object"), typeSystem.GetType("System.Type"))))
.Stfld(field);
}
@ -107,26 +106,26 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
IXamlILContextDefinition<IXamlILEmitter> definition,
IXamlType runtimeHelpers)
{
var interfaceType = typeSystem.FindType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlEagerParentStackProvider");
var interfaceType = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlEagerParentStackProvider");
definition.TypeBuilder.AddInterfaceImplementation(interfaceType);
// IReadOnlyList<object> DirectParentsStack => (IReadOnlyList<object>)ParentsStack;
var directParentsGetter = ImplementInterfacePropertyGetter("DirectParentsStack");
directParentsGetter.Generator
.LdThisFld(definition.ParentListField)
.LdThisFld(definition.ParentListField!)
.Castclass(directParentsGetter.ReturnType)
.Ret();
var serviceProviderGetServiceMethod = mappings.ServiceProvider.GetMethod(new FindMethodMethodSignature(
"GetService",
typeSystem.FindType("System.Object"),
typeSystem.FindType("System.Type")));
typeSystem.GetType("System.Object"),
typeSystem.GetType("System.Type")));
var asEagerParentStackProviderMethod = runtimeHelpers.GetMethod(new FindMethodMethodSignature(
"AsEagerParentStackProvider",
interfaceType,
mappings.ParentStackProvider)
mappings.ParentStackProvider!)
{
IsStatic = true
});
@ -136,14 +135,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
var parentProviderGetter = ImplementInterfacePropertyGetter("ParentProvider");
parentProviderGetter.Generator
.LdThisFld(definition.ParentServiceProviderField)
.Ldtype(mappings.ParentStackProvider)
.Ldtype(mappings.ParentStackProvider!)
.EmitCall(serviceProviderGetServiceMethod)
.EmitCall(asEagerParentStackProviderMethod)
.Ret();
IXamlMethodBuilder<IXamlILEmitter> ImplementInterfacePropertyGetter(string propertyName)
{
var interfaceGetter = interfaceType.FindMethod(m => m.Name == "get_" + propertyName);
var interfaceGetter = interfaceType.GetMethod(m => m.Name == "get_" + propertyName);
var getter = definition.TypeBuilder.DefineMethod(
interfaceGetter.ReturnType,
@ -193,7 +192,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_avaloniaListConverter = typeSystem.GetType("Avalonia.Collections.AvaloniaListConverter`1");
}
IXamlType LookupConverter(IXamlType type)
IXamlType? LookupConverter(IXamlType type)
{
foreach(var p in _converters)
if (p.Key.Equals(type))
@ -205,41 +204,44 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class ConstructedAttribute : IXamlCustomAttribute
{
public bool Equals(IXamlCustomAttribute other) => false;
public bool Equals(IXamlCustomAttribute? other) => false;
public IXamlType Type { get; }
public List<object> Parameters { get; }
public Dictionary<string, object> Properties { get; }
public List<object?> Parameters { get; }
public Dictionary<string, object?> Properties { get; }
public ConstructedAttribute(IXamlType type, List<object> parameters, Dictionary<string, object> properties)
public ConstructedAttribute(IXamlType type, List<object?>? parameters, Dictionary<string, object?>? properties)
{
Type = type;
Parameters = parameters ?? new List<object>();
Properties = properties ?? new Dictionary<string, object>();
Parameters = parameters ?? new List<object?>();
Properties = properties ?? new Dictionary<string, object?>();
}
}
public IXamlCustomAttribute GetCustomAttribute(IXamlType type, IXamlType attributeType)
public IXamlCustomAttribute? GetCustomAttribute(IXamlType type, IXamlType attributeType)
{
if (attributeType.Equals(_typeConverterAttribute))
{
var conv = LookupConverter(type);
if (conv != null)
return new ConstructedAttribute(_typeConverterAttribute, new List<object>() {conv}, null);
return new ConstructedAttribute(_typeConverterAttribute, [conv], null);
}
return null;
}
public IXamlCustomAttribute GetCustomAttribute(IXamlProperty property, IXamlType attributeType)
public IXamlCustomAttribute? GetCustomAttribute(IXamlProperty property, IXamlType attributeType)
{
return null;
}
}
public static bool CustomValueConverter(AstTransformationContext context,
IXamlAstValueNode node, IReadOnlyList<IXamlCustomAttribute> customAttributes, IXamlType type,
out IXamlAstValueNode result)
public static bool CustomValueConverter(
AstTransformationContext context,
IXamlAstValueNode node,
IReadOnlyList<IXamlCustomAttribute>? customAttributes,
IXamlType type,
[NotNullWhen(true)] out IXamlAstValueNode? result)
{
if (node is AvaloniaXamlIlOptionMarkupExtensionTransformer.OptionsMarkupExtensionNode optionsNode)
{

29
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Avalonia.Controls;
@ -15,9 +16,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
class AvaloniaXamlIlLanguageParseIntrinsics
{
public static bool TryConvert(AstTransformationContext context, IXamlAstValueNode node, string text, IXamlType type, AvaloniaXamlIlWellKnownTypes types, out IXamlAstValueNode result)
public static bool TryConvert(
AstTransformationContext context,
IXamlAstValueNode node,
string text,
IXamlType type,
AvaloniaXamlIlWellKnownTypes types,
[NotNullWhen(true)] out IXamlAstValueNode? result)
{
bool ReturnOnParseError(string title, out IXamlAstValueNode result)
bool ReturnOnParseError(string title, out IXamlAstValueNode? result)
{
context.ReportDiagnostic(new XamlDiagnostic(
AvaloniaXamlDiagnosticCodes.AvaloniaIntrinsicsError,
@ -50,7 +57,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
result = new XamlStaticOrTargetedReturnMethodCallNode(node,
type.FindMethod("FromTicks", type, false, types.Long),
type.GetMethod("FromTicks", type, false, types.Long),
new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
return true;
}
@ -272,7 +279,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if (property.PropertyType == types.TextTrimming && property.Name.Equals(text, StringComparison.OrdinalIgnoreCase))
{
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter, Enumerable.Empty<IXamlAstValueNode>());
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter!, Enumerable.Empty<IXamlAstValueNode>());
return true;
}
@ -285,7 +292,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if (property.PropertyType == types.TextDecorationCollection && property.Name.Equals(text, StringComparison.OrdinalIgnoreCase))
{
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter, Enumerable.Empty<IXamlAstValueNode>());
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter!, Enumerable.Empty<IXamlAstValueNode>());
return true;
}
@ -298,7 +305,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if (property.PropertyType == types.WindowTransparencyLevel && property.Name.Equals(text, StringComparison.OrdinalIgnoreCase))
{
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter, Enumerable.Empty<IXamlAstValueNode>());
result = new XamlStaticOrTargetedReturnMethodCallNode(node, property.Getter!, Enumerable.Empty<IXamlAstValueNode>());
return true;
}
@ -309,7 +316,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
var uriText = text.Trim();
var kind = ((!uriText?.StartsWith("/") == true) ? UriKind.RelativeOrAbsolute : UriKind.Relative);
var kind = !uriText.StartsWith("/") ? UriKind.RelativeOrAbsolute : UriKind.Relative;
if (string.IsNullOrWhiteSpace(uriText) || !Uri.TryCreate(uriText, kind, out var _))
{
@ -373,12 +380,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if (attribute.Properties.TryGetValue("Separators", out var separatorsArray))
{
separators = ((Array)separatorsArray)?.OfType<string>().ToArray();
separators = ((Array?)separatorsArray)?.OfType<string>().ToArray();
}
if (attribute.Properties.TryGetValue("SplitOptions", out var splitOptionsObj))
{
splitOptions = (StringSplitOptions)splitOptionsObj;
splitOptions = (StringSplitOptions)splitOptionsObj!;
}
}
@ -403,7 +410,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return false;
}
nodes[index] = itemNode;
nodes[index] = itemNode!;
}
foreach (var element in nodes)
@ -440,7 +447,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return false;
}
private static IXamlType GetElementType(IXamlType type, XamlTypeWellKnownTypes types)
private static IXamlType? GetElementType(IXamlType type, XamlTypeWellKnownTypes types)
{
if (type.IsArray)
{

7
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/IXamlAstGroupTransformer.cs

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Xml;
using XamlX;
using System.Collections.Generic;
using XamlX.Ast;
using XamlX.Transform;
@ -18,7 +15,7 @@ internal class AstGroupTransformationContext : AstTransformationContext
}
public override string Document => CurrentDocument?.FileSource?.FilePath ?? "{unknown document}";
public IXamlDocumentResource CurrentDocument { get; set; }
public IXamlDocumentResource? CurrentDocument { get; set; }
public IReadOnlyCollection<IXamlDocumentResource> Documents { get; }

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs

@ -192,7 +192,7 @@ internal class AvaloniaXamlIncludeTransformer : IXamlAstGroupTransformer
var uriPath = new Uri(originalAssetPath, (UriKind)uriKind);
if (!uriPath.IsAbsoluteUri)
{
var baseUrl = context.CurrentDocument.Uri ?? throw new InvalidOperationException("CurrentDocument URI is null.");
var baseUrl = context.CurrentDocument?.Uri ?? throw new InvalidOperationException("CurrentDocument URI is null.");
uriPath = new Uri(new Uri(baseUrl, UriKind.Absolute), uriPath);
}
else if (!uriPath.Scheme.Equals("avares", StringComparison.CurrentCultureIgnoreCase))
@ -218,7 +218,7 @@ internal class AvaloniaXamlIncludeTransformer : IXamlAstGroupTransformer
{
codeGen.Ldloc(context.ContextLocal);
var method = context.GetAvaloniaTypes().RuntimeHelpers
.FindMethod(m => m.Name == "CreateRootServiceProviderV3");
.GetMethod(m => m.Name == "CreateRootServiceProviderV3");
codeGen.EmitCall(method);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlMergeResourceGroupTransformer.cs

@ -7,7 +7,6 @@ using XamlX.Ast;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.GroupTransformers;
#nullable enable
internal class XamlMergeResourceGroupTransformer : IXamlAstGroupTransformer
{
@ -94,7 +93,7 @@ internal class XamlMergeResourceGroupTransformer : IXamlAstGroupTransformer
$"Node MergeResourceInclude is unable to resolve \"{originalAssetPath}\" path.", propertyNode, node);
}
var singleRootObject = ((XamlManipulationGroupNode)targetDocumentRoot.Manipulation)
var singleRootObject = ((XamlManipulationGroupNode)targetDocumentRoot.Manipulation!)
.Children.OfType<XamlObjectInitializationNode>().Single();
if (singleRootObject.Type != resourceDictionaryType)
{

10
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AddNameScopeRegistration.cs

@ -22,7 +22,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& mg.Children.OfType<AvaloniaNameScopeRegistrationXamlIlNode>().Any())
return node;
IXamlAstValueNode value = null;
IXamlAstValueNode? value = null;
for (var c = 0; c < pa.Values.Count; c++)
if (pa.Values[c].Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
{
@ -73,9 +73,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class AvaloniaNameScopeRegistrationXamlIlNode : XamlAstNode, IXamlAstManipulationNode
{
public IXamlAstValueNode Name { get; set; }
public IXamlType TargetType { get; }
public IXamlType? TargetType { get; }
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlAstValueNode name, IXamlType targetType) : base(name)
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlAstValueNode name, IXamlType? targetType) : base(name)
{
TargetType = targetType;
Name = name;
@ -87,7 +87,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class AvaloniaNameScopeRegistrationXamlIlNodeEmitter : IXamlAstLocalsNodeEmitter<IXamlILEmitter, XamlILNodeEmitResult>
{
public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
public XamlILNodeEmitResult? Emit(IXamlAstNode node, XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (node is AvaloniaNameScopeRegistrationXamlIlNode registration)
{
@ -114,7 +114,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return XamlILNodeEmitResult.Void(1);
}
return default;
return null;
}
}
}

5
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaBindingExtensionTransformer.cs

@ -4,14 +4,11 @@ using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlParseException = XamlX.XamlParseException;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class XamlBindingsTransformException : XamlTransformException
{
public XamlBindingsTransformException(string message, IXamlLineInfo lineInfo, Exception innerException = null)
public XamlBindingsTransformException(string message, IXamlLineInfo lineInfo, Exception? innerException = null)
: base(message, lineInfo, innerException)
{
}

32
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathParser.cs

@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Avalonia.Markup.Parsers;
using Avalonia.Utilities;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
using XamlParseException = XamlX.XamlParseException;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
@ -81,11 +79,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
private static BindingExpressionGrammar.INode ConvertLongFormPropertiesToBindingExpressionNode(
private static BindingExpressionGrammar.INode? ConvertLongFormPropertiesToBindingExpressionNode(
AstTransformationContext context,
XamlAstObjectNode binding)
{
BindingExpressionGrammar.INode convertedNode = null;
BindingExpressionGrammar.INode? convertedNode = null;
var syntheticCompiledBindingProperties = binding.Children.OfType<XamlAstXamlPropertyValueNode>()
.Where(v => v.Property is AvaloniaSyntheticCompiledBindingProperty)
@ -195,17 +193,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (treeType == "Visual")
{
convertedNode = new VisualAncestorBindingExpressionNode
convertedNode = new VisualAncestorBindingExpressionNode(ancestorType!)
{
Type = ancestorType,
Level = ancestorLevel
};
}
else if (treeType == "Logical")
{
convertedNode = new LogicalAncestorBindingExpressionNode
convertedNode = new LogicalAncestorBindingExpressionNode(ancestorType!)
{
Type = ancestorType,
Level = ancestorLevel
};
}
@ -238,7 +234,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
throw new XamlBindingsTransformException("TargetType has to be set on ControlTemplate or it should be defined inside of a Style.", binding);
}
convertedNode = new TemplatedParentBindingExpressionNode { Type = parentType };
convertedNode = new TemplatedParentBindingExpressionNode(parentType);
}
else
{
@ -260,8 +256,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
private static bool GetRelativeSourceObjectFromAssignment(
AstTransformationContext context,
XamlAstXamlPropertyValueNode relativeSourceProperty,
out XamlAstObjectNode relativeSourceObject)
XamlAstXamlPropertyValueNode? relativeSourceProperty,
[NotNullWhen(true)] out XamlAstObjectNode? relativeSourceObject)
{
relativeSourceObject = null;
if (relativeSourceProperty is null)
@ -320,20 +316,20 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
class VisualAncestorBindingExpressionNode : BindingExpressionGrammar.INode
class VisualAncestorBindingExpressionNode(IXamlType type) : BindingExpressionGrammar.INode
{
public IXamlType Type { get; set; }
public IXamlType Type { get; set; } = type;
public int Level { get; set; }
}
class LogicalAncestorBindingExpressionNode : BindingExpressionGrammar.INode
class LogicalAncestorBindingExpressionNode(IXamlType type) : BindingExpressionGrammar.INode
{
public IXamlType Type { get; set; }
public IXamlType Type { get; set; } = type;
public int Level { get; set; }
}
class TemplatedParentBindingExpressionNode : BindingExpressionGrammar.INode
class TemplatedParentBindingExpressionNode(IXamlType type) : BindingExpressionGrammar.INode
{
public IXamlType Type { get; set; }
public IXamlType Type { get; set; } = type;
}
}

12
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlBindingPathTransformer.cs

@ -14,7 +14,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
if (node is XamlAstConstructableObjectNode binding && binding.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension))
{
IXamlType startType = null;
IXamlType? startType = null;
var sourceProperty = binding.Children.OfType<XamlPropertyAssignmentNode>().FirstOrDefault(c => c.Property.Name == "Source");
var dataTypeProperty = binding.Children.OfType<XamlPropertyAssignmentNode>().FirstOrDefault(c => c.Property.Name == "DataType");
if (sourceProperty?.Values.Count is 1)
@ -23,11 +23,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
switch (sourceValue)
{
case XamlAstTextNode textNode:
startType = textNode.Type?.GetClrType();
startType = textNode.Type.GetClrType();
break;
case XamlMarkupExtensionNode extension:
startType = extension.Type?.GetClrType();
startType = extension.Type.GetClrType();
//let's try to infer StaticResource type from parent resources in xaml
if (extension.Value.Type.GetClrType().FullName == "Avalonia.Markup.Xaml.MarkupExtensions.StaticResourceExtension" &&
@ -47,7 +47,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
string getResourceValue_xKey(XamlPropertyAssignmentNode node)
=> node.Values.Count == 2 && node.Values[0] is XamlAstTextNode t ? t.Text : "";
IXamlType getResourceValue_Type(XamlPropertyAssignmentNode node, IXamlType xamlType)
IXamlType? getResourceValue_Type(XamlPropertyAssignmentNode node, IXamlType? xamlType)
=> node.Values.Count == 2 ? node.Values[1].Type.GetClrType() : xamlType;
IEnumerable<XamlPropertyAssignmentNode> getResourceValues(IXamlAstNode node)
@ -85,7 +85,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.Where(o => styledElement.IsAssignableFrom(o.Type.GetClrType()))
.Select(o => o.Children.FirstOrDefault(p => matchProperty(p, styledElement, "Resources")))
.Where(r => r != null)
.SelectMany(r => getResourceValues(r))
.SelectMany(r => getResourceValues(r!))
.FirstOrDefault(r => getResourceValue_xKey(r) == key);
if (resource != null)
@ -96,7 +96,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
break;
case XamlStaticExtensionNode staticExtension:
startType = staticExtension.Type?.GetClrType();
startType = staticExtension.Type.GetClrType();
break;
}
}

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlClassesPropertyResolver.cs

@ -49,7 +49,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
emitter
.Stloc(value.Local)
.EmitCall(_types.StyledElementClassesProperty.Getter)
.EmitCall(_types.StyledElementClassesProperty.Getter!)
.Ldstr(_className)
.Ldloc(value.Local)
.EmitCall(_types.Classes.GetMethod(new FindMethodMethodSignature("Set",

24
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDataContextTypeTransformer.cs

@ -12,7 +12,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class XamlDataContextException : XamlTransformException
{
public XamlDataContextException(string message, IXamlLineInfo lineInfo, Exception innerException = null)
public XamlDataContextException(string message, IXamlLineInfo lineInfo, Exception? innerException = null)
: base(message, lineInfo, innerException)
{
}
@ -30,8 +30,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (node is XamlAstConstructableObjectNode on)
{
AvaloniaXamlIlDataContextTypeMetadataNode inferredDataContextTypeNode = null;
AvaloniaXamlIlDataContextTypeMetadataNode directiveDataContextTypeNode = null;
AvaloniaXamlIlDataContextTypeMetadataNode? inferredDataContextTypeNode = null;
AvaloniaXamlIlDataContextTypeMetadataNode? directiveDataContextTypeNode = null;
for (int i = 0; i < on.Children.Count; ++i)
{
@ -81,13 +81,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
// Infer data type from collection binding on a control that displays items.
var property = context.ParentNodes().OfType<XamlPropertyAssignmentNode>().FirstOrDefault();
var attributeType = context.GetAvaloniaTypes().InheritDataTypeFromItemsAttribute;
var attribute = property?.Property?.GetClrProperty().CustomAttributes
var attribute = property?.Property.GetClrProperty().CustomAttributes
.FirstOrDefault(a => a.Type == attributeType);
if (attribute is not null)
{
var propertyName = (string)attribute.Parameters.First();
XamlAstConstructableObjectNode parentObject;
var propertyName = (string?)attribute.Parameters.First();
XamlAstConstructableObjectNode? parentObject;
if (attribute.Properties.TryGetValue("AncestorType", out var type)
&& type is IXamlType xamlType)
{
@ -99,7 +99,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
parentObject = context.ParentNodes().OfType<XamlAstConstructableObjectNode>().FirstOrDefault();
}
if (parentObject != null)
if (parentObject != null && !string.IsNullOrEmpty(propertyName))
{
inferredDataContextTypeNode = InferDataContextOfPresentedItem(context, on, parentObject, propertyName);
}
@ -122,7 +122,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return node;
}
private static AvaloniaXamlIlDataContextTypeMetadataNode InferDataContextOfPresentedItem(
private static AvaloniaXamlIlDataContextTypeMetadataNode? InferDataContextOfPresentedItem(
AstTransformationContext context, XamlAstConstructableObjectNode on,
XamlAstConstructableObjectNode parentObject, string propertyName)
{
@ -135,7 +135,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return null;
}
IXamlType itemsCollectionType = null;
IXamlType? itemsCollectionType = null;
if (context.GetAvaloniaTypes().IBinding.IsAssignableFrom(parentItemsValue.Type.GetClrType()))
{
if (parentItemsValue.Type.GetClrType().Equals(context.GetAvaloniaTypes().CompiledBindingExtension)
@ -217,7 +217,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
[DebuggerDisplay("DataType = {DataContextType}")]
class AvaloniaXamlIlDataContextTypeMetadataNode : XamlValueWithSideEffectNodeBase
{
public virtual IXamlType DataContextType { get; }
public IXamlType DataContextType { get; }
public AvaloniaXamlIlDataContextTypeMetadataNode(IXamlAstValueNode value, IXamlType targetType)
: base(value, value)
@ -230,10 +230,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
class AvaloniaXamlIlUninferrableDataContextMetadataNode : AvaloniaXamlIlDataContextTypeMetadataNode
{
public AvaloniaXamlIlUninferrableDataContextMetadataNode(IXamlAstValueNode value)
: base(value, null)
: base(value, XamlPseudoType.Unknown)
{
}
public override IXamlType DataContextType => XamlPseudoType.Unknown;
}
}

6
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs

@ -28,7 +28,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
new XamlDirectCallPropertySetter(types.ResourceDictionaryDeferredAdd),
};
}
else if (pa.Property.Name == "Resources" && pa.Property.Getter.ReturnType.Equals(types.IResourceDictionary)
else if (pa.Property.Name == "Resources" && pa.Property.Getter?.ReturnType.Equals(types.IResourceDictionary) == true
&& ShouldBeDeferred(pa.Values[1]))
{
pa.Values[1] = new XamlDeferredContentNode(pa.Values[1], types.XamlIlTypes.Object, context.Configuration);
@ -132,7 +132,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
emitter.EmitCall(_adder, true);
}
public bool Equals(AdderSetter other)
public bool Equals(AdderSetter? other)
{
if (ReferenceEquals(null, other))
return false;
@ -142,7 +142,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return _getter.Equals(other._getter) && _adder.Equals(other._adder);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
=> Equals(obj as AdderSetter);
public override int GetHashCode()

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlEnsureResourceDictionaryCapacityTransformer.cs

@ -70,8 +70,8 @@ internal sealed class AvaloniaXamlIlEnsureResourceDictionaryCapacityTransformer
{
"Content" when node.Property.DeclaringType == types.ResourceDictionary
=> new ResourcesInfo(ResourcesMode.ResourceDictionaryContent, null) { Count = 1 },
"Resources" when types.IResourceDictionary.IsAssignableFrom(node.Property.Getter.ReturnType)
=> new ResourcesInfo(ResourcesMode.ElementResources, node.Property.Getter) { Count = 1 },
"Resources" when node.Property.Getter is { } getter && types.IResourceDictionary.IsAssignableFrom(getter.ReturnType)
=> new ResourcesInfo(ResourcesMode.ElementResources, getter) { Count = 1 },
_
=> default
};

33
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlOptionMarkupExtensionTransformer.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Emit;
using XamlX;
@ -25,9 +26,9 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
var optionAttribute = context.GetAvaloniaTypes().MarkupExtensionOptionAttribute;
var defaultOptionAttribute = context.GetAvaloniaTypes().MarkupExtensionDefaultOptionAttribute;
var typeArgument = type.GenericArguments?.FirstOrDefault();
var typeArgument = type.GenericArguments.FirstOrDefault();
IXamlAstValueNode defaultValue = null;
IXamlAstValueNode? defaultValue = null;
var values = new List<OptionsMarkupExtensionBranch>();
if (objectNode.Arguments.FirstOrDefault() is { } argument)
@ -64,7 +65,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
var optionsPropNode = onObj.Children.OfType<XamlAstXamlPropertyValueNode>()
.SingleOrDefault(v => v.Property.GetClrProperty().Name == "Options")
?.Values.Single();
var options = (optionsPropNode as XamlAstTextNode)?.Text?.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
var options = (optionsPropNode as XamlAstTextNode)?.Text.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?? Array.Empty<string>();
if (options.Length == 0)
{
@ -128,8 +129,8 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
throw new XamlTransformException("MarkupExtension option must not be null", li);
}
var optionAsString = option.ToString();
IXamlAstValueNode optionNode = null;
var optionAsString = option.ToString() ?? string.Empty;
IXamlAstValueNode? optionNode = null;
foreach (var method in methods)
{
try
@ -184,7 +185,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
IXamlAstValueNode TransformNode(
IReadOnlyCollection<IXamlAstValueNode> values,
IXamlType suggestedType,
IXamlType? suggestedType,
IXamlLineInfo line)
{
if (suggestedType is not null)
@ -212,7 +213,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
public OptionsMarkupExtensionNode(
XamlMarkupExtensionNode original,
OptionsMarkupExtensionBranch[] branches,
IXamlAstValueNode defaultNode,
IXamlAstValueNode? defaultNode,
IXamlType contextParameter)
: base(
original.Value,
@ -232,9 +233,9 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
base.VisitChildren(visitor);
}
public bool ConvertToReturnType(AstTransformationContext context, IXamlType type, out OptionsMarkupExtensionNode res)
public bool ConvertToReturnType(AstTransformationContext context, IXamlType type, [NotNullWhen(true)] out OptionsMarkupExtensionNode? res)
{
IXamlAstValueNode convertedDefaultNode = null;
IXamlAstValueNode? convertedDefaultNode = null;
if (ProvideValue.ExtensionNodeContainer.DefaultNode is { } defaultNode)
{
@ -255,7 +256,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
return false;
}
res = new OptionsMarkupExtensionNode(this, convertedBranches, convertedDefaultNode, _contextParameter);
res = new OptionsMarkupExtensionNode(this, convertedBranches!, convertedDefaultNode, _contextParameter);
return true;
}
}
@ -264,19 +265,19 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
{
public OptionsMarkupExtensionNodesContainer(
OptionsMarkupExtensionBranch[] branches,
IXamlAstValueNode defaultNode) : base(branches.FirstOrDefault()?.Value ?? defaultNode)
IXamlAstValueNode? defaultNode) : base((branches.FirstOrDefault()?.Value ?? defaultNode)!)
{
Branches = branches;
DefaultNode = defaultNode;
}
public OptionsMarkupExtensionBranch[] Branches { get; }
public IXamlAstValueNode DefaultNode { get; private set; }
public IXamlAstValueNode? DefaultNode { get; private set; }
public override void VisitChildren(IXamlAstVisitor visitor)
{
VisitList(Branches, visitor);
DefaultNode = (IXamlAstValueNode)DefaultNode?.Visit(visitor);
DefaultNode = (IXamlAstValueNode?)DefaultNode?.Visit(visitor);
}
public IXamlType GetReturnType()
@ -351,7 +352,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
// - markup ext "@this" instance (always)
// We always pop context from the stack, as this method decide by itself either context is needed.
// We store "@this" as a local variable. But only if any conditional method is an instance method.
IXamlLocal @this = null;
IXamlLocal? @this = null;
if (Parameters.Count > 0)
{
codeGen.Pop();
@ -377,7 +378,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
}
if (!branch.ConditionMethod.IsStatic)
{
codeGen.Ldloc(@this);
codeGen.Ldloc(@this!);
}
context.Emit(branch.Option, codeGen, branch.Option.Type.GetClrType());
codeGen.EmitCall(branch.ConditionMethod);
@ -402,7 +403,7 @@ internal class AvaloniaXamlIlOptionMarkupExtensionTransformer : IXamlAstTransfor
codeGen.MarkLabel(ret);
}
public bool Equals(IXamlMethod other) => ReferenceEquals(this, other);
public bool Equals(IXamlMethod? other) => ReferenceEquals(this, other);
}
}

35
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs

@ -14,7 +14,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class XamlPropertyPathException : XamlTransformException
{
public XamlPropertyPathException(string message, IXamlLineInfo lineInfo, Exception innerException = null)
public XamlPropertyPathException(string message, IXamlLineInfo lineInfo, Exception? innerException = null)
: base(message, lineInfo, innerException)
{
}
@ -50,7 +50,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
var elements = new List<IXamlIlPropertyPathElementNode>();
IXamlType currentType = parentScope.TargetType.GetClrType();
var currentType = parentScope.TargetType.GetClrType();
var expectProperty = true;
@ -58,13 +58,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var expectTraversal = false;
var types = context.GetAvaloniaTypes();
IXamlType GetType(string ns, string name)
IXamlType GetType(string? ns, string name)
{
return TypeReferenceResolver.ResolveType(context, $"{ns}:{name}", false,
text, true).GetClrType();
}
void HandleProperty(string name, string typeNamespace, string typeName)
void HandleProperty(string name, string? typeNamespace, string? typeName)
{
if(!expectProperty || currentType == null)
throw new XamlPropertyPathException("Unexpected property node", text);
@ -72,7 +72,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
var propertySearchType =
typeName != null ? GetType(typeNamespace, typeName) : currentType;
IXamlIlPropertyPathElementNode prop = null;
IXamlIlPropertyPathElementNode? prop = null;
var avaloniaPropertyFieldName = name + "Property";
var avaloniaPropertyField = propertySearchType.GetAllFields().FirstOrDefault(f =>
f.IsStatic && f.IsPublic && f.Name == avaloniaPropertyFieldName);
@ -84,7 +84,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
else
{
var clrProperty = propertySearchType.GetAllProperties().FirstOrDefault(p => p.Name == name);
prop = new XamlIClrPropertyPathElementNode(clrProperty);
if (clrProperty is not null)
prop = new XamlIClrPropertyPathElementNode(clrProperty);
}
if (prop == null)
@ -151,7 +152,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
interface IXamlIlPropertyPathElementNode
{
void Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen);
IXamlType Type { get; }
IXamlType? Type { get; }
}
class XamlIlChildTraversalPropertyPathElementNode : IXamlIlPropertyPathElementNode
@ -159,9 +160,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public void Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
=> codeGen.EmitCall(
context.GetAvaloniaTypes()
.PropertyPathBuilder.FindMethod(m => m.Name == "ChildTraversal"));
.PropertyPathBuilder.GetMethod(m => m.Name == "ChildTraversal"));
public IXamlType Type => null;
public IXamlType? Type => null;
}
class XamlIlAvaloniaPropertyPropertyPathElementNode : IXamlIlPropertyPathElementNode
@ -178,7 +179,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
=> codeGen
.Ldsfld(_field)
.EmitCall(context.GetAvaloniaTypes()
.PropertyPathBuilder.FindMethod(m => m.Name == "Property"));
.PropertyPathBuilder.GetMethod(m => m.Name == "Property"));
public IXamlType Type { get; }
}
@ -198,10 +199,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
.Emit(context, codeGen, _property);
codeGen.EmitCall(context.GetAvaloniaTypes()
.PropertyPathBuilder.FindMethod(m => m.Name == "Property"));
.PropertyPathBuilder.GetMethod(m => m.Name == "Property"));
}
public IXamlType Type => _property.Getter?.ReturnType ?? _property.Setter?.Parameters[0];
public IXamlType Type => _property.PropertyType;
}
class XamlIlCastPropertyPathElementNode : IXamlIlPropertyPathElementNode
@ -220,7 +221,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
codeGen
.Ldtype(_type)
.EmitCall(context.GetAvaloniaTypes()
.PropertyPathBuilder.FindMethod(m => m.Name == (_ensureType ? "EnsureType" : "Cast")));
.PropertyPathBuilder.GetMethod(m => m.Name == (_ensureType ? "EnsureType" : "Cast")));
}
public IXamlType Type => _type;
@ -241,14 +242,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
public IXamlAstTypeReference Type { get; }
public IXamlType PropertyType => _elements.LastOrDefault()?.Type;
public IXamlType? PropertyType => _elements.LastOrDefault()?.Type;
public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen
.Newobj(_types.PropertyPathBuilder.FindConstructor());
.Newobj(_types.PropertyPathBuilder.GetConstructor());
foreach(var e in _elements)
e.Emit(context, codeGen);
codeGen.EmitCall(_types.PropertyPathBuilder.FindMethod(m => m.Name == "Build"));
codeGen.EmitCall(_types.PropertyPathBuilder.GetMethod(m => m.Name == "Build"));
return XamlILNodeEmitResult.Type(0, _types.PropertyPath);
}
}
@ -256,6 +257,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
interface IXamlIlPropertyPathNode : IXamlAstValueNode
{
IXamlType PropertyType { get; }
IXamlType? PropertyType { get; }
}
}

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlReorderClassesPropertiesTransformer.cs

@ -9,8 +9,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
if (node is XamlAstObjectNode obj)
{
IXamlAstNode classesNode = null;
IXamlAstNode firstSingleClassNode = null;
IXamlAstNode? classesNode = null;
IXamlAstNode? firstSingleClassNode = null;
var types = context.GetAvaloniaTypes();
foreach (var child in obj.Children)
{

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlRootObjectScopeTransformer.cs

@ -19,7 +19,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
mnode.Manipulation = new XamlManipulationGroupNode(mnode,
new[]
{
mnode.Manipulation,
mnode.Manipulation!,
new HandleRootObjectScopeNode(mnode, context.GetAvaloniaTypes())
});
}
@ -37,7 +37,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
internal class Emitter : IXamlILAstNodeEmitter
{
public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
public XamlILNodeEmitResult? Emit(IXamlAstNode node, XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (!(node is HandleRootObjectScopeNode))
{

72
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs

@ -15,7 +15,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
internal class XamlSelectorsTransformException : XamlTransformException
{
public XamlSelectorsTransformException(string message, IXamlLineInfo lineInfo, Exception innerException = null)
public XamlSelectorsTransformException(string message, IXamlLineInfo lineInfo, Exception? innerException = null)
: base(message, lineInfo, innerException)
{
}
@ -46,14 +46,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (!(pn.Values[0] is XamlAstTextNode tn))
throw new XamlSelectorsTransformException("Selector property should be a text node", node);
var selectorType = pn.Property.GetClrProperty().Getter.ReturnType;
var selectorType = pn.Property.GetClrProperty().Getter!.ReturnType;
var initialNode = new XamlIlSelectorInitialNode(node, selectorType);
var avaloniaAttachedPropertyT = context.GetAvaloniaTypes().AvaloniaAttachedPropertyT;
XamlIlSelectorNode Create(IEnumerable<SelectorGrammar.ISyntax> syntax,
Func<string, string, XamlAstClrTypeReference> typeResolver)
{
XamlIlSelectorNode result = initialNode;
XamlIlOrSelectorNode results = null;
XamlIlOrSelectorNode? results = null;
foreach (var i in syntax)
{
switch (i)
@ -73,7 +73,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
break;
case SelectorGrammar.PropertySyntax property:
{
var type = result?.TargetType;
var type = result.TargetType;
if (type == null)
throw new XamlTransformException("Property selectors must be applied to a type.", node);
@ -96,7 +96,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
case SelectorGrammar.AttachedPropertySyntax attachedProperty:
{
var targetType = result?.TargetType;
var targetType = result.TargetType;
if (targetType == null)
{
throw new XamlTransformException("Attached Property selectors must be applied to a type.",node);
@ -172,7 +172,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
}
if (results != null && result != null)
if (results != null)
{
results.Add(result);
}
@ -191,14 +191,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
var selector = Create(parsed, (p, n)
=> TypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true)
?? new XamlAstClrTypeReference(node, XamlPseudoType.Unknown, false));
=> TypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));
pn.Values[0] = selector;
var templateType = GetLastTemplateTypeFromSelector(selector);
var styleNode = new AvaloniaXamlIlTargetTypeMetadataNode(on,
new XamlAstClrTypeReference(selector, selector.TargetType, false),
new XamlAstClrTypeReference(selector, selector.TargetType!, false),
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style);
return templateType switch
@ -210,7 +209,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
};
}
private static IXamlType GetLastTemplateTypeFromSelector(XamlIlSelectorNode node)
private static IXamlType? GetLastTemplateTypeFromSelector(XamlIlSelectorNode? node)
{
while (node is not null)
{
@ -219,7 +218,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
SelectorType: XamlIlCombinatorSelector.CombinatorSelectorType.Template
})
{
return node.Previous.TargetType;
return node.Previous?.TargetType;
}
node = node.Previous;
}
@ -230,15 +229,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
abstract class XamlIlSelectorNode : XamlAstNode, IXamlAstValueNode, IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
{
internal XamlIlSelectorNode Previous { get; }
public abstract IXamlType TargetType { get; }
internal XamlIlSelectorNode? Previous { get; }
public abstract IXamlType? TargetType { get; }
public XamlIlSelectorNode(XamlIlSelectorNode previous,
IXamlLineInfo info = null,
IXamlType selectorType = null) : base(info ?? previous)
public XamlIlSelectorNode(XamlIlSelectorNode? previous,
IXamlLineInfo? info = null,
IXamlType? selectorType = null) : base((info ?? previous)!)
{
Previous = previous;
Type = selectorType == null ? previous.Type : new XamlAstClrTypeReference(this, selectorType, false);
Type = selectorType == null ? previous!.Type : new XamlAstClrTypeReference(this, selectorType, false);
}
public IXamlAstTypeReference Type { get; }
@ -256,7 +255,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
protected void EmitCall(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen, Func<IXamlMethod, bool> method)
{
var selectors = context.Configuration.TypeSystem.GetType("Avalonia.Styling.Selectors");
var found = selectors.FindMethod(m => m.IsStatic && m.Parameters.Count > 0 && method(m));
var found = selectors.GetMethod(m => m.IsStatic && m.Parameters.Count > 0 && method(m));
codeGen.EmitCall(found);
}
}
@ -268,7 +267,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
}
public override IXamlType TargetType => null;
public override IXamlType? TargetType => null;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen) => codeGen.Ldnull();
}
@ -310,7 +309,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
public override IXamlType TargetType => Previous?.TargetType;
public override IXamlType? TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldstr(String);
@ -336,7 +336,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
}
public CombinatorSelectorType SelectorType => _type;
public override IXamlType TargetType => null;
public override IXamlType? TargetType => null;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
var name = _type.ToString();
@ -354,7 +354,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
Argument = argument;
}
public override IXamlType TargetType => Previous?.TargetType;
public override IXamlType? TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
context.Emit(Argument, codeGen, Type.GetClrType());
@ -382,7 +383,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_type = type;
}
public override IXamlType TargetType => Previous?.TargetType;
public override IXamlType? TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldc_I4(_step);
@ -406,12 +408,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlProperty Property { get; set; }
public IXamlAstValueNode Value { get; set; }
public override IXamlType TargetType => Previous?.TargetType;
public override IXamlType? TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
if (!XamlIlAvaloniaPropertyHelper.Emit(context, codeGen, Property))
throw new XamlX.XamlLoadException(
$"{Property.Name} of {(Property.Setter ?? Property.Getter).DeclaringType.GetFqn()} doesn't seem to be an AvaloniaProperty",
$"{Property.Name} of {Property.DeclaringType.GetFqn()} doesn't seem to be an AvaloniaProperty",
this);
context.Emit(Value, codeGen, context.Configuration.WellKnownTypes.Object);
EmitCall(context, codeGen,
@ -437,7 +440,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlField PropertyFiled { get; set; }
public IXamlAstValueNode Value { get; set; }
public override IXamlType TargetType => Previous?.TargetType;
public override IXamlType? TargetType => Previous?.TargetType;
protected override void DoEmit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
codeGen.Ldsfld(PropertyFiled);
@ -462,25 +466,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_selectors.Add(node);
}
public override IXamlType TargetType
public override IXamlType? TargetType
{
get
{
IXamlType result = null;
IXamlType? result = null;
foreach (var selector in _selectors)
{
if (selector.TargetType == null)
if (selector.TargetType is not { } targetType)
{
return null;
}
else if (result == null)
{
result = selector.TargetType;
result = targetType;
}
else
{
while (!result.IsAssignableFrom(selector.TargetType))
while (result is not null && !result.IsAssignableFrom(selector.TargetType))
{
result = result.BaseType;
}
@ -500,11 +504,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_selectors[0].Emit(context, codeGen);
return;
}
var listType = context.Configuration.TypeSystem.FindType("System.Collections.Generic.List`1")
var listType = context.Configuration.TypeSystem.GetType("System.Collections.Generic.List`1")
.MakeGenericType(base.Type.GetClrType());
var add = listType.FindMethod("Add", context.Configuration.WellKnownTypes.Void, false, Type.GetClrType());
var add = listType.GetMethod("Add", context.Configuration.WellKnownTypes.Void, false, Type.GetClrType());
codeGen
.Newobj(listType.FindConstructor());
.Newobj(listType.GetConstructor());
foreach (var s in _selectors)
{
codeGen.Dup();

26
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs

@ -12,7 +12,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
class XamlStyleTransformException : XamlTransformException
{
public XamlStyleTransformException(string message, IXamlLineInfo lineInfo, Exception innerException = null)
public XamlStyleTransformException(string message, IXamlLineInfo lineInfo, Exception? innerException = null)
: base(message, lineInfo, innerException)
{
}
@ -26,8 +26,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& on.Type.GetClrType().FullName == "Avalonia.Styling.Setter"))
return node;
IXamlType targetType = null;
IXamlLineInfo lineInfo = null;
IXamlType? targetType = null;
var avaloniaTypes = context.GetAvaloniaTypes();
@ -39,7 +38,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
targetType = styleParent.TargetType.GetClrType()
?? throw new XamlStyleTransformException("Can not find parent Style Selector or ControlTemplate TargetType. If setter is not part of the style, you can set x:SetterTargetType directive on its parent.", node);
lineInfo = on;
}
if (targetType == null)
@ -47,13 +45,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
throw new XamlStyleTransformException("Could not determine target type of Setter", node);
}
IXamlType propType = null;
IXamlIlAvaloniaPropertyNode avaloniaPropertyNode = null;
IXamlType? propType;
var property = @on.Children.OfType<XamlAstXamlPropertyValueNode>()
.FirstOrDefault(x => x.Property.GetClrProperty().Name == "Property");
if (property != null)
{
avaloniaPropertyNode = property.Values.OfType<IXamlIlAvaloniaPropertyNode>().FirstOrDefault();
var avaloniaPropertyNode = property.Values.OfType<IXamlIlAvaloniaPropertyNode>().FirstOrDefault();
if (avaloniaPropertyNode is null)
{
var propertyName = property.Values.OfType<XamlAstTextNode>().FirstOrDefault()?.Text;
@ -61,7 +58,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
throw new XamlStyleTransformException("Setter.Property must be a string.", node);
avaloniaPropertyNode = XamlIlAvaloniaPropertyHelper.CreateNode(context, propertyName,
new XamlAstClrTypeReference(lineInfo, targetType, false), property.Values[0]);
new XamlAstClrTypeReference(on, targetType, false), property.Values[0]);
property.Values = new List<IXamlAstValueNode> {avaloniaPropertyNode};
}
@ -90,9 +87,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& XamlTransformHelpers.TryGetCorrectlyTypedValue(context, textValue,
propType, out _))
{
var setterValueProperty = new SetterValueProperty(
(IXamlLineInfo)valueProperty?.Property ?? textValue,
(IXamlLineInfo?)valueProperty?.Property ?? textValue,
on.Type.GetClrType(), propType, avaloniaTypes);
if (valueProperty is not null)
{
@ -116,8 +112,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
// but we have better validation in runtime for TemplatedBinding.
// See Correctly_Resolve_TemplateBinding_In_Theme_Detached_Template test.
if (!avaloniaTypes.ITemplateOfControl.IsAssignableFrom(propType)
&& on.Children.OfType<XamlAstObjectNode>()?.FirstOrDefault() is { } valueObj
&& avaloniaTypes.ITemplateOfControl.IsAssignableFrom(valueObj?.Type.GetClrType()))
&& on.Children.OfType<XamlAstObjectNode>().FirstOrDefault() is { } valueObj
&& avaloniaTypes.ITemplateOfControl.IsAssignableFrom(valueObj.Type.GetClrType()))
{
on.Children[on.Children.IndexOf(valueObj)] = new AvaloniaXamlIlTargetTypeMetadataNode(valueObj,
new XamlAstClrTypeReference(on, targetType, false),
@ -169,10 +165,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
};
}
private bool Equals(XamlIlDirectCallPropertySetter other)
=> Equals(_method, other._method) && Equals(_type, other._type);
private bool Equals(XamlIlDirectCallPropertySetter? other)
=> other is not null && Equals(_method, other._method) && Equals(_type, other._type);
public override bool Equals(object obj)
public override bool Equals(object? obj)
=> Equals(obj as XamlIlDirectCallPropertySetter);
public override int GetHashCode()

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlThemeVariantProviderTransformer.cs

@ -24,7 +24,8 @@ internal class AvaloniaXamlIlThemeVariantProviderTransformer : IXamlAstTransform
var themeDictionariesColl = avTypes.IDictionaryT.MakeGenericType(avTypes.ThemeVariant, avTypes.IThemeVariantProvider);
if (context.ParentNodes().FirstOrDefault() is not XamlAstXamlPropertyValueNode propertyValueNode
|| !themeDictionariesColl.IsAssignableFrom(propertyValueNode.Property.GetClrProperty().Getter.ReturnType))
|| propertyValueNode.Property.GetClrProperty().Getter is not { } getter
|| !themeDictionariesColl.IsAssignableFrom(getter.ReturnType))
{
return node;
}

14
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlTransformInstanceAttachedProperties.cs

@ -30,7 +30,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (clrProp != null
&& (clrProp.Getter?.IsStatic == false || clrProp.Setter?.IsStatic == false))
{
var declaringType = (clrProp.Getter ?? clrProp.Setter)?.DeclaringType;
var declaringType = clrProp.DeclaringType;
var avaloniaPropertyFieldName = prop.Name + "Property";
var avaloniaPropertyField = declaringType.Fields.FirstOrDefault(f => f.IsStatic && f.Name == avaloniaPropertyFieldName);
if (avaloniaPropertyField != null)
@ -52,10 +52,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
if (avaloniaPropertyType == null)
return node;
if (avaloniaPropertyType.GenericArguments?.Count > 1)
if (avaloniaPropertyType.GenericArguments.Count > 1)
return node;
var propertyType = avaloniaPropertyType.GenericArguments?.Count == 1 ?
var propertyType = avaloniaPropertyType.GenericArguments.Count == 1 ?
avaloniaPropertyType.GenericArguments[0] :
context.Configuration.WellKnownTypes.Object;
@ -97,8 +97,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_avaloniaPropertyType = avaloniaPropertyType;
// XamlIl doesn't support generic methods yet
if (_avaloniaPropertyType.GenericArguments?.Count > 0)
_avaloniaPropertyType = _avaloniaPropertyType.BaseType;
if (_avaloniaPropertyType.GenericArguments.Count > 0)
_avaloniaPropertyType = _avaloniaPropertyType.BaseType!;
_avaloniaObject = avaloniaObject;
_field = field;
@ -173,9 +173,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments)
=> throw new System.NotSupportedException();
public bool Equals(IXamlMethod other) =>
public bool Equals(IXamlMethod? other) =>
other is GetterMethod m && m.Name == Name && m.DeclaringType.Equals(DeclaringType);
public IXamlType ReturnType => Parent.PropertyType;
public IReadOnlyList<IXamlType> Parameters { get; }

31
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -28,7 +28,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType IDisposable { get; }
public IXamlType ICommand { get; }
public XamlTypeWellKnownTypes XamlIlTypes { get; }
public XamlLanguageTypeMappings XamlIlMappings { get; }
public IXamlType Transitions { get; }
public IXamlType AssignBindingAttribute { get; }
public IXamlType DependsOnAttribute { get; }
@ -143,12 +142,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
internal InteractivityWellKnownTypes(TransformerConfiguration cfg)
{
var ts = cfg.TypeSystem;
Interactive = ts.FindType("Avalonia.Interactivity.Interactive");
RoutedEvent = ts.FindType("Avalonia.Interactivity.RoutedEvent");
RoutedEventArgs = ts.FindType("Avalonia.Interactivity.RoutedEventArgs");
var eventHanlderT = ts.FindType("System.EventHandler`1");
Interactive = ts.GetType("Avalonia.Interactivity.Interactive");
RoutedEvent = ts.GetType("Avalonia.Interactivity.RoutedEvent");
RoutedEventArgs = ts.GetType("Avalonia.Interactivity.RoutedEventArgs");
var eventHanlderT = ts.GetType("System.EventHandler`1");
RoutedEventHandler = eventHanlderT.MakeGenericType(RoutedEventArgs);
AddHandler = Interactive.FindMethod(m => m.IsPublic
AddHandler = Interactive.GetMethod(m => m.IsPublic
&& !m.IsStatic
&& m.Name == "AddHandler"
&& m.Parameters.Count == 4
@ -157,15 +156,15 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
&& m.Parameters[2].IsEnum
&& m.Parameters[3].Equals(cfg.WellKnownTypes.Boolean)
);
AddHandlerT = Interactive.FindMethod(m => m.IsPublic
AddHandlerT = Interactive.GetMethod(m => m.IsPublic
&& !m.IsStatic
&& m.Name == "AddHandler"
&& m.Parameters.Count == 4
&& RoutedEvent.IsAssignableFrom(m.Parameters[0])
&& m.Parameters[0].GenericArguments?.Count == 1 // This is specific this case workaround to check is generic method
&& m.Parameters[0].GenericArguments.Count == 1 // This is specific this case workaround to check is generic method
&& (cfg.WellKnownTypes.Delegate).IsAssignableFrom(m.Parameters[1])
&& m.Parameters[2].IsEnum
&& m.Parameters[3].Equals(cfg.WellKnownTypes.Boolean) == true
&& m.Parameters[3].Equals(cfg.WellKnownTypes.Boolean)
);
}
@ -186,7 +185,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AvaloniaAttachedPropertyT = cfg.TypeSystem.GetType("Avalonia.AttachedProperty`1");
BindingPriority = cfg.TypeSystem.GetType("Avalonia.Data.BindingPriority");
AvaloniaObjectSetStyledPropertyValue = AvaloniaObject
.FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
.GetMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
&& m.Parameters.Count == 3
&& m.Parameters[0].Name == "StyledProperty`1"
&& m.Parameters[2].Equals(BindingPriority));
@ -205,7 +204,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AvaloniaListAttribute = cfg.TypeSystem.GetType("Avalonia.Metadata.AvaloniaListAttribute");
AvaloniaList = cfg.TypeSystem.GetType("Avalonia.Collections.AvaloniaList`1");
OnExtensionType = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.On");
AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, AvaloniaObject,
AvaloniaObjectBindMethod = AvaloniaObjectExtensions.GetMethod("Bind", IDisposable, false, AvaloniaObject,
AvaloniaProperty,
IBinding, cfg.WellKnownTypes.Object);
UnsetValueType = cfg.TypeSystem.GetType("Avalonia.UnsetValueType");
@ -230,7 +229,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope",
XamlIlTypes.Void, StyledElement, INameScope)
{ IsStatic = true });
AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", IDisposable,
AvaloniaObjectSetValueMethod = AvaloniaObject.GetMethod("SetValue", IDisposable,
false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority);
IPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.IPropertyInfo");
ClrPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.ClrPropertyInfo");
@ -292,7 +291,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
StyledElementClassesProperty =
StyledElement.Properties.First(x => x.Name == "Classes" && x.PropertyType.Equals(Classes));
ClassesBindMethod = cfg.TypeSystem.GetType("Avalonia.StyledElementExtensions")
.FindMethod("BindClass", IDisposable, false, StyledElement,
.GetMethod("BindClass", IDisposable, false, StyledElement,
cfg.WellKnownTypes.String,
IBinding, cfg.WellKnownTypes.Object);
@ -311,10 +310,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
MergeResourceInclude = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.Styling.MergeResourceInclude");
IResourceDictionary = cfg.TypeSystem.GetType("Avalonia.Controls.IResourceDictionary");
ResourceDictionary = cfg.TypeSystem.GetType("Avalonia.Controls.ResourceDictionary");
ResourceDictionaryDeferredAdd = ResourceDictionary.FindMethod("AddDeferred", XamlIlTypes.Void, true, XamlIlTypes.Object,
ResourceDictionaryDeferredAdd = ResourceDictionary.GetMethod("AddDeferred", XamlIlTypes.Void, true, XamlIlTypes.Object,
cfg.TypeSystem.GetType("Avalonia.Controls.IDeferredContent"));
ResourceDictionaryEnsureCapacity = ResourceDictionary.FindMethod("EnsureCapacity", XamlIlTypes.Void, true, XamlIlTypes.Int32);
ResourceDictionaryGetCount = ResourceDictionary.FindMethod("get_Count", XamlIlTypes.Int32, true);
ResourceDictionaryEnsureCapacity = ResourceDictionary.GetMethod("EnsureCapacity", XamlIlTypes.Void, true, XamlIlTypes.Int32);
ResourceDictionaryGetCount = ResourceDictionary.GetMethod("get_Count", XamlIlTypes.Int32, true);
IThemeVariantProvider = cfg.TypeSystem.GetType("Avalonia.Controls.IThemeVariantProvider");
UriKind = cfg.TypeSystem.GetType("System.UriKind");
UriConstructor = Uri.GetConstructor(new List<IXamlType>() { cfg.WellKnownTypes.String, UriKind });

2
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Visitors/NameScopeRegistrationVisitor.cs

@ -25,7 +25,7 @@ internal class NameScopeRegistrationVisitor : Dictionary<string, (IXamlType type
&& node is AvaloniaNameScopeRegistrationXamlIlNode nameScopeRegistration
&& nameScopeRegistration.Name is XamlAstTextNode textNode)
{
this[textNode.Text] = (nameScopeRegistration.TargetType, textNode);
this[textNode.Text] = (nameScopeRegistration.TargetType ?? XamlPseudoType.Unknown, textNode);
}
return node;

43
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs

@ -51,9 +51,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public static bool Emit(XamlIlEmitContext context, IXamlILEmitter emitter, IXamlProperty property)
{
var type = (property.Getter ?? property.Setter).DeclaringType;
var name = property.Name + "Property";
var found = type.Fields.FirstOrDefault(f => f.IsStatic && f.Name == name);
var found = property.DeclaringType.Fields.FirstOrDefault(f => f.IsStatic && f.Name == name);
if (found == null)
return false;
@ -225,11 +224,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType,
IXamlField avaloniaProperty,
bool allowNull)
bool allowNull,
IReadOnlyList<IXamlType> parameters)
{
Types = types;
AvaloniaProperty = avaloniaProperty;
TargetType = declaringType;
Parameters = parameters;
BinderParameters = new PropertySetterBinderParameters
{
AllowXNull = allowNull,
@ -241,7 +242,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public PropertySetterBinderParameters BinderParameters { get; }
public IReadOnlyList<IXamlType> Parameters { get; set; }
public IReadOnlyList<IXamlType> Parameters { get; }
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => Array.Empty<IXamlCustomAttribute>();
public abstract void Emit(IXamlILEmitter emitter);
@ -251,7 +252,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments);
public bool Equals(AvaloniaPropertyCustomSetter other)
public bool Equals(AvaloniaPropertyCustomSetter? other)
{
if (ReferenceEquals(null, other))
return false;
@ -261,7 +262,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return GetType() == other.GetType() && AvaloniaProperty.Equals(other.AvaloniaProperty);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
=> Equals(obj as AvaloniaPropertyCustomSetter);
public override int GetHashCode()
@ -270,11 +271,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class BindingSetter : AvaloniaPropertyCustomSetter
{
public BindingSetter(AvaloniaXamlIlWellKnownTypes types,
public BindingSetter(
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType,
IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false)
IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty, false, [types.IBinding])
{
Parameters = new[] { types.IBinding };
}
public override void Emit(IXamlILEmitter emitter)
@ -307,11 +309,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class BindingWithPrioritySetter : AvaloniaPropertyCustomSetter
{
public BindingWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types,
public BindingWithPrioritySetter(
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType,
IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false)
IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty, false, [types.BindingPriority, types.IBinding])
{
Parameters = new[] { types.BindingPriority, types.IBinding };
}
public override void Emit(IXamlILEmitter emitter)
@ -345,11 +348,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class SetValueWithPrioritySetter : AvaloniaPropertyCustomSetter
{
public SetValueWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty,
public SetValueWithPrioritySetter(
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType,
IXamlField avaloniaProperty,
IXamlType propertyType)
: base(types, declaringType, avaloniaProperty, propertyType.AcceptsNull())
: base(types, declaringType, avaloniaProperty, propertyType.AcceptsNull(), [types.BindingPriority, propertyType])
{
Parameters = new[] { types.BindingPriority, propertyType };
}
public override void Emit(IXamlILEmitter emitter)
@ -393,10 +398,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class UnsetValueSetter : AvaloniaPropertyCustomSetter
{
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty, false)
public UnsetValueSetter(
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType,
IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty, false, [types.UnsetValueType])
{
Parameters = new[] { types.UnsetValueType };
}
public override void Emit(IXamlILEmitter codegen)

99
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs

@ -21,7 +21,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
public static IXamlType UpdateCompiledBindingExtension(AstTransformationContext context, XamlAstConstructableObjectNode binding, Func<IXamlType> startTypeResolver, IXamlType selfType)
{
IXamlType bindingResultType = null;
IXamlType? bindingResultType;
if (binding.Arguments.Count > 0 && binding.Arguments[0] is ParsedBindingPathNode bindingPath)
{
var transformed = TransformBindingPath(
@ -90,8 +90,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
if (GetPropertyType(context, parentNode) == context.GetAvaloniaTypes().ICommand && lastElement is XamlIlClrMethodPathElementNode methodPathElement)
{
IXamlMethod executeMethod = methodPathElement.Method;
IXamlMethod canExecuteMethod = executeMethod.DeclaringType.FindMethod(new FindMethodMethodSignature($"Can{executeMethod.Name}", context.Configuration.WellKnownTypes.Boolean, context.Configuration.WellKnownTypes.Object));
var executeMethod = methodPathElement.Method;
var canExecuteMethod = executeMethod.DeclaringType.FindMethod(new FindMethodMethodSignature(
$"Can{executeMethod.Name}",
context.Configuration.WellKnownTypes.Boolean,
context.Configuration.WellKnownTypes.Object));
List<string> dependsOnProperties = new();
if (canExecuteMethod is not null)
{
@ -99,7 +103,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
if (attr.Type == context.GetAvaloniaTypes().DependsOnAttribute)
{
dependsOnProperties.Add((string)attr.Parameters[0]);
dependsOnProperties.Add((string)attr.Parameters[0]!);
}
}
}
@ -110,7 +114,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return transformed;
}
private static IXamlType GetPropertyType(AstTransformationContext context, XamlPropertyAssignmentNode node)
private static IXamlType? GetPropertyType(AstTransformationContext context, XamlPropertyAssignmentNode node)
{
var setterType = context.GetAvaloniaTypes().Setter;
@ -126,11 +130,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.FirstOrDefault(x => x.Property.GetClrProperty().Name == "Property");
var property = propertyAssignment?.Values.FirstOrDefault() as IXamlIlAvaloniaPropertyNode;
if (property.AvaloniaPropertyType is { } propertyType)
if (property?.AvaloniaPropertyType is { } propertyType)
return propertyType;
}
return node.Property?.Getter?.ReturnType;
return node.Property.Getter?.ReturnType;
}
private static XamlIlBindingPathNode TransformBindingPath(AstTransformationContext context, IXamlLineInfo lineInfo, Func<IXamlType> startTypeResolver, IXamlType selfType, IEnumerable<BindingExpressionGrammar.INode> bindingExpression)
@ -150,7 +154,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
case BindingExpressionGrammar.StreamNode _:
{
IXamlType targetType = targetTypeResolver();
IXamlType observableType;
IXamlType? observableType;
if (targetType.GenericTypeDefinition?.Equals(context.Configuration.TypeSystem.FindType("System.IObservable`1")) == true)
{
observableType = targetType;
@ -165,10 +169,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
nodes.Add(new XamlIlStreamObservablePathElementNode(observableType.GenericArguments[0]));
break;
}
bool foundTask = false;
var taskType = context.Configuration.TypeSystem.GetType("System.Threading.Tasks.Task`1");
for (var currentType = targetType; currentType != null; currentType = currentType.BaseType)
{
if (currentType.GenericTypeDefinition.Equals(context.Configuration.TypeSystem.GetType("System.Threading.Tasks.Task`1")))
if (currentType.GenericTypeDefinition?.Equals(taskType) == true)
{
foundTask = true;
nodes.Add(new XamlIlStreamTaskPathElementNode(currentType.GenericArguments[0]));
@ -216,13 +223,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
break;
}
IXamlProperty property = null;
IXamlProperty? property = null;
foreach (var currentType in TraverseTypeHierarchy(targetType))
{
var defaultMemberAttribute = currentType.CustomAttributes.FirstOrDefault(x => x.Type.Namespace == "System.Reflection" && x.Type.Name == "DefaultMemberAttribute");
if (defaultMemberAttribute != null)
{
property = currentType.GetAllProperties().FirstOrDefault(x => x.Name == (string)defaultMemberAttribute.Parameters[0]);
property = currentType.GetAllProperties().FirstOrDefault(x => x.Name == (string)defaultMemberAttribute.Parameters[0]!);
break;
}
}
@ -255,8 +262,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
case BindingExpressionGrammar.AttachedPropertyNameNode attachedProp:
var avaloniaPropertyFieldName = attachedProp.PropertyName + "Property";
var avaloniaPropertyField = GetType(attachedProp.Namespace, attachedProp.TypeName).GetAllFields().FirstOrDefault(f =>
var propertyOwnerType = GetType(attachedProp.Namespace, attachedProp.TypeName);
var avaloniaPropertyField = propertyOwnerType.GetAllFields().FirstOrDefault(f =>
f.IsStatic && f.IsPublic && f.Name == avaloniaPropertyFieldName);
if (avaloniaPropertyField is null)
{
throw new XamlTransformException(
$"Unable to find {avaloniaPropertyFieldName} field on type {propertyOwnerType.GetFullName()}",
lineInfo);
}
nodes.Add(new XamlIlAvaloniaPropertyPropertyPathElementNode(avaloniaPropertyField,
XamlIlAvaloniaPropertyHelper.GetAvaloniaPropertyType(avaloniaPropertyField, context.GetAvaloniaTypes(), lineInfo)));
break;
@ -305,7 +321,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
break;
case BindingExpressionGrammar.NameNode elementName:
IXamlType elementType = null;
IXamlType? elementType = null;
foreach (var deferredContent in context.ParentNodes().OfType<NestedScopeMetadataNode>())
{
elementType = ScopeRegistrationFinder.GetTargetType(deferredContent, elementName.Name);
@ -340,7 +356,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return new XamlIlBindingPathNode(lineInfo, context.GetAvaloniaTypes().CompiledBindingPath, transformNodes, nodes);
IXamlType GetType(string ns, string name)
IXamlType GetType(string? ns, string? name)
{
return TypeReferenceResolver.ResolveType(context, $"{ns}:{name}", false,
lineInfo, true).GetClrType();
@ -403,9 +419,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
string Name { get; }
IXamlType TargetType { get; set; }
IXamlType? TargetType { get; set; }
public static IXamlType GetTargetType(IXamlAstNode namescopeRoot, string name)
public static IXamlType? GetTargetType(IXamlAstNode namescopeRoot, string name)
{
// If we start from the nested scope - skip it.
if (namescopeRoot is NestedScopeMetadataNode scope)
@ -468,7 +484,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "Not"));
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "Not"));
}
}
@ -483,7 +499,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "StreamObservable").MakeGenericMethod(new[] { Type }));
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "StreamObservable").MakeGenericMethod(new[] { Type }));
}
}
@ -498,7 +514,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "StreamTask").MakeGenericMethod(new[] { Type }));
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "StreamTask").MakeGenericMethod(new[] { Type }));
}
}
@ -513,7 +529,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "Self"));
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "Self"));
}
}
@ -533,7 +549,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
codeGen.Ldtype(Type)
.Ldc_I4(_level)
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "Ancestor"));
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "Ancestor"));
}
}
@ -553,7 +569,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
codeGen.Ldtype(Type)
.Ldc_I4(_level)
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "VisualAncestor"));
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "VisualAncestor"));
}
}
@ -578,7 +594,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.Ldloc(context.ContextLocal)
.Ldfld(scopeField)
.Ldstr(_name)
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "ElementName"));
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "ElementName"));
}
}
@ -594,7 +610,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "TemplatedParent"));
.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "TemplatedParent"));
}
}
@ -614,7 +630,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
context.Configuration.GetExtra<XamlIlPropertyInfoAccessorFactoryEmitter>()
.EmitLoadAvaloniaPropertyAccessorFactory(context, codeGen);
codeGen.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Property"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Property"));
}
public IXamlType Type { get; }
@ -639,10 +655,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen
.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Property"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Property"));
}
public IXamlType Type => _property.Getter?.ReturnType ?? _property.Setter?.Parameters[0];
public IXamlType Type => _property.PropertyType;
}
class XamlIlClrMethodPathElementNode : IXamlIlBindingPathElementNode
@ -659,7 +675,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
IXamlTypeBuilder<IXamlILEmitter> newDelegateTypeBuilder = null;
IXamlTypeBuilder<IXamlILEmitter>? newDelegateTypeBuilder = null;
IXamlType specificDelegateType;
if (Method.ReturnType == context.Configuration.WellKnownTypes.Void && Method.Parameters.Count == 0)
{
@ -696,7 +712,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.Ldtoken(Method)
.Ldtoken(specificDelegateType)
.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Method"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Method"));
newDelegateTypeBuilder?.CreateType();
}
@ -705,10 +721,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
class XamlIlClrMethodAsCommandPathElementNode : IXamlIlBindingPathElementNode
{
private readonly IXamlMethod _executeMethod;
private readonly IXamlMethod _canExecuteMethod;
private readonly IXamlMethod? _canExecuteMethod;
private readonly IReadOnlyList<string> _dependsOnProperties;
public XamlIlClrMethodAsCommandPathElementNode(IXamlType iCommandType, IXamlMethod executeMethod, IXamlMethod canExecuteMethod, IReadOnlyList<string> dependsOnProperties)
public XamlIlClrMethodAsCommandPathElementNode(
IXamlType iCommandType,
IXamlMethod executeMethod,
IXamlMethod? canExecuteMethod,
IReadOnlyList<string> dependsOnProperties)
{
Type = iCommandType;
_executeMethod = executeMethod;
@ -716,7 +736,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_dependsOnProperties = dependsOnProperties;
}
public IXamlType Type { get; }
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
@ -770,7 +789,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen
.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Command"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Command"));
}
}
@ -810,10 +829,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
codeGen.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Property"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Property"));
}
public IXamlType Type => _property.Getter?.ReturnType ?? _property.Setter?.Parameters[0];
public IXamlType Type => _property.PropertyType;
}
class XamlIlArrayIndexerPathElementNode : IXamlIlBindingPathElementNode
@ -853,10 +872,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
codeGen.Ldloc(indices)
.Ldtype(Type)
.EmitCall(context.GetAvaloniaTypes()
.CompiledBindingPathBuilder.FindMethod(m => m.Name == "ArrayElement"));
.CompiledBindingPathBuilder.GetMethod(m => m.Name == "ArrayElement"));
}
public IXamlType Type => _arrayType.ArrayElementType;
public IXamlType Type => _arrayType.ArrayElementType!;
}
class TypeCastPathElementNode : IXamlIlBindingPathElementNode
@ -870,7 +889,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
{
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "TypeCast").MakeGenericMethod(new[] { Type }));
codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.GetMethod(m => m.Name == "TypeCast").MakeGenericMethod(new[] { Type }));
}
}
@ -906,7 +925,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
// of 1 to indicate that we don't want TemplatedParent compatibility hacks enabled.
codeGen
.Ldc_I4(1)
.Newobj(types.CompiledBindingPathBuilder.FindConstructor(new() { intType }));
.Newobj(types.CompiledBindingPathBuilder.GetConstructor(new() { intType }));
foreach (var transform in _transformElements)
{
@ -918,7 +937,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
element.Emit(context, codeGen);
}
codeGen.EmitCall(types.CompiledBindingPathBuilder.FindMethod(m => m.Name == "Build"));
codeGen.EmitCall(types.CompiledBindingPathBuilder.GetMethod(m => m.Name == "Build"));
return XamlILNodeEmitResult.Type(0, types.CompiledBindingPath);
}

23
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlClrPropertyInfoHelper.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.TypeSystem;
using XamlX.IL;
using XamlX.Emit;
@ -22,9 +21,12 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
_builder = builder;
}
static string GetKey(IXamlProperty property, string indexerArgumentsKey)
static string GetKey(IXamlProperty property, string? indexerArgumentsKey)
{
var baseKey = property.Getter.DeclaringType.GetFullName() + "." + property.Name;
var declaringType = (property.Getter ?? property.Setter)?.DeclaringType
?? throw new InvalidOperationException($"Couldn't get declaring type for property {property}");
var baseKey = declaringType.GetFullName() + "." + property.Name;
if (indexerArgumentsKey is null)
{
@ -34,9 +36,14 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return baseKey + $"[{indexerArgumentsKey}]";
}
public IXamlType Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen, IXamlProperty property, IReadOnlyCollection<IXamlAstValueNode> indexerArguments = null, string indexerArgumentsKey = null)
public IXamlType Emit(
XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter codeGen,
IXamlProperty property,
IReadOnlyCollection<IXamlAstValueNode>? indexerArguments = null,
string? indexerArgumentsKey = null)
{
indexerArguments = indexerArguments ?? Array.Empty<IXamlAstValueNode>();
indexerArguments ??= [];
var types = context.GetAvaloniaTypes();
IXamlMethod Get()
{
@ -83,7 +90,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
new[] {types.XamlIlTypes.Object}, name + "!Getter", XamlVisibility.Private, true, false);
if (getter != null)
{
Load(property.Getter, getter.Generator, !property.Getter.IsStatic);
Load(property.Getter!, getter.Generator, !property.Getter!.IsStatic);
getter.Generator.EmitCall(property.Getter);
if (property.Getter.ReturnType.IsValueType)
@ -98,7 +105,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
name + "!Setter", XamlVisibility.Private, true, false);
if (setter != null)
{
Load(property.Setter, setter.Generator, !property.Getter.IsStatic);
Load(property.Setter!, setter.Generator, !property.Setter!.IsStatic);
setter.Generator.Ldarg(1);
@ -128,7 +135,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.MarkLabel(cacheMiss)
.Ldstr(property.Name);
void EmitFunc(IXamlILEmitter emitter, IXamlMethod method, IXamlType del)
void EmitFunc(IXamlILEmitter emitter, IXamlMethod? method, IXamlType del)
{
if (method == null)
emitter.Ldnull();

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlPropertyInfoAccessorFactoryEmitter.cs

@ -17,7 +17,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{
private const string IndexerClosureFactoryMethodName = "CreateAccessor";
private readonly IXamlTypeBuilder<IXamlILEmitter> _indexerClosureTypeBuilder;
private IXamlType _indexerClosureType;
private IXamlType? _indexerClosureType;
public XamlIlPropertyInfoAccessorFactoryEmitter(IXamlTypeBuilder<IXamlILEmitter> indexerClosureType)
{
_indexerClosureTypeBuilder = indexerClosureType;
@ -57,7 +57,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
context.Emit(value, codeGen, intType);
codeGen.Newobj(_indexerClosureType.FindConstructor(new List<IXamlType> { intType }));
codeGen.Newobj(_indexerClosureType.GetConstructor(new List<IXamlType> { intType }));
EmitLoadPropertyAccessorFactory(context, codeGen, _indexerClosureType, IndexerClosureFactoryMethodName, isStatic: false);
return EmitCreateAccessorFactoryDelegate(context, codeGen);
}

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlTrampolineBuilder.cs

@ -54,10 +54,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
var convertedValue = gen.DefineLocal(context.Configuration.WellKnownTypes.Object);
gen.Ldtype(executeMethod.Parameters[0])
.Ldarg(1)
.EmitCall(context.Configuration.WellKnownTypes.CultureInfo.FindMethod(m => m.Name == "get_CurrentCulture"))
.EmitCall(context.Configuration.WellKnownTypes.CultureInfo.GetMethod(m => m.Name == "get_CurrentCulture"))
.Ldloca(convertedValue)
.EmitCall(
context.GetAvaloniaTypes().TypeUtilities.FindMethod(m => m.Name == "TryConvert"),
context.GetAvaloniaTypes().TypeUtilities.GetMethod(m => m.Name == "TryConvert"),
swallowResult: true)
.Ldloc(convertedValue)
.Unbox_Any(executeMethod.Parameters[0]);

2
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@ -1 +1 @@
Subproject commit 941dafce490ffd21178f4493a7f0425e9d478e60
Subproject commit 14fed0cb0666a9b3f71cb635cf61eb6010d4ff64

2
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -361,7 +361,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
{
return new RootServiceProvider(new NameScope(), null);
}
public static IServiceProvider CreateRootServiceProviderV3(IServiceProvider parentServiceProvider)
public static IServiceProvider CreateRootServiceProviderV3(IServiceProvider? parentServiceProvider)
{
return new RootServiceProvider(new NameScope(), parentServiceProvider);
}

3
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -14,11 +14,12 @@
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerExtensions\**\*.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerDynamicDependencies.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Metadata\NullableAttributes.cs" Link="Compatibility\NullableAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\NullableAttributes.cs" Link="Compatibility\NullableAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="Compatibility\TrimmingAttributes.cs" />
<Compile Include="..\..\..\src\Shared\IsExternalInit.cs" Link="Compatibility\IsExternalInit.cs" />
</ItemGroup>
<Import Project="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\IncludeXamlIlSre.props" />
<Import Project="..\..\..\build\DevAnalyzers.props" />
<Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="..\..\..\build\NullableEnable.props" />
</Project>

6
src/tools/Avalonia.Designer.HostApp/DesignXamlLoader.cs

@ -19,11 +19,11 @@ class DesignXamlLoader : AvaloniaXamlLoader.IRuntimeXamlLoader
return AvaloniaXamlIlRuntimeCompiler.Load(document, configuration);
}
private void PreloadDepsAssemblies(Assembly targetAssembly)
private void PreloadDepsAssemblies(Assembly? targetAssembly)
{
// Assemblies loaded in memory (e.g. single file) return empty string from Location.
// In these cases, don't try probing next to the assembly.
var assemblyLocation = targetAssembly.Location;
var assemblyLocation = targetAssembly?.Location;
if (string.IsNullOrEmpty(assemblyLocation))
{
return;
@ -32,7 +32,7 @@ class DesignXamlLoader : AvaloniaXamlLoader.IRuntimeXamlLoader
var depsJsonFile = Path.ChangeExtension(assemblyLocation, ".deps.json");
if (!File.Exists(depsJsonFile))
{
var sameDir = Path.GetDirectoryName(depsJsonFile);
var sameDir = Path.GetDirectoryName(depsJsonFile)!;
var fallbackDepsFiles = Directory.GetFiles(sameDir, "*.deps.json");
if (fallbackDepsFiles.Length == 1)
{

12
src/tools/Avalonia.Generators/Avalonia.Generators.csproj

@ -8,6 +8,7 @@
<IncludeSymbols>false</IncludeSymbols>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
@ -16,20 +17,21 @@
</ItemGroup>
<ItemGroup>
<Compile Link="Compiler\XamlX\filename" Include="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/**/*.cs" />
<Compile Link="Compiler/XamlX/filename" Include="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/**/*.cs" />
<Compile Remove="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/obj/**/*.cs" />
<Compile Remove="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/**/SreTypeSystem.cs" />
<Compile Include="..\..\Shared\IsExternalInit.cs" Link="IsExternalInit.cs" Visible="False" />
<Compile Include="..\..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
<Compile Include="../../Shared/IsExternalInit.cs" Link="IsExternalInit.cs" Visible="False" />
<Compile Include="../../Avalonia.Base/Compatibility/TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
<Compile Include="../../Avalonia.Base/Compatibility/NullableAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
</ItemGroup>
<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="$(OutputPath)/$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
<ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Avalonia.Generators.Tests, PublicKey=$(AvaloniaPublicKey)" />
</ItemGroup>
<Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="../../../build/TrimmingEnable.props" />
</Project>

2
src/tools/Avalonia.Generators/Common/Domain/IViewResolver.cs

@ -5,7 +5,7 @@ namespace Avalonia.Generators.Common.Domain;
internal interface IViewResolver
{
ResolvedView ResolveView(string xaml);
ResolvedView? ResolveView(string xaml);
}
internal record ResolvedView(string ClassName, IXamlType XamlType, string Namespace, XamlDocument Xaml);

16
src/tools/Avalonia.Generators/Common/XamlXViewResolver.cs

@ -14,18 +14,18 @@ internal class XamlXViewResolver : IViewResolver, IXamlAstVisitor
private readonly RoslynTypeSystem _typeSystem;
private readonly MiniCompiler _compiler;
private readonly bool _checkTypeValidity;
private readonly Action<string> _onTypeInvalid;
private readonly Action<Exception> _onUnhandledError;
private readonly Action<string>? _onTypeInvalid;
private readonly Action<Exception>? _onUnhandledError;
private ResolvedView _resolvedClass;
private XamlDocument _xaml;
private ResolvedView? _resolvedClass;
private XamlDocument? _xaml;
public XamlXViewResolver(
RoslynTypeSystem typeSystem,
MiniCompiler compiler,
bool checkTypeValidity = false,
Action<string> onTypeInvalid = null,
Action<Exception> onUnhandledError = null)
Action<string>? onTypeInvalid = null,
Action<Exception>? onUnhandledError = null)
{
_checkTypeValidity = checkTypeValidity;
_onTypeInvalid = onTypeInvalid;
@ -34,7 +34,7 @@ internal class XamlXViewResolver : IViewResolver, IXamlAstVisitor
_compiler = compiler;
}
public ResolvedView ResolveView(string xaml)
public ResolvedView? ResolveView(string xaml)
{
try
{
@ -86,7 +86,7 @@ internal class XamlXViewResolver : IViewResolver, IXamlAstVisitor
var nameSpace = string.Join(".", split.Take(split.Length - 1));
var className = split.Last();
_resolvedClass = new ResolvedView(className, clrType, nameSpace, _xaml);
_resolvedClass = new ResolvedView(className, clrType, nameSpace, _xaml!);
return node;
}
}

63
src/tools/Avalonia.Generators/Compiler/RoslynTypeSystem.cs

@ -28,18 +28,18 @@ internal class RoslynTypeSystem : IXamlTypeSystem
public IEnumerable<IXamlAssembly> Assemblies => _assemblies;
public IXamlAssembly FindAssembly(string name) =>
public IXamlAssembly? FindAssembly(string name) =>
Assemblies
.FirstOrDefault(a => string.Equals(a.Name, name, StringComparison.OrdinalIgnoreCase));
[UnconditionalSuppressMessage("Trimming", "IL2092", Justification = TrimmingMessages.Roslyn)]
public IXamlType FindType(string name) =>
public IXamlType? FindType(string name) =>
_assemblies
.Select(assembly => assembly.FindType(name))
.FirstOrDefault(type => type != null);
[UnconditionalSuppressMessage("Trimming", "IL2092", Justification = TrimmingMessages.Roslyn)]
public IXamlType FindType(string name, string assembly) =>
public IXamlType? FindType(string name, string assembly) =>
_assemblies
.Select(assemblyInstance => assemblyInstance.FindType(name))
.FirstOrDefault(type => type != null);
@ -62,7 +62,7 @@ internal class RoslynAssembly : IXamlAssembly
.Select(data => new RoslynAttribute(data, this))
.ToList();
public IXamlType FindType(string fullName)
public IXamlType? FindType(string fullName)
{
var type = _symbol.GetTypeByMetadataName(fullName);
return type is null ? null : new RoslynType(type, this);
@ -84,14 +84,14 @@ internal class RoslynAttribute : IXamlCustomAttribute
other is RoslynAttribute attribute &&
_data == attribute._data;
public IXamlType Type => new RoslynType(_data.AttributeClass, _assembly);
public IXamlType Type => new RoslynType(_data.AttributeClass!, _assembly);
public List<object> Parameters =>
public List<object?> Parameters =>
_data.ConstructorArguments
.Select(argument => argument.Value)
.ToList();
public Dictionary<string, object> Properties =>
public Dictionary<string, object?> Properties =>
_data.NamedArguments.ToDictionary(
pair => pair.Key,
pair => pair.Value.Value);
@ -132,7 +132,7 @@ internal class RoslynType : IXamlType
public bool IsNestedPrivate => _symbol.DeclaredAccessibility == Accessibility.Private;
public IXamlType DeclaringType =>
public IXamlType? DeclaringType =>
_symbol.ContainingType is { } containingType ? new RoslynType(containingType, _assembly) : null;
public IReadOnlyList<IXamlProperty> Properties =>
@ -142,18 +142,18 @@ internal class RoslynType : IXamlType
.Select(property => new RoslynProperty(property, _assembly))
.ToList();
public IReadOnlyList<IXamlEventInfo> Events { get; } = new List<IXamlEventInfo>();
public IReadOnlyList<IXamlEventInfo> Events => [];
public IReadOnlyList<IXamlField> Fields { get; } = new List<IXamlField>();
public IReadOnlyList<IXamlField> Fields => [];
public IReadOnlyList<IXamlMethod> Methods { get; } = new List<IXamlMethod>();
public IReadOnlyList<IXamlMethod> Methods => [];
public IReadOnlyList<IXamlConstructor> Constructors =>
_symbol.Constructors
.Select(method => new RoslynConstructor(method, _assembly))
.ToList();
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = Array.Empty<IXamlCustomAttribute>();
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => [];
public IReadOnlyList<IXamlType> GenericArguments { get; private set; } = new List<IXamlType>();
@ -169,15 +169,15 @@ internal class RoslynType : IXamlType
public bool IsArray => false;
public IXamlType ArrayElementType { get; } = null;
public IXamlType? ArrayElementType => null;
public IXamlType MakeArrayType(int dimensions) => null;
public IXamlType MakeArrayType(int dimensions) => throw new NotSupportedException();
public IXamlType BaseType => _symbol.BaseType == null ? null : new RoslynType(_symbol.BaseType, _assembly);
public IXamlType? BaseType => _symbol.BaseType is { } baseType ? new RoslynType(baseType, _assembly) : null;
public bool IsValueType { get; } = false;
public bool IsValueType => false;
public bool IsEnum { get; } = false;
public bool IsEnum => false;
public IReadOnlyList<IXamlType> Interfaces =>
_symbol.AllInterfaces
@ -186,9 +186,9 @@ internal class RoslynType : IXamlType
public bool IsInterface => _symbol.IsAbstract;
public IXamlType GetEnumUnderlyingType() => null;
public IXamlType GetEnumUnderlyingType() => throw new NotSupportedException();
public IReadOnlyList<IXamlType> GenericParameters { get; } = new List<IXamlType>();
public IReadOnlyList<IXamlType> GenericParameters => [];
public bool IsFunctionPointer => false;
}
@ -217,6 +217,10 @@ internal class RoslynConstructor : IXamlConstructor
.Select(parameter => new RoslynParameter(_assembly, parameter).ParameterType)
.ToList();
public string Name => _symbol.Name;
public IXamlType DeclaringType => new RoslynType(_symbol.ContainingType, _assembly);
public IXamlParameterInfo GetParameterInfo(int index) => new RoslynParameter(_assembly, _symbol.Parameters[index]);
}
@ -237,18 +241,20 @@ internal class RoslynProperty : IXamlProperty
public string Name => _symbol.Name;
public IXamlType DeclaringType => new RoslynType(_symbol.ContainingType, _assembly);
public IXamlType PropertyType =>
_symbol.Type is INamedTypeSymbol namedTypeSymbol
? new RoslynType(namedTypeSymbol, _assembly)
: null;
: XamlPseudoType.Unknown;
public IXamlMethod Getter => _symbol.GetMethod == null ? null : new RoslynMethod(_symbol.GetMethod, _assembly);
public IXamlMethod? Getter => _symbol.GetMethod == null ? null : new RoslynMethod(_symbol.GetMethod, _assembly);
public IXamlMethod Setter => _symbol.SetMethod == null ? null : new RoslynMethod(_symbol.SetMethod, _assembly);
public IXamlMethod? Setter => _symbol.SetMethod == null ? null : new RoslynMethod(_symbol.SetMethod, _assembly);
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = Array.Empty<IXamlCustomAttribute>();
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => [];
public IReadOnlyList<IXamlType> IndexerParameters { get; } = new List<IXamlType>();
public IReadOnlyList<IXamlType> IndexerParameters => [];
}
internal class RoslynParameter : IXamlParameterInfo
@ -298,10 +304,11 @@ internal class RoslynMethod : IXamlMethod
_symbol.Parameters.Select(parameter => new RoslynParameter(_assembly, parameter).ParameterType)
.ToList();
public IXamlType DeclaringType => new RoslynType((INamedTypeSymbol)_symbol.ReceiverType, _assembly);
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments) => null;
public IXamlType DeclaringType => new RoslynType(_symbol.ContainingType, _assembly);
public IXamlMethod MakeGenericMethod(IReadOnlyList<IXamlType> typeArguments) => throw new NotSupportedException();
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes => [];
public IReadOnlyList<IXamlCustomAttribute> CustomAttributes { get; } = Array.Empty<IXamlCustomAttribute>();
public IXamlParameterInfo GetParameterInfo(int index) => new RoslynParameter(_assembly, _symbol.Parameters[index]);
}

2
src/tools/Avalonia.Generators/GeneratorContextExtensions.cs

@ -29,7 +29,7 @@ internal static class GeneratorContextExtensions
$"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " +
$"The type '{typeName}' does not exist in the assembly.");
private static void Report(this GeneratorExecutionContext context, string id, string title, string message = null, string description = null) =>
private static void Report(this GeneratorExecutionContext context, string id, string title, string? message = null, string? description = null) =>
context.ReportDiagnostic(
Diagnostic.Create(
new DiagnosticDescriptor(

2
src/tools/Avalonia.Generators/NameGenerator/AvaloniaNameSourceGenerator.cs

@ -57,7 +57,7 @@ public class AvaloniaNameSourceGenerator : ISourceGenerator
&& sourceItemGroup == "AvaloniaXaml");
}
private static INameGenerator CreateNameGenerator(GeneratorExecutionContext context)
private static INameGenerator? CreateNameGenerator(GeneratorExecutionContext context)
{
var options = new GeneratorOptions(context);
if (!options.AvaloniaNameGeneratorIsEnabled)

3
tests/Avalonia.Generators.Tests/InitializeComponent/InitializeComponentTests.cs

@ -44,11 +44,12 @@ public class InitializeComponentTests
var xaml = await View.Load(markup);
var classInfo = classResolver.ResolveView(xaml);
Assert.NotNull(classInfo);
var nameResolver = new XamlXNameResolver();
var names = nameResolver.ResolveNames(classInfo.Xaml);
var generator = new InitializeComponentCodeGenerator(types, devToolsMode);
var generatorVersion = typeof(InitializeComponentCodeGenerator).Assembly.GetName().Version.ToString();
var generatorVersion = typeof(InitializeComponentCodeGenerator).Assembly.GetName().Version?.ToString();
var code = generator
.GenerateCode("SampleView", "Sample.App", classInfo.XamlType, names)

3
tests/Avalonia.Generators.Tests/OnlyProperties/OnlyPropertiesTests.cs

@ -37,11 +37,12 @@ public class OnlyPropertiesTests
var xaml = await View.Load(markup);
var classInfo = classResolver.ResolveView(xaml);
Assert.NotNull(classInfo);
var nameResolver = new XamlXNameResolver();
var names = nameResolver.ResolveNames(classInfo.Xaml);
var generator = new OnlyPropertiesCodeGenerator();
var generatorVersion = typeof(OnlyPropertiesCodeGenerator).Assembly.GetName().Version.ToString();
var generatorVersion = typeof(OnlyPropertiesCodeGenerator).Assembly.GetName().Version?.ToString();
var code = generator
.GenerateCode("SampleView", "Sample.App", classInfo.XamlType, names)

1
tests/Avalonia.Generators.Tests/XamlXClassResolverTests.cs

@ -34,6 +34,7 @@ public class XamlXClassResolverTests
MiniCompiler.CreateDefault(types, MiniCompiler.AvaloniaXmlnsDefinitionAttribute));
var resolvedClass = resolver.ResolveView(xaml);
Assert.NotNull(resolvedClass);
Assert.Equal(className, resolvedClass.ClassName);
Assert.Equal(nameSpace, resolvedClass.Namespace);
}

1
tests/Avalonia.Generators.Tests/XamlXNameResolverTests.cs

@ -135,6 +135,7 @@ public class XamlXNameResolverTests
MiniCompiler.AvaloniaXmlnsDefinitionAttribute));
var classInfo = classResolver.ResolveView(xaml);
Assert.NotNull(classInfo);
var nameResolver = new XamlXNameResolver();
return nameResolver.ResolveNames(classInfo.Xaml);
}

Loading…
Cancel
Save