Browse Source
* remove uncompilable code guarded by platform defines * Remove OperatingSystemEx * remove NativeLibraryEx * remove unused classes * fix unused usingspull/20892/head
committed by
GitHub
97 changed files with 67 additions and 1022 deletions
@ -1,32 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Diagnostics.CodeAnalysis; |
|
||||
|
|
||||
namespace System; |
|
||||
|
|
||||
#if !NET6_0_OR_GREATER
|
|
||||
internal static class CollectionCompatibilityExtensions |
|
||||
{ |
|
||||
public static bool Remove<TKey, TValue>( |
|
||||
this Dictionary<TKey, TValue> o, |
|
||||
TKey key, |
|
||||
[MaybeNullWhen(false)] out TValue value) |
|
||||
where TKey : notnull |
|
||||
{ |
|
||||
if (o.TryGetValue(key, out value)) |
|
||||
return o.Remove(key); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> o, TKey key, TValue value) |
|
||||
where TKey : notnull |
|
||||
{ |
|
||||
if (!o.ContainsKey(key)) |
|
||||
{ |
|
||||
o.Add(key, value); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
#endif
|
|
||||
@ -1,122 +0,0 @@ |
|||||
using System; |
|
||||
using System.ComponentModel; |
|
||||
using System.Reflection; |
|
||||
using System.Runtime.InteropServices; |
|
||||
using Avalonia.Compatibility; |
|
||||
using Avalonia.Platform.Interop; |
|
||||
|
|
||||
namespace Avalonia.Compatibility |
|
||||
{ |
|
||||
internal class NativeLibraryEx |
|
||||
{ |
|
||||
#if NET6_0_OR_GREATER
|
|
||||
public static IntPtr Load(string dll, Assembly assembly) => NativeLibrary.Load(dll, assembly, null); |
|
||||
public static IntPtr Load(string dll) => NativeLibrary.Load(dll); |
|
||||
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) => |
|
||||
NativeLibrary.TryGetExport(handle, name, out address); |
|
||||
#else
|
|
||||
public static IntPtr Load(string dll, Assembly assembly) => Load(dll); |
|
||||
public static IntPtr Load(string dll) |
|
||||
{ |
|
||||
var handle = DlOpen!(dll); |
|
||||
if (handle != IntPtr.Zero) |
|
||||
return handle; |
|
||||
throw new InvalidOperationException("Unable to load " + dll, DlError!()); |
|
||||
} |
|
||||
|
|
||||
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
address = DlSym!(handle, name); |
|
||||
return address != default; |
|
||||
} |
|
||||
catch (Exception) |
|
||||
{ |
|
||||
address = default; |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
static NativeLibraryEx() |
|
||||
{ |
|
||||
if (OperatingSystemEx.IsWindows()) |
|
||||
{ |
|
||||
Win32Imports.Init(); |
|
||||
} |
|
||||
else if (OperatingSystemEx.IsLinux() || OperatingSystemEx.IsMacOS()) |
|
||||
{ |
|
||||
var buffer = Marshal.AllocHGlobal(0x1000); |
|
||||
uname(buffer); |
|
||||
var unixName = Marshal.PtrToStringAnsi(buffer); |
|
||||
Marshal.FreeHGlobal(buffer); |
|
||||
if (unixName == "Darwin") |
|
||||
OsXImports.Init(); |
|
||||
else |
|
||||
LinuxImports.Init(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private static Func<string, IntPtr>? DlOpen; |
|
||||
private static Func<IntPtr, string, IntPtr>? DlSym; |
|
||||
private static Func<Exception?>? DlError; |
|
||||
|
|
||||
[DllImport("libc")] |
|
||||
static extern int uname(IntPtr buf); |
|
||||
|
|
||||
static class Win32Imports |
|
||||
{ |
|
||||
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] |
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); |
|
||||
|
|
||||
[DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)] |
|
||||
private static extern IntPtr LoadLibrary(string lpszLib); |
|
||||
|
|
||||
public static void Init() |
|
||||
{ |
|
||||
DlOpen = LoadLibrary; |
|
||||
DlSym = GetProcAddress; |
|
||||
DlError = () => new Win32Exception(Marshal.GetLastWin32Error()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
static class LinuxImports |
|
||||
{ |
|
||||
[DllImport("libdl.so.2")] |
|
||||
private static extern IntPtr dlopen(string path, int flags); |
|
||||
|
|
||||
[DllImport("libdl.so.2")] |
|
||||
private static extern IntPtr dlsym(IntPtr handle, string symbol); |
|
||||
|
|
||||
[DllImport("libdl.so.2")] |
|
||||
private static extern IntPtr dlerror(); |
|
||||
|
|
||||
public static void Init() |
|
||||
{ |
|
||||
DlOpen = s => dlopen(s, 1); |
|
||||
DlSym = dlsym; |
|
||||
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror())); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
static class OsXImports |
|
||||
{ |
|
||||
[DllImport("/usr/lib/libSystem.dylib")] |
|
||||
private static extern IntPtr dlopen(string path, int flags); |
|
||||
|
|
||||
[DllImport("/usr/lib/libSystem.dylib")] |
|
||||
private static extern IntPtr dlsym(IntPtr handle, string symbol); |
|
||||
|
|
||||
[DllImport("/usr/lib/libSystem.dylib")] |
|
||||
private static extern IntPtr dlerror(); |
|
||||
|
|
||||
public static void Init() |
|
||||
{ |
|
||||
DlOpen = s => dlopen(s, 1); |
|
||||
DlSym = dlsym; |
|
||||
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror())); |
|
||||
} |
|
||||
} |
|
||||
#endif
|
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
using System; |
|
||||
using System.Runtime.InteropServices; |
|
||||
|
|
||||
namespace Avalonia.Compatibility |
|
||||
{ |
|
||||
internal sealed class OperatingSystemEx |
|
||||
{ |
|
||||
#if NET6_0_OR_GREATER
|
|
||||
public static bool IsWindows() => OperatingSystem.IsWindows(); |
|
||||
public static bool IsMacOS() => OperatingSystem.IsMacOS(); |
|
||||
public static bool IsMacCatalyst() => OperatingSystem.IsMacCatalyst(); |
|
||||
public static bool IsLinux() => OperatingSystem.IsLinux(); |
|
||||
public static bool IsFreeBSD() => OperatingSystem.IsFreeBSD(); |
|
||||
public static bool IsAndroid() => OperatingSystem.IsAndroid(); |
|
||||
public static bool IsIOS() => OperatingSystem.IsIOS(); |
|
||||
public static bool IsTvOS() => OperatingSystem.IsTvOS(); |
|
||||
public static bool IsBrowser() => OperatingSystem.IsBrowser(); |
|
||||
public static bool IsOSPlatform(string platform) => OperatingSystem.IsOSPlatform(platform); |
|
||||
#else
|
|
||||
public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); |
|
||||
public static bool IsMacOS() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); |
|
||||
public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); |
|
||||
public static bool IsFreeBSD() => false; |
|
||||
public static bool IsAndroid() => false; |
|
||||
public static bool IsIOS() => false; |
|
||||
public static bool IsMacCatalyst() => false; |
|
||||
public static bool IsTvOS() => false; |
|
||||
public static bool IsBrowser() => false; |
|
||||
public static bool IsOSPlatform(string platform) => RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform)); |
|
||||
#endif
|
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
#pragma warning disable MA0048 // File name must match type name
|
|
||||
// https://github.com/dotnet/runtime/blob/v8.0.4/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.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.
|
|
||||
|
|
||||
// ReSharper disable once CheckNamespace
|
|
||||
namespace System.Diagnostics.CodeAnalysis |
|
||||
{ |
|
||||
#if !NET7_0_OR_GREATER
|
|
||||
/// <summary>Specifies the syntax used in a string.</summary>
|
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] |
|
||||
internal sealed class StringSyntaxAttribute : Attribute |
|
||||
{ |
|
||||
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
|
|
||||
/// <param name="syntax">The syntax identifier.</param>
|
|
||||
public StringSyntaxAttribute(string syntax) |
|
||||
{ |
|
||||
Syntax = syntax; |
|
||||
Arguments = Array.Empty<object?>(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
|
|
||||
/// <param name="syntax">The syntax identifier.</param>
|
|
||||
/// <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
|
|
||||
public StringSyntaxAttribute(string syntax, params object?[] arguments) |
|
||||
{ |
|
||||
Syntax = syntax; |
|
||||
Arguments = arguments; |
|
||||
} |
|
||||
|
|
||||
/// <summary>Gets the identifier of the syntax used.</summary>
|
|
||||
public string Syntax { get; } |
|
||||
|
|
||||
/// <summary>Optional arguments associated with the specific syntax employed.</summary>
|
|
||||
public object?[] Arguments { get; } |
|
||||
|
|
||||
/// <summary>The syntax identifier for strings containing XML.</summary>
|
|
||||
public const string Xml = nameof(Xml); |
|
||||
} |
|
||||
#endif
|
|
||||
} |
|
||||
@ -1,156 +0,0 @@ |
|||||
#if NET6_0_OR_GREATER
|
|
||||
// In .NET Core, the security context and call context are not supported, however,
|
|
||||
// the impersonation context and culture would typically flow with the execution context.
|
|
||||
// See: https://learn.microsoft.com/en-us/dotnet/api/system.threading.executioncontext
|
|
||||
//
|
|
||||
// So we can safely use ExecutionContext without worrying about culture flowing issues.
|
|
||||
#else
|
|
||||
using System; |
|
||||
using System.Diagnostics; |
|
||||
using System.Diagnostics.CodeAnalysis; |
|
||||
using System.Globalization; |
|
||||
using System.Threading; |
|
||||
|
|
||||
namespace Avalonia.Threading; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// An ExecutionContext that preserves culture information across async operations.
|
|
||||
/// This is a modernized version that removes legacy compatibility switches and
|
|
||||
/// includes nullable reference type annotations.
|
|
||||
/// </summary>
|
|
||||
internal sealed class CulturePreservingExecutionContext |
|
||||
{ |
|
||||
private readonly ExecutionContext _context; |
|
||||
private CultureAndContext? _cultureAndContext; |
|
||||
|
|
||||
private CulturePreservingExecutionContext(ExecutionContext context) |
|
||||
{ |
|
||||
_context = context; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Captures the current ExecutionContext and culture information.
|
|
||||
/// </summary>
|
|
||||
/// <returns>A new CulturePreservingExecutionContext instance, or null if no context needs to be captured.</returns>
|
|
||||
public static CulturePreservingExecutionContext? Capture() |
|
||||
{ |
|
||||
// ExecutionContext.SuppressFlow had been called.
|
|
||||
// We expect ExecutionContext.Capture() to return null, so match that behavior and return null.
|
|
||||
if (ExecutionContext.IsFlowSuppressed()) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
var context = ExecutionContext.Capture(); |
|
||||
if (context == null) |
|
||||
return null; |
|
||||
|
|
||||
return new CulturePreservingExecutionContext(context); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Runs the specified callback in the captured execution context while preserving culture information.
|
|
||||
/// This method is used for .NET Framework and earlier .NET versions.
|
|
||||
/// </summary>
|
|
||||
/// <param name="executionContext">The execution context to run in.</param>
|
|
||||
/// <param name="callback">The callback to execute.</param>
|
|
||||
/// <param name="state">The state to pass to the callback.</param>
|
|
||||
public static void Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, object? state) |
|
||||
{ |
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
|
||||
if (callback == null) |
|
||||
return; |
|
||||
|
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
|
||||
if (executionContext == null) |
|
||||
ThrowNullContext(); |
|
||||
|
|
||||
// Save culture information - we will need this to restore just before
|
|
||||
// the callback is actually invoked from CallbackWrapper.
|
|
||||
executionContext._cultureAndContext = CultureAndContext.Initialize(callback, state); |
|
||||
|
|
||||
try |
|
||||
{ |
|
||||
ExecutionContext.Run( |
|
||||
executionContext._context, |
|
||||
s_callbackWrapperDelegate, |
|
||||
executionContext._cultureAndContext); |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
// Restore culture information - it might have been modified during callback execution.
|
|
||||
executionContext._cultureAndContext.RestoreCultureInfos(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[DoesNotReturn] |
|
||||
private static void ThrowNullContext() |
|
||||
{ |
|
||||
throw new InvalidOperationException("ExecutionContext cannot be null."); |
|
||||
} |
|
||||
|
|
||||
private static readonly ContextCallback s_callbackWrapperDelegate = CallbackWrapper; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Executes the callback and saves culture values immediately afterwards.
|
|
||||
/// </summary>
|
|
||||
/// <param name="obj">Contains the actual callback and state.</param>
|
|
||||
private static void CallbackWrapper(object? obj) |
|
||||
{ |
|
||||
var cultureAndContext = (CultureAndContext)obj!; |
|
||||
|
|
||||
// Restore culture information saved during Run()
|
|
||||
cultureAndContext.RestoreCultureInfos(); |
|
||||
|
|
||||
try |
|
||||
{ |
|
||||
// Execute the actual callback
|
|
||||
cultureAndContext.Callback(cultureAndContext.State); |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
// Save any culture changes that might have occurred during callback execution
|
|
||||
cultureAndContext.CaptureCultureInfos(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Helper class to manage culture information across execution contexts.
|
|
||||
/// </summary>
|
|
||||
private sealed class CultureAndContext |
|
||||
{ |
|
||||
public ContextCallback Callback { get; } |
|
||||
public object? State { get; } |
|
||||
|
|
||||
private CultureInfo? _culture; |
|
||||
private CultureInfo? _uiCulture; |
|
||||
|
|
||||
private CultureAndContext(ContextCallback callback, object? state) |
|
||||
{ |
|
||||
Callback = callback; |
|
||||
State = state; |
|
||||
CaptureCultureInfos(); |
|
||||
} |
|
||||
|
|
||||
public static CultureAndContext Initialize(ContextCallback callback, object? state) |
|
||||
{ |
|
||||
return new CultureAndContext(callback, state); |
|
||||
} |
|
||||
|
|
||||
public void CaptureCultureInfos() |
|
||||
{ |
|
||||
_culture = Thread.CurrentThread.CurrentCulture; |
|
||||
_uiCulture = Thread.CurrentThread.CurrentUICulture; |
|
||||
} |
|
||||
|
|
||||
public void RestoreCultureInfos() |
|
||||
{ |
|
||||
if (_culture != null) |
|
||||
Thread.CurrentThread.CurrentCulture = _culture; |
|
||||
|
|
||||
if (_uiCulture != null) |
|
||||
Thread.CurrentThread.CurrentUICulture = _uiCulture; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
#endif
|
|
||||
@ -1,34 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Avalonia.Utilities |
|
||||
{ |
|
||||
internal class EnumHelper |
|
||||
{ |
|
||||
#if NET6_0_OR_GREATER
|
|
||||
public static T Parse<T>(ReadOnlySpan<char> key, bool ignoreCase) where T : struct |
|
||||
{ |
|
||||
return Enum.Parse<T>(key, ignoreCase); |
|
||||
} |
|
||||
|
|
||||
public static bool TryParse<T>(ReadOnlySpan<char> key, bool ignoreCase, out T result) where T : struct |
|
||||
{ |
|
||||
return Enum.TryParse(key, ignoreCase, out result); |
|
||||
} |
|
||||
#else
|
|
||||
public static T Parse<T>(string key, bool ignoreCase) where T : struct |
|
||||
{ |
|
||||
return (T)Enum.Parse(typeof(T), key, ignoreCase); |
|
||||
} |
|
||||
|
|
||||
public static bool TryParse<T>(string key, bool ignoreCase, out T result) where T : struct |
|
||||
{ |
|
||||
return Enum.TryParse(key, ignoreCase, out result); |
|
||||
} |
|
||||
|
|
||||
public static bool TryParse<T>(ReadOnlySpan<char> key, bool ignoreCase, out T result) where T : struct |
|
||||
{ |
|
||||
return Enum.TryParse(key.ToString(), ignoreCase, out result); |
|
||||
} |
|
||||
#endif
|
|
||||
} |
|
||||
} |
|
||||
@ -1,43 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.Diagnostics.CodeAnalysis; |
|
||||
|
|
||||
internal static class Polyfills |
|
||||
{ |
|
||||
#if !NET6_0_OR_GREATER
|
|
||||
|
|
||||
public static bool TryDequeue<T>(this Queue<T> queue, [MaybeNullWhen(false)]out T item) |
|
||||
{ |
|
||||
if (queue.Count == 0) |
|
||||
{ |
|
||||
item = default; |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
item = queue.Dequeue(); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
#if !NET7_0_OR_GREATER
|
|
||||
|
|
||||
namespace System.Diagnostics.CodeAnalysis |
|
||||
{ |
|
||||
[System.AttributeUsage( |
|
||||
System.AttributeTargets.Method | System.AttributeTargets.Parameter | System.AttributeTargets.Property, |
|
||||
AllowMultiple = false, Inherited = false)] |
|
||||
internal sealed class UnscopedRefAttribute : Attribute |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
struct S |
|
||||
{ |
|
||||
int _field; |
|
||||
|
|
||||
// Okay: `field` has the ref-safe-to-escape of `this` which is *calling method* because
|
|
||||
// it is a `ref`
|
|
||||
[UnscopedRef] ref int Prop1 => ref _field; |
|
||||
} |
|
||||
} |
|
||||
#endif
|
|
||||
Loading…
Reference in new issue