mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
128 lines
4.1 KiB
Swift
128 lines
4.1 KiB
Swift
//
|
|
// RulesDocsCommand.swift
|
|
// SwiftLint
|
|
//
|
|
// Created by Marcelo Fabri on 01/01/17.
|
|
// Copyright © 2017 Realm. All rights reserved.
|
|
//
|
|
|
|
import Commandant
|
|
import Result
|
|
import SwiftLintFramework
|
|
|
|
struct RulesDocsCommand: CommandProtocol {
|
|
let verb = "rules_docs"
|
|
let function = "Generates a markdown with all rules documentation"
|
|
|
|
func run(_ options: RulesDocsOptions) -> Result<(), CommandantError<()>> {
|
|
let rules = masterRuleList.list.sorted { $0.0 < $1.0 }.map { $0.value }
|
|
let rulesText = rules.map(ruleMarkdown)
|
|
let rulesSummary = rules.map(ruleSummary)
|
|
|
|
var text = h1("Rules")
|
|
text += rulesSummary.joined()
|
|
text += "--------\n"
|
|
text += rulesText.joined(separator: "\n\n")
|
|
|
|
if let path = options.path {
|
|
do {
|
|
try text.write(toFile: path, atomically: true, encoding: .utf8)
|
|
} catch {
|
|
return .failure(.usageError(description: error.localizedDescription))
|
|
}
|
|
} else {
|
|
queuedPrint(text)
|
|
}
|
|
|
|
return .success()
|
|
}
|
|
|
|
private func ruleSummary(_ rule: Rule.Type) -> String {
|
|
return summaryItem(rule.description.name)
|
|
}
|
|
|
|
private func ruleMarkdown(_ rule: Rule.Type) -> String {
|
|
let description = rule.description
|
|
var content = h2(description.name)
|
|
content += detailsSummary(rule.init())
|
|
content += description.description + "\n"
|
|
|
|
if !description.nonTriggeringExamples.isEmpty || !description.triggeringExamples.isEmpty {
|
|
content += h3("Examples")
|
|
}
|
|
|
|
if !description.nonTriggeringExamples.isEmpty {
|
|
let examples = description.nonTriggeringExamples.map(formattedCode).joined(separator: "\n")
|
|
content += details(summary: "Non Triggering Examples", details: examples)
|
|
}
|
|
|
|
if !description.triggeringExamples.isEmpty {
|
|
let examples = description.triggeringExamples.map(formattedCode).joined(separator: "\n")
|
|
content += details(summary: "Triggering Examples", details: examples)
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
private func details(summary: String, details: String) -> String {
|
|
var content = "<details>\n"
|
|
content += "<summary>\(summary)</summary>\n\n"
|
|
content += details + "\n"
|
|
content += "</details>\n"
|
|
|
|
return content
|
|
}
|
|
|
|
private func formattedCode(_ code: String) -> String {
|
|
var content = "```swift\n"
|
|
content += code
|
|
content += "\n```\n"
|
|
|
|
return content
|
|
}
|
|
|
|
private func detailsSummary(_ rule: Rule) -> String {
|
|
var content = "Identifier | Enabled by default | Supports autocorrection | Kind \n"
|
|
content += "--- | --- | --- | ---\n"
|
|
let identifier = type(of: rule).description.identifier
|
|
let defaultStatus = rule is OptInRule ? "Disabled" : "Enabled"
|
|
let correctable = rule is CorrectableRule ? "Yes" : "No"
|
|
let kind = type(of: rule).description.kind
|
|
content += "`\(identifier)` | \(defaultStatus) | \(correctable) | \(kind)\n\n"
|
|
|
|
return content
|
|
}
|
|
|
|
private func h1(_ text: String) -> String {
|
|
return "\n# \(text)\n\n"
|
|
}
|
|
|
|
private func h2(_ text: String) -> String {
|
|
return "\n## \(text)\n\n"
|
|
}
|
|
|
|
private func h3(_ text: String) -> String {
|
|
return "\n### \(text)\n\n"
|
|
}
|
|
|
|
private func summaryItem(_ text: String) -> String {
|
|
let anchor = text.lowercased().components(separatedBy: .whitespaces).joined(separator: "-")
|
|
return "* [\(text)](#\(anchor))\n"
|
|
}
|
|
}
|
|
|
|
struct RulesDocsOptions: OptionsProtocol {
|
|
let path: String?
|
|
|
|
static func create(_ path: String?) -> RulesDocsOptions {
|
|
return self.init(path: path)
|
|
}
|
|
|
|
static func evaluate(_ mode: CommandMode) -> Result<RulesDocsOptions, CommandantError<CommandantError<()>>> {
|
|
return create
|
|
<*> mode <| Option(key: "path", defaultValue: nil,
|
|
usage: "the path where the documentation should be saved. " +
|
|
"If not present, it'll be printed to the output.")
|
|
}
|
|
}
|