From 259bd888ca37f4be6e137c2a7e1f3b921918faf5 Mon Sep 17 00:00:00 2001 From: Andy Black Date: Mon, 31 Aug 2026 09:30:35 -0700 Subject: [PATCH 1/2] Attempt at fixing LT-22708 Change-Id: I24735bad6cd9e8823a0a028151afdc64722d5a8e --- Src/FwParatextLexiconPlugin/FdoLexicon.cs | 38 +++++++++++------- .../ParserCoreTests/ParseWorkerTests.cs | 13 +++++-- Src/LexText/ParserCore/ParserWorker.cs | 2 +- Src/LexText/ParserCore/XAmpleParser.cs | 22 +++++++---- .../ParserCore/XAmplePropertiesPreparer.cs | 39 ++++++++++++------- .../ToneParsFLExDll/ToneParsFLExForm.cs | 3 +- 6 files changed, 78 insertions(+), 39 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/FdoLexicon.cs b/Src/FwParatextLexiconPlugin/FdoLexicon.cs index c46ec16b91..e1f2ad54ee 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexicon.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexicon.cs @@ -2,27 +2,28 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text; -using System.Web; using Paratext.LexicalContracts; -using SIL.LCModel.Core.Text; -using SIL.LCModel.Core.KernelInterfaces; +using SIL.FieldWorks.WordWorks.Parser; using SIL.LCModel; +using SIL.LCModel.Core.KernelInterfaces; +using SIL.LCModel.Core.Text; using SIL.LCModel.DomainImpl; using SIL.LCModel.DomainServices; using SIL.LCModel.Infrastructure; using SIL.LCModel.Utils; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Machine.Morphology; using SIL.ObjectModel; using SIL.PlatformUtilities; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Web; +using XCore; using WordAnalysis = Paratext.LexicalContracts.WordAnalysis; namespace SIL.FieldWorks.ParatextLexiconPlugin @@ -39,7 +40,8 @@ internal class FdoLexicon : DisposableBase, Paratext.LexicalContracts.Lexicon, W private readonly int m_defaultVernWs; private PoorMansStemmer m_stemmer; private readonly string m_projectId; - + Mediator Mediator { get; set; } + PropertyTable PropertyTable { get; set; } internal FdoLexicon(string scrTextName, string projectId, LcmCache cache, int defaultVernWs) { m_scrTextName = scrTextName; @@ -79,6 +81,10 @@ protected override void DisposeManagedResources() { m_parser.Dispose(); m_parser = null; + Mediator.Dispose(); + Mediator = null; + PropertyTable.Dispose(); + PropertyTable = null; } } @@ -646,7 +652,11 @@ private void InstantiateParser() switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) { case "XAmple": - m_parser = new XAmpleParser(m_cache, parserDataDir); + // LT-22708 As of 2026.08.26, this is only called within FLEx from FdoLexiconTests. + // Creating the mediator and property table here works fine. + Mediator = new Mediator(); + PropertyTable = new PropertyTable(Mediator); + m_parser = new XAmpleParser(m_cache, parserDataDir, PropertyTable); break; case "HC": m_parser = new HCParser(m_cache); diff --git a/Src/LexText/ParserCore/ParserCoreTests/ParseWorkerTests.cs b/Src/LexText/ParserCore/ParserCoreTests/ParseWorkerTests.cs index a62cfb9e1a..99879e64cb 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/ParseWorkerTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/ParseWorkerTests.cs @@ -24,6 +24,8 @@ public class ParseWorkerTests : MemoryOnlyBackendProviderTestBase private String m_taskDetailsString; private IdleQueue m_idleQueue; private CoreWritingSystemDefinition m_vernacularWS; + Mediator Mediator { get; set; } + PropertyTable PropertyTable { get; set; } #endregion Data Members #region Non-test methods @@ -67,6 +69,8 @@ public override void FixtureSetup() base.FixtureSetup(); m_vernacularWS = Cache.ServiceLocator.WritingSystems.DefaultVernacularWritingSystem; m_idleQueue = new IdleQueue {IsPaused = true}; + Mediator = new Mediator(); + PropertyTable = new PropertyTable(Mediator); } public override void FixtureTeardown() @@ -74,7 +78,10 @@ public override void FixtureTeardown() m_vernacularWS = null; m_idleQueue.Dispose(); m_idleQueue = null; - + Mediator.Dispose(); + Mediator = null; + PropertyTable.Dispose(); + PropertyTable = null; base.FixtureTeardown(); } @@ -106,7 +113,7 @@ protected void UndoAll() public void TryAWord() { XDocument lowerXDoc = new XDocument(new XComment("cats")); - var parserWorker = new ParserWorker(Cache, null, HandleTaskUpdate, m_idleQueue, null); + var parserWorker = new ParserWorker(Cache, PropertyTable, HandleTaskUpdate, m_idleQueue, null); parserWorker.Parser = new TestParserClass(null, lowerXDoc); // SUT @@ -141,7 +148,7 @@ public void UpdateWordform() }); }); - var parserWorker = new ParserWorker(Cache, null, HandleTaskUpdate, m_idleQueue, null); + var parserWorker = new ParserWorker(Cache, PropertyTable, HandleTaskUpdate, m_idleQueue, null); parserWorker.Parser = new TestParserClass(lowerResult, null); // SUT diff --git a/Src/LexText/ParserCore/ParserWorker.cs b/Src/LexText/ParserCore/ParserWorker.cs index 58f494f7bd..dd8260963f 100644 --- a/Src/LexText/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserCore/ParserWorker.cs @@ -63,7 +63,7 @@ public ParserWorker(LcmCache cache, PropertyTable propertyTable, Action().GetObject(CmAgentTags.kguidAgentXAmpleParser); break; case "HC": diff --git a/Src/LexText/ParserCore/XAmpleParser.cs b/Src/LexText/ParserCore/XAmpleParser.cs index 98c03aad17..39fec0d36e 100644 --- a/Src/LexText/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserCore/XAmpleParser.cs @@ -2,6 +2,12 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +using SIL.FieldWorks.Common.FwUtils; +using SIL.LCModel; +using SIL.LCModel.DomainServices; +using SIL.LCModel.Infrastructure; +using SIL.ObjectModel; +using SIL.Xml; using System; using System.Collections.Generic; using System.Diagnostics; @@ -11,12 +17,8 @@ using System.Text; using System.Xml; using System.Xml.Linq; -using SIL.LCModel; -using SIL.LCModel.DomainServices; -using SIL.LCModel.Infrastructure; -using SIL.ObjectModel; -using SIL.Xml; using XAmpleManagedWrapper; +using XCore; namespace SIL.FieldWorks.WordWorks.Parser { @@ -25,6 +27,7 @@ public class XAmpleParser : DisposableBase, IParser private static readonly char[] Digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; private XAmpleWrapper m_xample; + private PropertyTable m_propTable; private readonly string m_dataDir; private readonly LcmCache m_cache; private ParserModelChangeListener m_changeListener; @@ -33,7 +36,7 @@ public class XAmpleParser : DisposableBase, IParser private bool m_forceUpdate; private XElement xampleAddonFileRoot; - public XAmpleParser(LcmCache cache, string dataDir) + public XAmpleParser(LcmCache cache, string dataDir, PropertyTable propertyTable) { m_cache = cache; m_xample = new XAmpleWrapper(); @@ -43,6 +46,7 @@ public XAmpleParser(LcmCache cache, string dataDir) m_database = ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); m_transformer = new M3ToXAmpleTransformer(m_database); m_forceUpdate = true; + m_propTable = propertyTable; InitXAmpleAddonDataInfo(); } private void InitXAmpleAddonDataInfo() @@ -58,7 +62,11 @@ private void InitXAmpleAddonDataInfo() { xampleAddonFileRoot = doc.Root; var preparer = new XAmplePropertiesPreparer(m_cache, xampleAddonFileRoot, false); - preparer.AddListsAndFields(); + if (!preparer.ListsAlreadyAdded()) + { + preparer.AddListsAndFields(); + FwUtils.Publisher.Publish(new PublisherParameterObject(EventConstants.ReloadAreaTools, "lists", m_propTable.GetWindow())); + } } } } diff --git a/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs b/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs index 033503c3c8..02bb841bb5 100644 --- a/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs +++ b/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs @@ -2,6 +2,7 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) +using SIL.FieldWorks.Common.FwUtils; using SIL.LCModel; using SIL.LCModel.Core.Cellar; using SIL.LCModel.DomainServices; @@ -10,8 +11,8 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; -using System.Collections; using System.Xml.XPath; +using XCore; namespace SIL.FieldWorks.WordWorks.Parser { @@ -57,13 +58,33 @@ where fd.IsCustomField select fd).ToList(); } + public Boolean ListsAlreadyAdded() + { + var possListRepository = Cache.ServiceLocator.GetInstance(); + var customList = possListRepository.AllInstances().FirstOrDefault(list => list.Name.BestAnalysisAlternative.Text == customListName); + if (customList != null) + { + return true; + } + return false; + } + + public Boolean XAmplePropertiesCustomFieldAlreadyAdded(string fieldName, int fieldClassId) + { + var customFields = GetListOfCustomFields(); + if (customFields.Find(fd => fd.Name == fieldName) != null) + { + return true; + } + return false; + } + public void AddListsAndFields() { if (Root == null) { return; } - AddXAmplePropertiesList(); var customFields = GetListOfCustomFields(); AddXAmplePropertiesCustomField(entryCustomFieldName, LexEntryTags.kClassId); @@ -75,8 +96,7 @@ public void AddListsAndFields() /// public void AddXAmplePropertiesCustomField(string fieldName, int fieldClassId) { - var customFields = GetListOfCustomFields(); - if (customFields.Find(fd => fd.Name == fieldName) != null) + if (XAmplePropertiesCustomFieldAlreadyAdded(fieldName, fieldClassId)) { // already done; quit return; @@ -117,22 +137,15 @@ public void AddXAmplePropertiesCustomField(string fieldName, int fieldClassId) /// public void AddXAmplePropertiesList() { - if (Root == null) + if (Root == null || ListsAlreadyAdded()) { // nothing to do return; } - var possListRepository = Cache.ServiceLocator.GetInstance(); - var customList = possListRepository.AllInstances().FirstOrDefault(list => list.Name.BestAnalysisAlternative.Text == customListName); - if (customList != null) - { - return; - } NonUndoableUnitOfWorkHelper.Do(Cache.ActionHandlerAccessor, () => { int ws = WritingSystemServices.kwsAnal; - Cache.ServiceLocator.GetInstance().CreateUnowned(customListName, ws); - customList = possListRepository.AllInstances().Last(); + var customList = Cache.ServiceLocator.GetInstance().CreateUnowned(customListName, ws); var propPoss = Cache.ServiceLocator.GetInstance(); ws = Cache.DefaultAnalWs; var elements = Root.XPathSelectElements("CustomList/Contents/Element"); diff --git a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs index e02328b948..4b4d3ba97f 100644 --- a/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs +++ b/Src/Utilities/pcpatrflex/ToneParsFLExDll/ToneParsFLExForm.cs @@ -723,7 +723,8 @@ private bool XAmpleFilesAreUpToDate() Path.Combine( FwDirectoryFinder.CodeDirectory, FwDirectoryFinder.ksFlexFolderName - ) + ), + PropTable ); } return m_XAmpleParser.IsUpToDate(); From bbe9293d5dea92a4ccce87efff294b04d434e349 Mon Sep 17 00:00:00 2001 From: Andy Black Date: Fri, 4 Sep 2026 10:25:34 -0700 Subject: [PATCH 2/2] Improve clarity and fix comment length Change-Id: Ie7662021a72fe8e6f47d639d2ea4ea05dc54f3d9 --- Src/FwParatextLexiconPlugin/FdoLexicon.cs | 3 ++- Src/LexText/ParserCore/XAmplePropertiesPreparer.cs | 14 ++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/FdoLexicon.cs b/Src/FwParatextLexiconPlugin/FdoLexicon.cs index e1f2ad54ee..0f239fcef0 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexicon.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexicon.cs @@ -652,7 +652,8 @@ private void InstantiateParser() switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) { case "XAmple": - // LT-22708 As of 2026.08.26, this is only called within FLEx from FdoLexiconTests. + // LT-22708 As of 2026.08.26, this is only called within FLEx from + // FdoLexiconTests. // Creating the mediator and property table here works fine. Mediator = new Mediator(); PropertyTable = new PropertyTable(Mediator); diff --git a/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs b/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs index 02bb841bb5..c447660d8b 100644 --- a/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs +++ b/Src/LexText/ParserCore/XAmplePropertiesPreparer.cs @@ -2,7 +2,6 @@ // This software is licensed under the LGPL, version 2.1 or later // (http://www.gnu.org/licenses/lgpl-2.1.html) -using SIL.FieldWorks.Common.FwUtils; using SIL.LCModel; using SIL.LCModel.Core.Cellar; using SIL.LCModel.DomainServices; @@ -61,22 +60,13 @@ where fd.IsCustomField public Boolean ListsAlreadyAdded() { var possListRepository = Cache.ServiceLocator.GetInstance(); - var customList = possListRepository.AllInstances().FirstOrDefault(list => list.Name.BestAnalysisAlternative.Text == customListName); - if (customList != null) - { - return true; - } - return false; + return possListRepository.AllInstances().Any(list => list.Name.BestAnalysisAlternative.Text == customListName); } public Boolean XAmplePropertiesCustomFieldAlreadyAdded(string fieldName, int fieldClassId) { var customFields = GetListOfCustomFields(); - if (customFields.Find(fd => fd.Name == fieldName) != null) - { - return true; - } - return false; + return customFields.Any(fd => fd.Name == fieldName && fd.Class == fieldClassId); } public void AddListsAndFields()