Skip to content

Commit 78fdead

Browse files
Integrate web Tree sitter
1 parent 810ad4f commit 78fdead

33 files changed

+161
-434
lines changed

packages/common/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"cross-spawn": "7.0.5",
2727
"fast-check": "3.22.0",
2828
"js-yaml": "^4.1.0",
29-
"mocha": "^10.7.3"
29+
"mocha": "^10.7.3",
30+
"web-tree-sitter": "^0.25.3"
3031
},
3132
"types": "./out/index.d.ts",
3233
"exports": {

packages/common/src/types/TreeSitter.ts

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

44
export interface TreeSitter {
55
/**
66
* Function to access nodes in the tree sitter.
77
*/
8-
getNodeAtLocation(document: TextDocument, range: Range): SyntaxNode;
8+
getNodeAtLocation(document: TextDocument, range: Range): Node;
99

1010
/**
1111
* Function to access the tree sitter tree.

packages/cursorless-engine/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"nearley": "2.20.1",
3333
"talon-snippets": "1.3.0",
3434
"uuid": "^10.0.0",
35+
"web-tree-sitter": "^0.25.3",
3536
"zod": "3.23.8"
3637
},
3738
"devDependencies": {

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { TextDocument, Range, Listener } from "@cursorless/common";
2-
import type { SyntaxNode } from "web-tree-sitter";
2+
import type { Node } from "web-tree-sitter";
33
import type { LanguageDefinition } from "../languages/LanguageDefinition";
44
import type { LanguageDefinitions } from "../languages/LanguageDefinitions";
55

@@ -16,10 +16,7 @@ export class DisabledLanguageDefinitions implements LanguageDefinitions {
1616
return undefined;
1717
}
1818

19-
getNodeAtLocation(
20-
_document: TextDocument,
21-
_range: Range,
22-
): SyntaxNode | undefined {
19+
getNodeAtLocation(_document: TextDocument, _range: Range): Node | undefined {
2320
return undefined;
2421
}
2522

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

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

44
export class DisabledTreeSitter implements TreeSitter {
55
getTree(_document: TextDocument): Tree {
@@ -14,7 +14,7 @@ export class DisabledTreeSitter implements TreeSitter {
1414
throw new Error("Tree sitter not provided");
1515
}
1616

17-
getNodeAtLocation(_document: TextDocument, _range: Range): SyntaxNode {
17+
getNodeAtLocation(_document: TextDocument, _range: Range): Node {
1818
throw new Error("Tree sitter not provided");
1919
}
2020
}

packages/cursorless-engine/src/languages/LanguageDefinition.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
type IDE,
1212
type TextDocument,
1313
} from "@cursorless/common";
14+
import { Query } from "web-tree-sitter";
1415
import { TreeSitterScopeHandler } from "../processTargets/modifiers/scopeHandlers";
1516
import { TreeSitterQuery } from "./TreeSitterQuery";
1617
import type { QueryCapture } from "./TreeSitterQuery/QueryCapture";
@@ -59,9 +60,14 @@ export class LanguageDefinition {
5960
return undefined;
6061
}
6162

62-
const rawQuery = treeSitter
63-
.getLanguage(languageId)!
64-
.query(rawLanguageQueryString);
63+
const language = treeSitter.getLanguage(languageId);
64+
65+
if (language == null) {
66+
throw Error(`Could not get Tree sitter language for ${languageId}`);
67+
}
68+
69+
const rawQuery = new Query(language, rawLanguageQueryString);
70+
6571
const query = TreeSitterQuery.create(languageId, treeSitter, rawQuery);
6672

6773
return new LanguageDefinition(query);

packages/cursorless-engine/src/languages/LanguageDefinitions.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
type TreeSitter,
99
} from "@cursorless/common";
1010
import { toString } from "lodash-es";
11-
import type { SyntaxNode } from "web-tree-sitter";
11+
import type { Node } from "web-tree-sitter";
1212
import { LanguageDefinition } from "./LanguageDefinition";
1313
import { treeSitterQueryCache } from "./TreeSitterQuery/treeSitterQueryCache";
1414

@@ -36,10 +36,7 @@ export interface LanguageDefinitions {
3636
/**
3737
* @deprecated Only for use in legacy containing scope stage
3838
*/
39-
getNodeAtLocation(
40-
document: TextDocument,
41-
range: Range,
42-
): SyntaxNode | undefined;
39+
getNodeAtLocation(document: TextDocument, range: Range): Node | undefined;
4340
}
4441

4542
/**
@@ -163,7 +160,7 @@ export class LanguageDefinitionsImpl
163160
return definition === LANGUAGE_UNDEFINED ? undefined : definition;
164161
}
165162

166-
public getNodeAtLocation(document: TextDocument, range: Range): SyntaxNode {
163+
public getNodeAtLocation(document: TextDocument, range: Range): Node {
167164
return this.treeSitter.getNodeAtLocation(document, range);
168165
}
169166

packages/cursorless-engine/src/languages/TreeSitterQuery/PredicateOperatorSchemaTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export type InferSchemaType<T extends HasSchema> = T["schema"];
3232
* Maps from an operand schema output type to the type of the argument that
3333
* will be passed to the `accept` function of the predicate operator. For example:
3434
*
35-
* - `{type: "capture", name: string}` -> `SyntaxNode`
35+
* - `{type: "capture", name: string}` -> `Node`
3636
* - `{type: "integer", value: number}` -> `number`
3737
*/
3838
type PredicateParameterType<T extends SchemaOutputType> = T extends {

packages/cursorless-engine/src/languages/TreeSitterQuery/QueryPredicateOperator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PredicateOperand } from "web-tree-sitter";
1+
import type { PredicateStep } from "web-tree-sitter";
22
import type { z } from "zod";
33
import type {
44
AcceptFunctionArgs,
@@ -41,7 +41,7 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
4141
*
4242
* @param args The arguments to the operator, converted to the types specified
4343
* in the schema. For example, if the schema is `z.tuple([q.node, q.string])`,
44-
* then `args` will be `SyntaxNode, string`.
44+
* then `args` will be `Node, string`.
4545
*/
4646
protected abstract run(
4747
...args: AcceptFunctionArgs<z.infer<InferSchemaType<T>>>
@@ -71,7 +71,7 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
7171
* @returns Either a predicate function, or a list of error messages if the operands
7272
* were invalid.
7373
*/
74-
createPredicate(inputOperands: PredicateOperand[]): PredicateResult {
74+
createPredicate(inputOperands: PredicateStep[]): PredicateResult {
7575
const result = this.schema.safeParse(inputOperands);
7676

7777
return result.success

packages/cursorless-engine/src/languages/TreeSitterQuery/constructZodErrorMessages.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import type { PredicateOperand } from "web-tree-sitter";
1+
import type { PredicateStep } from "web-tree-sitter";
22
import type { z } from "zod";
33
import { operandToString } from "./predicateToString";
44

55
export function constructZodErrorMessages(
6-
inputOperands: PredicateOperand[],
7-
error: z.ZodError<PredicateOperand[]>,
6+
inputOperands: PredicateStep[],
7+
error: z.ZodError<PredicateStep[]>,
88
): string[] {
99
return error.errors
1010
.filter(
@@ -21,7 +21,7 @@ export function constructZodErrorMessages(
2121
.map((error) => getErrorMessage(inputOperands, error));
2222
}
2323

24-
function getErrorMessage(inputOperands: PredicateOperand[], error: z.ZodIssue) {
24+
function getErrorMessage(inputOperands: PredicateStep[], error: z.ZodIssue) {
2525
if (error.path.length === 0) {
2626
if (error.code === "too_small") {
2727
return "Too few arguments";

0 commit comments

Comments
 (0)