Merged
Show file tree
Hide file tree
Changes from all commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Failed to load files.
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ import {
} from "vscode-languageclient";
import { LanguageClient } from "vscode-languageclient/node";
import { Logger } from "../logging";
import { getSettings } from "../settings";
import { getSettings, validateCwdSetting } from "../settings";
import { LanguageClientConsumer } from "../languageClientConsumer";

export interface IExtensionCommand {
Expand DownExpand Up@@ -368,32 +368,20 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
return EditorOperationResponse.Completed;
}

private openFile(openFileDetails: IOpenFileDetails): Thenable<EditorOperationResponse> {
const filePath = this.normalizeFilePath(openFileDetails.filePath);

const promise =
vscode.workspace.openTextDocument(filePath)
.then((doc) => vscode.window.showTextDocument(
doc,
{ preview: openFileDetails.preview }))
.then((_) => EditorOperationResponse.Completed);

return promise;
private async openFile(openFileDetails: IOpenFileDetails): Promise<EditorOperationResponse> {
const filePath = await this.normalizeFilePath(openFileDetails.filePath);
const doc = await vscode.workspace.openTextDocument(filePath);
await vscode.window.showTextDocument(doc, { preview: openFileDetails.preview });
return EditorOperationResponse.Completed;
}

private closeFile(filePath: string): Thenable<EditorOperationResponse> {
let promise: Thenable<EditorOperationResponse>;
if (this.findTextDocument(this.normalizeFilePath(filePath))) {
promise =
vscode.workspace.openTextDocument(filePath)
.then((doc) => vscode.window.showTextDocument(doc))
.then((_) => vscode.commands.executeCommand("workbench.action.closeActiveEditor"))
.then((_) => EditorOperationResponse.Completed);
} else {
promise = Promise.resolve(EditorOperationResponse.Completed);
private async closeFile(filePath: string): Promise<EditorOperationResponse> {
if (this.findTextDocument(await this.normalizeFilePath(filePath))) {
const doc = await vscode.workspace.openTextDocument(filePath);
await vscode.window.showTextDocument(doc);
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
}

return promise;
return EditorOperationResponse.Completed;
}

/**
Expand All@@ -413,7 +401,7 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
switch (currentFileUri.scheme) {
case "file": {
// If the file to save can't be found, just complete the request
if (!this.findTextDocument(this.normalizeFilePath(currentFileUri.fsPath))) {
if (!this.findTextDocument(await this.normalizeFilePath(currentFileUri.fsPath))) {
void this.logger.writeAndShowError(`File to save not found: ${currentFileUri.fsPath}.`);
return EditorOperationResponse.Completed;
}
Expand DownExpand Up@@ -449,23 +437,8 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
if (path.isAbsolute(saveFileDetails.newPath)) {
newFileAbsolutePath = saveFileDetails.newPath;
} else {
// In fresh contexts, workspaceFolders is not defined...
if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) {
void this.logger.writeAndShowWarning("Cannot save file to relative path: no workspaces are open. " +
"Try saving to an absolute path, or open a workspace.");
return EditorOperationResponse.Completed;
}

// If not, interpret the path as relative to the workspace root
const workspaceRootUri = vscode.workspace.workspaceFolders[0].uri;
// We don't support saving to a non-file URI-schemed workspace
if (workspaceRootUri.scheme !== "file") {
void this.logger.writeAndShowWarning(
"Cannot save untitled file to a relative path in an untitled workspace. " +
"Try saving to an absolute path or opening a workspace folder.");
return EditorOperationResponse.Completed;
}
newFileAbsolutePath = path.join(workspaceRootUri.fsPath, saveFileDetails.newPath);
const cwd = await validateCwdSetting(this.logger);
newFileAbsolutePath = path.join(cwd, saveFileDetails.newPath);
}
break; }

Expand DownExpand Up@@ -511,24 +484,21 @@ export class ExtensionCommandsFeature extends LanguageClientConsumer {
await vscode.window.showTextDocument(newFile, { preview: true });
}

private normalizeFilePath(filePath: string): string {
private async normalizeFilePath(filePath: string): Promise<string> {
const cwd = await validateCwdSetting(this.logger);
const platform = os.platform();
if (platform === "win32") {
// Make sure the file path is absolute
if (!path.win32.isAbsolute(filePath)) {
filePath = path.win32.resolve(
vscode.workspace.rootPath!,
filePath);
filePath = path.win32.resolve(cwd, filePath);
}

// Normalize file path case for comparison for Windows
return filePath.toLowerCase();
} else {
// Make sure the file path is absolute
if (!path.isAbsolute(filePath)) {
filePath = path.resolve(
vscode.workspace.rootPath!,
filePath);
filePath = path.resolve(cwd, filePath);
}

// macOS is case-insensitive
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,9 @@

import * as path from "path";
import vscode = require("vscode");
import { Logger } from "../logging";
import { SessionManager } from "../session";
import { getSettings } from "../settings";
import { getSettings, chosenWorkspace, validateCwdSetting } from "../settings";
import utils = require("../utils");

enum LaunchType {
Expand All@@ -16,7 +17,7 @@ export class PesterTestsFeature implements vscode.Disposable {
private commands: vscode.Disposable[];
private invokePesterStubScriptPath: string;

constructor(private sessionManager: SessionManager) {
constructor(private sessionManager: SessionManager, private logger: Logger) {
this.invokePesterStubScriptPath = path.resolve(__dirname, "../modules/PowerShellEditorServices/InvokePesterStub.ps1");
this.commands = [
// File context-menu command - Run Pester Tests
Expand DownExpand Up@@ -129,11 +130,10 @@ export class PesterTestsFeature implements vscode.Disposable {
// TODO: #367 Check if "newSession" mode is configured
this.sessionManager.showDebugTerminal(true);

// TODO: Update to handle multiple root workspaces.
//
// Ensure the necessary script exists (for testing). The debugger will
// start regardless, but we also pass its success along.
await validateCwdSetting(this.logger);
return await utils.checkIfFileExists(this.invokePesterStubScriptPath)
&& vscode.debug.startDebugging(vscode.workspace.workspaceFolders?.[0], launchConfig);
&& vscode.debug.startDebugging(chosenWorkspace, launchConfig);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -145,8 +145,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
new GenerateBugReportFeature(sessionManager),
new ISECompatibilityFeature(),
new OpenInISEFeature(),
new PesterTestsFeature(sessionManager),
new RunCodeFeature(sessionManager),
new PesterTestsFeature(sessionManager, logger),
new RunCodeFeature(sessionManager, logger),
new CodeActionsFeature(logger),
new SpecifyScriptArgsFeature(context),
];
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -207,9 +207,10 @@ export async function changeSetting(

// We don't want to query the user more than once, so this is idempotent.
let hasPrompted = false;
export let chosenWorkspace: vscode.WorkspaceFolder | undefined = undefined;

export async function validateCwdSetting(logger: Logger): Promise<string> {
let cwd = vscode.workspace.getConfiguration(utils.PowerShellLanguageId).get<string | undefined>("cwd");
let cwd: string | undefined = vscode.workspace.getConfiguration(utils.PowerShellLanguageId).get<string>("cwd");

// Only use the cwd setting if it exists.
if (cwd !== undefined && await utils.checkIfDirectoryExists(cwd)) {
Expand All@@ -227,9 +228,10 @@ export async function validateCwdSetting(logger: Logger): Promise<string> {
} else if (vscode.workspace.workspaceFolders.length > 1 && !hasPrompted) {
hasPrompted = true;
const options: vscode.WorkspaceFolderPickOptions = {
placeHolder: "Select a folder to use as the PowerShell extension's working directory.",
placeHolder: "Select a workspace folder to use for the PowerShell Extension.",
};
cwd = (await vscode.window.showWorkspaceFolderPick(options))?.uri.fsPath;
chosenWorkspace = await vscode.window.showWorkspaceFolderPick(options);
cwd = chosenWorkspace?.uri.fsPath;
// Save the picked 'cwd' to the workspace settings.
// We have to check again because the user may not have picked.
if (cwd !== undefined && await utils.checkIfDirectoryExists(cwd)) {
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,6 +24,9 @@ export function getPipePath(pipeName: string) {
// Check that the file or directory exists in an asynchronous manner that relies
// solely on the VS Code API, not Node's fs library, ignoring symlinks.
async function checkIfFileOrDirectoryExists(targetPath: string | vscode.Uri, type: vscode.FileType): Promise<boolean> {
if (targetPath === "") {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SeeminglyScience since the settings overhaul PR, the default cwd was "" which conspicuously vscode.workspace.fs.stat was totally fine saying it existed.

return false;
}
try {
const stat: vscode.FileStat = await vscode.workspace.fs.stat(
targetPath instanceof vscode.Uri
Expand Down