Skip to content

Commit

Permalink
Merge branch 'LT-21586' of https://github.com/sillsdev/liblcm into LT…
Browse files Browse the repository at this point in the history
…-21586
  • Loading branch information
jtmaxwell3 committed Jul 31, 2024
2 parents 2ee3fdd + 216e3a4 commit 696255b
Show file tree
Hide file tree
Showing 19 changed files with 394 additions and 56 deletions.
37 changes: 32 additions & 5 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ jobs:
- name: Solve problems
run: Remove-Item c:\tools\php\icuuc*.dll -Force
if: matrix.os == 'windows-latest'

- name: Download 461 targeting pack
uses: suisei-cn/actions-download-file@818d6b7dc8fe73f2f924b6241f2b1134ca1377d9 # 1.6.0
id: downloadfile # Remember to give an ID if you need the output filename
with:
url: "https://download.microsoft.com/download/F/1/D/F1DEB8DB-D277-4EF9-9F48-3A65D4D8F965/NDP461-DevPack-KB3105179-ENU.exe"
target: public/
if: matrix.os == 'windows-latest'

- name: Install targeting pack
shell: cmd
working-directory: public
Expand All @@ -67,12 +67,18 @@ jobs:
- name: Test on Linux
run: |
. environ
dotnet test --no-restore --no-build -p:ParallelizeAssembly=false --configuration Release -- RunConfiguration.FailWhenNoTestsFound=true
dotnet test --no-restore --no-build -p:ParallelizeAssembly=false --configuration Release --logger:"trx" --results-directory ./test-results
if: matrix.os == 'ubuntu-latest'

- name: Test on Windows
run: dotnet test -a "%UserProfile%\.nuget\packages\nunit3testadapter\4.5.0\build\net462" --no-restore --no-build -p:ParallelizeAssembly=false --configuration Release -- RunConfiguration.FailWhenNoTestsFound=true
run: dotnet test --no-restore --no-build -p:ParallelizeAssembly=false --configuration Release --logger:"trx" --results-directory ./test-results
if: matrix.os != 'ubuntu-latest'
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: Test results (${{ matrix.os }})
path: ./test-results

- name: Package
run: dotnet pack --include-symbols --no-restore --no-build -p:SymbolPackageFormat=snupkg --configuration Release
Expand All @@ -81,9 +87,30 @@ jobs:
run: dotnet nuget push artifacts/*.nupkg -s https://api.nuget.org/v3/index.json -k ${{secrets.SILLSDEV_PUBLISH_NUGET_ORG}} --skip-duplicate
if: github.event_name == 'push' && matrix.os == 'ubuntu-latest'

- name: Publish to Github packages
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
run: dotnet nuget push artifacts/*.nupkg -s https://nuget.pkg.github.com/sillsdev/index.json -k ${{secrets.GITHUB_TOKEN}} --skip-duplicate

- name: Publish Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: NugetPackages
path: artifacts/*.nupkg
if: github.event_name == 'pull_request'
publish-test-results:
runs-on: ubuntu-latest
needs: build
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
path: artifacts
pattern: Test results *
- name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@8885e273a4343cd7b48eaa72428dea0c3067ea98 # v2.14.0
with:
check_name: LCM Tests
files: artifacts/**/*.trx
action_fail: true
action_fail_on_inconclusive: true
34 changes: 21 additions & 13 deletions src/SIL.LCModel.FixData/HomographFixer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2012-2018 SIL International
// Copyright (c) 2012-2018 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)

Expand Down Expand Up @@ -100,6 +100,10 @@ internal override void FinalFixerInitialization(Dictionary<Guid, Guid> owners, H
{
base.FinalFixerInitialization(owners, guids, parentToOwnedObjsur, rtElementsToDelete); // Sets base class member variables

// Filter the entriesWithCitationForm to only include those that match the homograph writing system.
var relevantCitationEntries = entriesWithCitationForm.Where(kvp =>
kvp.Value.Elements("AUni").Any(e => e.Attribute("ws")?.Value == m_homographWs)).ToDictionary(kv => kv.Key, kv => kv.Value);

// Create a dictionary with the Form and MorphType guid as the key and a list of ownerguid's as the value. This
// will show us which LexEntries should have homograph numbers. If the list of ownerguids has only one entry then
// it's homograph number should be zero. If the list of owerguids has more than one guid then the LexEntries
Expand All @@ -113,10 +117,10 @@ internal override void FinalFixerInitialization(Dictionary<Guid, Guid> owners, H
if (!m_firstAllomorphs.Contains(morphGuid))
continue;
string rtFormText;
if (entriesWithCitationForm.Keys.Contains(owners[morphGuid]))
if (relevantCitationEntries.Keys.Contains(owners[morphGuid]))
{
var entryGuid = owners[morphGuid];
var cfElement = entriesWithCitationForm[entryGuid];
var cfElement = relevantCitationEntries[entryGuid];
rtFormText = GetStringInHomographWritingSystem(cfElement);
if (string.IsNullOrWhiteSpace(rtFormText))
continue;
Expand All @@ -127,6 +131,7 @@ internal override void FinalFixerInitialization(Dictionary<Guid, Guid> owners, H
var rtForm = rtElem.Element("Form");
if (rtForm == null)
continue;

rtFormText = GetStringInHomographWritingSystem(rtForm);
if (string.IsNullOrWhiteSpace(rtFormText))
continue; // entries with no lexeme form are not considered homographs.
Expand All @@ -142,17 +147,20 @@ internal override void FinalFixerInitialization(Dictionary<Guid, Guid> owners, H

// if there was a citation form which matches the form of this MoStemAllomorph the MorphType
// is not important to the homograph determination.
var key = m_Homographs.ContainsKey(rtFormText) ? rtFormText : rtFormText + m_MorphTypeSort[new Guid(guid)];

var ownerguid = new Guid(rtElem.Attribute("ownerguid").Value);
if (m_Homographs.TryGetValue(key, out guidsForHomograph))
{
guidsForHomograph.Add(ownerguid);
}
else
if (m_Homographs.ContainsKey(rtFormText) || m_MorphTypeSort.Any())
{
guidsForHomograph = new List<Guid> { ownerguid };
m_Homographs.Add(key, guidsForHomograph);
var key = m_Homographs.ContainsKey(rtFormText) ? rtFormText : rtFormText + m_MorphTypeSort[new Guid(guid)];

var ownerguid = new Guid(rtElem.Attribute("ownerguid").Value);
if (m_Homographs.TryGetValue(key, out guidsForHomograph))
{
guidsForHomograph.Add(ownerguid);
}
else
{
guidsForHomograph = new List<Guid> { ownerguid };
m_Homographs.Add(key, guidsForHomograph);
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/SIL.LCModel/DomainImpl/OverridesLing_Lex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4028,6 +4028,11 @@ internal IEnumerable<ILexEntryRef> ComplexFormRefsWithThisComponentSense
{
get
{
// Test the cache for null and yield an empty list - This can happen during a bulk delete operation
if (m_cache == null)
{
yield break;
}
((ICmObjectRepositoryInternal) Services.ObjectRepository).EnsureCompleteIncomingRefsFrom(
LexEntryRefTags.kflidComponentLexemes);
foreach (var item in m_incomingRefs)
Expand Down
18 changes: 6 additions & 12 deletions src/SIL.LCModel/DomainImpl/Vectors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,19 +421,13 @@ public void CopyTo(T[] array, int arrayIndex)
// TODO: Check for multidimensional 'array' and throw ArgumentException, if it is.
lock (SyncRoot)
{
//if (arrayIndex >= array.Length || m_items.Count - arrayIndex >= array.Length)
// equals sign causes spurious ArgumentException when copying entire array
if (array.Length == 0)
return;
if (arrayIndex >= array.Length || m_items.Count - arrayIndex > array.Length)
throw new ArgumentException();

int currentIndex = 0;
int currentcopiedIndex = 0;
foreach (var objOrId in m_items.ToArray())
if (m_items.Count + arrayIndex > array.Length)
throw new ArgumentOutOfRangeException("arrayIndex");

int currentcopiedIndex = arrayIndex;
foreach (var cmObjectOrId in m_items)
{
if (currentIndex++ < arrayIndex) continue;
array.SetValue(FluffUpObjectIfNeeded(objOrId), currentcopiedIndex++);
array[currentcopiedIndex++] = FluffUpObjectIfNeeded(cmObjectOrId);
}
}
}
Expand Down
25 changes: 22 additions & 3 deletions src/SIL.LCModel/DomainServices/AnalysisGuessServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,11 @@ public IAnalysis GetBestGuess(IWfiAnalysis wa)
/// True: Do lowercase matching only if the occurrence index is zero.
/// False: Do lowercase matching regardless of the occurrence index.
/// </param>
public IAnalysis GetBestGuess(AnalysisOccurrence occurrence, bool onlyIndexZeroLowercaseMatching = true)
/// <param name="includeContext">
/// True: Consider previous word when getting best guess.
/// False: Ignore previous word when getting best guess.
/// </param>
public IAnalysis GetBestGuess(AnalysisOccurrence occurrence, bool onlyIndexZeroLowercaseMatching = true, bool includeContext = true)
{
// first see if there is a relevant lowercase form of a sentence initial (non-lowercase) wordform
// TODO: make it look for the first word in the sentence...may not be at Index 0!
Expand All @@ -654,7 +658,7 @@ public IAnalysis GetBestGuess(AnalysisOccurrence occurrence, bool onlyIndexZeroL
if (ws == -1)
return new NullWAG(); // happens with empty translation lines
IAnalysis bestGuess;
IAnalysis previous = GetPreviousWordform(occurrence.Segment, occurrence.Index);
IAnalysis previous = includeContext ? GetPreviousWordform(occurrence.Segment, occurrence.Index) : m_nullWAG;
if (TryGetContextAwareGuess(occurrence.Analysis, lowercaseWf, previous, out bestGuess))
return bestGuess;
return new NullWAG();
Expand Down Expand Up @@ -1028,12 +1032,17 @@ private void GenerateEntryGuesses(IDictionary<IWfiWordform, EmptyWwfInfo> map)
var newAnalysis = waFactory.Create(ww, wgFactory);
newAnalysis.CategoryRA = info.Pos;
// Not all entries have senses.
if (info.Sense != null)
if (info.Sense != null && !IsEmptyMultiUnicode(info.Sense.Gloss))
{
// copy all the gloss alternatives from the sense into the word gloss.
IWfiGloss wg = newAnalysis.MeaningsOC.First();
wg.Form.MergeAlternatives(info.Sense.Gloss);
}
else
{
// Eliminate the dummy gloss (LT-21815).
newAnalysis.MeaningsOC.Clear();
}
var wmb = wmbFactory.Create();
newAnalysis.MorphBundlesOS.Add(wmb);
if (info.Form != null)
Expand All @@ -1054,6 +1063,16 @@ private void GenerateEntryGuesses(IDictionary<IWfiWordform, EmptyWwfInfo> map)
}
}
}

bool IsEmptyMultiUnicode(IMultiUnicode multiUnicode)
{
foreach (var ws in multiUnicode.AvailableWritingSystemIds)
{
if (multiUnicode.get_String(ws).Length > 0)
return false;
}
return true;
}
#endregion GenerateEntryGuesses
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System;
using System.Diagnostics;
using Microsoft.Practices.ServiceLocation;
using SIL.LCModel.Core.KernelInterfaces;
using SIL.LCModel.Core.Text;
using SIL.LCModel.Core.WritingSystems;
Expand All @@ -23,7 +22,7 @@ internal static class BootstrapNewLanguageProject
/// <summary>
/// Create a new Language Project.
/// </summary>
internal static void BootstrapNewSystem(IServiceLocator servLoc)
internal static void BootstrapNewSystem(IServiceProvider servLoc)
{
using (var nonUndoableUOW = new NonUndoableUnitOfWorkHelper(servLoc.GetInstance<IActionHandler>()))
{
Expand Down
7 changes: 3 additions & 4 deletions src/SIL.LCModel/DomainServices/M3ModelExportServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Text;
using System.Xml.Linq;
using Icu;
using Microsoft.Practices.ServiceLocation;
using SIL.LCModel.Core.KernelInterfaces;
using SIL.LCModel.Core.Text;
using SIL.LCModel.Core.WritingSystems;
Expand Down Expand Up @@ -344,7 +343,7 @@ select ExportItemAsReference(slot, "Slots"),
/// <summary>
/// Export the full lexicon when exporting both grammar and lexicon.
/// </summary>
private static XElement ExportLexiconFull(IServiceLocator servLoc, Normalizer.UNormalizationMode mode)
private static XElement ExportLexiconFull(IServiceProvider servLoc, Normalizer.UNormalizationMode mode)
{
return new XElement("Lexicon",
ExportEntries(servLoc.GetInstance<ILexEntryRepository>()),
Expand Down Expand Up @@ -378,7 +377,7 @@ from lexEntryType in lexEntryRef.VariantEntryTypesRS
select ExportItemAsReference(lexEntryType, "LexEntryType"))));
}

private static XElement ExportMsas(IServiceLocator servLoc)
private static XElement ExportMsas(IServiceProvider servLoc)
{
return new XElement("MorphoSyntaxAnalyses",
from stemMsa in servLoc.GetInstance<IMoStemMsaRepository>().AllInstances()
Expand Down Expand Up @@ -436,7 +435,7 @@ from sense in senseRepos.AllInstances()
ExportBestAnalysis(sense.Definition, "Definition", mode)));
}

private static XElement ExportAllomorphs(IServiceLocator servLoc, Normalizer.UNormalizationMode mode)
private static XElement ExportAllomorphs(IServiceProvider servLoc, Normalizer.UNormalizationMode mode)
{
return new XElement("Allomorphs",
from stemAllo in servLoc.GetInstance<IMoStemAllomorphRepository>().AllInstances()
Expand Down
31 changes: 29 additions & 2 deletions src/SIL.LCModel/ILcmServiceLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
// (http://www.gnu.org/licenses/lgpl-2.1.html)

using System;
using Microsoft.Practices.ServiceLocation;
using System.Collections.Generic;
using CommonServiceLocator;
using SIL.LCModel.Core.KernelInterfaces;
using SIL.LCModel.Core.WritingSystems;
using SIL.LCModel.Infrastructure;
using SIL.LCModel.Infrastructure.Impl;
using SIL.LCModel.IOC;

namespace SIL.LCModel
{
/// <summary>
/// This interface defines LCM extensions to IServiceLocator, mainly shortcuts for particular
/// GetService() calls.
/// </summary>
public interface ILcmServiceLocator : IServiceLocator
public interface ILcmServiceLocator : IServiceProvider
{
/// <summary>
/// Shortcut to the IActionHandler instance.
Expand Down Expand Up @@ -95,4 +97,29 @@ internal interface IServiceLocatorInternal
LoadingServices LoadingServices { get; }
IUnitOfWorkService UnitOfWorkService { get; }
}

/// <summary>
/// Helpers to provide drop in methods that match the api of IServiceLocator, but use IServiceProvider instead.
/// </summary>
public static class IocHelpers
{
public static object GetInstance(this IServiceProvider provider, Type serviceType)
{
//todo how to handle null? Should we throw an exception?
return provider.GetService(serviceType);
}

public static TService GetInstance<TService>(this IServiceProvider provider)
{
return (TService)provider.GetService(typeof(TService));
}

public static IEnumerable<TService> GetAllInstances<TService>(this IServiceProvider provider)
{
//structure map might not work the same way as the standard service provider, so we need to handle it separately.
if (provider is IServiceLocator serviceLocator) return serviceLocator.GetAllInstances<TService>();
//the standard service provider handles listing all services like this, however that might not work the same in structure map if an IEnumerable is explicitly registered.
return (IEnumerable<TService>) provider.GetService(typeof(IEnumerable<TService>));
}
}
}
4 changes: 2 additions & 2 deletions src/SIL.LCModel/IOC/LcmServiceLocatorFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Practices.ServiceLocation;
using CommonServiceLocator;
using SIL.LCModel.Application;
using SIL.LCModel.Application.Impl;
using SIL.LCModel.Core.KernelInterfaces;
Expand Down Expand Up @@ -54,7 +54,7 @@ internal LcmServiceLocatorFactory(BackendProviderType backendProviderType, ILcmU
/// </summary>
/// <returns>An IServiceLocator instance.</returns>
/// ------------------------------------------------------------------------------------
public IServiceLocator CreateServiceLocator()
public IServiceProvider CreateServiceLocator()
{
// NOTE: When creating an object through IServiceLocator.GetInstance the caller has
// to call Dispose() on the newly created object, unless it's a singleton
Expand Down
2 changes: 1 addition & 1 deletion src/SIL.LCModel/SIL.LCModel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommonServiceLocator" Version="1.4.0" />
<PackageReference Include="CommonServiceLocator" Version="2.0.7" />
<PackageReference Include="GitVersion.MsBuild" Version="5.6.10" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="protobuf-net" Version="2.4.6" />
Expand Down
4 changes: 2 additions & 2 deletions tests/SIL.LCModel.Core.Tests/SIL.LCModel.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ This package provides unit tests for SIL.LCModel.Core.</Description>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.2" />
<PackageReference Include="SIL.ReleaseTasks" Version="2.5.0" PrivateAssets="All" />
<PackageReference Include="SIL.TestUtilities" Version="13.0.1" />
<PackageReference Include="SIL.TestUtilities" Version="12.0.0-*" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 696255b

Please sign in to comment.