Skip to content

Commit 864af4d

Browse files
Add verify-config-schema command to sourcekit-lsp-dev-utils
1 parent e399754 commit 864af4d

File tree

4 files changed

+84
-11
lines changed

4 files changed

+84
-11
lines changed

SourceKitLSPDevUtils/Sources/ConfigSchemaGen/ConfigSchemaGen.swift

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ import SwiftSyntax
1919
/// (`.sourcekit-lsp/config.json`) from the Swift type definitions in
2020
/// `SKOptions` Swift module.
2121
public struct ConfigSchemaGen {
22+
public struct WritePlan {
23+
public let category: String
24+
public let path: URL
25+
public let contents: () throws -> Data
26+
27+
public func write() throws {
28+
try contents().write(to: path)
29+
}
30+
}
31+
2232
static let projectRoot = URL(fileURLWithPath: #filePath)
2333
.deletingLastPathComponent()
2434
.deletingLastPathComponent()
@@ -37,6 +47,14 @@ public struct ConfigSchemaGen {
3747
.appendingPathComponent("Configuration File.md")
3848

3949
public static func generate() throws {
50+
let plans = try plan()
51+
for plan in plans {
52+
print("Writing \(plan.category) to \"\(plan.path.path)\"")
53+
try plan.write()
54+
}
55+
}
56+
57+
public static func plan() throws -> [WritePlan] {
4058
let sourceFiles = FileManager.default.enumerator(at: sourceDir, includingPropertiesForKeys: nil)!
4159
let typeNameResolver = TypeDeclResolver()
4260

@@ -71,15 +89,20 @@ public struct ConfigSchemaGen {
7189
)
7290
)
7391

74-
print("Writing schema to \(configSchemaJSONPath.path)")
75-
try generateJSONSchema(from: schema, context: context).write(to: configSchemaJSONPath)
92+
var plans: [WritePlan] = []
7693

77-
print("Writing schema documentation to \(configSchemaDocPath.path)")
78-
try generateDocumentation(from: schema, context: context).write(
79-
to: configSchemaDocPath,
80-
atomically: true,
81-
encoding: .utf8
82-
)
94+
plans.append(WritePlan(
95+
category: "JSON Schema",
96+
path: configSchemaJSONPath,
97+
contents: { try generateJSONSchema(from: schema, context: context) }
98+
))
99+
100+
plans.append(WritePlan(
101+
category: "Schema Documentation",
102+
path: configSchemaDocPath,
103+
contents: { try generateDocumentation(from: schema, context: context) }
104+
))
105+
return plans
83106
}
84107

85108
static func generateJSONSchema(from schema: OptionTypeSchama, context: OptionSchemaContext) throws -> Data {
@@ -92,8 +115,22 @@ public struct ConfigSchemaGen {
92115
return try encoder.encode(jsonSchema)
93116
}
94117

95-
static func generateDocumentation(from schema: OptionTypeSchama, context: OptionSchemaContext) throws -> String {
118+
static func generateDocumentation(from schema: OptionTypeSchama, context: OptionSchemaContext) throws -> Data {
96119
let docBuilder = OptionDocumentBuilder(context: context)
97-
return try docBuilder.build(from: schema)
120+
guard let data = try docBuilder.build(from: schema).data(using: .utf8) else {
121+
throw ConfigSchemaGenError.documentationEncodingFailed
122+
}
123+
return data
124+
}
125+
}
126+
127+
enum ConfigSchemaGenError: Error, CustomStringConvertible {
128+
case documentationEncodingFailed
129+
130+
var description: String {
131+
switch self {
132+
case .documentationEncodingFailed:
133+
return "Failed to encode documentation as UTF-8"
134+
}
98135
}
99136
}

SourceKitLSPDevUtils/Sources/SourceKitLSPDevUtils/Commands/GenerateConfigSchema.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import ConfigSchemaGen
1515

1616
struct GenerateConfigSchema: ParsableCommand {
1717
static let configuration = CommandConfiguration(
18-
commandName: "generate-config-schema",
1918
abstract: "Generate a JSON schema and documentation for the SourceKit-LSP configuration file"
2019
)
2120

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import ArgumentParser
14+
import ConfigSchemaGen
15+
import Foundation
16+
17+
struct VerifyConfigSchema: ParsableCommand {
18+
static let configuration = CommandConfiguration(
19+
abstract: "Verify that the generated JSON schema and documentation for the SourceKit-LSP configuration file are up-to-date"
20+
)
21+
22+
func run() throws {
23+
let plans = try ConfigSchemaGen.plan()
24+
for plan in plans {
25+
print("Verifying \(plan.category) at \"\(plan.path.path)\"")
26+
let expectedContents = try plan.contents()
27+
let actualContents = try Data(contentsOf: plan.path)
28+
guard expectedContents == actualContents else {
29+
print("FATAL: \(plan.category) is out-of-date!")
30+
print("Please run `./sourcekit-lsp-dev-utils generate-config-schema` to update it.")
31+
throw ExitCode.failure
32+
}
33+
}
34+
print("All schemas are up-to-date!")
35+
}
36+
}

SourceKitLSPDevUtils/Sources/SourceKitLSPDevUtils/SourceKitLSPDevUtils.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct SourceKitLSPDevUtils: ParsableCommand {
1919
abstract: "Utilities for developing SourceKit-LSP",
2020
subcommands: [
2121
GenerateConfigSchema.self,
22+
VerifyConfigSchema.self,
2223
]
2324
)
2425
}

0 commit comments

Comments
 (0)