Upgrade to .NET 10, update packages, enable AOT and cleanup code

This commit is contained in:
Stone_Red
2026-03-05 18:00:34 +01:00
parent 1080873deb
commit 8ef621e61b
17 changed files with 146 additions and 71 deletions
+4 -2
View File
@@ -2,8 +2,10 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<PublishAot>True</PublishAot>
<AssemblyName>yesntcode</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -11,7 +13,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -1,9 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<PublishAot>True</PublishAot>
<AssemblyName>yesnt</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -8,19 +8,20 @@ using System.Text;
namespace YesNt.Interpreter.Generator; namespace YesNt.Interpreter.Generator;
[Generator] [Generator]
public sealed class StatementRegistryGenerator : ISourceGenerator public sealed class StatementRegistryGenerator : IIncrementalGenerator
{ {
private const string StatementAttributeName = "YesNt.Interpreter.Attributes.StatementAttribute"; private const string StatementAttributeName = "YesNt.Interpreter.Attributes.StatementAttribute";
private const string StaticStatementAttributeName = "YesNt.Interpreter.Attributes.StaticStatementAttribute"; private const string StaticStatementAttributeName = "YesNt.Interpreter.Attributes.StaticStatementAttribute";
public void Initialize(GeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
context.RegisterSourceOutput(
context.CompilationProvider,
Execute);
} }
public void Execute(GeneratorExecutionContext context) private static void Execute(SourceProductionContext context, Compilation compilation)
{ {
Compilation compilation = context.Compilation;
List<MethodRegistration> statementMethods = []; List<MethodRegistration> statementMethods = [];
List<MethodRegistration> staticStatementMethods = []; List<MethodRegistration> staticStatementMethods = [];
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsRoslynComponent>true</IsRoslynComponent> <IsRoslynComponent>true</IsRoslynComponent>
@@ -8,6 +8,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+9 -10
View File
@@ -4,7 +4,6 @@ using System.Collections.Generic;
using YesNt.Interpreter.Attributes; using YesNt.Interpreter.Attributes;
using YesNt.Interpreter.Enums; using YesNt.Interpreter.Enums;
using YesNt.Interpreter.Runtime;
namespace YesNt.Interpreter.Tests; namespace YesNt.Interpreter.Tests;
@@ -21,7 +20,7 @@ public class AddStatementTests
string? capturedArgs = null; string? capturedArgs = null;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement("my_command", SearchMode.StartOfLine, SpaceAround.End, args => interpreter.AddStatement("my_command", SearchMode.StartOfLine, SpaceAround.End, args =>
{ {
@@ -42,7 +41,7 @@ public class AddStatementTests
bool handlerCalled = false; bool handlerCalled = false;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement("custom_cmd", SearchMode.StartOfLine, SpaceAround.End, _ => interpreter.AddStatement("custom_cmd", SearchMode.StartOfLine, SpaceAround.End, _ =>
{ {
@@ -63,9 +62,9 @@ public class AddStatementTests
bool handlerCalled = false; bool handlerCalled = false;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
var attr = new StatementAttribute("attr_cmd", SearchMode.StartOfLine, SpaceAround.End); StatementAttribute attr = new StatementAttribute("attr_cmd", SearchMode.StartOfLine, SpaceAround.End);
interpreter.AddStatement(attr, _ => interpreter.AddStatement(attr, _ =>
{ {
handlerCalled = true; handlerCalled = true;
@@ -85,7 +84,7 @@ public class AddStatementTests
bool handlerCalled = false; bool handlerCalled = false;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement("exact_cmd", SearchMode.Exact, SpaceAround.None, _ => interpreter.AddStatement("exact_cmd", SearchMode.Exact, SpaceAround.None, _ =>
{ {
@@ -106,7 +105,7 @@ public class AddStatementTests
bool handlerCalled = false; bool handlerCalled = false;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement(" ~mark~ ", SearchMode.Contains, SpaceAround.None, _ => interpreter.AddStatement(" ~mark~ ", SearchMode.Contains, SpaceAround.None, _ =>
{ {
@@ -127,7 +126,7 @@ public class AddStatementTests
bool handlerCalled = false; bool handlerCalled = false;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement(" !end", SearchMode.EndOfLine, SpaceAround.None, _ => interpreter.AddStatement(" !end", SearchMode.EndOfLine, SpaceAround.None, _ =>
{ {
@@ -148,7 +147,7 @@ public class AddStatementTests
string? capturedArgs = null; string? capturedArgs = null;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement("capture_cmd", SearchMode.StartOfLine, SpaceAround.End, args => interpreter.AddStatement("capture_cmd", SearchMode.StartOfLine, SpaceAround.End, args =>
{ {
@@ -279,7 +278,7 @@ public class AddStatementTests
int highPriorityOrder = -1; int highPriorityOrder = -1;
int normalPriorityOrder = -1; int normalPriorityOrder = -1;
YesNtAssert.GetLastLineWithSetup(lines, interpreter => _ = YesNtAssert.GetLastLineWithSetup(lines, interpreter =>
{ {
interpreter.AddStatement( interpreter.AddStatement(
new StatementAttribute("priority_cmd", SearchMode.StartOfLine, SpaceAround.End) { Priority = Priority.High }, new StatementAttribute("priority_cmd", SearchMode.StartOfLine, SpaceAround.End) { Priority = Priority.High },
-1
View File
@@ -217,7 +217,6 @@ public class CodeFlowTests
YesNtAssert.IsLastLineEqual(lines, "yes"); YesNtAssert.IsLastLineEqual(lines, "yes");
} }
[TestMethod] [TestMethod]
public void LabelWithoutColonFailsTest() public void LabelWithoutColonFailsTest()
{ {
@@ -46,7 +46,7 @@ public class ConsoleStatementsTests
"clear" "clear"
]; ];
_ = Assert.ThrowsException<IOException>(() => YesNtAssert.GetLastLine(lines)); _ = Assert.Throws<IOException>(() => YesNtAssert.GetLastLine(lines));
} }
[TestMethod] [TestMethod]
@@ -80,7 +80,7 @@ public class ConsoleStatementsTests
{ {
YesNtInterpreter interpreter = new YesNtInterpreter(); YesNtInterpreter interpreter = new YesNtInterpreter();
AutoResetEvent onDone= new AutoResetEvent(false); AutoResetEvent onDone = new AutoResetEvent(false);
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
interpreter.OnDebugOutput += (s) => _ = output.Append(s); interpreter.OnDebugOutput += (s) => _ = output.Append(s);
@@ -150,7 +150,6 @@ public class FunctionStatementsTests
YesNtAssert.IsLastLineEqual(lines, "outer"); YesNtAssert.IsLastLineEqual(lines, "outer");
} }
[TestMethod] [TestMethod]
public void ClearCallStackRunsTest() public void ClearCallStackRunsTest()
{ {
@@ -88,7 +88,6 @@ public class ProcessingStatementsTests
YesNtAssert.IsLastLineEqual(lines, "ok"); YesNtAssert.IsLastLineEqual(lines, "ok");
} }
[TestMethod] [TestMethod]
public void SleepInvalidValueFailsTest() public void SleepInvalidValueFailsTest()
{ {
@@ -118,7 +118,6 @@ public class VariableStatementsTests
YesNtAssert.IsLastLineEqual(lines, "0"); YesNtAssert.IsLastLineEqual(lines, "0");
} }
[TestMethod] [TestMethod]
public void MissingVariableReferenceFailsTest() public void MissingVariableReferenceFailsTest()
{ {
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
@@ -10,10 +10,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" /> <PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" /> <PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" /> <PackageReference Include="coverlet.collector" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+54 -11
View File
@@ -26,15 +26,58 @@ internal static class ExitMessages
internal const string NoInArgumentInStack = "No in argument in stack"; internal const string NoInArgumentInStack = "No in argument in stack";
internal const string NoFunctionInStack = "No function in stack"; internal const string NoFunctionInStack = "No function in stack";
internal static string LabelNotFound(string label) => $"Label \"{label}\" not found"; internal static string LabelNotFound(string label)
internal static string FunctionNotFound(string function) => $"Function \"{function}\" not found"; {
internal static string VariableNotFound(string variable) => $"Variable \"{variable}\" not found"; return $"Label \"{label}\" not found";
internal static string ListNotFound(string list) => $"List \"{list}\" not found"; }
internal static string InvalidIndex(string rawIndex) => $"\"{rawIndex}\" is not a valid index";
internal static string IndexOutOfRange(int index) => $"Index {index} out of range"; internal static string FunctionNotFound(string function)
internal static string InvalidTimeoutValue(string value) => $"\"{value}\" is not a valid time-out value"; {
internal static string CouldNotLoadFile(string path) => $"Could not load file \"{path}\""; return $"Function \"{function}\" not found";
internal static string CouldNotFindFile(string path) => $"Could not find file \"{path}\""; }
internal static string CannotFindFile(string path) => $"Cannot find file \"{path}\".";
internal static string FailedToStart(string program, string message) => $"Failed to start \"{program}\". {message}"; internal static string VariableNotFound(string variable)
{
return $"Variable \"{variable}\" not found";
}
internal static string ListNotFound(string list)
{
return $"List \"{list}\" not found";
}
internal static string InvalidIndex(string rawIndex)
{
return $"\"{rawIndex}\" is not a valid index";
}
internal static string IndexOutOfRange(int index)
{
return $"Index {index} out of range";
}
internal static string InvalidTimeoutValue(string value)
{
return $"\"{value}\" is not a valid time-out value";
}
internal static string CouldNotLoadFile(string path)
{
return $"Could not load file \"{path}\"";
}
internal static string CouldNotFindFile(string path)
{
return $"Could not find file \"{path}\"";
}
internal static string CannotFindFile(string path)
{
return $"Cannot find file \"{path}\".";
}
internal static string FailedToStart(string program, string message)
{
return $"Failed to start \"{program}\". {message}";
}
} }
+13 -20
View File
@@ -23,9 +23,7 @@ internal sealed class RuntimeInformation
private static int internalTaskId = 0; private static int internalTaskId = 0;
private readonly Dictionary<string, string> topVariables = []; private readonly Dictionary<string, string> topVariables = [];
private readonly Dictionary<string, List<string>> topLists = []; private readonly Dictionary<string, List<string>> topLists = [];
private readonly Dictionary<string, int> topLabels = [];
private RuntimeInformation parentRuntimeInformation;
private int taskId = 0;
public Dictionary<string, string> GlobalVariables { get; set; } = []; public Dictionary<string, string> GlobalVariables { get; set; } = [];
public Dictionary<string, int> Functions { get; } = []; public Dictionary<string, int> Functions { get; } = [];
public Stack<FunctionScope> FunctionCallStack { get; } = new(); public Stack<FunctionScope> FunctionCallStack { get; } = new();
@@ -41,7 +39,7 @@ internal sealed class RuntimeInformation
public bool IsDebugMode { get; set; } = false; public bool IsDebugMode { get; set; } = false;
public string WorkingDirectory { get; set; } = string.Empty; public string WorkingDirectory { get; set; } = string.Empty;
public bool IsTask => ParentRuntimeInformation is not null; public bool IsTask => ParentRuntimeInformation is not null;
public int TaskId => IsTask ? taskId : 0; public int TaskId { get => IsTask ? field : 0; private set; } = 0;
public bool InternalIsInFunction { get; set; } public bool InternalIsInFunction { get; set; }
public bool IsInFunction public bool IsInFunction
@@ -53,18 +51,15 @@ internal sealed class RuntimeInformation
public Dictionary<string, string> Variables => FunctionCallStack.Count == 0 ? topVariables : FunctionCallStack.Peek().Variables; public Dictionary<string, string> Variables => FunctionCallStack.Count == 0 ? topVariables : FunctionCallStack.Peek().Variables;
public Dictionary<string, List<string>> Lists => FunctionCallStack.Count == 0 ? topLists : FunctionCallStack.Peek().Lists; public Dictionary<string, List<string>> Lists => FunctionCallStack.Count == 0 ? topLists : FunctionCallStack.Peek().Lists;
public Dictionary<string, int> Labels => FunctionCallStack.Count == 0 ? topLabels : FunctionCallStack.Peek().Labels; public Dictionary<string, int> Labels { get => FunctionCallStack.Count == 0 ? field : FunctionCallStack.Peek().Labels; } = [];
public RuntimeInformation ParentRuntimeInformation public RuntimeInformation ParentRuntimeInformation
{ {
get => parentRuntimeInformation; get;
set set
{ {
parentRuntimeInformation = value; field = value;
if (parentRuntimeInformation is not null) field?.OnExit += ParentRuntimeInformation_OnExit;
{
parentRuntimeInformation.OnExit += ParentRuntimeInformation_OnExit;
}
} }
} }
@@ -73,7 +68,7 @@ internal sealed class RuntimeInformation
public void WriteLine(string output, bool forceWrite = false) public void WriteLine(string output, bool forceWrite = false)
{ {
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite)) if ((Stop && !forceWrite) || (ParentRuntimeInformation?.StopAllTasks == true && !forceWrite))
{ {
return; return;
} }
@@ -82,7 +77,7 @@ internal sealed class RuntimeInformation
{ {
if (IsTask) if (IsTask)
{ {
parentRuntimeInformation!.WriteLine(output.FromSafeString(), forceWrite); ParentRuntimeInformation!.WriteLine(output.FromSafeString(), forceWrite);
} }
else else
{ {
@@ -97,7 +92,7 @@ internal sealed class RuntimeInformation
public void Write(string output, bool forceWrite = false) public void Write(string output, bool forceWrite = false)
{ {
if ((Stop && !forceWrite) || (parentRuntimeInformation?.StopAllTasks == true && !forceWrite)) if ((Stop && !forceWrite) || (ParentRuntimeInformation?.StopAllTasks == true && !forceWrite))
{ {
return; return;
} }
@@ -106,7 +101,7 @@ internal sealed class RuntimeInformation
{ {
if (IsTask) if (IsTask)
{ {
parentRuntimeInformation!.Write(output.FromSafeString(), forceWrite); ParentRuntimeInformation!.Write(output.FromSafeString(), forceWrite);
} }
else else
{ {
@@ -154,7 +149,7 @@ internal sealed class RuntimeInformation
{ {
StopAllTasks = true; StopAllTasks = true;
OnExit?.Invoke(message, StopAllTasks); OnExit?.Invoke(message, StopAllTasks);
parentRuntimeInformation?.Exit(ExitMessages.TerminatedByChildTask, true); ParentRuntimeInformation?.Exit(ExitMessages.TerminatedByChildTask, true);
} }
} }
@@ -162,7 +157,7 @@ internal sealed class RuntimeInformation
{ {
if (IsTask) if (IsTask)
{ {
parentRuntimeInformation.LineExecuted(debugEventArgs); ParentRuntimeInformation.LineExecuted(debugEventArgs);
} }
else else
{ {
@@ -192,10 +187,8 @@ internal sealed class RuntimeInformation
IsInFunction = false; IsInFunction = false;
IsLocalSearch = false; IsLocalSearch = false;
LineNumber = 0; LineNumber = 0;
taskId = internalTaskId + 1; TaskId = internalTaskId + 1;
#pragma warning disable S2696 // Instance members should not write to "static" fields
internalTaskId++; internalTaskId++;
#pragma warning restore S2696 // Instance members should not write to "static" fields
} }
private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopAllTasks) private void ParentRuntimeInformation_OnExit(string exitMessage, bool stopAllTasks)
@@ -44,7 +44,7 @@ public class YesNtInterpreter
private readonly RuntimeInformation runtimeInfo = new RuntimeInformation(); private readonly RuntimeInformation runtimeInfo = new RuntimeInformation();
private Dictionary<StatementAttribute, Action<string>> statements; private Dictionary<StatementAttribute, Action<string>> statements;
private readonly List<KeyValuePair<StaticStatementAttribute, Action>> staticStatements; private readonly List<KeyValuePair<StaticStatementAttribute, Action>> staticStatements;
private readonly Dictionary<string, List<KeyValuePair<StatementAttribute, Action<string>>>> disabledStatements = new(); private readonly Dictionary<string, List<KeyValuePair<StatementAttribute, Action<string>>>> disabledStatements = [];
/// <summary> /// <summary>
/// Gets a read-only snapshot of all currently registered statements. /// Gets a read-only snapshot of all currently registered statements.
@@ -138,10 +138,10 @@ public class YesNtInterpreter
{ {
foreach (StatementAttribute key in statements.Keys.Where(k => k.Name == name).ToList()) foreach (StatementAttribute key in statements.Keys.Where(k => k.Name == name).ToList())
{ {
statements.Remove(key); _ = statements.Remove(key);
} }
disabledStatements.Remove(name); _ = disabledStatements.Remove(name);
} }
/// <summary> /// <summary>
@@ -191,7 +191,7 @@ public class YesNtInterpreter
statements[kv.Key] = kv.Value; statements[kv.Key] = kv.Value;
} }
disabledStatements.Remove(name); _ = disabledStatements.Remove(name);
} }
/// <summary> /// <summary>
+40 -4
View File
@@ -1,18 +1,54 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>YesNt.Interpreter</RootNamespace> <RootNamespace>YesNt.Interpreter</RootNamespace>
<ApplicationIcon /> <ApplicationIcon />
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<StartupObject /> <StartupObject />
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/Stone-Red-Code/YesNt-Interpreter/</RepositoryUrl>
<PackageTags>scripting, modding, language</PackageTags>
<PackageIcon>Logo.png</PackageIcon>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IsAotCompatible>True</IsAotCompatible>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\YesNt.Interpreter.Generator\YesNt.Interpreter.Generator.csproj" <None Include="..\assets\Logo.png">
OutputItemType="Analyzer" <Pack>True</Pack>
ReferenceOutputAssembly="false" /> <PackagePath>\</PackagePath>
</None>
<None Include="..\LICENSE">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\YesNt.Interpreter.Generator\YesNt.Interpreter.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup> </ItemGroup>
</Project> </Project>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB