Skip to content

Commit 5419e38

Browse files
committed
Refactor matchers to add function name transform
1 parent 43f1e7e commit 5419e38

File tree

7 files changed

+355
-297
lines changed

7 files changed

+355
-297
lines changed

src/Types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export type ScopeType =
5050
| "comment"
5151
| "dictionary"
5252
| "functionCall"
53+
| "functionName"
5354
| "ifStatement"
5455
| "list"
5556
| "listElement"
@@ -254,4 +255,11 @@ export interface DecorationColorSetting {
254255
dark: string;
255256
light: string;
256257
highContrast: string;
257-
}
258+
}
259+
260+
export type NodeFinder = (node: SyntaxNode) => SyntaxNode | null;
261+
262+
export type SelectionExtractor = (
263+
editor: vscode.TextEditor,
264+
node: SyntaxNode
265+
) => SelectionWithContext | null;

src/languages/getPojoMatchers.ts

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,38 @@
11
import { SyntaxNode } from "web-tree-sitter";
2-
import { TextEditor } from "vscode";
3-
import {
4-
delimitedMatcher,
5-
hasType,
6-
simpleSelectionExtractor,
7-
childNodeMatcher,
8-
getNodeWithLeadingDelimiter,
9-
} from "../nodeMatchers";
102
import { getNameNode, getKeyNode, getValueNode } from "../treeSitterUtils";
3+
import { selectDelimited, selectWithLeadingDelimiter } from "../nodeSelectors";
4+
import { composedMatcher, matcher, typeMatcher } from "../nodeMatchers";
5+
import { findNode, findNodeOfType } from "../nodeFinders";
116

127
export function getPojoMatchers(
138
dictionaryTypes: string[],
149
listTypes: string[],
1510
listElementMatcher: (node: SyntaxNode) => boolean
1611
) {
1712
return {
18-
dictionary: hasType(...dictionaryTypes),
19-
pair: delimitedMatcher(
20-
(node) => node.type === "pair",
21-
(node) => node.type === "," || node.type === "}" || node.type === "{",
22-
", "
13+
dictionary: typeMatcher(...dictionaryTypes),
14+
pair: matcher(
15+
findNode((node) => node.type === "pair"),
16+
selectDelimited(
17+
(node) => node.type === "," || node.type === "}" || node.type === "{",
18+
", "
19+
)
2320
),
24-
pairKey(editor: TextEditor, node: SyntaxNode) {
25-
if (node.type !== "pair") {
26-
return null;
27-
}
28-
29-
return simpleSelectionExtractor(getKeyNode(node)!);
30-
},
31-
value: childNodeMatcher(getValueNode, getNodeWithLeadingDelimiter),
32-
name: childNodeMatcher(getNameNode, simpleSelectionExtractor),
33-
list: hasType(...listTypes),
34-
listElement: delimitedMatcher(
35-
(node) =>
36-
listTypes.includes(node.parent?.type ?? "") && listElementMatcher(node),
37-
(node) => node.type === "," || node.type === "[" || node.type === "]",
38-
", "
21+
pairKey: composedMatcher([findNodeOfType("pair"), getKeyNode]),
22+
value: matcher(getValueNode, selectWithLeadingDelimiter),
23+
name: matcher(getNameNode),
24+
list: typeMatcher(...listTypes),
25+
listElement: matcher(
26+
findNode(
27+
(node) =>
28+
listTypes.includes(node.parent?.type ?? "") &&
29+
listElementMatcher(node)
30+
),
31+
selectDelimited(
32+
(node) => node.type === "," || node.type === "[" || node.type === "]",
33+
", "
34+
)
3935
),
40-
string: hasType("string"),
36+
string: typeMatcher("string"),
4137
};
4238
}

src/languages/python.ts

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ import { SyntaxNode } from "web-tree-sitter";
22
import { getPojoMatchers } from "./getPojoMatchers";
33
import {
44
cascadingMatcher,
5-
childNodeMatcher,
6-
delimitedMatcher,
7-
getNodeWithLeadingDelimiter,
8-
hasType,
9-
possiblyWrappedNode,
10-
simpleSelectionExtractor,
5+
matcher,
6+
notSupported,
7+
typeMatcher,
118
} from "../nodeMatchers";
12-
import { NodeMatcher, ScopeType } from "../Types";
9+
import { NodeFinder, NodeMatcher, ScopeType } from "../Types";
1310
import {
1411
getDefinitionNode,
1512
getLeftNode,
1613
getNameNode,
1714
} from "../treeSitterUtils";
15+
import {
16+
findNode,
17+
findNodeOfType,
18+
findPossiblyWrappedNode,
19+
} from "../nodeFinders";
20+
import { selectDelimited, selectWithLeadingDelimiter } from "../nodeSelectors";
1821

1922
// TODO figure out how to properly use super types
2023
// Generated by the following command:
@@ -119,10 +122,10 @@ const ARGUMENT_TYPES = [
119122
"keyword_argument",
120123
];
121124

122-
function possiblyDecoratedDefinition(...typeNames: string[]): NodeMatcher {
123-
return possiblyWrappedNode(
124-
(node) => node.type === "decorated_definition",
125-
(node) => typeNames.includes(node.type),
125+
function possiblyDecoratedDefinition(...typeNames: string[]): NodeFinder {
126+
return findPossiblyWrappedNode(
127+
findNodeOfType("decorated_definition"),
128+
findNodeOfType(...typeNames),
126129
(node) => [getDefinitionNode(node)]
127130
);
128131
}
@@ -136,30 +139,32 @@ const nodeMatchers: Record<ScopeType, NodeMatcher> = {
136139
["list", "list_comprehension"],
137140
(node) => LIST_ELEMENT_TYPES.includes(node.type)
138141
),
139-
ifStatement: hasType("if_statement"),
140-
class: possiblyDecoratedDefinition("class_definition"),
141-
statement: hasType(...STATEMENT_TYPES),
142+
ifStatement: typeMatcher("if_statement"),
143+
class: matcher(possiblyDecoratedDefinition("class_definition")),
144+
statement: typeMatcher(...STATEMENT_TYPES),
142145
name: cascadingMatcher(
143-
childNodeMatcher(getNameNode, simpleSelectionExtractor),
144-
childNodeMatcher(
145-
(node) => (node.type === "assignment" ? getLeftNode(node) : null),
146-
simpleSelectionExtractor
147-
)
146+
matcher(getNameNode),
147+
matcher((node) => (node.type === "assignment" ? getLeftNode(node) : null))
148148
),
149-
arrowFunction: hasType("lambda"),
150-
functionCall: hasType("call"),
151-
argumentOrParameter: delimitedMatcher(
152-
(node) =>
153-
(node.parent?.type === "argument_list" &&
154-
ARGUMENT_TYPES.includes(node.type)) ||
155-
(PARAMETER_LIST_TYPES.includes(node.parent?.type ?? "") &&
156-
PARAMETER_TYPES.includes(node.type)),
157-
(node) => node.type === "," || node.type === "(" || node.type === ")",
158-
", "
149+
functionName: notSupported,
150+
arrowFunction: typeMatcher("lambda"),
151+
functionCall: typeMatcher("call"),
152+
argumentOrParameter: matcher(
153+
findNode(
154+
(node) =>
155+
(node.parent?.type === "argument_list" &&
156+
ARGUMENT_TYPES.includes(node.type)) ||
157+
(PARAMETER_LIST_TYPES.includes(node.parent?.type ?? "") &&
158+
PARAMETER_TYPES.includes(node.type))
159+
),
160+
selectDelimited(
161+
(node) => node.type === "," || node.type === "(" || node.type === ")",
162+
", "
163+
)
159164
),
160-
namedFunction: possiblyDecoratedDefinition("function_definition"),
161-
comment: hasType("comment"),
162-
type: childNodeMatcher(getTypeNode, getNodeWithLeadingDelimiter),
165+
namedFunction: matcher(possiblyDecoratedDefinition("function_definition")),
166+
comment: typeMatcher("comment"),
167+
type: matcher(getTypeNode, selectWithLeadingDelimiter),
163168
};
164169

165170
export default nodeMatchers;

src/languages/typescript.ts

Lines changed: 73 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { SyntaxNode } from "web-tree-sitter";
2-
import { TextEditor } from "vscode";
32
import { getPojoMatchers } from "./getPojoMatchers";
43
import {
54
cascadingMatcher,
6-
delimitedMatcher,
7-
hasType,
8-
possiblyWrappedNode,
9-
simpleSelectionExtractor,
10-
getNodeWithLeadingDelimiter,
11-
childNodeMatcher,
5+
composedMatcher,
6+
matcher,
7+
typeMatcher,
128
} from "../nodeMatchers";
13-
import { NodeMatcher, ScopeType } from "../Types";
14-
import { getDeclarationNode, getValueNode } from "../treeSitterUtils";
9+
import { NodeMatcher, ScopeType, NodeFinder } from "../Types";
10+
import {
11+
getDeclarationNode,
12+
getNameNode,
13+
getValueNode,
14+
} from "../treeSitterUtils";
15+
import {
16+
findNode,
17+
findNodeOfType,
18+
findPossiblyWrappedNode,
19+
} from "../nodeFinders";
20+
import { selectDelimited, selectWithLeadingDelimiter } from "../nodeSelectors";
1521

1622
// TODO figure out how to properly use super types
1723
// Generated by the following command:
@@ -101,28 +107,34 @@ const STATEMENT_TYPES = [
101107
"with_statement",
102108
];
103109

104-
function possiblyExportedDeclaration(...typeNames: string[]): NodeMatcher {
105-
return possiblyWrappedNode(
106-
(node) => node.type === "export_statement",
107-
(node) => typeNames.includes(node.type),
110+
function possiblyExportedDeclaration(...typeNames: string[]): NodeFinder {
111+
return findPossiblyWrappedNode(
112+
findNodeOfType("export_statement"),
113+
findNodeOfType(...typeNames),
108114
(node) => [getDeclarationNode(node), getValueNode(node)]
109115
);
110116
}
111117

112-
const isNamedArrowFunction = (node: SyntaxNode) => {
118+
const findNamedArrowFunction = (node: SyntaxNode) => {
113119
if (node.type !== "lexical_declaration" || node.namedChildCount !== 1) {
114-
return false;
120+
return null;
115121
}
116122

117123
const child = node.firstNamedChild!;
118124

119-
return (
120-
child.type === "variable_declarator" &&
125+
return child.type === "variable_declarator" &&
121126
getValueNode(child)!.type === "arrow_function"
122-
);
127+
? node
128+
: null;
123129
};
124130

125-
export const getTypeNode = (node: SyntaxNode) => {
131+
const findClassPropertyArrowFunction = (node: SyntaxNode) =>
132+
node.type === "public_field_definition" &&
133+
getValueNode(node)!.type === "arrow_function"
134+
? node
135+
: null;
136+
137+
export const findTypeNode = (node: SyntaxNode) => {
126138
const typeAnnotationNode = node.children.find((child) =>
127139
["type_annotation", "opting_type_annotation"].includes(child.type)
128140
);
@@ -135,55 +147,68 @@ const nodeMatchers: Record<ScopeType, NodeMatcher> = {
135147
["array"],
136148
(node) => isExpression(node) || node.type === "spread_element"
137149
),
138-
ifStatement: hasType("if_statement"),
139-
class: possiblyExportedDeclaration("class_declaration", "class"),
140-
statement: possiblyExportedDeclaration(...STATEMENT_TYPES),
141-
arrowFunction: hasType("arrow_function"),
142-
functionCall: hasType("call_expression", "new_expression"),
150+
ifStatement: typeMatcher("if_statement"),
151+
class: matcher(possiblyExportedDeclaration("class_declaration", "class")),
152+
statement: matcher(possiblyExportedDeclaration(...STATEMENT_TYPES)),
153+
arrowFunction: typeMatcher("arrow_function"),
154+
functionCall: typeMatcher("call_expression", "new_expression"),
155+
functionName: cascadingMatcher(
156+
composedMatcher([
157+
findNodeOfType("function_declaration", "method_definition"),
158+
getNameNode,
159+
]),
160+
composedMatcher([findClassPropertyArrowFunction, getNameNode]),
161+
composedMatcher([findNamedArrowFunction, getNameNode])
162+
),
143163
type: cascadingMatcher(
144164
// Typed parameters, properties, and functions
145-
childNodeMatcher(getTypeNode, getNodeWithLeadingDelimiter),
146-
165+
matcher(findTypeNode, selectWithLeadingDelimiter),
147166
// Type alias/interface declarations
148-
possiblyExportedDeclaration(
149-
"type_alias_declaration",
150-
"interface_declaration"
167+
matcher(
168+
possiblyExportedDeclaration(
169+
"type_alias_declaration",
170+
"interface_declaration"
171+
)
151172
)
152173
),
153-
argumentOrParameter: delimitedMatcher(
154-
(node) =>
155-
(node.parent?.type === "arguments" &&
156-
(isExpression(node) || node.type === "spread_element")) ||
157-
node.type === "optional_parameter" ||
158-
node.type === "required_parameter",
159-
(node) => node.type === "," || node.type === "(" || node.type === ")",
160-
", "
174+
argumentOrParameter: matcher(
175+
findNode(
176+
(node) =>
177+
(node.parent?.type === "arguments" &&
178+
(isExpression(node) || node.type === "spread_element")) ||
179+
node.type === "optional_parameter" ||
180+
node.type === "required_parameter"
181+
),
182+
selectDelimited(
183+
(node) => node.type === "," || node.type === "(" || node.type === ")",
184+
", "
185+
)
161186
),
162187
namedFunction: cascadingMatcher(
163188
// Simple case, eg
164189
// function foo() {}
165-
possiblyExportedDeclaration("function_declaration", "method_definition"),
190+
matcher(
191+
possiblyExportedDeclaration("function_declaration", "method_definition")
192+
),
166193

167194
// Class property defined as field definition with arrow
168195
// eg:
169196
// class Foo {
170197
// bar = () => "hello";
171198
// }
172-
(editor: TextEditor, node: SyntaxNode) =>
173-
node.type === "public_field_definition" &&
174-
getValueNode(node)!.type === "arrow_function"
175-
? simpleSelectionExtractor(node)
176-
: null,
199+
matcher(findClassPropertyArrowFunction),
177200

178201
// eg:
179202
// const foo = () => "hello"
180-
possiblyWrappedNode(
181-
(node) => node.type === "export_statement",
182-
isNamedArrowFunction,
183-
(node) => [getDeclarationNode(node)]
203+
matcher(
204+
findPossiblyWrappedNode(
205+
findNodeOfType("export_statement"),
206+
findNamedArrowFunction,
207+
(node) => [getDeclarationNode(node)]
208+
)
184209
)
185210
),
186-
comment: hasType("comment"),
211+
comment: matcher(findNodeOfType("comment")),
187212
};
188213

189214
export default nodeMatchers;

0 commit comments

Comments
 (0)