/// <summary>
        ///     Get task attribute completions.
        /// </summary>
        /// <param name="projectDocument">
        ///     The <see cref="ProjectDocument"/> for which completions will be offered.
        /// </param>
        /// <param name="taskMetadata">
        ///     Metadata for the task whose parameters are being offered as completions.
        /// </param>
        /// <param name="existingAttributeNames">
        ///     Existing parameter names (if any) declared on the element.
        /// </param>
        /// <param name="replaceRange">
        ///     The range of text to be replaced by the completions.
        /// </param>
        /// <param name="needsPadding">
        ///     The type of padding (if any) required.
        /// </param>
        /// <returns>
        ///     A sequence of <see cref="CompletionItem"/>s.
        /// </returns>
        public IEnumerable <CompletionItem> GetCompletionItems(ProjectDocument projectDocument, MSBuildTaskMetadata taskMetadata, HashSet <string> existingAttributeNames, Range replaceRange, PaddingType needsPadding)
        {
            if (replaceRange == null)
            {
                throw new ArgumentNullException(nameof(replaceRange));
            }

            LspModels.Range replaceRangeLsp = replaceRange.ToLsp();

            foreach (MSBuildTaskParameterMetadata taskParameter in taskMetadata.Parameters.OrderBy(parameter => parameter.Name))
            {
                if (existingAttributeNames.Contains(taskParameter.Name))
                {
                    continue;
                }

                if (taskParameter.IsOutput)
                {
                    continue;
                }

                string parameterDocumentation = MSBuildSchemaHelp.ForTaskParameter(taskMetadata.Name, taskParameter.Name);

                yield return(TaskParameterCompletionItem(taskMetadata.Name, taskParameter, parameterDocumentation, replaceRangeLsp, needsPadding));
            }
        }