Skip to content

Commit 850f352

Browse files
authored
Merge pull request #21 from award999/main
Add new playground types
2 parents b51ba93 + 827b3a8 commit 850f352

File tree

7 files changed

+191
-1
lines changed

7 files changed

+191
-1
lines changed

Sources/LanguageServerProtocol/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ add_library(LanguageServerProtocol
9494
Requests/WillSaveWaitUntilTextDocumentRequest.swift
9595
Requests/WorkspaceDiagnosticsRequest.swift
9696
Requests/WorkspaceFoldersRequest.swift
97+
Requests/WorkspacePlaygroundsRequest.swift
9798
Requests/WorkspaceSemanticTokensRefreshRequest.swift
9899
Requests/WorkspaceSymbolResolveRequest.swift
99100
Requests/WorkspaceSymbolsRequest.swift
@@ -122,6 +123,7 @@ add_library(LanguageServerProtocol
122123
SupportTypes/NotebookDocument.swift
123124
SupportTypes/NotebookDocumentChangeEvent.swift
124125
SupportTypes/NotebookDocumentIdentifier.swift
126+
SupportTypes/Playground.swift
125127
SupportTypes/Position.swift
126128
SupportTypes/PositionEncoding.swift
127129
SupportTypes/ProgressToken.swift
@@ -138,6 +140,7 @@ add_library(LanguageServerProtocol
138140
SupportTypes/TextDocumentEdit.swift
139141
SupportTypes/TextDocumentIdentifier.swift
140142
SupportTypes/TextDocumentItem.swift
143+
SupportTypes/TextDocumentPlayground.swift
141144
SupportTypes/TextDocumentSaveReason.swift
142145
SupportTypes/TextEdit.swift
143146
SupportTypes/Tracing.swift

Sources/LanguageServerProtocol/Messages.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public let builtinRequests: [_RequestType.Type] = [
8787
WillSaveWaitUntilTextDocumentRequest.self,
8888
WorkspaceDiagnosticsRequest.self,
8989
WorkspaceFoldersRequest.self,
90+
WorkspacePlaygroundsRequest.self,
9091
WorkspaceSemanticTokensRefreshRequest.self,
9192
WorkspaceSymbolResolveRequest.self,
9293
WorkspaceSymbolsRequest.self,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 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+
/// A request that returns the location and identifiers for all the #Playground macro playgrounds within the current workspace.
14+
///
15+
/// **(LSP Extension)**
16+
public struct WorkspacePlaygroundsRequest: LSPRequest, Hashable {
17+
public static let method: String = "workspace/playgrounds"
18+
public typealias Response = [Playground]
19+
20+
public init() {}
21+
}

Sources/LanguageServerProtocol/SupportTypes/Location.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
/// Range within a particular document.
1414
///
1515
/// For a location where the document is implied, use `Position` or `Range<Position>`.
16-
public struct Location: ResponseType, Hashable, Codable, CustomDebugStringConvertible, Comparable, Sendable {
16+
public struct Location: ResponseType, Hashable, Codable, CustomDebugStringConvertible, Comparable, Sendable,
17+
LSPAnyCodable
18+
{
1719
public static func < (lhs: Location, rhs: Location) -> Bool {
1820
if lhs.uri != rhs.uri {
1921
return lhs.uri.stringValue < rhs.uri.stringValue
@@ -34,7 +36,27 @@ public struct Location: ResponseType, Hashable, Codable, CustomDebugStringConver
3436
self._range = CustomCodable<PositionRange>(wrappedValue: range)
3537
}
3638

39+
public init?(fromLSPDictionary dictionary: [String: LSPAny]) {
40+
guard
41+
case .string(let uriString) = dictionary["uri"],
42+
case .dictionary(let rangeDict) = dictionary["range"],
43+
let uri = try? DocumentURI(string: uriString),
44+
let range = Range<Position>(fromLSPDictionary: rangeDict)
45+
else {
46+
return nil
47+
}
48+
self.uri = uri
49+
self._range = CustomCodable<PositionRange>(wrappedValue: range)
50+
}
51+
3752
public var debugDescription: String {
3853
return "\(uri):\(range.lowerBound)-\(range.upperBound)"
3954
}
55+
56+
public func encodeToLSPAny() -> LSPAny {
57+
return .dictionary([
58+
"uri": .string(uri.stringValue),
59+
"range": range.encodeToLSPAny(),
60+
])
61+
}
4062
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 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+
/// A `Playground` represents a usage of the #Playground macro, providing the editor with the
14+
/// location of the playground and identifiers to allow executing the playground through a "swift play" command.
15+
///
16+
/// **(LSP Extension)**
17+
public struct Playground: ResponseType, Equatable, LSPAnyCodable {
18+
/// Unique identifier for the `Playground` with the format `<target>/<filename>:<line>:[column]` where `target`
19+
/// corresponds to the Swift package's target where the playground is defined, `filename` is the basename of the file
20+
/// (not entire relative path), and `column` is optional only required if multiple playgrounds are defined on the same
21+
/// line. Client can run the playground by executing `swift play <id>`.
22+
///
23+
/// This property is always present whether the `Playground` has a `label` or not.
24+
///
25+
/// Follows the format output by `swift play --list`.
26+
public var id: String
27+
28+
/// The label that can be used as a display name for the playground. This optional property is only available
29+
/// for named playgrounds. For example: `#Playground("hello") { print("Hello!) }` would have a `label` of `"hello"`.
30+
public var label: String?
31+
32+
/// The location of where the #Playground macro was used in the source code.
33+
public var location: Location
34+
35+
public init(
36+
id: String,
37+
label: String?,
38+
location: Location,
39+
) {
40+
self.id = id
41+
self.label = label
42+
self.location = location
43+
}
44+
45+
public init?(fromLSPDictionary dictionary: [String: LSPAny]) {
46+
guard
47+
case .string(let id) = dictionary["id"],
48+
let location = Location(fromLSPAny: dictionary["location"])
49+
else {
50+
return nil
51+
}
52+
self.id = id
53+
self.location = location
54+
if case .string(let label) = dictionary["label"] {
55+
self.label = label
56+
}
57+
}
58+
59+
public func encodeToLSPAny() -> LSPAny {
60+
var dict: [String: LSPAny] = [
61+
"id": .string(id),
62+
"location": location.encodeToLSPAny(),
63+
]
64+
65+
if let label {
66+
dict["label"] = .string(label)
67+
}
68+
69+
return .dictionary(dict)
70+
}
71+
}

Sources/LanguageServerProtocol/SupportTypes/SupportedCodeLensCommand.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ public struct SupportedCodeLensCommand: Codable, Hashable, RawRepresentable, Sen
2626

2727
/// Lens to debug the application
2828
public static let debug: Self = Self(rawValue: "swift.debug")
29+
30+
/// Lens to run the playground
31+
public static let play: Self = Self(rawValue: "swift.play")
2932
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 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+
/// A `TextDocumentPlayground` item can be used to identify playground and identify it
14+
/// to allow executing the playground through a "swift play" command. Differs from `Playground`
15+
/// by only including the `range` instead of full `location` with the expectation being that
16+
/// it is only returned as part of a textDocument/* request such as textDocument/codelens
17+
public struct TextDocumentPlayground: ResponseType, Equatable, LSPAnyCodable {
18+
/// Unique identifier for the `Playground` with the format `<target>/<filename>:<line>:[column]` where `target`
19+
/// corresponds to the Swift package's target where the playground is defined, `filename` is the basename of the file
20+
/// (not entire relative path), and `column` is optional only required if multiple playgrounds are defined on the same
21+
/// line. Client can run the playground by executing `swift play <id>`.
22+
///
23+
/// This property is always present whether the `Playground` has a `label` or not.
24+
///
25+
/// Follows the format output by `swift play --list`.
26+
public var id: String
27+
28+
/// The label that can be used as a display name for the playground. This optional property is only available
29+
/// for named playgrounds. For example: `#Playground("hello") { print("Hello!) }` would have a `label` of `"hello"`.
30+
public var label: String?
31+
32+
/// The full range of the #Playground macro body in the given file.
33+
public var range: Range<Position>
34+
35+
public init(
36+
id: String,
37+
label: String?,
38+
range: Range<Position>
39+
) {
40+
self.id = id
41+
self.label = label
42+
self.range = range
43+
}
44+
45+
public init?(fromLSPDictionary dictionary: [String: LSPAny]) {
46+
guard
47+
case .string(let id) = dictionary["id"],
48+
let range = Range<Position>(fromLSPAny: dictionary["range"])
49+
else {
50+
return nil
51+
}
52+
self.id = id
53+
self.range = range
54+
if case .string(let label) = dictionary["label"] {
55+
self.label = label
56+
}
57+
}
58+
59+
public func encodeToLSPAny() -> LSPAny {
60+
var dict: [String: LSPAny] = [
61+
"id": .string(id),
62+
"range": range.encodeToLSPAny(),
63+
]
64+
if let label {
65+
dict["label"] = .string(label)
66+
}
67+
return .dictionary(dict)
68+
}
69+
}

0 commit comments

Comments
 (0)