Skip to content

Commit

Permalink
Finish frozen bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
Ygg01 committed Jan 9, 2024
1 parent 6975655 commit 2cbde6c
Show file tree
Hide file tree
Showing 11 changed files with 678 additions and 371 deletions.
29 changes: 27 additions & 2 deletions Linguini.Bundle.Test/Unit/BundleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,16 @@ public void TestConcurrencyOption()
UseConcurrent = true,
};
var optBundle = FluentBundle.MakeUnchecked(bundleOpt);

Parallel.For(0, 10, i => optBundle.AddResource($"term-1 = {i}", out _));
Parallel.For(0, 10, i => optBundle.AddResource($"term-2= {i}", out _));
Parallel.For(0, 10, i => optBundle.TryGetAttrMessage("term-1", null, out _, out _));
Parallel.For(0, 10, i => optBundle.AddResourceOverriding($"term-2= {i + 1}"));
Assert.That(optBundle.HasMessage("term-1"));

// Frozen bundle are read only and should be thread-safe
var frozenBundle = optBundle.ToFrozenBundle();
Parallel.For(0, 10, i => frozenBundle.TryGetAttrMessage("term-1", null, out _, out _));
}

[Test]
Expand Down Expand Up @@ -253,7 +258,7 @@ public static IEnumerable<TestCaseData> TestBundleErrors
yield return new TestCaseData("### Comment\r\nterm1")
.Returns(new List<ErrorSpan?>
{
new ErrorSpan(2, 13, 18, 18, 19)
new(2, 13, 18, 18, 19)
});
}
}
Expand Down Expand Up @@ -315,7 +320,7 @@ [neuter] It

[Test]
[Parallelizable]
public void TestMacrosFail()
public void TestExtensionsWork()
{
var (bundle, err) = LinguiniBuilder.Builder(useExperimental: true).Locale("en-US")
.AddResource(Macros)
Expand All @@ -327,6 +332,11 @@ public void TestMacrosFail()
};
Assert.That(bundle.TryGetMessage("call-attr-no-args", args, out _, out var message));
Assert.That("It", Is.EqualTo(message));

// Check Frozen bundle behaves similarly
var frozenBundle = bundle.ToFrozenBundle();
Assert.That(frozenBundle.TryGetMessage("call-attr-no-args", args, out _, out var frozenMessage));
Assert.That("It", Is.EqualTo(frozenMessage));
}
private const string DynamicSelectors = @"
-creature-fairy = fairy
Expand Down Expand Up @@ -360,6 +370,21 @@ public void TestDynamicSelectors()
};
Assert.That(bundle.TryGetMessage("you-see", args, out _, out var message2));
Assert.That("You see a fairy.", Is.EqualTo(message2));

// Check Frozen bundle behaves similarly
var frozenBundle = bundle.ToFrozenBundle();
args = new Dictionary<string, IFluentType>
{
["object"] = (FluentReference)"creature-elf",
};
Assert.That(frozenBundle.TryGetMessage("you-see", args, out _, out var frozenMessage1));
Assert.That("You see an elf.", Is.EqualTo(frozenMessage1));
args = new Dictionary<string, IFluentType>
{
["object"] = (FluentReference)"creature-fairy",
};
Assert.That(frozenBundle.TryGetMessage("you-see", args, out _, out var frozenMessage2));
Assert.That("You see a fairy.", Is.EqualTo(frozenMessage2));
}

[Test]
Expand Down
4 changes: 2 additions & 2 deletions Linguini.Bundle.Test/Yaml/YamlSuiteParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ private static string GetFullPathFor(string file)


private static void AssertErrorCases(List<ResolverTestSuite.ResolverTestError> expectedErrors,
IList<FluentError> errs,
IList<FluentError>? errs,
String testName)
{
Assert.That(expectedErrors.Count, Is.EqualTo(errs.Count), testName);
Assert.That(expectedErrors.Count, Is.EqualTo(errs!.Count), testName);
for (var i = 0; i < expectedErrors.Count; i++)
{
var actualError = errs[i];
Expand Down
54 changes: 43 additions & 11 deletions Linguini.Bundle/ConcurrentBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,27 @@ namespace Linguini.Bundle
{
public sealed class ConcurrentBundle : FluentBundle, IEquatable<ConcurrentBundle>
{
internal ConcurrentDictionary<string, FluentFunction> FuncList = new();
internal ConcurrentDictionary<string, FluentFunction> Functions = new();
private ConcurrentDictionary<string, AstTerm> _terms = new();
private ConcurrentDictionary<string, AstMessage> _messages = new();

public static ConcurrentBundle Thaw(FrozenBundle frozenBundle)
{
return new ConcurrentBundle
{
_messages = new ConcurrentDictionary<string, AstMessage>(frozenBundle.Messages),
Functions = new ConcurrentDictionary<string, FluentFunction>(frozenBundle.Functions),
_terms = new ConcurrentDictionary<string, AstTerm>(frozenBundle.Terms),
FormatterFunc = frozenBundle.FormatterFunc,
Locales = frozenBundle.Locales,
UseIsolating = frozenBundle.UseIsolating,
MaxPlaceable = frozenBundle.MaxPlaceable,
EnableExtensions = frozenBundle.EnableExtensions,
TransformFunc = frozenBundle.TransformFunc,
Culture = frozenBundle.Culture
};
}

/// <inheritdoc />
protected override void AddMessageOverriding(AstMessage message)
{
Expand Down Expand Up @@ -53,19 +70,19 @@ protected override bool TryAddMessage(AstMessage message, List<FluentError>? err
/// <inheritdoc />
public override bool TryAddFunction(string funcName, ExternalFunction fluentFunction)
{
return FuncList.TryAdd(funcName, fluentFunction);
return Functions.TryAdd(funcName, fluentFunction);
}

/// <inheritdoc />
public override void AddFunctionOverriding(string funcName, ExternalFunction fluentFunction)
{
FuncList[funcName] = fluentFunction;
Functions[funcName] = fluentFunction;
}

/// <inheritdoc />
public override void AddFunctionUnchecked(string funcName, ExternalFunction fluentFunction)
{
if (FuncList.TryAdd(funcName, fluentFunction)) return;
if (Functions.TryAdd(funcName, fluentFunction)) return;
throw new ArgumentException($"Function with name {funcName} already exist");
}

Expand All @@ -91,33 +108,48 @@ public override bool TryGetAstTerm(string ident, [NotNullWhen(true)] out AstTerm
/// <inheritdoc />
public override bool TryGetFunction(string funcName, [NotNullWhen(true)] out FluentFunction? function)
{
return FuncList.TryGetValue(funcName, out function);
return Functions.TryGetValue(funcName, out function);
}

/// <inheritdoc />
public override IEnumerable<string> GetMessageEnumerable()
{
return _messages.Keys.ToArray();
return _messages.Keys;
}

/// <inheritdoc />
public override IEnumerable<string> GetFuncEnumerable()
{
return FuncList.Keys.ToArray();
return Functions.Keys;
}

/// <inheritdoc />
public override IEnumerable<string> GetTermEnumerable()
{
return _terms.Keys.ToArray();
return _terms.Keys;
}

internal override IDictionary<string, AstMessage> GetMessagesDictionary()
{
return _messages;
}

internal override IDictionary<string, AstTerm> GetTermsDictionary()
{
return _terms;
}

internal override IDictionary<string, FluentFunction> GetFunctionDictionary()
{
return Functions;
}

/// <inheritdoc/>
public override FluentBundle DeepClone()
{
return new ConcurrentBundle
{
FuncList = new ConcurrentDictionary<string, FluentFunction>(FuncList),
Functions = new ConcurrentDictionary<string, FluentFunction>(Functions),
_terms = new ConcurrentDictionary<string, AstTerm>(_terms),
_messages = new ConcurrentDictionary<string, AstMessage>(_messages),
Culture = (CultureInfo)Culture.Clone(),
Expand All @@ -135,7 +167,7 @@ public bool Equals(ConcurrentBundle? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && FuncList.SequenceEqual(other.FuncList) && _terms.SequenceEqual(other._terms) &&
return base.Equals(other) && Functions.SequenceEqual(other.Functions) && _terms.SequenceEqual(other._terms) &&
_messages.SequenceEqual(other._messages);
}

Expand All @@ -148,7 +180,7 @@ public override bool Equals(object? obj)
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), FuncList, _terms, _messages);
return HashCode.Combine(base.GetHashCode(), Functions, _terms, _messages);
}
}
}
Loading

0 comments on commit 2cbde6c

Please sign in to comment.