Skip to content

Commit baff848

Browse files
General clean up and refactoring (#3215)
1 parent 9a98d48 commit baff848

8 files changed

Lines changed: 140 additions & 162 deletions

File tree

packages/common/src/types/TreeSitter.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
1-
import type { Range, TextDocument } from "@cursorless/common";
2-
import type { Node, Query, Tree } from "web-tree-sitter";
1+
import type { TextDocument } from "@cursorless/common";
2+
import type { Query, Tree } from "web-tree-sitter";
33

44
export interface TreeSitter {
5-
/**
6-
* Function to access nodes in the tree sitter.
7-
*/
8-
getNodeAtLocation(document: TextDocument, range: Range): Node;
9-
10-
/**
11-
* Function to access the tree sitter tree.
12-
*/
13-
getTree(document: TextDocument): Tree;
14-
155
/**
166
* Loads a language, returning true if it was successfully loaded
177
*
@@ -20,6 +10,11 @@ export interface TreeSitter {
2010
*/
2111
loadLanguage(languageId: string): Promise<boolean>;
2212

13+
/**
14+
* Function to access the tree sitter tree.
15+
*/
16+
getTree(document: TextDocument): Tree;
17+
2318
/**
2419
* Create a query if the language is loaded.
2520
*

packages/cursorless-engine/src/disabledComponents/DisabledTreeSitter.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
1-
import type { Range, TextDocument, TreeSitter } from "@cursorless/common";
2-
import type { Node, Query, Tree } from "web-tree-sitter";
1+
import type { TextDocument, TreeSitter } from "@cursorless/common";
2+
import type { Query, Tree } from "web-tree-sitter";
33

44
export class DisabledTreeSitter implements TreeSitter {
5-
getTree(_document: TextDocument): Tree {
6-
throw new Error("Tree sitter not provided");
7-
}
8-
95
loadLanguage(_languageId: string): Promise<boolean> {
106
return Promise.resolve(false);
117
}
128

13-
getNodeAtLocation(_document: TextDocument, _range: Range): Node {
9+
getTree(_document: TextDocument): Tree {
1410
throw new Error("Tree sitter not provided");
1511
}
1612

packages/cursorless-engine/src/testUtil/TestTreeSitter.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import type { Range, TextDocument, TreeSitter } from "@cursorless/common";
1+
import type { TextDocument, TreeSitter } from "@cursorless/common";
22
import { createRequire } from "node:module";
33
import * as path from "node:path";
44
import type {
5-
Node,
65
Tree,
7-
Parser as TreeSitterParser,
86
Language as TreeSitterLanguage,
7+
Parser as TreeSitterParser,
98
Query as TreeSitterQuery,
109
} from "web-tree-sitter";
1110

@@ -38,10 +37,6 @@ function initTreeSitter() {
3837
}
3938

4039
export class TestTreeSitter implements TreeSitter {
41-
getNodeAtLocation(_document: TextDocument, _range: Range): Node {
42-
throw new Error("getNodeAtLocation: not implemented.");
43-
}
44-
4540
getTree(document: TextDocument): Tree {
4641
const language = languageCache.get(document.languageId);
4742

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type {
2+
Disposable,
3+
IDE,
4+
ScopeProvider,
5+
ScopeType,
6+
} from "@cursorless/common";
7+
import { pull } from "lodash-es";
8+
import {
9+
type VscodeScopeVisualizer,
10+
createVscodeScopeVisualizer,
11+
} from "./ide/vscode/VSCodeScopeVisualizer";
12+
import type {
13+
ScopeVisualizer,
14+
ScopeVisualizerListener,
15+
VisualizationType,
16+
} from "./ScopeVisualizerCommandApi";
17+
18+
export function createScopeVisualizer(
19+
ide: IDE,
20+
scopeProvider: ScopeProvider,
21+
): ScopeVisualizer {
22+
let scopeVisualizer: VscodeScopeVisualizer | undefined;
23+
let currentScopeType: ScopeType | undefined;
24+
25+
const listeners: ScopeVisualizerListener[] = [];
26+
27+
return {
28+
start(scopeType: ScopeType, visualizationType: VisualizationType) {
29+
scopeVisualizer?.dispose();
30+
scopeVisualizer = createVscodeScopeVisualizer(
31+
ide,
32+
scopeProvider,
33+
scopeType,
34+
visualizationType,
35+
);
36+
scopeVisualizer.start();
37+
currentScopeType = scopeType;
38+
listeners
39+
.slice()
40+
.forEach((listener) => listener(scopeType, visualizationType));
41+
},
42+
43+
stop() {
44+
scopeVisualizer?.dispose();
45+
scopeVisualizer = undefined;
46+
currentScopeType = undefined;
47+
listeners.slice().forEach((listener) => listener(undefined, undefined));
48+
},
49+
50+
get scopeType() {
51+
return currentScopeType;
52+
},
53+
54+
onDidChangeScopeType(listener: ScopeVisualizerListener): Disposable {
55+
listeners.push(listener);
56+
57+
return {
58+
dispose() {
59+
pull(listeners, listener);
60+
},
61+
};
62+
},
63+
};
64+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { TreeSitter } from "@cursorless/common";
2+
import type { ParseTreeApi } from "@cursorless/vscode-common";
3+
4+
export function createTreeSitter(parseTreeApi: ParseTreeApi): TreeSitter {
5+
return {
6+
loadLanguage: parseTreeApi.loadLanguage,
7+
createQuery: parseTreeApi.createQuery,
8+
getTree: (document) => parseTreeApi.getTreeForUri(document.uri),
9+
};
10+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as crypto from "crypto";
2+
import * as os from "node:os";
3+
import * as path from "node:path";
4+
import type { ExtensionContext } from "vscode";
5+
import { FakeFontMeasurements } from "./ide/vscode/hats/FakeFontMeasurements";
6+
import { FontMeasurementsImpl } from "./ide/vscode/hats/FontMeasurementsImpl";
7+
import { VscodeHats } from "./ide/vscode/hats/VscodeHats";
8+
import { VscodeFileSystem } from "./ide/vscode/VscodeFileSystem";
9+
import { VscodeIDE } from "./ide/vscode/VscodeIDE";
10+
import { vscodeApi } from "./vscodeApi";
11+
12+
export async function createVscodeIde(context: ExtensionContext) {
13+
const vscodeIDE = new VscodeIDE(context);
14+
15+
const hats = new VscodeHats(
16+
vscodeIDE,
17+
vscodeApi,
18+
context,
19+
vscodeIDE.runMode === "test"
20+
? new FakeFontMeasurements()
21+
: new FontMeasurementsImpl(context),
22+
);
23+
24+
await hats.init();
25+
26+
// FIXME: Inject this from test harness. Would need to arrange to delay
27+
// extension initialization, probably by returning a function from extension
28+
// init that has parameters consisting of test configuration, and have that
29+
// function do the actual initialization.
30+
const cursorlessDir =
31+
vscodeIDE.runMode === "test"
32+
? path.join(os.tmpdir(), crypto.randomBytes(16).toString("hex"))
33+
: path.join(os.homedir(), ".cursorless");
34+
35+
const fileSystem = new VscodeFileSystem(
36+
context,
37+
vscodeIDE.runMode,
38+
cursorlessDir,
39+
);
40+
41+
await fileSystem.initialize();
42+
43+
return { vscodeIDE, hats, fileSystem };
44+
}

packages/cursorless-vscode/src/extension.ts

Lines changed: 8 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
import type {
2-
Disposable,
3-
EnforceUndefined,
4-
IDE,
5-
Range,
6-
ScopeProvider,
7-
ScopeType,
8-
TextDocument,
9-
TreeSitter,
10-
} from "@cursorless/common";
1+
import type { EnforceUndefined } from "@cursorless/common";
112
import {
123
FakeCommandServerApi,
134
FakeIDE,
@@ -27,36 +18,22 @@ import {
2718
ScopeTestRecorder,
2819
TestCaseRecorder,
2920
} from "@cursorless/test-case-recorder";
30-
import type { CursorlessApi, ParseTreeApi } from "@cursorless/vscode-common";
21+
import type { CursorlessApi } from "@cursorless/vscode-common";
3122
import {
3223
getCommandServerApi,
3324
getParseTreeApi,
34-
toVscodeRange,
3525
} from "@cursorless/vscode-common";
36-
import * as crypto from "crypto";
37-
import { pull } from "lodash-es";
38-
import * as os from "node:os";
39-
import * as path from "node:path";
40-
import * as vscode from "vscode";
26+
import type { ExtensionContext } from "vscode";
4127
import { InstallationDependencies } from "./InstallationDependencies";
4228
import { ReleaseNotes } from "./ReleaseNotes";
4329
import { ScopeTreeProvider } from "./ScopeTreeProvider";
44-
import type {
45-
ScopeVisualizer,
46-
ScopeVisualizerListener,
47-
VisualizationType,
48-
} from "./ScopeVisualizerCommandApi";
4930
import { StatusBarItem } from "./StatusBarItem";
5031
import { VscodeSnippets } from "./VscodeSnippets";
5132
import { constructTestHelpers } from "./constructTestHelpers";
33+
import { createScopeVisualizer } from "./createScopeVisualizer";
34+
import { createTreeSitter } from "./createTreeSitter";
5235
import { createTutorial } from "./createTutorial";
53-
import type { VscodeScopeVisualizer } from "./ide/vscode/VSCodeScopeVisualizer";
54-
import { createVscodeScopeVisualizer } from "./ide/vscode/VSCodeScopeVisualizer";
55-
import { VscodeFileSystem } from "./ide/vscode/VscodeFileSystem";
56-
import { VscodeIDE } from "./ide/vscode/VscodeIDE";
57-
import { FakeFontMeasurements } from "./ide/vscode/hats/FakeFontMeasurements";
58-
import { FontMeasurementsImpl } from "./ide/vscode/hats/FontMeasurementsImpl";
59-
import { VscodeHats } from "./ide/vscode/hats/VscodeHats";
36+
import { createVscodeIde } from "./createVscodeIde";
6037
import { KeyboardCommands } from "./keyboard/KeyboardCommands";
6138
import { registerCommands } from "./registerCommands";
6239
import { revisualizeOnCustomRegexChange } from "./revisualizeOnCustomRegexChange";
@@ -72,9 +49,10 @@ import { vscodeApi } from "./vscodeApi";
7249
* - Creates an entrypoint for running commands {@link CommandRunner}.
7350
*/
7451
export async function activate(
75-
context: vscode.ExtensionContext,
52+
context: ExtensionContext,
7653
): Promise<CursorlessApi> {
7754
const parseTreeApi = await getParseTreeApi();
55+
const treeSitter = createTreeSitter(parseTreeApi);
7856

7957
const { vscodeIDE, hats, fileSystem } = await createVscodeIde(context);
8058
const isTesting = vscodeIDE.runMode === "test";
@@ -89,7 +67,6 @@ export async function activate(
8967
? fakeCommandServerApi
9068
: await getCommandServerApi();
9169

92-
const treeSitter = createTreeSitter(parseTreeApi);
9370
const talonSpokenForms = new FileSystemTalonSpokenForms(fileSystem);
9471

9572
const snippets = new VscodeSnippets(normalizedIde);
@@ -212,105 +189,3 @@ export async function activate(
212189
: undefined,
213190
};
214191
}
215-
216-
async function createVscodeIde(context: vscode.ExtensionContext) {
217-
const vscodeIDE = new VscodeIDE(context);
218-
219-
const hats = new VscodeHats(
220-
vscodeIDE,
221-
vscodeApi,
222-
context,
223-
vscodeIDE.runMode === "test"
224-
? new FakeFontMeasurements()
225-
: new FontMeasurementsImpl(context),
226-
);
227-
await hats.init();
228-
229-
// FIXME: Inject this from test harness. Would need to arrange to delay
230-
// extension initialization, probably by returning a function from extension
231-
// init that has parameters consisting of test configuration, and have that
232-
// function do the actual initialization.
233-
const cursorlessDir =
234-
vscodeIDE.runMode === "test"
235-
? path.join(os.tmpdir(), crypto.randomBytes(16).toString("hex"))
236-
: path.join(os.homedir(), ".cursorless");
237-
238-
const fileSystem = new VscodeFileSystem(
239-
context,
240-
vscodeIDE.runMode,
241-
cursorlessDir,
242-
);
243-
await fileSystem.initialize();
244-
245-
return { vscodeIDE, hats, fileSystem };
246-
}
247-
248-
function createTreeSitter(parseTreeApi: ParseTreeApi): TreeSitter {
249-
return {
250-
getNodeAtLocation(document: TextDocument, range: Range) {
251-
return parseTreeApi.getNodeAtLocation(
252-
new vscode.Location(document.uri, toVscodeRange(range)),
253-
);
254-
},
255-
256-
getTree(document: TextDocument) {
257-
return parseTreeApi.getTreeForUri(document.uri);
258-
},
259-
260-
loadLanguage: parseTreeApi.loadLanguage,
261-
createQuery: parseTreeApi.createQuery,
262-
};
263-
}
264-
265-
function createScopeVisualizer(
266-
ide: IDE,
267-
scopeProvider: ScopeProvider,
268-
): ScopeVisualizer {
269-
let scopeVisualizer: VscodeScopeVisualizer | undefined;
270-
let currentScopeType: ScopeType | undefined;
271-
272-
const listeners: ScopeVisualizerListener[] = [];
273-
274-
return {
275-
start(scopeType: ScopeType, visualizationType: VisualizationType) {
276-
scopeVisualizer?.dispose();
277-
scopeVisualizer = createVscodeScopeVisualizer(
278-
ide,
279-
scopeProvider,
280-
scopeType,
281-
visualizationType,
282-
);
283-
scopeVisualizer.start();
284-
currentScopeType = scopeType;
285-
listeners
286-
.slice()
287-
.forEach((listener) => listener(scopeType, visualizationType));
288-
},
289-
290-
stop() {
291-
scopeVisualizer?.dispose();
292-
scopeVisualizer = undefined;
293-
currentScopeType = undefined;
294-
listeners.slice().forEach((listener) => listener(undefined, undefined));
295-
},
296-
297-
get scopeType() {
298-
return currentScopeType;
299-
},
300-
301-
onDidChangeScopeType(listener: ScopeVisualizerListener): Disposable {
302-
listeners.push(listener);
303-
304-
return {
305-
dispose() {
306-
pull(listeners, listener);
307-
},
308-
};
309-
},
310-
};
311-
}
312-
313-
// this method is called when your extension is deactivated
314-
export function deactivate() {
315-
// do nothing
316-
}

packages/vscode-common/src/getExtensionApi.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import type { CommandServerApi } from "@cursorless/common";
22
import * as vscode from "vscode";
3-
import type { Node, Query, Tree } from "web-tree-sitter";
3+
import type { Query, Tree } from "web-tree-sitter";
44
import type { VscodeTestHelpers } from "./TestHelpers";
55

66
export interface CursorlessApi {
77
testHelpers: VscodeTestHelpers | undefined;
88
}
99

1010
export interface ParseTreeApi {
11-
getNodeAtLocation(location: vscode.Location): Node;
12-
getTreeForUri(uri: vscode.Uri): Tree;
1311
loadLanguage(languageId: string): Promise<boolean>;
12+
getTreeForUri(uri: vscode.Uri): Tree;
1413
createQuery(languageId: string, source: string): Query | undefined;
1514
}
1615

0 commit comments

Comments
 (0)