Ver código fonte

Validation Project v2 (#471)

Original PR had issues in the CI when building.

> Refactor of the Validation System for more ease of use in the future.
The project now builds a standalone executable and executes it before
the main project is built or published.
Since it is now a standalone executable we are also able to use .NET
Core features as we are no longer locked to netstandard.

> The project currently includes 1 task, LocalesValidationTask, that
will check if the locales.json file has any of the following issues:
>   - The json is invalid.
>   - The json has locales with missing languages.
> - The json has locales with langauges that are just duplicates of the
en_US field.

> If the project is built or published locally it will also fix any
missing languages or duplicate fields.

---------

Co-authored-by: LotP1 <68976644+LotP1@users.noreply.github.com>
Evan Husted 1 ano atrás
pai
commit
d0a344d632

+ 2 - 3
Ryujinx.sln

@@ -249,13 +249,12 @@ Global
 		{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
-		{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU

+ 0 - 73
src/Ryujinx.BuildValidationTasks/LocaleValidationTask.cs

@@ -1,73 +0,0 @@
-using System;
-using Microsoft.Build.Utilities;
-using System.Collections.Generic;
-using System.Linq;
-using System.IO;
-using Newtonsoft.Json;
-using Microsoft.Build.Framework;
-
-namespace Ryujinx.BuildValidationTasks
-{
-    public class LocaleValidationTask : Task
-    {
-        public override bool Execute()
-        {
-            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
-
-            if (path.Split(["src"], StringSplitOptions.None).Length == 1)
-            {
-                //i assume that we are in a build directory in the solution dir
-                path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
-            }
-            else
-            {
-                path = path.Split(["src"], StringSplitOptions.None)[0];
-                path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
-            }
-
-            string data;
-
-            using (StreamReader sr = new(path))
-            {
-                data = sr.ReadToEnd();
-            }
-
-            LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
-
-            for (int i = 0; i < json.Locales.Count; i++)
-            {
-                LocalesEntry locale = json.Locales[i];
-
-                foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
-                {
-                    locale.Translations.Add(langCode, string.Empty);
-                    Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
-                }
-
-                locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
-                json.Locales[i] = locale;
-            }
-
-            string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
-
-            using (StreamWriter sw = new(path))
-            {
-                sw.Write(jsonString);
-            }
-
-            return true;
-        }
-
-        struct LocalesJson
-        {
-            public List<string> Languages { get; set; }
-            public List<LocalesEntry> Locales { get; set; }
-        }
-
-        struct LocalesEntry
-        {
-            public string ID { get; set; }
-            public Dictionary<string, string> Translations { get; set; }
-        }
-    }
-}

+ 117 - 0
src/Ryujinx.BuildValidationTasks/LocalesValidationTask.cs

@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+using System.Text.Json;
+using System.Text.Encodings.Web;
+
+namespace Ryujinx.BuildValidationTasks
+{
+    public class LocalesValidationTask : ValidationTask
+    {
+        public LocalesValidationTask() { }
+
+        public bool Execute(string projectPath, bool isGitRunner)
+        {
+            Console.WriteLine("Running Locale Validation Task...");
+
+            string path = projectPath + "src/Ryujinx/Assets/locales.json";
+            string data;
+
+            using (StreamReader sr = new(path))
+            {
+                data = sr.ReadToEnd();
+            }
+
+            LocalesJson json;
+
+            if (isGitRunner && data.Contains("\r\n"))
+                throw new FormatException("locales.json is using CRLF line endings! It should be using LF line endings, build locally to fix...");
+
+            try
+            {
+                json = JsonSerializer.Deserialize<LocalesJson>(data);
+
+            }
+            catch (JsonException e)
+            {
+                throw new JsonException(e.Message); //shorter and easier stacktrace
+            }
+
+
+
+            bool encounteredIssue = false;
+
+            for (int i = 0; i < json.Locales.Count; i++)
+            {
+                LocalesEntry locale = json.Locales[i];
+
+                foreach (string langCode in json.Languages.Where(lang => !locale.Translations.ContainsKey(lang)))
+                {
+                    encounteredIssue = true;
+
+                    if (!isGitRunner)
+                    {
+                        locale.Translations.Add(langCode, string.Empty);
+                        Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
+                    }
+                    else
+                    {
+                        Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
+                    }
+                }
+
+                foreach (string langCode in json.Languages.Where(lang => locale.Translations.ContainsKey(lang) && lang != "en_US" && locale.Translations[lang] == locale.Translations["en_US"]))
+                {
+                    encounteredIssue = true;
+
+                    if (!isGitRunner)
+                    {
+                        locale.Translations[langCode] = string.Empty;
+                        Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
+                    }
+                    else
+                    {
+                        Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
+                    }
+                }
+
+                locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
+                json.Locales[i] = locale;
+            }
+
+            if (isGitRunner && encounteredIssue)
+                throw new JsonException("1 or more locales are invalid!");
+
+            JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
+            {
+                WriteIndented = true,
+                NewLine = "\n",
+                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+            };
+
+            string jsonString = JsonSerializer.Serialize(json, jsonOptions);
+
+            using (StreamWriter sw = new(path))
+            {
+                sw.Write(jsonString);
+            }
+
+            Console.WriteLine("Finished Locale Validation Task!");
+
+            return true;
+        }
+
+        struct LocalesJson
+        {
+            public List<string> Languages { get; set; }
+            public List<LocalesEntry> Locales { get; set; }
+        }
+
+        struct LocalesEntry
+        {
+            public string ID { get; set; }
+            public Dictionary<string, string> Translations { get; set; }
+        }
+    }
+}

+ 37 - 0
src/Ryujinx.BuildValidationTasks/Program.cs

@@ -0,0 +1,37 @@
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Ryujinx.BuildValidationTasks
+{
+    public class Program
+    {
+        static void Main(string[] args)
+        {
+            // Display the number of command line arguments.
+            if (args.Length == 0)
+                throw new ArgumentException("Error: too few arguments!");
+
+            string path = args[0];
+
+            if (string.IsNullOrEmpty(path))
+                throw new ArgumentException("Error: path is null or empty!");
+
+            if (!Path.Exists(path))
+                throw new FileLoadException($"path {{{path}}} does not exist!");
+
+            path = Path.GetFullPath(path);
+
+            if (!Directory.GetDirectories(path).Contains($"{path}src"))
+                throw new FileLoadException($"path {{{path}}} is not a valid ryujinx project!");
+
+            bool isGitRunner = path.Contains("runner") || path.Contains("D:\\a\\Ryujinx\\Ryujinx");
+            if (isGitRunner)
+                Console.WriteLine("Is Git Runner!");
+
+            // Run tasks
+            // Pass extra info needed in the task constructors
+            new LocalesValidationTask().Execute(path, isGitRunner);
+        }
+    }
+}

+ 9 - 11
src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj

@@ -1,19 +1,17 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
+    <OutputType>Exe</OutputType>
   </PropertyGroup>
 
-  <ItemGroup>
-    <PackageReference Include="Microsoft.Build.Utilities.Core" />
-    <PackageReference Include="Newtonsoft.Json" />
-  </ItemGroup>
+  <Target Name="PostBuildTarget" AfterTargets="AfterBuild">
+    <Message Text="Running Validation Project" Importance="high" />
 
-  <UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
-
-  <Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
-    <LocaleValidationTask />
+    <Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
+      Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;" 
+      ConsoleToMsBuild="true"
+      Condition="'$(RuntimeIdentifier)' == ''"
+      />
   </Target>
 
-</Project>
+</Project>

+ 7 - 0
src/Ryujinx.BuildValidationTasks/ValidationTask.cs

@@ -0,0 +1,7 @@
+namespace Ryujinx.BuildValidationTasks
+{
+    public interface ValidationTask
+    {
+        public bool Execute(string projectPath, bool isGitRunner);
+    }
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 146 - 146
src/Ryujinx/Assets/locales.json


+ 4 - 3
src/Ryujinx/Ryujinx.csproj

@@ -13,9 +13,10 @@
     <DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
   </PropertyGroup>
 
-  <Target Name="BuildValidationProj" BeforeTargets="BeforeRebuild">
-    <MSBuild Projects="..\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj" Targets="Rebuild">
-    </MSBuild>
+  <Target Name="BuildValidationProj" BeforeTargets="BeforeBuild">
+    <Message Text="Building Validation Project for $(TargetFramework)" Importance="high" Condition="'$(RuntimeIdentifier)' == ''" />
+    <Exec WorkingDirectory="..\Ryujinx.BuildValidationTasks\" Command="dotnet build -c Debug /clp:NoSummary" />
+    
   </Target>
 
   <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff