Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Sources/SKLogging/CustomLogStringConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,55 @@ extension Optional where Wrapped: CustomLogStringConvertible {
return CustomLogStringConvertibleWrapper(OptionalWrapper(optional: self))
}
}

/// A JSON-like description of the object.
public func recursiveDescription(of subject: Any) -> String {
return "{"
+ Mirror(reflecting: subject).children.map { (key, value) in
"\(key ?? "<nil>"): \(String(describing: value))"
}.joined(separator: ", ")
+ "}"
}

fileprivate protocol OptionalProtocol {
associatedtype Wrapped
var asOptional: Wrapped? { get }
}
extension Optional: OptionalProtocol {
var asOptional: Wrapped? { self }
}

/// A JSON-like description of the object that shows trivial values but redacts values that might contain sensitive
/// information.
public func recursiveRedactedDescription(of value: Any) -> String {
switch value {
case let value as Bool:
return value.description
case let value as Int:
return value.description
case let value as Double:
return value.description
case let value as String:
return value.hashForLogging
case let value as any CustomLogStringConvertible:
return value.redactedDescription
case let value as any OptionalProtocol:
if let value = value.asOptional {
return recursiveRedactedDescription(of: value)
} else {
return "nil"
}
default:
break
}

let children = Mirror(reflecting: value).children.sorted { $0.label ?? "" < $1.label ?? "" }
if !children.isEmpty {
return "{"
+ children.map { (label, value) -> String in
"\(label ?? "<nil>"): \(recursiveRedactedDescription(of: value))"
}.joined(separator: ", ")
+ "}"
}
return "<private>"
}
50 changes: 45 additions & 5 deletions Sources/SKOptions/SourceKitLSPOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import struct TSCBasic.AbsolutePath
/// Options that can be used to modify SourceKit-LSP's behavior.
///
/// See `ConfigurationFile.md` for a description of the configuration file's behavior.
public struct SourceKitLSPOptions: Sendable, Codable {
public struct SwiftPMOptions: Sendable, Codable {
public struct SourceKitLSPOptions: Sendable, Codable, CustomLogStringConvertible {
public struct SwiftPMOptions: Sendable, Codable, CustomLogStringConvertible {
/// Build configuration (debug|release).
///
/// Equivalent to SwiftPM's `--configuration` option.
Expand Down Expand Up @@ -88,9 +88,17 @@ public struct SourceKitLSPOptions: Sendable, Codable {
linkerFlags: override?.linkerFlags ?? base.linkerFlags
)
}

public var description: String {
recursiveDescription(of: self)
}

public var redactedDescription: String {
recursiveRedactedDescription(of: self)
}
}

public struct CompilationDatabaseOptions: Sendable, Codable {
public struct CompilationDatabaseOptions: Sendable, Codable, CustomLogStringConvertible {
/// Additional paths to search for a compilation database, relative to a workspace root.
public var searchPaths: [String]?

Expand All @@ -104,9 +112,17 @@ public struct SourceKitLSPOptions: Sendable, Codable {
) -> CompilationDatabaseOptions {
return CompilationDatabaseOptions(searchPaths: override?.searchPaths ?? base.searchPaths)
}

public var description: String {
recursiveDescription(of: self)
}

public var redactedDescription: String {
recursiveRedactedDescription(of: self)
}
}

public struct FallbackBuildSystemOptions: Sendable, Codable {
public struct FallbackBuildSystemOptions: Sendable, Codable, CustomLogStringConvertible {
public var cCompilerFlags: [String]?
public var cxxCompilerFlags: [String]?
public var swiftCompilerFlags: [String]?
Expand All @@ -131,9 +147,17 @@ public struct SourceKitLSPOptions: Sendable, Codable {
swiftCompilerFlags: override?.swiftCompilerFlags ?? base.swiftCompilerFlags
)
}

public var description: String {
recursiveDescription(of: self)
}

public var redactedDescription: String {
recursiveRedactedDescription(of: self)
}
}

public struct IndexOptions: Sendable, Codable {
public struct IndexOptions: Sendable, Codable, CustomLogStringConvertible {
public var indexStorePath: String?
public var indexDatabasePath: String?
public var indexPrefixMap: [String: String]?
Expand Down Expand Up @@ -176,6 +200,14 @@ public struct SourceKitLSPOptions: Sendable, Codable {
updateIndexStoreTimeout: override?.updateIndexStoreTimeout ?? base.updateIndexStoreTimeout
)
}

public var description: String {
recursiveDescription(of: self)
}

public var redactedDescription: String {
recursiveRedactedDescription(of: self)
}
}

public enum BackgroundPreparationMode: String {
Expand Down Expand Up @@ -392,4 +424,12 @@ public struct SourceKitLSPOptions: Sendable, Codable {
forKey: CodingKeys.workDoneProgressDebounceDuration
)
}

public var description: String {
recursiveDescription(of: self)
}

public var redactedDescription: String {
recursiveRedactedDescription(of: self)
}
}
3 changes: 3 additions & 0 deletions Sources/SourceKitLSP/SourceKitLSPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,7 @@ extension SourceKitLSPServer {
.appendingPathComponent("config.json")
)
)
logger.log("Creating workspace at \(workspaceFolder.uri.forLogging) with options: \(options.forLogging)")
let buildSystem = await createBuildSystem(
rootUri: workspaceFolder.uri,
options: options,
Expand Down Expand Up @@ -998,6 +999,8 @@ extension SourceKitLSPServer {
override: orLog("Parsing SourceKitLSPOptions", { try SourceKitLSPOptions(fromLSPAny: req.initializationOptions) })
)

logger.log("Initialized SourceKit-LSP with options: \(self.options.forLogging)")

await workspaceQueue.async { [testHooks] in
if let workspaceFolders = req.workspaceFolders {
self.workspacesAndIsImplicit += await workspaceFolders.asyncCompactMap {
Expand Down
26 changes: 26 additions & 0 deletions Tests/SKLoggingTests/LoggingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,30 @@ final class LoggingTests: XCTestCase {
$0.log("got \(LogStringConvertible().forLogging)")
}
}

func testRecursiveRedactedDescription() {
struct Outer {
struct Inner {
var publicValue: Int
var redactedValue: String
}
var inner: Inner
}

XCTAssertEqual(
recursiveRedactedDescription(of: Outer(inner: Outer.Inner(publicValue: 42, redactedValue: "password"))),
"""
{inner: {publicValue: 42, redactedValue: MD5 digest: 5f4dcc3b5aa765d61d8327deb882cf99}}
"""
)

XCTAssertEqual(recursiveRedactedDescription(of: (nil as Int?) as Any), "nil")

XCTAssertEqual(recursiveRedactedDescription(of: (42 as Int?) as Any), "42")

XCTAssertEqual(
recursiveRedactedDescription(of: ("abc" as String?) as Any),
"MD5 digest: 900150983cd24fb0d6963f7d28e17f72"
)
}
}