Move prepareCodeTour to separate file
This commit is contained in:
55
extensions/ql-vscode/src/code-tour.ts
Normal file
55
extensions/ql-vscode/src/code-tour.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { AppCommandManager } from "./common/commands";
|
||||
import { Uri, workspace } from "vscode";
|
||||
import { join } from "path";
|
||||
import { pathExists } from "fs-extra";
|
||||
import { isCodespacesTemplate } from "./config";
|
||||
import { showBinaryChoiceDialog } from "./common/vscode/dialog";
|
||||
import { extLogger } from "./common";
|
||||
|
||||
/**
|
||||
* Check if the current workspace is the CodeTour and open the workspace folder.
|
||||
* Without this, we can't run the code tour correctly.
|
||||
**/
|
||||
export async function prepareCodeTour(
|
||||
commandManager: AppCommandManager,
|
||||
): Promise<void> {
|
||||
if (workspace.workspaceFolders?.length) {
|
||||
const currentFolder = workspace.workspaceFolders[0].uri.fsPath;
|
||||
|
||||
const tutorialWorkspacePath = join(
|
||||
currentFolder,
|
||||
"tutorial.code-workspace",
|
||||
);
|
||||
const toursFolderPath = join(currentFolder, ".tours");
|
||||
|
||||
/** We're opening the tutorial workspace, if we detect it.
|
||||
* This will only happen if the following three conditions are met:
|
||||
* - the .tours folder exists
|
||||
* - the tutorial.code-workspace file exists
|
||||
* - the CODESPACES_TEMPLATE setting doesn't exist (it's only set if the user has already opened
|
||||
* the tutorial workspace so it's a good indicator that the user is in the folder but has ignored
|
||||
* the prompt to open the workspace)
|
||||
*/
|
||||
if (
|
||||
(await pathExists(tutorialWorkspacePath)) &&
|
||||
(await pathExists(toursFolderPath)) &&
|
||||
!isCodespacesTemplate()
|
||||
) {
|
||||
const answer = await showBinaryChoiceDialog(
|
||||
"We've detected you're in the CodeQL Tour repo. We will need to open the workspace file to continue. Reload?",
|
||||
);
|
||||
|
||||
if (!answer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tutorialWorkspaceUri = Uri.file(tutorialWorkspacePath);
|
||||
|
||||
void extLogger.log(
|
||||
`In prepareCodeTour() method, going to open the tutorial workspace file: ${tutorialWorkspacePath}`,
|
||||
);
|
||||
|
||||
await commandManager.execute("vscode.openFolder", tutorialWorkspaceUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,8 +62,8 @@ import {
|
||||
showAndLogWarningMessage,
|
||||
tmpDir,
|
||||
tmpDirDisposal,
|
||||
prepareCodeTour,
|
||||
} from "./helpers";
|
||||
import { prepareCodeTour } from "./code-tour";
|
||||
import {
|
||||
showBinaryChoiceDialog,
|
||||
showInformationMessageWithAction,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ensureDirSync, pathExists, ensureDir, writeFile } from "fs-extra";
|
||||
import { ensureDirSync, ensureDir, writeFile } from "fs-extra";
|
||||
import { join } from "path";
|
||||
import { dirSync } from "tmp-promise";
|
||||
import { Uri, window as Window, workspace } from "vscode";
|
||||
import { Uri, window as Window } from "vscode";
|
||||
import { CodeQLCliServer } from "./codeql-cli/cli";
|
||||
import { UserCancellationException } from "./common/vscode/progress";
|
||||
import { extLogger, OutputChannelLogger } from "./common";
|
||||
@@ -9,10 +9,7 @@ import { QueryMetadata } from "./pure/interface-types";
|
||||
import { telemetryListener } from "./telemetry";
|
||||
import { RedactableError } from "./pure/errors";
|
||||
import { isQueryLanguage, QueryLanguage } from "./common/query-language";
|
||||
import { isCodespacesTemplate } from "./config";
|
||||
import { AppCommandManager } from "./common/commands";
|
||||
import { getOnDiskWorkspaceFolders } from "./common/vscode/workspace-folders";
|
||||
import { showBinaryChoiceDialog } from "./common/vscode/dialog";
|
||||
|
||||
// Shared temporary folder for the extension.
|
||||
export const tmpDir = dirSync({
|
||||
@@ -140,53 +137,6 @@ async function internalShowAndLog(
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Check if the current workspace is the CodeTour and open the workspace folder.
|
||||
* Without this, we can't run the code tour correctly.
|
||||
**/
|
||||
export async function prepareCodeTour(
|
||||
commandManager: AppCommandManager,
|
||||
): Promise<void> {
|
||||
if (workspace.workspaceFolders?.length) {
|
||||
const currentFolder = workspace.workspaceFolders[0].uri.fsPath;
|
||||
|
||||
const tutorialWorkspacePath = join(
|
||||
currentFolder,
|
||||
"tutorial.code-workspace",
|
||||
);
|
||||
const toursFolderPath = join(currentFolder, ".tours");
|
||||
|
||||
/** We're opening the tutorial workspace, if we detect it.
|
||||
* This will only happen if the following three conditions are met:
|
||||
* - the .tours folder exists
|
||||
* - the tutorial.code-workspace file exists
|
||||
* - the CODESPACES_TEMPLATE setting doesn't exist (it's only set if the user has already opened
|
||||
* the tutorial workspace so it's a good indicator that the user is in the folder but has ignored
|
||||
* the prompt to open the workspace)
|
||||
*/
|
||||
if (
|
||||
(await pathExists(tutorialWorkspacePath)) &&
|
||||
(await pathExists(toursFolderPath)) &&
|
||||
!isCodespacesTemplate()
|
||||
) {
|
||||
const answer = await showBinaryChoiceDialog(
|
||||
"We've detected you're in the CodeQL Tour repo. We will need to open the workspace file to continue. Reload?",
|
||||
);
|
||||
|
||||
if (!answer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tutorialWorkspaceUri = Uri.file(tutorialWorkspacePath);
|
||||
|
||||
void extLogger.log(
|
||||
`In prepareCodeTour() method, going to open the tutorial workspace file: ${tutorialWorkspacePath}`,
|
||||
);
|
||||
|
||||
await commandManager.execute("vscode.openFolder", tutorialWorkspaceUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the language that a query targets.
|
||||
* If it can't be autodetected, prompt the user to specify the language manually.
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import { Uri, window, workspace, WorkspaceFolder } from "vscode";
|
||||
import * as tmp from "tmp";
|
||||
import { join } from "path";
|
||||
import { mkdir, writeFile } from "fs-extra";
|
||||
|
||||
import { prepareCodeTour } from "../../../src/code-tour";
|
||||
import { Setting } from "../../../src/config";
|
||||
import { createMockCommandManager } from "../../__mocks__/commandsMock";
|
||||
|
||||
describe("prepareCodeTour", () => {
|
||||
let dir: tmp.DirResult;
|
||||
let showInformationMessageSpy: jest.SpiedFunction<
|
||||
typeof window.showInformationMessage
|
||||
>;
|
||||
|
||||
beforeEach(() => {
|
||||
dir = tmp.dirSync();
|
||||
|
||||
const mockWorkspaceFolders = [
|
||||
{
|
||||
uri: Uri.file(dir.name),
|
||||
name: "test",
|
||||
index: 0,
|
||||
},
|
||||
] as WorkspaceFolder[];
|
||||
|
||||
jest
|
||||
.spyOn(workspace, "workspaceFolders", "get")
|
||||
.mockReturnValue(mockWorkspaceFolders);
|
||||
|
||||
showInformationMessageSpy = jest
|
||||
.spyOn(window, "showInformationMessage")
|
||||
.mockResolvedValue({ title: "Yes" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
dir.removeCallback();
|
||||
});
|
||||
|
||||
describe("if we're in the tour repo", () => {
|
||||
describe("if the workspace is not already open", () => {
|
||||
it("should open the tutorial workspace", async () => {
|
||||
// set up directory to have a 'tutorial.code-workspace' file
|
||||
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
|
||||
await writeFile(tutorialWorkspacePath, "{}");
|
||||
|
||||
// set up a .tours directory to indicate we're in the tour codespace
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(showInformationMessageSpy).toHaveBeenCalled();
|
||||
expect(executeCommand).toHaveBeenCalledWith(
|
||||
"vscode.openFolder",
|
||||
expect.objectContaining({
|
||||
path: expect.stringMatching(/tutorial.code-workspace$/),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("if the workspace is already open", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// Set isCodespacesTemplate to true to indicate the workspace has already been opened
|
||||
jest.spyOn(Setting.prototype, "getValue").mockReturnValue(true);
|
||||
|
||||
// set up directory to have a 'tutorial.code-workspace' file
|
||||
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
|
||||
await writeFile(tutorialWorkspacePath, "{}");
|
||||
|
||||
// set up a .tours directory to indicate we're in the tour codespace
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("if we're in a different tour repo", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// set up a .tours directory
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("if we're in a different repo with no tour", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,4 @@
|
||||
import { Uri, window, workspace, WorkspaceFolder } from "vscode";
|
||||
import * as tmp from "tmp";
|
||||
import { join } from "path";
|
||||
import { writeFile, mkdir } from "fs-extra";
|
||||
|
||||
import { prepareCodeTour } from "../../../src/helpers";
|
||||
import { reportStreamProgress } from "../../../src/common/vscode/progress";
|
||||
import { Setting } from "../../../src/config";
|
||||
import { createMockCommandManager } from "../../__mocks__/commandsMock";
|
||||
|
||||
describe("helpers", () => {
|
||||
it("should report stream progress", () => {
|
||||
@@ -66,105 +58,3 @@ describe("helpers", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("prepareCodeTour", () => {
|
||||
let dir: tmp.DirResult;
|
||||
let showInformationMessageSpy: jest.SpiedFunction<
|
||||
typeof window.showInformationMessage
|
||||
>;
|
||||
|
||||
beforeEach(() => {
|
||||
dir = tmp.dirSync();
|
||||
|
||||
const mockWorkspaceFolders = [
|
||||
{
|
||||
uri: Uri.file(dir.name),
|
||||
name: "test",
|
||||
index: 0,
|
||||
},
|
||||
] as WorkspaceFolder[];
|
||||
|
||||
jest
|
||||
.spyOn(workspace, "workspaceFolders", "get")
|
||||
.mockReturnValue(mockWorkspaceFolders);
|
||||
|
||||
showInformationMessageSpy = jest
|
||||
.spyOn(window, "showInformationMessage")
|
||||
.mockResolvedValue({ title: "Yes" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
dir.removeCallback();
|
||||
});
|
||||
|
||||
describe("if we're in the tour repo", () => {
|
||||
describe("if the workspace is not already open", () => {
|
||||
it("should open the tutorial workspace", async () => {
|
||||
// set up directory to have a 'tutorial.code-workspace' file
|
||||
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
|
||||
await writeFile(tutorialWorkspacePath, "{}");
|
||||
|
||||
// set up a .tours directory to indicate we're in the tour codespace
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(showInformationMessageSpy).toHaveBeenCalled();
|
||||
expect(executeCommand).toHaveBeenCalledWith(
|
||||
"vscode.openFolder",
|
||||
expect.objectContaining({
|
||||
path: expect.stringMatching(/tutorial.code-workspace$/),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("if the workspace is already open", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// Set isCodespacesTemplate to true to indicate the workspace has already been opened
|
||||
jest.spyOn(Setting.prototype, "getValue").mockReturnValue(true);
|
||||
|
||||
// set up directory to have a 'tutorial.code-workspace' file
|
||||
const tutorialWorkspacePath = join(dir.name, "tutorial.code-workspace");
|
||||
await writeFile(tutorialWorkspacePath, "{}");
|
||||
|
||||
// set up a .tours directory to indicate we're in the tour codespace
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("if we're in a different tour repo", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// set up a .tours directory
|
||||
const tourDirPath = join(dir.name, ".tours");
|
||||
await mkdir(tourDirPath);
|
||||
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("if we're in a different repo with no tour", () => {
|
||||
it("should not open the tutorial workspace", async () => {
|
||||
// spy that we open the workspace file by calling the 'vscode.openFolder' command
|
||||
const executeCommand = jest.fn();
|
||||
await prepareCodeTour(createMockCommandManager({ executeCommand }));
|
||||
|
||||
expect(executeCommand).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user