From a18c97c0ada402798bd28c4625e3afdb43090d2e Mon Sep 17 00:00:00 2001 From: bcssov Date: Wed, 30 Oct 2024 23:17:00 +0100 Subject: [PATCH] Fix #528 --- .../Parsers/BaseParser.cs | 7 +- .../ParametrizedParserTests.cs | 106 ++++++++++++++++++ .../ParametrizedParser.cs | 37 +++++- .../ModPatchCollectionService.cs | 22 +++- .../Registrations/GameRegistration.cs | 6 +- 5 files changed, 166 insertions(+), 12 deletions(-) diff --git a/src/IronyModManager.Parser.Common/Parsers/BaseParser.cs b/src/IronyModManager.Parser.Common/Parsers/BaseParser.cs index 890279a8..244ddce9 100644 --- a/src/IronyModManager.Parser.Common/Parsers/BaseParser.cs +++ b/src/IronyModManager.Parser.Common/Parsers/BaseParser.cs @@ -4,7 +4,7 @@ // Created : 02-17-2020 // // Last Modified By : Mario -// Last Modified On : 10-29-2024 +// Last Modified On : 10-30-2024 // *********************************************************************** // // Mario @@ -476,6 +476,11 @@ protected virtual IEnumerable ParseSimpleTypes(IEnumerable p.Id.Equals("BIO_PROPULSION_5_BATTLESHIP")).Should().BeTrue(); } + /// + /// Defines the test method GetObjectId_on_first_level_should_yield_results_with_simple_inline. + /// + [Fact] + public void GetObjectId_on_first_level_should_yield_results_with_simple_inline() + { + DISetup.SetupContainer(); + + var sb = new System.Text.StringBuilder(328); + sb.AppendLine(@"# ship class placeholder"); + sb.AppendLine(@"entity = corvette_entity"); + sb.AppendLine(@"resources = { category = starbase_stations }"); + sb.AppendLine(@"potential_construction = { always = no }"); + sb.AppendLine(@"possible_construction = { always = no }"); + sb.AppendLine(@"is_designable = no"); + sb.AppendLine(@"enable_default_design = yes"); + sb.AppendLine(@"prerequisites = { }"); + sb.AppendLine(@"class = shipclass_starbase"); + sb.AppendLine(@"icon_frame = 1"); + sb.AppendLine(@"icon = ship_size_military_station"); + + var sb2 = new StringBuilder(77); + sb2.AppendLine(@"rs_heavy_dreadnought = {"); + sb2.AppendLine(@" inline_script = giga_placeholders/ship_sizes"); + sb2.AppendLine(@"}"); + + var parser = new ParametrizedParser(new CodeParser(new Logger())); + var result = parser.Process(sb.ToString(), sb2.ToString()); + result.Should().NotBeNullOrEmpty(); + var m = DIResolver.Get(); + var parserResult = m.Parse(new ParserManagerArgs { File = "common\\ship_sizes\\dummy.txt", GameType = "Stellaris", IsBinary = false, Lines = result.SplitOnNewLine() }); + parserResult.Count().Should().Be(1); + parserResult.Any(p => p.Id.Equals("rs_heavy_dreadnought")).Should().BeTrue(); + } + + /// + /// Defines the test method GetObjectId_should_yield_results_with_simple_inline. + /// + [Fact] + public void GetObjectId_should_yield_results_with_simple_inline() + { + DISetup.SetupContainer(); + + var sb = new System.Text.StringBuilder(); + sb.AppendLine(@"rs_heavy_dreadnought = {"); + sb.AppendLine(@"# ship class placeholder"); + sb.AppendLine(@"entity = corvette_entity"); + sb.AppendLine(@"resources = { category = starbase_stations }"); + sb.AppendLine(@"potential_construction = { always = no }"); + sb.AppendLine(@"possible_construction = { always = no }"); + sb.AppendLine(@"is_designable = no"); + sb.AppendLine(@"enable_default_design = yes"); + sb.AppendLine(@"prerequisites = { }"); + sb.AppendLine(@"class = shipclass_starbase"); + sb.AppendLine(@"icon_frame = 1"); + sb.AppendLine(@"icon = ship_size_military_station"); + sb.AppendLine(@"}"); + + + var sb2 = new StringBuilder(77); + sb2.AppendLine(@""); + sb2.AppendLine(@"inline_script = giga_placeholders/ship_sizes"); + sb2.AppendLine(@""); + + var parser = new ParametrizedParser(new CodeParser(new Logger())); + var result = parser.Process(sb.ToString(), sb2.ToString()); + result.Should().NotBeNullOrEmpty(); + var m = DIResolver.Get(); + var parserResult = m.Parse(new ParserManagerArgs { File = "common\\ship_sizes\\dummy.txt", GameType = "Stellaris", IsBinary = false, Lines = result.SplitOnNewLine() }); + parserResult.Count().Should().Be(1); + parserResult.Any(p => p.Id.Equals("rs_heavy_dreadnought")).Should().BeTrue(); + } + /// /// Defines the test method GetScriptPath_should_yield_results. @@ -1090,5 +1163,38 @@ public void GetScriptPath_as_sub_element_should_yield_results() var result = parser.GetScriptPath(sb.ToString()); result.Should().Be("grand_archive\\mutations\\core_components\\component_thrusters_bio"); } + + /// + /// Defines the test method GetScriptPath_as_sub_element_should_handle_simple_inline_scripts. + /// + [Fact] + public void GetScriptPath_as_sub_element_should_handle_simple_inline_scripts() + { + DISetup.SetupContainer(); + + var sb = new StringBuilder(77); + sb.AppendLine(@"rs_heavy_dreadnought = {"); + sb.AppendLine(@" inline_script = giga_placeholders/ship_sizes"); + sb.AppendLine(@"}"); + + var parser = new ParametrizedParser(new CodeParser(new Logger())); + var result = parser.GetScriptPath(sb.ToString()); + result.Should().Be("giga_placeholders\\ship_sizes"); + } + + [Fact] + public void GetScriptPath_as_should_handle_simple_inline_scripts() + { + DISetup.SetupContainer(); + + var sb = new StringBuilder(77); + sb.AppendLine(@""); + sb.AppendLine(@"inline_script = giga_placeholders/ship_sizes"); + sb.AppendLine(@""); + + var parser = new ParametrizedParser(new CodeParser(new Logger())); + var result = parser.GetScriptPath(sb.ToString()); + result.Should().Be("giga_placeholders\\ship_sizes"); + } } } diff --git a/src/IronyModManager.Parser/ParametrizedParser.cs b/src/IronyModManager.Parser/ParametrizedParser.cs index a8fcfb60..d92f59f8 100644 --- a/src/IronyModManager.Parser/ParametrizedParser.cs +++ b/src/IronyModManager.Parser/ParametrizedParser.cs @@ -78,6 +78,11 @@ public string GetScriptPath(string parameters) { if (elParams.Values.Count(p => p.Key.Equals(Common.Constants.Stellaris.InlineScriptId, StringComparison.OrdinalIgnoreCase)) == 1) { + var simpleResult = elParams.Values.FirstOrDefault(p => !string.IsNullOrWhiteSpace(p.Value)); + if (simpleResult != null) + { + return simpleResult.Value.StandardizeDirectorySeparator(); + } var elObj = elParams.Values.FirstOrDefault(p => p.Values != null); var match = elObj?.Values.FirstOrDefault(p => p.Key.Equals(Script, StringComparison.OrdinalIgnoreCase)); if (match != null) @@ -88,10 +93,18 @@ public string GetScriptPath(string parameters) else if (elParams.Values.Count() == 1 && elParams.Values.FirstOrDefault()!.Values.Count(p => p.Key.Equals(Common.Constants.Stellaris.InlineScriptId, StringComparison.OrdinalIgnoreCase)) == 1) { var elObj = elParams.Values.FirstOrDefault(p => p.Values != null)?.Values.FirstOrDefault(); - var match = elObj?.Values.FirstOrDefault(p => p.Key.Equals(Script, StringComparison.OrdinalIgnoreCase)); - if (match != null) + if (elObj != null) { - return (match.Value ?? string.Empty).Trim(Quotes).StandardizeDirectorySeparator(); + if (!string.IsNullOrWhiteSpace(elObj.Value)) + { + return elObj.Value.StandardizeDirectorySeparator(); + } + + var match = elObj.Values.FirstOrDefault(p => p.Key.Equals(Script, StringComparison.OrdinalIgnoreCase)); + if (match != null) + { + return (match.Value ?? string.Empty).Trim(Quotes).StandardizeDirectorySeparator(); + } } } } @@ -133,8 +146,8 @@ public string Process(string code, string parameters) else if (elParams.Values.Count() == 1 && elParams.Values.FirstOrDefault()!.Values.Count(p => p.Key.Equals(Common.Constants.Stellaris.InlineScriptId, StringComparison.OrdinalIgnoreCase)) == 1) { var processed = code; - var elObj = elParams.Values.FirstOrDefault(p => p.Values != null)?.Values.FirstOrDefault(); - if (elObj != null) + var elObj = elParams.Values.FirstOrDefault(p => p.Values != null)?.Values?.FirstOrDefault(); + if (elObj is { Values: not null }) { foreach (var value in elObj.Values) { @@ -159,6 +172,20 @@ public string Process(string code, string parameters) } } } + else if (!string.IsNullOrWhiteSpace(elObj?.Value)) + { + var replacementCode = codeParser.ParseScriptWithoutValidation(processed.SplitOnNewLine(), string.Empty); + if (replacementCode is { Values: not null, Error: null }) + { + var newCode = elParams.Values.FirstOrDefault(p => p.Values != null); + if (newCode != null) + { + newCode.Values = replacementCode.Values; + processed = codeParser.FormatCode(newCode); + return processed; + } + } + } } } diff --git a/src/IronyModManager.Services/ModPatchCollectionService.cs b/src/IronyModManager.Services/ModPatchCollectionService.cs index ffd0b38f..e1679b11 100644 --- a/src/IronyModManager.Services/ModPatchCollectionService.cs +++ b/src/IronyModManager.Services/ModPatchCollectionService.cs @@ -466,7 +466,7 @@ public virtual async Task FindConflictsAsync(IIndexedDefinition foreach (var item in allDefs) { var addDefault = true; - if (item.Id.Equals(Parser.Common.Constants.Stellaris.InlineScriptId, StringComparison.OrdinalIgnoreCase) || item.ContainsInlineIdentifier) + if ((item.Id.Equals(Parser.Common.Constants.Stellaris.InlineScriptId, StringComparison.OrdinalIgnoreCase) || item.ContainsInlineIdentifier) && item.File.StartsWith(provider.InlineScriptsPath)) { addDefault = false; var path = Path.Combine(Parser.Common.Constants.Stellaris.InlineScripts, parametrizedParser.GetScriptPath(item.Code)); @@ -568,6 +568,11 @@ public virtual async Task FindConflictsAsync(IIndexedDefinition prunedInlineDefinitions = null; GCRunner.RunGC(GCCollectionMode.Optimized, false); + // Redeclare stuff + fileKeys = await indexedDefinitions.GetAllFileKeysAsync(); + typeAndIdKeys = await indexedDefinitions.GetAllTypeAndIdKeysAsync(); + overwritten = (await indexedDefinitions.GetByValueTypeAsync(ValueType.OverwrittenObject)).Concat(await indexedDefinitions.GetByValueTypeAsync(ValueType.OverwrittenObjectSingleFile)); + empty = await indexedDefinitions.GetByValueTypeAsync(ValueType.EmptyFile); var stopWatch = new Stopwatch(); stopWatch.Start(); @@ -3074,6 +3079,16 @@ protected virtual IEnumerable ParseModFiles(IGame game, IEnumerable } } + var validationType = ValidationType.Full; + if (definitionInfoProvider.SupportsInlineScripts) + { + if (fileInfo.FileName != null && fileInfo.FileName.StartsWith(definitionInfoProvider.InlineScriptsPath)) + { + // Skip inline validation + validationType = ValidationType.SkipAll; + } + } + var fileDefs = parserManager.Parse(new ParserManagerArgs { ContentSHA = fileInfo.ContentSHA, @@ -3083,7 +3098,8 @@ protected virtual IEnumerable ParseModFiles(IGame game, IEnumerable ModDependencies = modObject.Dependencies, ModName = modObject.Name, FileLastModified = fileInfo.LastModified, - IsBinary = fileInfo.IsBinary + IsBinary = fileInfo.IsBinary, + ValidationType = validationType }); if (fileDefs.Any()) { @@ -3285,7 +3301,7 @@ async Task handleDefinition(IDefinition item) var others = parsed.Where(p => p.ValueType != ValueType.Variable && p.ValueType != ValueType.Namespace); foreach (var other in others) { - var variables = parsed.Where(p => p.ValueType == ValueType.Variable || p.ValueType == ValueType.Namespace); + var variables = parsed.Where(p => p.ValueType is ValueType.Variable or ValueType.Namespace); other.Variables = variables; var exportCopy = CopyDefinition(other); var allType = (await conflictResult.AllConflicts.GetByTypeAndIdAsync(definition!.TypeAndId)).ToList(); diff --git a/src/IronyModManager.Services/Registrations/GameRegistration.cs b/src/IronyModManager.Services/Registrations/GameRegistration.cs index c9ee4f32..2280bc25 100644 --- a/src/IronyModManager.Services/Registrations/GameRegistration.cs +++ b/src/IronyModManager.Services/Registrations/GameRegistration.cs @@ -4,7 +4,7 @@ // Created : 02-12-2020 // // Last Modified By : Mario -// Last Modified On : 10-29-2024 +// Last Modified On : 10-30-2024 // *********************************************************************** // // Mario @@ -39,12 +39,12 @@ public class GameRegistration : PostStartup /// /// The hoi4 cache version /// - private const int HOI4CacheVersion = 16; + private const int HOI4CacheVersion = 17; /// /// The stellaris cache version /// - private const int StellarisCacheVersion = 26; + private const int StellarisCacheVersion = 27; /// /// The path resolver