/// <summary> /// Create a <see cref="CompletionItem"/> for the specified MSBuild task element. /// </summary> /// <param name="taskName"> /// The MSBuild task name. /// </param> /// <param name="taskMetadata"> /// The MSBuild task's metadata. /// </param> /// <param name="replaceRange"> /// The range of text that will be replaced by the completion. /// </param> /// <returns> /// The <see cref="CompletionItem"/>. /// </returns> CompletionItem TaskElementCompletionItem(string taskName, MSBuildTaskMetadata taskMetadata, LspModels.Range replaceRange) { MSBuildTaskParameterMetadata[] requiredParameters = taskMetadata.Parameters.Where(parameter => parameter.IsRequired).ToArray(); string requiredAttributes = String.Join(" ", requiredParameters.Select( (parameter, index) => $"{parameter.Name}=\"${index + 1}\"" )); string attributePadding = (requiredAttributes.Length > 0) ? " " : String.Empty; string restOfElement = " />$0"; if (taskMetadata.Parameters.Any(parameter => parameter.IsOutput)) { // Create Outputs sub-element if there are any output parameters. restOfElement = $">\n\t${requiredParameters.Length + 1}\n</{taskName}>$0"; } return(new CompletionItem { Label = $"<{taskName}>", Detail = "Task", Documentation = MSBuildSchemaHelp.ForTask(taskName), SortText = $"{Priority:0000}<{taskName}>", TextEdit = new TextEdit { NewText = $"<{taskName}{attributePadding}{requiredAttributes}{restOfElement}", Range = replaceRange }, InsertTextFormat = InsertTextFormat.Snippet }); }