Exemple #1
0
        /// <summary>
        /// Creates a placeholder from a specified full qualifier.
        /// </summary>
        /// <param name="fullQualifier">Full qualifier.
        /// <para>It is in the format of [ThreatsManagerPlatform:ModelTest:parameter1#parameter2], where
        /// <list type="bullet">
        /// <item><description>ThreatsManagerPlatform is fixed.</description></item>
        /// <item><description>ModelTest represents the Qualifier which identifies the specific Placeholder.</description></item>
        /// <item><description>parameter1#parameter2 represent the parameters for the Placeholder, separated by #.</description></item>
        /// </list>
        /// </para></param>
        /// <param name="priority">[out] Integer representing the priority of the placeholder.</param>
        /// <returns>Generated Placeholder. It may be null, if no suitable placeholder has been found.</returns>
        public static IPlaceholder Create([Required] string fullQualifier, out int priority)
        {
            IPlaceholder result = null;

            priority = 100;

            var factories = ExtensionUtils.GetExtensions <IPlaceholderFactory>()?.ToArray();

            if (factories?.Any() ?? false)
            {
                var regex = new Regex(
                    @"\[ThreatsManagerPlatform:(?<qualifier>[\w]+):?(?<params>[\S ]*)?\]");
                var match = regex.Match(fullQualifier);
                if (match.Success)
                {
                    var factory = factories.FirstOrDefault(x =>
                                                           string.CompareOrdinal(x.Qualifier, match.Groups["qualifier"]?.Value) == 0);

                    if (factory != null)
                    {
                        priority = factory.GetExtensionPriority();
                        result   = factory.Create(match.Groups["params"]?.Value);
                    }
                }
            }

            return(result);
        }
        public static void UpdatePlaceholderColor(this TextBox textBox, IPlaceholder placeholder)
        {
            var brush = placeholder.PlaceholderColor?.ToNative();

            if (brush is null)
            {
                // Windows.Foundation.UniversalApiContract < 5
                textBox.Resources.Remove("TextControlPlaceholderForeground");
                textBox.Resources.Remove("TextControlPlaceholderForegroundPointerOver");
                textBox.Resources.Remove("TextControlPlaceholderForegroundFocused");
                textBox.Resources.Remove("TextControlPlaceholderForegroundDisabled");

                // Windows.Foundation.UniversalApiContract >= 5
                textBox.ClearValue(TextBox.PlaceholderForegroundProperty);
            }
            else
            {
                // Windows.Foundation.UniversalApiContract < 5
                textBox.Resources["TextControlPlaceholderForeground"]            = brush;
                textBox.Resources["TextControlPlaceholderForegroundPointerOver"] = brush;
                textBox.Resources["TextControlPlaceholderForegroundFocused"]     = brush;
                textBox.Resources["TextControlPlaceholderForegroundDisabled"]    = brush;

                // Windows.Foundation.UniversalApiContract >= 5
                textBox.PlaceholderForeground = brush;
            }
        }
        /// <summary>
        /// Compares whether two strings have equal placeholders.
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        static bool EqualPlaceholders(IString str1, IString str2)
        {
            if (str1 == null && str2 == null)
            {
                return(true);
            }
            if (str1 == null || str2 == null)
            {
                return(false);
            }
            if (str1.Placeholders.Length != str2.Placeholders.Length)
            {
                return(false);
            }
            int c = str1.Placeholders.Length;

            for (int i = 0; i < c; i++)
            {
                IPlaceholder ph1 = str1.Placeholders[i], ph2 = str2.Placeholders[i];
                if (!PlaceholderExpressionEquals.Equals(ph1.Expression, ph2.Expression))
                {
                    return(false);
                }
            }
            return(true);
        }
Exemple #4
0
        public static void UpdatePlaceholder(this AppCompatEditText editText, IPlaceholder textInput)
        {
            if (editText.Hint == textInput.Placeholder)
            {
                return;
            }

            editText.Hint = textInput.Placeholder;
        }
Exemple #5
0
        public static void UpdatePlaceholderColor(this MauiTextBox textBox, IPlaceholder placeholder, Brush?defaultPlaceholderColorBrush, Brush?defaultPlaceholderColorFocusBrush)
        {
            Color placeholderColor = placeholder.PlaceholderColor;

            BrushHelpers.UpdateColor(placeholderColor, ref defaultPlaceholderColorBrush,
                                     () => textBox.PlaceholderForegroundBrush, brush => textBox.PlaceholderForegroundBrush = brush);

            BrushHelpers.UpdateColor(placeholderColor, ref defaultPlaceholderColorFocusBrush,
                                     () => textBox.PlaceholderForegroundFocusBrush, brush => textBox.PlaceholderForegroundFocusBrush = brush);
        }
        /// <summary>
        /// Evaluate placeholders into string values.
        /// </summary>
        /// <param name="line">original requesting line</param>
        /// <param name="resolvedLine">(optional Line that was matched from IAsset or inlines</param>
        /// <param name="pluralLine">(optional) Line that was matched from IAsset or inlines for plural value</param>
        /// <param name="placeholders"></param>
        /// <param name="features">contextual data</param>
        /// <param name="placeholder_values">collection where strings are placed, one for each placeholder</param>
        /// <param name="culture">the culture in which to evaluate</param>
        void EvaluatePlaceholderValues(ILine line, ILine resolvedLine, ILine pluralLine, IPlaceholder[] placeholders, ref LineFeatures features, ref StructList12 <string> placeholder_values, CultureInfo culture)
        {
            PlaceholderExpressionEvaluator placeholder_evaluator = new PlaceholderExpressionEvaluator();

            placeholder_evaluator.Args = features.ValueArgs;
            placeholder_evaluator.FunctionEvaluationCtx.Culture        = culture;
            placeholder_evaluator.FunctionEvaluationCtx.Line           = line;
            placeholder_evaluator.FunctionEvaluationCtx.ResolvedLine   = resolvedLine;
            placeholder_evaluator.FunctionEvaluationCtx.PluralLine     = pluralLine;
            placeholder_evaluator.FunctionEvaluationCtx.StringResolver = this;
            placeholder_evaluator.FunctionEvaluationCtx.EnumResolver   = EnumResolver;
            if (features.FormatProviders.Count == 1)
            {
                placeholder_evaluator.FunctionEvaluationCtx.FormatProvider = features.FormatProviders[0];
            }
            else if (features.FormatProviders.Count > 1)
            {
                placeholder_evaluator.FunctionEvaluationCtx.FormatProvider = new FormatProviderComposition(features.FormatProviders.ToArray());
            }
            if (features.Functions.Count == 1)
            {
                placeholder_evaluator.FunctionEvaluationCtx.Functions = features.Functions[0];
            }
            else if (features.Functions.Count > 1)
            {
                placeholder_evaluator.FunctionEvaluationCtx.Functions = new FunctionsMap(features.Functions);
            }
            for (int i = 0; i < placeholders.Length; i++)
            {
                try
                {
                    // Get placeholder
                    IPlaceholder ph = placeholders[i];
                    // Evaluate value
                    string ph_value = placeholder_evaluator.toString(placeholder_evaluator.Evaluate(ph.Expression));
                    // Add to array
                    placeholder_values.Add(ph_value);
                    // Update code
                    features.Status.UpPlaceholder(placeholder_evaluator.Status);
                }
                catch (Exception e)
                {
                    // Log exceptions
                    features.Log(e);
                    // Mark error
                    features.Status.UpPlaceholder(LineStatus.PlaceholderErrorExpressionEvaluation);
                    // Put empty value
                    placeholder_values.Add(null);
                }
            }
        }
Exemple #7
0
        public void SetValue(string value)
        {
            value = value.CleanUpMetadataName().Replace("= =", "==");
            var match = Regex.Match(value, @"(.*) (==|!=) (.*)");

            if (!match.Success)
            {
                _checkPlaceholder = new Placeholder(Metadata, value, 0);
                _operation        = "!=";
                _expected         = "NULL";
            }
            else
            {
                _checkPlaceholder = new Placeholder(Metadata, match.Groups[1].Value, 0);
                _operation        = match.Groups[2].Value;
                _expected         = match.Groups[3].Value;
            }
        }
Exemple #8
0
        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                var control = GetTargetControl() as IPlaceholder;

                if (lastControl != control && lastControl != null)
                {
                    lastControl.OnLeave(this);
                }
                lastControl = control.With(_ => _.OnOver(this));

                var pos = Cursor.Position;
                Top    = Top + (pos.Y - oldPos.Y);
                Left   = Left + (pos.X - oldPos.X);
                oldPos = Cursor.Position;
            }
        }
Exemple #9
0
        public static void UpdatePlaceholderColor(this TextBox textBox, IPlaceholder placeholder)
        {
            var brush = placeholder.PlaceholderColor?.ToPlatform();

            if (brush is null)
            {
                // Windows.Foundation.UniversalApiContract < 5
                textBox.Resources.RemoveKeys(PlaceholderColorResourceKeys);
                // Windows.Foundation.UniversalApiContract >= 5
                textBox.ClearValue(TextBox.PlaceholderForegroundProperty);
            }
            else
            {
                // Windows.Foundation.UniversalApiContract < 5
                textBox.Resources.SetValueForAllKey(PlaceholderColorResourceKeys, brush);
                // Windows.Foundation.UniversalApiContract >= 5
                textBox.PlaceholderForeground = brush;
            }

            textBox.RefreshThemeResources();
        }
 public static void UpdatePlaceholder(this TextBox textBox, IPlaceholder placeholder)
 {
     textBox.PlaceholderText = placeholder.Placeholder ?? string.Empty;
 }
 public static void UpdatePlaceholderColor(this AppCompatEditText editText, IPlaceholder placeholder, ColorStateList?defaultColor)
 {
     editText.UpdatePlaceholderColor(placeholder.PlaceholderColor, defaultColor);
 }
Exemple #12
0
 public static void UpdatePlaceholderColor(this EditText editText, IPlaceholder placeholder)
 {
     editText.UpdatePlaceholderColor(placeholder.PlaceholderColor);
 }
        /// <summary>
        /// Add placeholder and cases that apply to that placeholder.
        /// </summary>
        /// <param name="placeholder"></param>
        /// <param name="placeholderValue"></param>
        /// <param name="pluralRules"></param>
        /// <param name="culture"></param>
        public void AddPlaceholder(IPlaceholder placeholder, IPluralNumber placeholderValue, IPluralRules pluralRules, string culture)
        {
            IExpression e = placeholder?.Expression;

            if (e == null)
            {
                return;
            }

            // Query cases
            PluralRuleInfo query = new PluralRuleInfo(null, placeholder.PluralCategory, culture, null, -1);

            IPluralRule[] cases = pluralRules.Evaluate(query, placeholderValue);
            if (cases == null || cases.Length == 0)
            {
                return;
            }
            int optionalCount = cases.Length == 1 ? 0 : cases.Length - 1;
            int requiredCount = cases.Length > 0 ? 1 : 0;

            // Scan arguments
            StructList4 <int> argIndices = new StructList4 <int>();

            GetArguments(e, ref argIndices);

            // Add and unify cases
            for (int ix = 0; ix < argIndices.Count; ix++)
            {
                int argIx = argIndices[ix];

                // Find if argument already exists
                int prevIx = -1;
                for (int j = 0; j < arguments.Count; j++)
                {
                    if (arguments[j].ArgumentIndex == argIx)
                    {
                        prevIx = j; break;
                    }
                }

                if (prevIx < 0)
                {
                    // Add argument
                    Entry entry = new Entry {
                        Cases = cases, ArgumentIndex = argIx, OptionalCases = optionalCount, RequiredCases = requiredCount
                    };
                    arguments.Add(entry);
                    this.Count  *= (1 + cases.Length);
                    this.count1 *= cases.Length;
                }
                else
                {
                    // Previous entry
                    Entry entry = arguments[prevIx];
                    // Unify entries
                    StructList8 <IPluralRule> optionalCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    StructList8 <IPluralRule> requiredCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    foreach (var c in entry.Cases)
                    {
                        if (c.Info.Optional == 1)
                        {
                            optionalCases.AddIfNew(c);
                        }
                        else if (c.Info.Optional == 0)
                        {
                            requiredCases.AddIfNew(c);
                        }
                    }
                    foreach (var c in cases)
                    {
                        if (c.Info.Optional == 1)
                        {
                            optionalCases.AddIfNew(c);
                        }
                        else if (c.Info.Optional == 0)
                        {
                            requiredCases.AddIfNew(c);
                        }
                    }
                    StructList8 <IPluralRule> allCases = new StructList8 <IPluralRule>(IPluralRuleComparer.Default);
                    for (int i = 0; i < optionalCases.Count; i++)
                    {
                        allCases.Add(optionalCases[i]);
                    }
                    for (int i = 0; i < requiredCases.Count; i++)
                    {
                        allCases.Add(requiredCases[i]);
                    }

                    // Create new entry
                    Entry newEntry = new Entry {
                        Cases = allCases.ToArray(), ArgumentIndex = argIx, OptionalCases = optionalCases.Count, RequiredCases = requiredCases.Count
                    };

                    // Update
                    arguments[prevIx] = newEntry;

                    this.Count  /= (1 + entry.Cases.Length);
                    this.Count  *= (1 + newEntry.Cases.Length);
                    this.count1 /= entry.Cases.Length;
                    this.count1 *= newEntry.Cases.Length;
                }
            }
        }
        /// <summary>
        /// Resolve <paramref name="key"/> into <see cref="IString"/>, but without applying format arguments.
        ///
        /// If the <see cref="IString"/> contains plural categories, then matches into the applicable plurality case.
        /// </summary>
        /// <param name="key"></param>
        /// <returns>format string</returns>
        public IString ResolveFormatString(ILine key)
        {
            // Extract parameters from line
            LineFeatures features = new LineFeatures {
                Resolvers = Resolvers
            };

            // Scan features
            try
            {
                features.ScanFeatures(key);
            }
            catch (Exception e)
            {
                features.Log(e);
                features.Status.UpResolve(LineStatus.ResolveFailedException);
                return(new StatusString(null, features.Status));
            }

            // Resolve key to line
            CultureInfo culture = features.Culture;
            ILine       line    = ResolveKeyToLine(key, ref features, ref culture);

            // No line or value
            if (line == null || !features.HasValue)
            {
                features.Status.UpResolve(LineStatus.ResolveFailedNoValue);
                LineString str = new LineString(key, (Exception)null, features.Status);
                features.Log(str);
                return(new StatusString(null, features.Status));
            }

            // Parse value
            IString value = features.EffectiveString;

            features.Status.Up(value.Status);

            // Value has error
            if (value.Parts == null || value.Status.Failed())
            {
                LineString str = new LineString(key, (Exception)null, features.Status);
                features.Log(str);
                return(new StatusString(null, features.Status));
            }

            // Plural Rules
            if (value.HasPluralRules())
            {
                if (features.PluralRules != null)
                {
                    // Evaluate expressions in placeholders into strings
                    StructList12 <string> placeholder_values = new StructList12 <string>();
                    CultureInfo           culture_for_format = features.Culture;
                    if (culture_for_format == null && features.CulturePolicy != null)
                    {
                        CultureInfo[] cultures = features.CulturePolicy.Cultures; if (cultures != null && cultures.Length > 0)
                        {
                            culture_for_format = cultures[0];
                        }
                    }
                    if (culture_for_format == null)
                    {
                        culture_for_format = CultureInfo.InvariantCulture;
                    }
                    EvaluatePlaceholderValues(key, line, null, value.Placeholders, ref features, ref placeholder_values, culture_for_format);

                    // Create permutation configuration
                    PluralCasePermutations permutations = new PluralCasePermutations(line);
                    for (int i = 0; i < value.Placeholders.Length; i++)
                    {
                        // Get placeholder
                        IPlaceholder placeholder = value.Placeholders[i];
                        // No plural category in this placeholder
                        if (placeholder.PluralCategory == null)
                        {
                            continue;
                        }
                        // Placeholder value after evaluation
                        string ph_value = placeholder_values[i];
                        // Placeholder evaluated value
                        IPluralNumber placeholderValue = ph_value == null ? DecimalNumber.Empty : new DecimalNumber.Text(ph_value?.ToString(), culture);
                        // Add placeholder to permutation configuration
                        permutations.AddPlaceholder(placeholder, placeholderValue, features.PluralRules, culture?.Name ?? "");
                    }

                    // Find first value that matches permutations
                    features.CulturePolicy = null;
                    features.String        = null;
                    features.StringText    = null;
                    for (int i = 0; i < permutations.Count - 1; i++)
                    {
                        // Create key with plurality cases
                        ILine key_with_plurality = permutations[i];
                        // Search line with the key
                        ILine line_for_plurality_arguments = ResolveKeyToLine(key_with_plurality, ref features, ref culture);
                        // Got no match
                        if (line_for_plurality_arguments == null)
                        {
                            continue;
                        }
                        // Parse value
                        IString value_for_plurality = line_for_plurality_arguments.GetString(Resolvers);
                        // Add status from parsing the value
                        features.Status.Up(value_for_plurality.Status);
                        // Value has error
                        if (value_for_plurality.Parts == null || value_for_plurality.Status.Failed())
                        {
                            LineString str = new LineString(key, (Exception)null, features.Status);
                            features.Log(str);
                            return(new StatusString(null, features.Status));
                        }
                        // Return with match
                        features.Status.UpPlurality(LineStatus.PluralityOkMatched);
                        // Update status codes
                        features.Status.Up(value_for_plurality.Status);
                        // Return values
                        value = value_for_plurality;
                        line  = line_for_plurality_arguments;
                        break;
                    }
                }
                else
                {
                    // Plural rules were not found
                    features.Status.Up(LineStatus.PluralityErrorRulesNotFound);
                }
            }
            else
            {
                // Plurality feature was not used.
                features.Status.UpPlurality(LineStatus.PluralityOkNotUsed);
            }

            return(value);
        }
        /// <summary>
        /// Resolve <paramref name="key"/> into <see cref="LineString"/> with format arguments applied.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public LineString ResolveString(ILine key)
        {
            // Extract parameters from line
            LineFeatures features = new LineFeatures {
                Resolvers = Resolvers
            };

            // Scan features
            try
            {
                features.ScanFeatures(key);
            }
            catch (Exception e)
            {
                features.Log(e);
                features.Status.UpResolve(LineStatus.ResolveFailedException);
                return(new LineString(key, e, features.Status));
            }

            try
            {
                // Resolve key to line
                CultureInfo culture = features.Culture;
                ILine       line    = ResolveKeyToLine(key, ref features, ref culture);

                // No line or value
                if (line == null || !features.HasValue)
                {
                    features.Status.UpResolve(LineStatus.ResolveFailedNoValue);
                    LineString str = new LineString(key, (Exception)null, features.Status);
                    features.Log(str);
                    return(str);
                }

                // Parse value
                IString value = features.EffectiveString;
                features.Status.Up(value.Status);

                // Value has error
                if (value.Parts == null || value.Status.Failed())
                {
                    LineString str = new LineString(key, (Exception)null, features.Status);
                    features.Log(str);
                    return(str);
                }

                // Evaluate expressions in placeholders into strings
                StructList12 <string> placeholder_values = new StructList12 <string>();
                CultureInfo           culture_for_format = features.Culture;
                if (culture_for_format == null && features.CulturePolicy != null)
                {
                    CultureInfo[] cultures = features.CulturePolicy.Cultures; if (cultures != null && cultures.Length > 0)
                    {
                        culture_for_format = cultures[0];
                    }
                }
                if (culture_for_format == null)
                {
                    culture_for_format = CultureInfo.InvariantCulture;
                }
                EvaluatePlaceholderValues(key, line, null, value.Placeholders, ref features, ref placeholder_values, culture_for_format);

                // Plural Rules
                if (value.HasPluralRules())
                {
                    if (features.PluralRules != null)
                    {
                        // Create permutation configuration
                        PluralCasePermutations permutations = new PluralCasePermutations(line);
                        for (int i = 0; i < value.Placeholders.Length; i++)
                        {
                            // Get placeholder
                            IPlaceholder placeholder = value.Placeholders[i];
                            // No plural category in this placeholder
                            if (placeholder.PluralCategory == null)
                            {
                                continue;
                            }
                            // Placeholder value after evaluation
                            string ph_value = placeholder_values[i];
                            // Placeholder evaluated value
                            IPluralNumber placeholderValue = ph_value == null ? DecimalNumber.Empty : new DecimalNumber.Text(ph_value?.ToString(), culture);
                            // Add placeholder to permutation configuration
                            permutations.AddPlaceholder(placeholder, placeholderValue, features.PluralRules, culture?.Name ?? "");
                        }

                        if (permutations.ArgumentCount <= MaxPluralArguments)
                        {
                            // Find first value that matches permutations
                            features.CulturePolicy = null;
                            features.String        = null;
                            features.StringText    = null;
                            for (int i = 0; i < permutations.Count - 1; i++)
                            {
                                // Create key with plurality cases
                                ILine key_with_plurality = permutations[i];
                                // Search line with the key
                                ILine line_for_plurality_arguments = ResolveKeyToLine(key_with_plurality, ref features, ref culture);
                                // Got no match
                                if (line_for_plurality_arguments == null)
                                {
                                    continue;
                                }
                                // Scan value
                                try
                                {
                                    features.ScanValueFeature(line_for_plurality_arguments);
                                }
                                catch (Exception e)
                                {
                                    features.Log(e);
                                    features.Status.Up(LineStatus.FailedUnknownReason);
                                    return(new LineString(key, e, features.Status));
                                }
                                // Parse value
                                IString value_for_plurality = features.EffectiveString;
                                // Add status from parsing the value
                                features.Status.Up(value_for_plurality.Status);
                                // Value has error
                                if (value_for_plurality.Parts == null || value_for_plurality.Status.Failed())
                                {
                                    LineString str = new LineString(key, (Exception)null, features.Status);
                                    features.Log(str);
                                    return(str);
                                }
                                // Return with match
                                features.Status.UpPlurality(LineStatus.PluralityOkMatched);
                                // Evaluate placeholders again
                                if (!EqualPlaceholders(value, value_for_plurality))
                                {
                                    placeholder_values.Clear(); EvaluatePlaceholderValues(key, line, line_for_plurality_arguments, value_for_plurality.Placeholders, ref features, ref placeholder_values, culture);
                                }
                                // Update status codes
                                features.Status.Up(value_for_plurality.Status);
                                // Return values
                                value = value_for_plurality;
                                line  = line_for_plurality_arguments;
                                break;
                            }
                        }
                        else
                        {
                            features.Status.UpPlaceholder(LineStatus.PluralityErrorMaxPluralArgumentsExceeded);
                        }
                    }
                    else
                    {
                        // Plural rules were not found
                        features.Status.Up(LineStatus.PluralityErrorRulesNotFound);
                    }
                }
                else
                {
                    // Plurality feature was not used.
                    features.Status.UpPlurality(LineStatus.PluralityOkNotUsed);
                }

                // Put string together
                string text = null;

                if (value == null || value.Parts == null)
                {
                    text = null;
                }

                // Only one part
                else if (value.Parts.Length == 1)
                {
                    if (value.Parts[0].Kind == StringPartKind.Text)
                    {
                        text = value.Parts[0].Text;
                        features.Status.UpStringFormat(LineStatus.StringFormatOkString);
                    }
                    else if (value.Parts[0].Kind == StringPartKind.Placeholder)
                    {
                        text = placeholder_values[0];
                        features.Status.UpStringFormat(LineStatus.StringFormatOkString);
                    }
                }
                // Compile multiple parts
                else
                {
                    // Calculate length
                    int length = 0;
                    for (int i = 0; i < value.Parts.Length; i++)
                    {
                        IStringPart part     = value.Parts[i];
                        string      partText = part.Kind switch { StringPartKind.Text => part.Text, StringPartKind.Placeholder => placeholder_values[((IPlaceholder)part).PlaceholderIndex], _ => null };
                        if (partText != null)
                        {
                            length += partText.Length;
                        }
                    }

                    // Copy characters
                    char[] arr = new char[length];
                    int    ix  = 0;
                    for (int i = 0; i < value.Parts.Length; i++)
                    {
                        IStringPart part = value.Parts[i];
                        string      str  = part.Kind switch { StringPartKind.Text => part.Text, StringPartKind.Placeholder => placeholder_values[((IPlaceholder)part).PlaceholderIndex], _ => null };
                        if (str != null)
                        {
                            str.CopyTo(0, arr, ix, str.Length); ix += str.Length;
                        }
                    }

                    // String
                    text = new string(arr);
                    features.Status.UpStringFormat(LineStatus.StringFormatOkString);
                }

                // Create result
                LineString result = new LineString(key, text, features.Status);

                // Log
                features.Log(result);

                // Return
                return(result);
            } catch (Exception e)
            {
                // Capture unexpected error
                features.Log(e);
                features.Status.UpResolve(LineStatus.ResolveFailedException);
                LineString lineString = new LineString(key, e, features.Status);
                features.Log(lineString);
                return(lineString);
            }
        }
 /// <summary>
 /// Get default value (as " ?? value" expression at the end) , if has one.
 /// </summary>
 /// <param name="placeholder"></param>
 /// <returns>Default value or null</returns>
 public static object DefaultValue(this IPlaceholder placeholder)
 => placeholder.Expression is IBinaryOpExpression bop && bop.Op == BinaryOp.Coalesce ? bop.Right is IConstantExpression ce ? ce.Value : null : null;