1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// Generates a markdown document for the configuration file based on the schema.
struct OptionDocumentBuilder {
static let preamble = """
<!-- DO NOT EDIT THIS FILE. This file is generated by \(#fileID). -->
# Configuration File
`.sourcekit-lsp/config.json` configuration files can be used to modify the behavior of SourceKit-LSP in various ways. The following locations are checked. Settings in later configuration files override settings in earlier configuration files
- `~/.sourcekit-lsp/config.json`
- On macOS: `~/Library/Application Support/org.swift.sourcekit-lsp/config.json` from the various `Library` folders on the system
- If the `XDG_CONFIG_HOME` environment variable is set: `$XDG_CONFIG_HOME/sourcekit-lsp/config.json`
- Initialization options passed in the initialize request
- A `.sourcekit-lsp/config.json` file in a workspace’s root
The structure of the file is currently not guaranteed to be stable. Options may be removed or renamed.
## Structure
`config.json` is a JSON file with the following structure. All keys are optional and unknown keys are ignored.
"""
let context: OptionSchemaContext
/// Builds a markdown document for the configuration file based on the schema.
func build(from schema: OptionTypeSchama) throws -> String {
var doc = Self.preamble
func appendProperty(_ property: OptionTypeSchama.Property, indentLevel: Int) throws {
let indent = String(repeating: " ", count: indentLevel)
let name = property.name
doc += "\(indent)- `\(name)"
let type = property.type
let typeDescription: String?
switch type.kind {
case .struct:
// Skip struct type as we describe its properties in the next level
typeDescription = nil
default:
typeDescription = Self.typeToDisplay(type)
}
if let typeDescription {
doc += ": \(typeDescription)`:"
} else {
doc += "`:"
}
if let description = property.description {
doc += " " + description.split(separator: "\n").joined(separator: "\n\(indent) ")
}
doc += "\n"
switch type.kind {
case .struct(let schema):
for property in schema.properties {
try appendProperty(property, indentLevel: indentLevel + 1)
}
case .enum(let schema):
for caseInfo in schema.cases {
// Add detailed description for each case if available
guard let description = caseInfo.description else {
continue
}
doc += "\(indent) - `\(caseInfo.name)`"
doc += ": " + description.split(separator: "\n").joined(separator: "\n\(indent) ")
doc += "\n"
}
default: break
}
}
guard case .struct(let schema) = schema.kind else {
throw ConfigSchemaGenError("Root schema must be a struct")
}
for property in schema.properties {
try appendProperty(property, indentLevel: 0)
}
return doc
}
static func typeToDisplay(_ type: OptionTypeSchama, shouldWrap: Bool = false) -> String {
switch type.kind {
case .boolean: return "boolean"
case .integer: return "integer"
case .number: return "number"
case .string: return "string"
case .array(let value):
return "\(typeToDisplay(value, shouldWrap: true))[]"
case .dictionary(let value):
return "[string: \(typeToDisplay(value))]"
case .struct(let structInfo):
return structInfo.name
case .enum(let enumInfo):
let cases = enumInfo.cases.map { "\"\($0.name)\"" }.joined(separator: "|")
return shouldWrap ? "(\(cases))" : cases
}
}
}
|