/// <summary>
        /// Gets the <see cref="BumpVersionDescriptor"/> corresponding to the
        /// <paramref name="item"/>.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        internal static BumpVersionDescriptor ToDescriptor(this ITaskItem item
                                                           , TaskLoggingHelper log = null)
        {
            // TODO: TBD: To Descriptor? used in what way?
            var descriptor = new BumpVersionDescriptor(item);

            // TODO: TBD: may combine these into a common area...
            void SetPropertyFromMetadata <T>(string metadataName, Func <string, T> convert
                                             , Action <BumpVersionDescriptor, T> setter)
            {
                if (item.HasMetadataName(metadataName))
                {
                    setter(descriptor, convert(item.GetMetadata(metadataName)));
                }
            }

            SetPropertyFromMetadata(UseUtc, bool.Parse, (d, x) => d.UseUtc                   = x);
            SetPropertyFromMetadata(CreateNew, bool.Parse, (d, x) => d.CreateNew             = x);
            SetPropertyFromMetadata(MayReset, bool.Parse, (d, x) => d.MayReset               = x);
            SetPropertyFromMetadata(IncludeWildcard, bool.Parse, (d, x) => d.IncludeWildcard = x);
            SetPropertyFromMetadata(DefaultVersion, s => s, (d, s) => d.DefaultVersion       = s);

            // TODO: TBD: look into it, see if there is a way that Property Groups could be used instead, i.e. that do not appear as "project items" ...
            // TODO: TBD: they must include attributes, etc...
            VersionKind ParseVersionKind(string s)
            {
                var kind = s.ToNullableVersionKind();

                if (kind != null)
                {
                    return(kind.Value);
                }

                IEnumerable <string> GetVersionKindListing()
                => from k in Enum.GetValues(typeof(VersionKind)).OfType <VersionKind>()
                select $"'{k}'";

                throw new InvalidOperationException(
                          $"Expecting '{typeof(ITaskItem).FullName + '.' + nameof(ITaskItem.ItemSpec)}' to be among: {{ {Join(", ", GetVersionKindListing())} }}"
                          );
            }

            descriptor.Kind = ParseVersionKind(item.ItemSpec);

#if TASK_LOGGING_HELPER_DIAGNOSTICS
            log?.LogWarning($"Parsed version kind '{descriptor.Kind}'.");
#endif

            return(descriptor);
        }
        /// <summary>
        /// Returns a <see cref="IVersionProvider"/> corresponding to the
        /// <paramref name="item"/>, <paramref name="providerRequest"/>, and
        /// <paramref name="timestamp"/>.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="providerRequest"></param>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        /// <see cref="!:http://semver.org/#spec-item-9"/>
        internal static IVersionProvider ToVersionProvider(this ITaskItem item
                                                           , string providerRequest, DateTime timestamp)
        {
            var preq = providerRequest;

            IVersionProvider Lookup()
            => item.HasMetadataName(preq)
                    ? item.GetMetadata(preq).LookupVersionProvider()
                    : NoOp;

            var provider = Lookup();

            int ParseInteger(string s) => int.Parse(s);
            bool ParseBoolean(string s) => bool.Parse(s);

            // ReSharper disable once ImplicitlyCapturedClosure
            void SetPropertyFromMetadata <T>(string metadataName, Func <string, T> convert
                                             , Action <IVersionProvider, T> setProviderAttribute)
            {
                if (!item.HasMetadataName(metadataName))
                {
                    return;
                }

                setProviderAttribute(provider, convert(item.GetMetadata(metadataName)));
            }

            SetPropertyFromMetadata($"{preq}{nameof(IVersionProvider.MayReset)}"
                                    , ParseBoolean, (versionProvider, x) => versionProvider.MayReset = x);

            // May specify whether to UseUtc across the entire request, or for specific Version Elements.
            SetPropertyFromMetadata($"{preq}{nameof(IVersionProvider.UseUtc)}"
                                    , ParseBoolean, (versionProvider, x) => versionProvider.SetTimestamp(timestamp, x));

            /* Most of the Providers are "vanilla" with base options. However, in a
             * couple of instances there are specialized options that we can expect. */

            // ReSharper disable once InvertIf
            if (provider is PreReleaseIncrementVersionProvider preReleaseProvider)
            {
                string FilterLabel(string s)
                {
                    s = s.Trim();

                    /* TODO: TBD: may want this to be a subset involving just the alpha characters, and maybe
                    * the hypen as well, but not the digits on account that is the Value of this Provider. */

                    const string acceptablePattern = @"^[0-9A-Za-z\-]+$";

                    if (IsNullOrEmpty(s))
                    {
                        // This is acceptable.
                    }
                    else if (!IsMatch(s, acceptablePattern))
                    {
                        /* This according to Semantic Versioning 2.0.0: http://semver.org/#spec-item-9.
                         * Not matching now, however, is not acceptable. */
                        throw new InvalidOperationException(
                                  $"Label '{s}' contains invalid Semantic Version characters '{acceptablePattern}'."
                                  );
                    }

                    return(s);
                }

                SetPropertyFromMetadata($"{preq}{nameof(preReleaseProvider.Label)}"
                                        , FilterLabel, (_, x) => preReleaseProvider.Label = x);

                SetPropertyFromMetadata($"{preq}{nameof(preReleaseProvider.ValueWidth)}"
                                        , ParseInteger, (_, x) => preReleaseProvider.ValueWidth = x);

                SetPropertyFromMetadata($"{preq}{nameof(preReleaseProvider.ShouldDiscard)}"
                                        , ParseBoolean, (_, x) => preReleaseProvider.ShouldDiscard = x);
            }

            return(provider);
        }