public void SetMetadata_UpdatesTaskAsExpected(string value)
        {
            // Arrange
            var item = new TaskItem("My Identity");
            var key  = "My key";

            // Act
            MetadataSerializer.SetMetadata(item, key, value);

            // Assert
            Assert.Equal(value, item.GetMetadata(key));
        }
        public void SetMetadata_UpdatesTaskAsExpected_WithLegacyItem(string value, string escapedValue)
        {
            // Arrange
            var item = new Mock <ITaskItem>(MockBehavior.Strict);
            var key  = "My key";

            item.Setup(i => i.SetMetadata(key, escapedValue)).Verifiable();

            // Act
            MetadataSerializer.SetMetadata(item.Object, key, value);

            // Assert
            item.Verify(i => i.SetMetadata(key, escapedValue), Times.Once);
        }
        /// <inheritdoc />
        public override bool Execute()
        {
            var outputs        = new List <ITaskItem>(Inputs.Length);
            var codeGenerators = new HashSet <string>();
            var destinations   = new HashSet <string>();

            foreach (var item in Inputs)
            {
                var codeGenerator = item.GetMetadata("CodeGenerator");
                if (string.IsNullOrEmpty(codeGenerator))
                {
                    // This case occurs when user overrides the required metadata with an empty string.
                    var type = string.IsNullOrEmpty(item.GetMetadata("SourceProject")) ?
                               "OpenApiReference" :
                               "OpenApiProjectReference";

                    Log.LogError(
                        Resources.FormatInvalidEmptyMetadataValue("CodeGenerator", "OpenApiReference", item.ItemSpec));
                    continue;
                }

                var newItem = new TaskItem(item);
                outputs.Add(newItem);

                if (codeGenerators.Add(codeGenerator))
                {
                    newItem.SetMetadata("FirstForGenerator", "true");
                }
                else
                {
                    newItem.SetMetadata("FirstForGenerator", "false");
                }

                var outputPath = item.GetMetadata("OutputPath");
                if (string.IsNullOrEmpty(outputPath))
                {
                    // No need to further sanitize this path because the file must exist.
                    var filename     = item.GetMetadata("Filename");
                    var isTypeScript = codeGenerator.EndsWith(
                        TypeScriptLanguageName,
                        StringComparison.OrdinalIgnoreCase);

                    outputPath = $"{filename}Client{(isTypeScript ? ".ts" : Extension)}";
                }

                // Place output file in correct directory (relative to project directory).
                if (!Path.IsPathRooted(outputPath) && !string.IsNullOrEmpty(OutputDirectory))
                {
                    outputPath = Path.Combine(OutputDirectory, outputPath);
                }

                if (!destinations.Add(outputPath))
                {
                    // This case may occur when user is experimenting e.g. with multiple code generators or options.
                    // May also occur when user accidentally duplicates OutputPath metadata.
                    Log.LogError(Resources.FormatDuplicateFileOutputPaths(outputPath));
                    continue;
                }

                MetadataSerializer.SetMetadata(newItem, "OutputPath", outputPath);

                var className = item.GetMetadata("ClassName");
                if (string.IsNullOrEmpty(className))
                {
                    var outputFilename = Path.GetFileNameWithoutExtension(outputPath);

                    className = CSharpIdentifier.SanitizeIdentifier(outputFilename);
                    MetadataSerializer.SetMetadata(newItem, "ClassName", className);
                }

                var @namespace = item.GetMetadata("Namespace");
                if (string.IsNullOrEmpty(@namespace))
                {
                    MetadataSerializer.SetMetadata(newItem, "Namespace", Namespace);
                }

                // Add metadata which may be used as a property and passed to an inner build.
                newItem.RemoveMetadata("SerializedMetadata");
                newItem.SetMetadata("SerializedMetadata", MetadataSerializer.SerializeMetadata(newItem));
            }

            Outputs = outputs.ToArray();

            return(!Log.HasLoggedErrors);
        }