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
21 changes: 11 additions & 10 deletions packages/common/src/types/TreeSitter.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
import type { Range, TextDocument } from "@cursorless/common";
import type { Language, SyntaxNode, Tree } from "web-tree-sitter";
import type { Node, Query, Tree } from "web-tree-sitter";

export interface TreeSitter {
/**
* Function to access nodes in the tree sitter.
*/
getNodeAtLocation(document: TextDocument, range: Range): SyntaxNode;
getNodeAtLocation(document: TextDocument, range: Range): Node;

/**
* Function to access the tree sitter tree.
*/
getTree(document: TextDocument): Tree;

/**
* Gets a language if it is loaded
*
* @param languageId The language id of the language to get
* @returns The language if it is already loaded
*/
getLanguage(languageId: string): Language | undefined;

/**
* Loads a language, returning true if it was successfully loaded
*
* @param languageId The language id of the language to load
* @returns `true` if the language was successfully loaded
*/
loadLanguage(languageId: string): Promise<boolean>;

/**
* Create a query if the language is loaded.
*
* @param languageId The language id of the language to get
* @param source The query source
* @returns The query if that language is already loaded
*/
createQuery(languageId: string, source: string): Query | undefined;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TextDocument, Range, Listener } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import type { LanguageDefinition } from "../languages/LanguageDefinition";
import type { LanguageDefinitions } from "../languages/LanguageDefinitions";

Expand All @@ -16,10 +16,7 @@ export class DisabledLanguageDefinitions implements LanguageDefinitions {
return undefined;
}

getNodeAtLocation(
_document: TextDocument,
_range: Range,
): SyntaxNode | undefined {
getNodeAtLocation(_document: TextDocument, _range: Range): Node | undefined {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Range, TextDocument, TreeSitter } from "@cursorless/common";
import type { Language, SyntaxNode, Tree } from "web-tree-sitter";
import type { Node, Query, Tree } from "web-tree-sitter";

export class DisabledTreeSitter implements TreeSitter {
getTree(_document: TextDocument): Tree {
Expand All @@ -10,11 +10,11 @@ export class DisabledTreeSitter implements TreeSitter {
return Promise.resolve(false);
}

getLanguage(_languageId: string): Language | undefined {
getNodeAtLocation(_document: TextDocument, _range: Range): Node {
throw new Error("Tree sitter not provided");
}

getNodeAtLocation(_document: TextDocument, _range: Range): SyntaxNode {
createQuery(_languageId: string, _source: string): Query | undefined {
throw new Error("Tree sitter not provided");
}
}
11 changes: 8 additions & 3 deletions packages/cursorless-engine/src/languages/LanguageDefinition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,14 @@ export class LanguageDefinition {
return undefined;
}

const rawQuery = treeSitter
.getLanguage(languageId)!
.query(rawLanguageQueryString);
const rawQuery = treeSitter.createQuery(languageId, rawLanguageQueryString);

if (rawQuery == null) {
throw Error(
`Could not create Tree sitter query for language ${languageId}`,
);
}

const query = TreeSitterQuery.create(languageId, treeSitter, rawQuery);

return new LanguageDefinition(query);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
type TreeSitter,
} from "@cursorless/common";
import { toString } from "lodash-es";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import { LanguageDefinition } from "./LanguageDefinition";
import { treeSitterQueryCache } from "./TreeSitterQuery/treeSitterQueryCache";

Expand Down Expand Up @@ -36,10 +36,7 @@ export interface LanguageDefinitions {
/**
* @deprecated Only for use in legacy containing scope stage
*/
getNodeAtLocation(
document: TextDocument,
range: Range,
): SyntaxNode | undefined;
getNodeAtLocation(document: TextDocument, range: Range): Node | undefined;
}

/**
Expand Down Expand Up @@ -163,7 +160,7 @@ export class LanguageDefinitionsImpl
return definition === LANGUAGE_UNDEFINED ? undefined : definition;
}

public getNodeAtLocation(document: TextDocument, range: Range): SyntaxNode {
public getNodeAtLocation(document: TextDocument, range: Range): Node {
return this.treeSitter.getNodeAtLocation(document, range);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export type InferSchemaType<T extends HasSchema> = T["schema"];
* Maps from an operand schema output type to the type of the argument that
* will be passed to the `accept` function of the predicate operator. For example:
*
* - `{type: "capture", name: string}` -> `SyntaxNode`
* - `{type: "capture", name: string}` -> `Node`
* - `{type: "integer", value: number}` -> `number`
*/
type PredicateParameterType<T extends SchemaOutputType> = T extends {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PredicateOperand } from "web-tree-sitter";
import type { PredicateStep } from "web-tree-sitter";
import type { z } from "zod";
import type {
AcceptFunctionArgs,
Expand Down Expand Up @@ -41,7 +41,7 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
*
* @param args The arguments to the operator, converted to the types specified
* in the schema. For example, if the schema is `z.tuple([q.node, q.string])`,
* then `args` will be `SyntaxNode, string`.
* then `args` will be `Node, string`.
*/
protected abstract run(
...args: AcceptFunctionArgs<z.infer<InferSchemaType<T>>>
Expand Down Expand Up @@ -71,7 +71,7 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
* @returns Either a predicate function, or a list of error messages if the operands
* were invalid.
*/
createPredicate(inputOperands: PredicateOperand[]): PredicateResult {
createPredicate(inputOperands: PredicateStep[]): PredicateResult {
const result = this.schema.safeParse(inputOperands);

return result.success
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { PredicateOperand } from "web-tree-sitter";
import type { PredicateStep } from "web-tree-sitter";
import type { z } from "zod";
import { operandToString } from "./predicateToString";

export function constructZodErrorMessages(
inputOperands: PredicateOperand[],
error: z.ZodError<PredicateOperand[]>,
inputOperands: PredicateStep[],
error: z.ZodError<PredicateStep[]>,
): string[] {
return error.errors
.filter(
Expand All @@ -21,7 +21,7 @@ export function constructZodErrorMessages(
.map((error) => getErrorMessage(inputOperands, error));
}

function getErrorMessage(inputOperands: PredicateOperand[], error: z.ZodIssue) {
function getErrorMessage(inputOperands: PredicateStep[], error: z.ZodIssue) {
if (error.path.length === 0) {
if (error.code === "too_small") {
return "Too few arguments";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";

/**
* Determines whether the given node or one of its ancestors is an error node
* @param node The node to check
* @returns True if the given node is contained in an error node
*/
export function isContainedInErrorNode(node: SyntaxNode) {
export function isContainedInErrorNode(node: Node) {
// This node or one of it descendants is an error node
if (node.hasError) {
return true;
}

let ancestorNode: SyntaxNode | null = node.parent;
let ancestorNode: Node | null = node.parent;

while (ancestorNode != null) {
// Ancestral node is an error node
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from "zod";
import { assertTypesEqual } from "./assertTypesEqual";
import type { PredicateOperand } from "web-tree-sitter";
import type { PredicateStep } from "web-tree-sitter";

const string = z.object({ type: z.literal("string"), value: z.string() });

Expand Down Expand Up @@ -62,9 +62,9 @@ export type SchemaTypes = (typeof q)[keyof typeof q];

/**
* The type of the input to the schema. This should always be
* `PredicateOperand`, as that is what we always get from tree-sitter
* `PredicateStep`, as that is what we always get from tree-sitter
*/
export type SchemaInputType = PredicateOperand;
export type SchemaInputType = PredicateStep;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
assertTypesEqual<SchemaInputType, z.input<SchemaTypes>, SchemaInputType>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import assert from "assert";
import { parsePredicates } from "./parsePredicates";
import type { PredicateResult } from "web-tree-sitter";
import type { QueryPredicate } from "web-tree-sitter";

const predicates: PredicateResult[][] = [
const predicates: QueryPredicate[][] = [
[
// (#not-type? @statement comment)
// Valid
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PredicateResult } from "web-tree-sitter";
import type { QueryPredicate } from "web-tree-sitter";
import type { MutableQueryMatch } from "./QueryCapture";
import { queryPredicateOperators } from "./queryPredicateOperators";

Expand All @@ -14,7 +14,7 @@ import { queryPredicateOperators } from "./queryPredicateOperators";
* function that takes a match and returns true if the match matches the
* predicate.
*/
export function parsePredicates(predicateDescriptors: PredicateResult[][]) {
export function parsePredicates(predicateDescriptors: QueryPredicate[][]) {
const errors: PredicateError[] = [];
const predicates: ((match: MutableQueryMatch) => boolean)[][] = [];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import type { PredicateOperand, PredicateResult } from "web-tree-sitter";
import type { PredicateStep, QueryPredicate } from "web-tree-sitter";

export function predicateToString(
predicateDescriptor: PredicateResult,
): string {
export function predicateToString(predicateDescriptor: QueryPredicate): string {
const operandList = predicateDescriptor.operands
.map(operandToString)
.join(" ");

return `(#${predicateDescriptor.operator} ${operandList})`;
}

export function operandToString(value: PredicateOperand): string {
export function operandToString(value: PredicateStep): string {
return value.type === "capture" ? `@${value.name}` : value.value;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { TextDocument } from "@cursorless/common";
import { Range } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import type { MutableQueryCapture } from "./QueryCapture";
import { rewriteStartOfEndOf } from "./rewriteStartOfEndOf";
import assert from "assert";
Expand Down Expand Up @@ -59,7 +59,7 @@ function fillOutCapture(capture: NameRange): MutableQueryCapture {
allowMultiple: false,
insertionDelimiter: undefined,
document: null as unknown as TextDocument,
node: null as unknown as SyntaxNode,
node: null as unknown as Node,
hasError,
};
}
Expand Down
9 changes: 4 additions & 5 deletions packages/cursorless-engine/src/languages/clojure.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SimpleScopeTypeType } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import type { NodeFinder, NodeMatcherAlternative } from "../typings/Types";
import { patternFinder } from "../util/nodeFinders";
import {
Expand Down Expand Up @@ -44,7 +44,7 @@ function indexNodeFinder(
parentFinder: NodeFinder,
indexTransform: (index: number) => number,
) {
return (node: SyntaxNode) => {
return (node: Node) => {
const parent = node.parent;

if (parent == null || parentFinder(parent) == null) {
Expand Down Expand Up @@ -76,8 +76,7 @@ function indexNodeFinder(
* @param node The node whose children to get
* @returns A list of the value node children of the given node
*/
const getValueNodes = (node: SyntaxNode) =>
getChildNodesForFieldName(node, "value");
const getValueNodes = (node: Node) => getChildNodesForFieldName(node, "value");

// A function call is a list literal which is not quoted
const functionCallPattern = "~quoting_lit.list_lit!";
Expand All @@ -89,7 +88,7 @@ const functionCallFinder = patternFinder(functionCallPattern);
* @returns The function call node if the name matches otherwise null
*/
function functionNameBasedFinder(...names: string[]) {
return (node: SyntaxNode) => {
return (node: Node) => {
const functionCallNode = functionCallFinder(node);
if (functionCallNode == null) {
return null;
Expand Down
6 changes: 3 additions & 3 deletions packages/cursorless-engine/src/languages/elseIfExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { TextEditor } from "@cursorless/common";
import { Selection } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import type {
SelectionExtractor,
SelectionWithContext,
Expand Down Expand Up @@ -29,7 +29,7 @@ export function elseIfExtractor(): SelectionExtractor {
includeUnnamedChildren: true,
});

return function (editor: TextEditor, node: SyntaxNode): SelectionWithContext {
return function (editor: TextEditor, node: Node): SelectionWithContext {
const contentRange = contentRangeExtractor(editor, node);

const parent = node.parent;
Expand Down Expand Up @@ -84,7 +84,7 @@ export function elseIfExtractor(): SelectionExtractor {
export function elseExtractor(ifNodeType: string): SelectionExtractor {
const nestedElseIfExtractor = elseIfExtractor();

return function (editor: TextEditor, node: SyntaxNode): SelectionWithContext {
return function (editor: TextEditor, node: Node): SelectionWithContext {
// If we are an `else if` statement, then we just run `elseIfExtractor` on
// our nested `if` node. Otherwise we are a simple `else` branch and don't
// need to do anything fancy.
Expand Down
8 changes: 4 additions & 4 deletions packages/cursorless-engine/src/languages/getNodeMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UnsupportedLanguageError } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import type { Node } from "web-tree-sitter";
import type { SimpleScopeTypeType } from "@cursorless/common";
import type {
NodeMatcher,
Expand Down Expand Up @@ -53,7 +53,7 @@ export const languageMatchers: Record<
function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher {
return (
selection: SelectionWithEditor,
node: SyntaxNode,
node: Node,
): NodeMatcherValue[] | null => {
let matches = matcher(selection, node);
if (matches == null) {
Expand All @@ -74,11 +74,11 @@ function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher {
}

function iterateNearestIterableAncestor(
node: SyntaxNode,
node: Node,
selection: SelectionWithEditor,
nodeMatcher: NodeMatcher,
) {
let parent: SyntaxNode | null = node.parent;
let parent: Node | null = node.parent;
while (parent != null) {
const matches = parent.namedChildren
.flatMap((sibling) => nodeMatcher(selection, sibling))
Expand Down
Loading
Loading