From 5b2013bdb92d451c0075d52af7686ffe68e03f8f Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Tue, 2 Sep 2025 10:25:18 -0400 Subject: [PATCH 1/2] Support "swift.play" CodeLens - Advertise to the LSP we support "swift.play" - Add a "swift.play" command, hiding it from the command palette - Fix order of env variables passed to task so variables like DYLD_LIBRARY_PATH are not overwritten accidentally Issue: #1782 --- package.json | 10 ++++ src/commands.ts | 6 +++ src/commands/runPlayground.ts | 48 +++++++++++++++++++ .../LanguageClientConfiguration.ts | 4 ++ src/tasks/SwiftTaskProvider.ts | 12 +++-- 5 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/commands/runPlayground.ts diff --git a/package.json b/package.json index 55e4a6c79..e1c1fce9c 100644 --- a/package.json +++ b/package.json @@ -289,6 +289,12 @@ "category": "Swift", "icon": "$(play)" }, + { + "command": "swift.play", + "title": "Run Swift playground", + "category": "Swift", + "icon": "$(play)" + }, { "command": "swift.debug", "title": "Debug Swift executable", @@ -1372,6 +1378,10 @@ { "command": "swift.openEducationalNote", "when": "false" + }, + { + "command": "swift.play", + "when": "false" } ], "editor/context": [ diff --git a/src/commands.ts b/src/commands.ts index 581d635a0..0f5a5d22f 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -42,6 +42,7 @@ import { reindexProject } from "./commands/reindexProject"; import { resetPackage } from "./commands/resetPackage"; import restartLSPServer from "./commands/restartLSPServer"; import { runAllTests } from "./commands/runAllTests"; +import { runPlayground } from "./commands/runPlayground"; import { runPluginTask } from "./commands/runPluginTask"; import { runSwiftScript } from "./commands/runSwiftScript"; import { runTask } from "./commands/runTask"; @@ -88,6 +89,7 @@ export function registerToolchainCommands( export enum Commands { RUN = "swift.run", DEBUG = "swift.debug", + PLAY = "swift.play", CLEAN_BUILD = "swift.cleanBuild", RESOLVE_DEPENDENCIES = "swift.resolveDependencies", SHOW_FLAT_DEPENDENCIES_LIST = "swift.flatDependenciesList", @@ -146,6 +148,10 @@ export function register(ctx: WorkspaceContext): vscode.Disposable[] { Commands.DEBUG, async target => await debugBuild(ctx, ...unwrapTreeItem(target)) ), + vscode.commands.registerCommand( + Commands.PLAY, + async target => await runPlayground(ctx, target) + ), vscode.commands.registerCommand(Commands.CLEAN_BUILD, async () => await cleanBuild(ctx)), vscode.commands.registerCommand( Commands.RUN_TESTS_MULTIPLE_TIMES, diff --git a/src/commands/runPlayground.ts b/src/commands/runPlayground.ts new file mode 100644 index 000000000..459ec3372 --- /dev/null +++ b/src/commands/runPlayground.ts @@ -0,0 +1,48 @@ +import * as vscode from "vscode"; +import { Location, Range } from "vscode-languageclient"; + +import { WorkspaceContext } from "../WorkspaceContext"; +import { createSwiftTask } from "../tasks/SwiftTaskProvider"; +import { packageName } from "../utilities/tasks"; + +export interface PlaygroundItem { + id: string; + label?: string; +} + +export interface DocumentPlaygroundItem extends PlaygroundItem { + id: string; + label?: string; + range: Range; +} + +export interface WorkspacePlaygroundItem extends PlaygroundItem { + id: string; + label?: string; + location: Location; +} + +/** + * Executes a {@link vscode.Task task} to run swift playground. + */ +export async function runPlayground(ctx: WorkspaceContext, item?: PlaygroundItem) { + const folderContext = ctx.currentFolder; + if (!folderContext || !item) { + return false; + } + const id = item.label ?? item.id; + const task = createSwiftTask( + ["play", id], + `Play "${id}"`, + { + cwd: folderContext.folder, + scope: folderContext.workspaceFolder, + packageName: packageName(folderContext), + presentationOptions: { reveal: vscode.TaskRevealKind.Always }, + }, + folderContext.toolchain + ); + + await vscode.tasks.executeTask(task); + return true; +} diff --git a/src/sourcekit-lsp/LanguageClientConfiguration.ts b/src/sourcekit-lsp/LanguageClientConfiguration.ts index 7a08b060b..fcc570140 100644 --- a/src/sourcekit-lsp/LanguageClientConfiguration.ts +++ b/src/sourcekit-lsp/LanguageClientConfiguration.ts @@ -36,6 +36,7 @@ function initializationOptions(swiftVersion: Version): any { supportedCommands: { "swift.run": "swift.run", "swift.debug": "swift.debug", + "swift.play": "swift.play", }, }, }; @@ -254,6 +255,9 @@ export function lspClientOptions( case "swift.debug": codelens.command.title = `$(debug)\u00A0${codelens.command.title}`; break; + case "swift.play": + codelens.command.title = `$(play)\u00A0${codelens.command.title}`; + break; } return codelens; }); diff --git a/src/tasks/SwiftTaskProvider.ts b/src/tasks/SwiftTaskProvider.ts index 140692bd4..c0bc32cb0 100644 --- a/src/tasks/SwiftTaskProvider.ts +++ b/src/tasks/SwiftTaskProvider.ts @@ -312,7 +312,11 @@ export function createSwiftTask( } else { cwd = config.cwd.fsPath; }*/ - const env = { ...configuration.swiftEnvironmentVariables, ...swiftRuntimeEnv(), ...cmdEnv }; + const env = { + ...swiftRuntimeEnv(), // From process.env first + ...configuration.swiftEnvironmentVariables, // Then swiftEnvironmentVariables settings + ...cmdEnv, // Task configuration takes highest precedence + }; const presentation = config?.presentationOptions ?? {}; if (config?.packageName) { name += ` (${config?.packageName})`; @@ -469,9 +473,9 @@ export class SwiftTaskProvider implements vscode.TaskProvider { const env = platform?.env ?? task.definition.env; const fullCwd = resolveTaskCwd(task, platform?.cwd ?? task.definition.cwd); const fullEnv = { - ...configuration.swiftEnvironmentVariables, - ...swiftRuntimeEnv(), - ...env, + ...swiftRuntimeEnv(), // From process.env first + ...configuration.swiftEnvironmentVariables, // Then swiftEnvironmentVariables settings + ...env, // Task configuration takes highest precedence }; const presentation = task.definition.presentation ?? task.presentationOptions ?? {}; From 29b751060b65819a3632c2aeea4d74d1d182e7c4 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Thu, 6 Nov 2025 08:04:56 -0500 Subject: [PATCH 2/2] Add copyright header --- src/commands/runPlayground.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/commands/runPlayground.ts b/src/commands/runPlayground.ts index 459ec3372..d26bd7dce 100644 --- a/src/commands/runPlayground.ts +++ b/src/commands/runPlayground.ts @@ -1,3 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2025 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// import * as vscode from "vscode"; import { Location, Range } from "vscode-languageclient";