Repository: CreateAPI/CreateAPI (swift)

Issue:
Simplify `comments` configuration
The `comments` configuration is currently an object with 5 customisations expressed as Bool and 1 main `isEnabled` flag.

In my head, we could express this the same way with an enum/option set of values and a single `commentFeatures` array/set.. Something like the following:

**Disable Comments:**
```yaml
commentFeatures: []
```

**Everything:**
```yaml
commentFeatures:
- title
- description
- example
- externalDocumentation
- capitalized
```

**Description (capitalized):**
```yaml
commentFeatures:
- description
- capitalized
```

In Swift, this would be something like the following:

```swift
public enum CommentFeature: String {
    case title, description, example, externalDocumentation, capitalized
}

public var commentFeatures: Set<CommentFeature> = [.title, .description, .example, .externalDocumentation, .capitalized]
```

Alternatively I'll just deswiftify the boolean properties on the existing object.

Pull request description:
- Closes #98 

Prior to this change, we had a whole object dedicated to configuration flags relating to generating comments. While this was the default, it looked somewhat like this when used:

**Disabling Comments**
```yaml
comments:
  isEnabled: false
```

**Generating Title and Description Only**
```yaml
comments:
  isAddingExamples: false
  isAddingExternalLinks: false
  isCapitalizationEnabled: false
```

**Generate everything without auto-capitalisation:**
```yaml
comments:
  isCapitalizationEnabled: false
```

It's relatively straightforward to use, but since I needed to rename all of the properties (#99), I thought it might be nicer to simplify it into an options set instead since its more expressive for what you are actually getting. For example:

**Disabling Comments**
```yaml
commentOptions: []
```

**Generating Title and Description Only**
```yaml
commentOptions: [title, description, capitalized]
```

**Generate everything without auto-capitalisation:**
```yaml
commentOptions:
- title
- description
- example
- externalLinks
```

As with other 0.1 changes, I've removed the old options and marked `commentOptions` as replacing `comments` to help produce a nicer warning when migrating.

Patch:
diff --git a/Docs/ConfigOptions.md b/Docs/ConfigOptions.md
index 538bb07a..7ee11cd7 100644
--- a/Docs/ConfigOptions.md
+++ b/Docs/ConfigOptions.md
@@ -57,13 +57,7 @@ Below you can find the complete documentation for all available options.
 - [useNaiveDate](#usenaivedate)
 - [useIntegersWithPredefinedCapacity](#useintegerswithpredefinedcapacity)
 - [fileHeaderComment](#fileheadercomment)
-- [comments](#comments)
-  - [isEnabled](#commentsisenabled)
-  - [isAddingTitles](#commentsisaddingtitles)
-  - [isAddingDescription](#commentsisaddingdescription)
-  - [isAddingExamples](#commentsisaddingexamples)
-  - [isAddingExternalDocumentation](#commentsisaddingexternaldocumentation)
-  - [isCapitalizationEnabled](#commentsiscapitalizationenabled)
+- [commentOptions](#commentoptions)
 - [entities](#entities)
   - [generateStructs](#entitiesgeneratestructs)
   - [entitiesGeneratedAsClasses](#entitiesentitiesgeneratedasclasses)
@@ -239,63 +233,46 @@ Overrides file header comment
 
 <br/>
 
+## commentOptions
 
-# Comments
+**Type:** Set<CommentOption><br />
+**Default:** `[.title, .description, .example, .externalDocumentation, .capitalized]`
 
-Customize specific behaviors when generating comments on entities/paths/properties.
+Options used when generating comments.
 
+**Available options:**
+- `title` - Include the schema title (if available)
+- `description` - Include the schema description (if available)
+- `example` - Include the schema example value (if available)
+- `externalDocumentation` - Include a markdown formatted link to the schema's external documentation (if available)
+- `capitalized` - Automatically capitalize the comments
 
-## comments.isEnabled
+To disable comments completely, set this property to an empty array.
 
-**Type:** Bool<br />
-**Default:** `true`
-
-Set to false to disable the generation of comments
-
-<br/>
-
-## comments.isAddingTitles
-
-**Type:** Bool<br />
-**Default:** `true`
-
-Include the schema title when generating comments
-
-<br/>
-
-## comments.isAddingDescription
-
-**Type:** Bool<br />
-**Default:** `true`
-
-Include the schema description when generating comments
-
-<br/>
-
-## comments.isAddingExamples
-
-**Type:** Bool<br />
-**Default:** `true`
-
-Include the schema example when generating comments
-
-<br/>
-
-## comments.isAddingExternalDocumentation
-
-**Type:** Bool<br />
-**Default:** `true`
-
-Include a link to external documentation when generating comments
+<details>
+<summary>Examples</summary>
 
-<br/>
+**No Comments**
+```yaml
+commentOptions: []
+```
 
-## comments.isCapitalizationEnabled
+**Simple Comment**
+```yaml
+commentOptions: [description, capitalized]
+```
 
-**Type:** Bool<br />
-**Default:** `true`
+**Detailed Comment** (default)
+```yaml
+commentOptions:
+- title
+- description
+- example
+- externalDocumentation
+- capitalized
+```
 
-Auto-capitalize comments
+</details>
 
 <br/>
 
diff --git a/Sources/CreateAPI/Generator/Templates.swift b/Sources/CreateAPI/Generator/Templates.swift
index 900434cf..229d800b 100644
--- a/Sources/CreateAPI/Generator/Templates.swift
+++ b/Sources/CreateAPI/Generator/Templates.swift
@@ -416,37 +416,35 @@ final class Templates {
 
     /// Generates inline comments for a declaration containing a title, description, and examples.
     func comments(for metadata: DeclarationMetadata, name: String, isProperty: Bool = false) -> String {
-        let options = options.comments
-        guard options.isEnabled else {
-            return ""
-        }
+        guard options.commentsEnabled else { return "" }
+        let options = options.commentOptions
         var output = ""
 
         var title = metadata.title ?? ""
         var description = metadata.description ?? ""
-        if title == description && options.isAddingTitles && options.isAddingDescription {
+        if title == description && options.contains(.title) && options.contains(.description) {
             description = ""
         }
         if title.components(separatedBy: .whitespaces).joined(separator: "").caseInsensitiveCompare(name) == .orderedSame {
             title = ""
         }
 
-        if options.isAddingTitles, !title.isEmpty {
-            let title = options.isCapitalizationEnabled ? title.capitalizingFirstLetter() : title
+        if options.contains(.title), !title.isEmpty {
+            let title = options.contains(.capitalized) ? title.capitalizingFirstLetter() : title
             for line in title.lines {
                 output += "/// \(line)\n"
             }
         }
-        if options.isAddingDescription, !description.isEmpty, description != metadata.title {
+        if options.contains(.description), !description.isEmpty, description != metadata.title {
             if !output.isEmpty {
                 output += "///\n"
             }
-            let description = options.isCapitalizationEnabled ? description.capitalizingFirstLetter() : description
+            let description = options.contains(.capitalized) ? description.capitalizingFirstLetter() : description
             for line in description.lines {
                 output += "/// \(line)\n"
             }
         }
-        if options.isAddingExamples, let example = metadata.example?.value {
+        if options.contains(.example), let example = metadata.example?.value {
             let value: String
 
             if let example = example as? String, !example.hasPrefix("\"") {
@@ -478,7 +476,7 @@ final class Templates {
                 }
             }
         }
-        if options.isAddingExternalDocumentation, let docsURL = metadata.externalDocsURL {
+        if options.contains(.externalDocumentation), let docsURL = metadata.externalDocsURL {
             if !output.isEmpty {
                 output += "///\n"
             }
@@ -542,9 +540,9 @@ final class Templates {
             name = PropertyName(processing: String(property.key.dropFirst(2)), options: options).rawValue
         }
         var output = ""
-        if options.comments.isEnabled, options.comments.isAddingDescription,
+        if options.commentsEnabled, options.commentOptions.contains(.description),
            let description = header.description, !description.isEmpty {
-            let description = options.comments.isCapitalizationEnabled ? description.capitalizingFirstLetter() : description
+            let description = options.commentOptions.contains(.capitalized) ? description.capitalizingFirstLetter() : description
             for line in description.lines {
                 output += "/// \(line)\n"
             }
diff --git a/Sources/CreateOptions/ConfigOptions+DecodableWithDefault.swift b/Sources/CreateOptions/ConfigOptions+DecodableWithDefault.swift
index 777b5ea5..19a5f210 100644
--- a/Sources/CreateOptions/ConfigOptions+DecodableWithDefault.swift
+++ b/Sources/CreateOptions/ConfigOptions+DecodableWithDefault.swift
@@ -19,7 +19,7 @@ extension ConfigOptions: Decodable {
         case useNaiveDate
         case useIntegersWithPredefinedCapacity
         case fileHeaderComment
-        case comments
+        case commentOptions
         case entities
         case paths
         case rename
@@ -98,9 +98,9 @@ extension ConfigOptions: Decodable {
             defaultValue: "// Generated by Create API\n// https://github.com/CreateAPI/CreateAPI"
         )
 
-        comments = try container.decode(Comments.self,
-            forKey: .comments,
-            defaultValue: .init()
+        commentOptions = try container.decode(Set<CommentOption>.self,
+            forKey: .commentOptions,
+            defaultValue: [.title, .description, .example, .externalDocumentation, .capitalized]
         )
 
         entities = try container.decode(Entities.self,
@@ -129,64 +129,13 @@ extension ConfigOptions: Decodable {
                 ("isPluralizationEnabled", "Use 'pluralizeProperties' instead."),
                 ("isNaiveDateEnabled", "Use 'useNaiveDate' instead."),
                 ("isUsingIntegersWithPredefinedCapacity", "Use 'useIntegersWithPredefinedCapacity' instead."),
+                ("comments", "Use 'commentOptions' instead."),
                 ("isSwiftLintDisabled", "Add to 'fileHeaderComment' instead."),
             ]
         )
     }
 }
 
-extension ConfigOptions.Comments: Decodable {
-    enum KnownKeys: String {
-        case isEnabled
-        case isAddingTitles
-        case isAddingDescription
-        case isAddingExamples
-        case isAddingExternalDocumentation
-        case isCapitalizationEnabled
-    }
-
-    public init(from decoder: Decoder) throws {
-        let container = try StringCodingContainer<KnownKeys>(decoder: decoder)
-
-        isEnabled = try container.decode(Bool.self,
-            forKey: .isEnabled,
-            defaultValue: true
-        )
-
-        isAddingTitles = try container.decode(Bool.self,
-            forKey: .isAddingTitles,
-            defaultValue: true
-        )
-
-        isAddingDescription = try container.decode(Bool.self,
-            forKey: .isAddingDescription,
-            defaultValue: true
-        )
-
-        isAddingExamples = try container.decode(Bool.self,
-            forKey: .isAddingExamples,
-            defaultValue: true
-        )
-
-        isAddingExternalDocumentation = try container.decode(Bool.self,
-            forKey: .isAddingExternalDocumentation,
-            defaultValue: true
-        )
-
-        isCapitalizationEnabled = try container.decode(Bool.self,
-            forKey: .isCapitalizationEnabled,
-            defaultValue: true
-        )
-
-        container.recordPotentialIssues(
-            deprecations: [
-            ],
-            replacements: [
-            ]
-        )
-    }
-}
-
 extension ConfigOptions.Entities: Decodable {
     enum KnownKeys: String {
         case generateStructs
diff --git a/Sources/CreateOptions/ConfigOptions.swift b/Sources/CreateOptions/ConfigOptions.swift
index 0a0c6139..2050127d 100644
--- a/Sources/CreateOptions/ConfigOptions.swift
+++ b/Sources/CreateOptions/ConfigOptions.swift
@@ -114,28 +114,50 @@ public struct ConfigOptions: Encodable {
     /// Overrides file header comment
     public var fileHeaderComment: String = "// Generated by Create API\n// https://github.com/CreateAPI/CreateAPI"
 
-    public var comments: Comments = .init()
-
-    // sourcery: document, decodableWithDefault
-    /// Customize specific behaviors when generating comments on entities/paths/properties.
-    public struct Comments: Encodable {
-        /// Set to false to disable the generation of comments
-        public var isEnabled: Bool = true
-
-        /// Include the schema title when generating comments
-        public var isAddingTitles: Bool = true
-
-        /// Include the schema description when generating comments
-        public var isAddingDescription: Bool = true
-
-        /// Include the schema example when generating comments
-        public var isAddingExamples: Bool = true
-
-        /// Include a link to external documentation when generating comments
-        public var isAddingExternalDocumentation: Bool = true
+    public enum CommentOption: String, Codable {
+        case title, description, example, externalDocumentation, capitalized
+    }
 
-        /// Auto-capitalize comments
-        public var isCapitalizationEnabled: Bool = true
+    /// Options used when generating comments.
+    ///
+    /// **Available options:**
+    /// - `title` - Include the schema title (if available)
+    /// - `description` - Include the schema description (if available)
+    /// - `example` - Include the schema example value (if available)
+    /// - `externalDocumentation` - Include a markdown formatted link to the schema's external documentation (if available)
+    /// - `capitalized` - Automatically capitalize the comments
+    ///
+    /// To disable comments completely, set this property to an empty array.
+    ///
+    /// <details>
+    /// <summary>Examples</summary>
+    ///
+    /// **No Comments**
+    /// ```yaml
+    /// commentOptions: []
+    /// ```
+    ///
+    /// **Simple Comment**
+    /// ```yaml
+    /// commentOptions: [description, capitalized]
+    /// ```
+    ///
+    /// **Detailed Comment** (default)
+    /// ```yaml
+    /// commentOptions:
+    /// - title
+    /// - description
+    /// - example
+    /// - externalDocumentation
+    /// - capitalized
+    /// ```
+    ///
+    /// </details>
+    public var commentOptions: Set<CommentOption> = [.title, .description, .example, .externalDocumentation, .capitalized] // sourcery: replacementFor = comments
+
+    /// `true` if `commentOptions` have been defined
+    public var commentsEnabled: Bool {
+        !commentOptions.isEmpty
     }
 
     public var entities: Entities = .init()


Test patch:
diff --git a/Tests/CreateAPITests/GenerateOptionsTests.swift b/Tests/CreateAPITests/GenerateOptionsTests.swift
index 37e14aa6..0fb83d54 100644
--- a/Tests/CreateAPITests/GenerateOptionsTests.swift
+++ b/Tests/CreateAPITests/GenerateOptionsTests.swift
@@ -220,9 +220,7 @@ final class GenerateOptionsTests: GenerateBaseTests {
             "--package", "petstore-disable-comments",
             "--config", config("""
             {
-                "comments": {
-                    "isEnabled": false
-                }
+                "commentOptions": []
             }
             """)
         ])