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
15 changes: 13 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,25 @@ jobs:
- name: Build
run: pnpm --color --filter '!cursorless-org' --filter '!cursorless-org-*' build

- name: Run tests (Linux)
- name: Lint
run: pnpm --color lint

- name: Run unit tests (Linux)
run: xvfb-run -a pnpm --color test
if: runner.os == 'Linux'

- name: Run tests (Win,Mac)
- name: Run unit tests (Win,Mac)
run: pnpm --color test
if: runner.os != 'Linux'

- name: Run VSCode tests (Linux)
run: xvfb-run -a pnpm -F @cursorless/test-harness test:vscode
if: runner.os == 'Linux'

- name: Run VSCode tests (Win,Mac)
run: pnpm -F @cursorless/test-harness test:vscode
if: runner.os != 'Linux'

- name: Run Talon-JS tests (Linux)
run: xvfb-run -a pnpm -F @cursorless/test-harness test:talonJs
if: runner.os == 'Linux' && matrix.app_version == 'stable'
Expand Down
35 changes: 0 additions & 35 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,41 +202,6 @@
]
},

// Unit tests launch configs
{
"name": "Unit tests: Test",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/packages/test-harness/dist/runUnitTestsOnly.cjs",
"env": {
"CURSORLESS_MODE": "test",
"CURSORLESS_REPO_ROOT": "${workspaceFolder}"
},
"outFiles": ["${workspaceFolder}/**/out/**/*.js"],
"preLaunchTask": "VSCode: Build extension and tests",
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
]
},
{
"name": "Unit tests: Update test fixtures",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/packages/test-harness/dist/runUnitTestsOnly.cjs",
"env": {
"CURSORLESS_MODE": "test",
"CURSORLESS_TEST_UPDATE_FIXTURES": "true",
"CURSORLESS_REPO_ROOT": "${workspaceFolder}"
},
"outFiles": ["${workspaceFolder}/**/out/**/*.js"],
"preLaunchTask": "VSCode: Build extension and tests",
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
]
},

// Docusaurus launch configs
{
"name": "Docusaurus: Run",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"meta-updater:base": "pnpm --filter=@cursorless/meta-updater build && meta-updater",
"preinstall": "npx only-allow pnpm",
"test-compile": "tsc --build",
"test": "pnpm compile && pnpm lint && pnpm -F '!test-harness' test && pnpm -F test-harness test",
"test": "pnpm -r test",
"generate-grammar": "pnpm -r generate-grammar",
"transform-recorded-tests": "./packages/common/scripts/my-ts-node.js packages/cursorless-engine/src/scripts/transformRecordedTests/index.ts",
"watch": "pnpm run -w --parallel '/^watch:.*/'",
Expand Down
3 changes: 2 additions & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"cross-spawn": "^7.0.6",
"fast-check": "^4.5.3",
"js-yaml": "^4.1.1",
"mocha": "^11.7.5"
"mocha": "^11.7.5",
"web-tree-sitter": "^0.26.6"
}
}
1 change: 1 addition & 0 deletions packages/common/scripts/my-ts-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ async function main() {
bundle: true,
format: "cjs",
outfile: outFile,
external: ["./reporters/parallel-buffered", "./worker.js"],
});

const nodeProcess = runCommand(
Expand Down
52 changes: 28 additions & 24 deletions packages/common/src/ide/fake/FakeIDE.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { pull } from "lodash-es";
import type { EditableTextEditor, NotebookEditor, TextEditor } from "../..";
import type {
EditableTextEditor,
Messages,
NotebookEditor,
TextEditor,
} from "../..";
import type { GeneralizedRange } from "../../types/GeneralizedRange";
import type { TextDocument } from "../../types/TextDocument";
import type { TextDocumentChangeEvent } from "../types/Events";
Expand All @@ -24,11 +29,11 @@ import FakeKeyValueStore from "./FakeKeyValueStore";
import FakeMessages from "./FakeMessages";

export class FakeIDE implements IDE {
configuration: FakeConfiguration = new FakeConfiguration();
messages: FakeMessages = new FakeMessages();
keyValueStore: FakeKeyValueStore = new FakeKeyValueStore();
clipboard: FakeClipboard = new FakeClipboard();
capabilities: FakeCapabilities = new FakeCapabilities();
configuration = new FakeConfiguration();
keyValueStore = new FakeKeyValueStore();
clipboard = new FakeClipboard();
capabilities = new FakeCapabilities();
messages: Messages;

runMode: RunMode = "test";
cursorlessVersion: string = "0.0.0";
Expand All @@ -37,6 +42,10 @@ export class FakeIDE implements IDE {
private assetsRoot_: string | undefined;
private quickPickReturnValue: string | undefined = undefined;

constructor(messages: Messages = new FakeMessages()) {
this.messages = messages;
}

async flashRanges(_flashDescriptors: FlashDescriptor[]): Promise<void> {
// empty
}
Expand All @@ -57,8 +66,9 @@ export class FakeIDE implements IDE {
dummyEvent;
onDidChangeTextEditorVisibleRanges: Event<TextEditorVisibleRangesChangeEvent> =
dummyEvent;
onDidChangeTextDocument: Event<TextDocumentChangeEvent> = dummyEvent;

public mockAssetsRoot(_assetsRoot: string) {
mockAssetsRoot(_assetsRoot: string) {
this.assetsRoot_ = _assetsRoot;
}

Expand All @@ -71,41 +81,41 @@ export class FakeIDE implements IDE {
}

get activeTextEditor(): TextEditor | undefined {
throw Error("Not implemented");
throw Error("activeTextEditor: not implemented");
}

get activeEditableTextEditor(): EditableTextEditor | undefined {
throw Error("Not implemented");
throw Error("activeEditableTextEditor: not implemented");
}

get visibleTextEditors(): TextEditor[] {
throw Error("Not implemented");
return [];
}

get visibleNotebookEditors(): NotebookEditor[] {
throw Error("Not implemented");
return [];
}

public getEditableTextEditor(_editor: TextEditor): EditableTextEditor {
throw Error("Not implemented");
throw Error("getEditableTextEditor: not implemented");
}

public findInDocument(_query: string, _editor: TextEditor): Promise<void> {
throw Error("Not implemented");
throw Error("findInDocument: not implemented");
}

public findInWorkspace(_query: string): Promise<void> {
throw Error("Not implemented");
throw Error("findInWorkspace: not implemented");
}

public openTextDocument(_path: string): Promise<TextEditor> {
throw Error("Not implemented");
throw Error("openTextDocument: not implemented");
}

public openUntitledTextDocument(
_options: OpenUntitledTextDocumentOptions,
): Promise<TextEditor> {
throw Error("Not implemented");
throw Error("openUntitledTextDocument: not implemented");
}

public setQuickPickReturnValue(value: string | undefined) {
Expand All @@ -120,17 +130,11 @@ export class FakeIDE implements IDE {
}

public showInputBox(_options?: any): Promise<string | undefined> {
throw Error("Not implemented");
throw Error("showInputBox: not implemented");
}

executeCommand<T>(_command: string, ..._args: any[]): Promise<T | undefined> {
throw new Error("Method not implemented.");
}

public onDidChangeTextDocument(
_listener: (event: TextDocumentChangeEvent) => void,
): Disposable {
throw Error("Not implemented");
throw new Error("executeCommand: not implemented");
}

disposeOnExit(...disposables: Disposable[]): () => void {
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export * from "./util/DefaultMap";
export * from "./util/disposableFrom";
export * from "./util/ensureCommandShape";
export * from "./util/getEnvironmentVariableStrict";
export * from "./util/getErrorMessage";
export * from "./util/itertools";
export * from "./util/Notifier";
export * from "./util/object";
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/util/getErrorMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error);
}
6 changes: 5 additions & 1 deletion packages/cursorless-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,18 @@
"zod": "^4.3.6"
},
"devDependencies": {
"@types/chai": "^5.2.3",
"@types/js-yaml": "^4.0.9",
"@types/lodash-es": "^4.17.12",
"@types/mocha": "^10.0.10",
"@types/moo": "^0.5.10",
"@types/nearley": "^2.11.5",
"@types/sinon": "^21.0.0",
"chai": "^6.2.2",
"js-yaml": "^4.1.1",
"mocha": "^11.7.5",
"sinon": "^21.0.2"
"sinon": "^21.0.2",
"vscode-uri": "^3.1.0",
"web-tree-sitter": "^0.26.6"
}
}
2 changes: 2 additions & 0 deletions packages/cursorless-engine/src/api/CursorlessEngineApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import type {
} from "@cursorless/common";
import type { CommandRunner } from "../CommandRunner";
import type { StoredTargetMap } from "../core/StoredTargets";
import type { LanguageDefinitions } from "../languages/LanguageDefinitions";

export interface CursorlessEngine {
commandApi: CommandApi;
languageDefinitions: LanguageDefinitions;
scopeProvider: ScopeProvider;
customSpokenFormGenerator: CustomSpokenFormGenerator;
storedTargets: StoredTargetMap;
Expand Down
1 change: 1 addition & 0 deletions packages/cursorless-engine/src/cursorlessEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export async function createCursorlessEngine({
};

return {
languageDefinitions,
commandApi: {
runCommand(command: Command) {
return runCommandClosure(command);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as assert from "assert";
import { unitTestSetup } from "../test/unitTestSetup";
import { unitTestSetup } from "../testUtil/unitTestSetup";
import type { NearleyLexer, NearleyToken } from "./CommandLexer";
import { lexer } from "./lexer";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ async function readQueryFileAndImports(
ide: IDE,
provider: RawTreeSitterQueryProvider,
languageQueryName: string,
) {
): Promise<string | undefined> {
// Seed the map with the query file itself
const rawQueryStrings: Record<string, string | null> = {
[languageQueryName]: null,
Expand Down
23 changes: 13 additions & 10 deletions packages/cursorless-engine/src/languages/LanguageDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import type {
RawTreeSitterQueryProvider,
TreeSitter,
} from "@cursorless/common";
import { Notifier, showError } from "@cursorless/common";
import { toString } from "lodash-es";
import { getErrorMessage, Notifier, showError } from "@cursorless/common";
import { LanguageDefinition } from "./LanguageDefinition";
import { treeSitterQueryCache } from "./TreeSitterQuery/TreeSitterQueryCache";

Expand All @@ -16,7 +15,7 @@ import { treeSitterQueryCache } from "./TreeSitterQuery/TreeSitterQueryCache";
*/
const LANGUAGE_UNDEFINED = Symbol("LANGUAGE_UNDEFINED");

export interface LanguageDefinitions {
export interface LanguageDefinitions extends Disposable {
onDidChangeDefinition: (listener: Listener) => Disposable;

loadLanguage(languageId: string): Promise<void>;
Expand All @@ -36,9 +35,7 @@ export interface LanguageDefinitions {
* Keeps a map from language ids to {@link LanguageDefinition} instances,
* constructing them as necessary
*/
export class LanguageDefinitionsImpl
implements LanguageDefinitions, Disposable
{
export class LanguageDefinitionsImpl implements LanguageDefinitions {
private notifier: Notifier = new Notifier();

/**
Expand Down Expand Up @@ -70,7 +67,13 @@ export class LanguageDefinitionsImpl
if (isTesting) {
treeSitterQueryCache.clear();
}
void this.loadLanguage(document.languageId);
this.loadLanguage(document.languageId).catch((err) => {
void showError(
this.ide.messages,
`Failed to load language definition: ${document.languageId}`,
getErrorMessage(err),
);
});
}),

ide.onDidChangeVisibleTextEditors((editors) => {
Expand All @@ -83,7 +86,7 @@ export class LanguageDefinitionsImpl
);
}

public static async create(
static async create(
ide: IDE,
treeSitter: TreeSitter,
treeSitterQueryProvider: RawTreeSitterQueryProvider,
Expand Down Expand Up @@ -112,15 +115,15 @@ export class LanguageDefinitionsImpl
void showError(
this.ide.messages,
"Failed to load language definitions",
toString(err),
getErrorMessage(err),
);
if (this.ide.runMode === "test") {
throw err;
}
}
}

public async loadLanguage(languageId: string): Promise<void> {
async loadLanguage(languageId: string): Promise<void> {
if (this.languageDefinitions.has(languageId)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TestScopeHandler extends BaseScopeHandler {
public scopeType = undefined;

public get iterationScopeType(): CustomScopeType {
throw new Error("Method not implemented.");
throw new Error("iterationScopeType: not implemented");
}

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ export class SortedScopeHandler extends BaseScopeHandler {
),
),
() => {
throw new Error("Not implemented");
throw new Error(
"SortedScopeHandler: Iteration scope is not implemented",
);
},
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class TreeSitterIterationScopeHandler extends BaseTreeSitterScopeHandler
// Doesn't have any iteration scope type itself; that would correspond to
// something like "every every"
public get iterationScopeType(): ScopeType {
throw Error("Not implemented");
throw new Error("iterationScopeType: not implemented");
}

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export class NotebookCellDestination implements Destination {
}

getEditNewActionType(): EditNewActionType {
throw new Error("Method not implemented.");
throw new Error("getEditNewActionType: not implemented");
}

constructChangeEdit(_text: string): EditWithRangeUpdater {
throw new Error("Method not implemented.");
throw new Error("constructChangeEdit: not implemented");
}
}
Loading
Loading