diff --git a/Linguini.Bundle/FluentBundle.cs b/Linguini.Bundle/FluentBundle.cs index 5cbe4b3..cd10cd6 100644 --- a/Linguini.Bundle/FluentBundle.cs +++ b/Linguini.Bundle/FluentBundle.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; @@ -20,7 +21,8 @@ namespace Linguini.Bundle public class FluentBundle { private IDictionary _funcList; - private IDictionary<(string, EntryKind), IEntry> _entries; + private IDictionary _terms; + private IDictionary _messages; #region Properties /// @@ -66,7 +68,8 @@ public class FluentBundle private FluentBundle() { - _entries = new Dictionary<(string, EntryKind), IEntry>(); + _terms = new Dictionary(); + _messages = new Dictionary(); _funcList = new Dictionary(); Culture = CultureInfo.CurrentCulture; Locales = new List(); @@ -95,16 +98,19 @@ private static FluentBundle ConstructBundle(FluentBundleOption option) : CultureInfo.CurrentCulture.Name; var cultureInfo = new CultureInfo(primaryLocale, false); var locales = new List { primaryLocale }; - IDictionary<(string, EntryKind), IEntry> entries; + IDictionary terms; + IDictionary messages; IDictionary functions; if (option.UseConcurrent) { - entries = new ConcurrentDictionary<(string, EntryKind), IEntry>(); + terms = new ConcurrentDictionary(); + messages = new ConcurrentDictionary(); functions = new ConcurrentDictionary(); } else { - entries = new Dictionary<(string, EntryKind), IEntry>(); + terms = new Dictionary(); + messages = new Dictionary(); functions = new Dictionary(); } @@ -112,7 +118,8 @@ private static FluentBundle ConstructBundle(FluentBundleOption option) { Culture = cultureInfo, Locales = locales, - _entries = entries, + _terms = terms, + _messages = messages, _funcList = functions, TransformFunc = option.TransformFunc, FormatterFunc = option.FormatterFunc, @@ -153,10 +160,10 @@ internal bool AddResource(Resource res, out List errors) switch (entry) { case AstMessage message: - AddEntry(errors, message); + AddMessage(errors, message); break; case AstTerm term: - AddEntry(errors, term); + AddTerm(errors, term); break; } } @@ -175,17 +182,26 @@ private void InternalResourceOverriding(Resource resource) { var entry = resource.Entries[entryPos]; - if (entry is AstTerm or AstMessage) + switch (entry) { - AddEntryOverriding(entry); + case AstMessage message: + AddMessageOverriding(message); + break; + case AstTerm term: + AddTermOverriding(term); + break; } } } - - private void AddEntryOverriding(IEntry term) + + private void AddMessageOverriding(AstMessage message) + { + _messages[message.GetId()] = message; + } + + private void AddTermOverriding(AstTerm term) { - var id = (term.GetId(), term.ToKind()); - _entries[id] = term; + _terms[term.GetId()] = term; } public void AddResourceOverriding(string input) @@ -200,19 +216,36 @@ public void AddResourceOverriding(TextReader input) InternalResourceOverriding(res); } - private void AddEntry(List errors, IEntry term) + private void AddTerm(List errors, AstTerm term) { - var id = (term.GetId(), term.ToKind()); - if (_entries.ContainsKey(id)) + var termId = term.GetId(); + // ReSharper disable once CanSimplifyDictionaryLookupWithTryAdd + // Using TryAdd here leads to undocumented exceptions + if (_terms.ContainsKey(termId)) { - errors.Add(new OverrideFluentError(id.Item1, id.Item2)); + errors.Add(new OverrideFluentError(termId, EntryKind.Term)); } else { - _entries[id] = term; + _terms[termId] = term; } } - + + private void AddMessage(List errors, AstMessage msg) + { + var msgId = msg.GetId(); + // ReSharper disable once CanSimplifyDictionaryLookupWithTryAdd + // Using TryAdd here leads to undocumented exceptions + if (_messages.ContainsKey(msgId)) + { + errors.Add(new OverrideFluentError(msg.GetId(), EntryKind.Message)); + } + else + { + _messages[msgId] = msg; + } + } + public bool TryAddFunction(string funcName, ExternalFunction fluentFunction) { return TryInsert(funcName, fluentFunction, InsertBehavior.None); @@ -276,9 +309,7 @@ private bool TryInsert(string funcName, ExternalFunction fluentFunction, [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool HasMessage(string identifier) { - var id = (identifier, EntryKind.Message); - return _entries.ContainsKey(id) - && _entries[id] is AstMessage; + return _messages.ContainsKey(identifier); } public bool HasAttrMessage(string idWithAttr) @@ -374,34 +405,12 @@ public bool TryGetMessage(string id, string? attribute, FluentArgs? args, public bool TryGetAstMessage(string ident, [NotNullWhen(true)] out AstMessage? message) { - var id = (ident, EntryKind.Message); - if (_entries.ContainsKey(id) - && _entries.TryGetValue(id, out var value) - && value.ToKind() == EntryKind.Message - && _entries[id] is AstMessage astMessage) - { - message = astMessage; - return true; - } - - message = null; - return false; + return _messages.TryGetValue(ident, out message); } public bool TryGetAstTerm(string ident, [NotNullWhen(true)] out AstTerm? term) { - var termId = (ident, EntryKind.Term); - if (_entries.ContainsKey(termId) - && _entries.TryGetValue(termId, out var value) - && value.ToKind() == EntryKind.Term - && _entries[termId] is AstTerm astTerm) - { - term = astTerm; - return true; - } - - term = null; - return false; + return _terms.TryGetValue(ident, out term); } public bool TryGetFunction(Identifier id, [NotNullWhen(true)] out FluentFunction? function) @@ -433,19 +442,17 @@ public string FormatPattern(Pattern pattern, FluentArgs? args, public IEnumerable GetMessageEnumerable() { - foreach (var keyValue in _entries) - { - if (keyValue.Value.ToKind() == EntryKind.Message) - yield return keyValue.Key.Item1; - } + return _messages.Keys; } public IEnumerable GetFuncEnumerable() { - foreach (var keyValue in _funcList) - { - yield return keyValue.Key; - } + return _funcList.Keys; + } + + public IEnumerable GetTermEnumerable() + { + return _terms.Keys; } public FluentBundle DeepClone() @@ -455,7 +462,8 @@ public FluentBundle DeepClone() Culture = (CultureInfo)Culture.Clone(), FormatterFunc = FormatterFunc, Locales = new List(Locales), - _entries = new Dictionary<(string, EntryKind), IEntry>(_entries), + _messages = new Dictionary(_messages), + _terms = new Dictionary(_terms), _funcList = new Dictionary(_funcList), TransformFunc = TransformFunc, UseIsolating = UseIsolating,