@letant/python 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +335 -0
- package/dist/index.mjs +298 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Juun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as letant from 'letant';
|
|
2
|
+
|
|
3
|
+
type QueryConfig = {
|
|
4
|
+
"module.binding": {
|
|
5
|
+
required: "source";
|
|
6
|
+
optional: "alias" | "name";
|
|
7
|
+
};
|
|
8
|
+
variable: {
|
|
9
|
+
required: "node" | "name";
|
|
10
|
+
optional: never;
|
|
11
|
+
};
|
|
12
|
+
class: {
|
|
13
|
+
required: "node" | "name" | "body";
|
|
14
|
+
optional: "extends";
|
|
15
|
+
};
|
|
16
|
+
function: {
|
|
17
|
+
required: "node" | "name" | "body";
|
|
18
|
+
optional: never;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
type NodeKind = letant.Head<keyof QueryConfig> | "parameter";
|
|
22
|
+
type Node = letant.Node<NodeKind>;
|
|
23
|
+
type Descriptor = letant.Plugin.Descriptor<QueryConfig, Node>;
|
|
24
|
+
|
|
25
|
+
declare const descriptor: Descriptor;
|
|
26
|
+
|
|
27
|
+
export { descriptor as default, descriptor };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as letant from 'letant';
|
|
2
|
+
|
|
3
|
+
type QueryConfig = {
|
|
4
|
+
"module.binding": {
|
|
5
|
+
required: "source";
|
|
6
|
+
optional: "alias" | "name";
|
|
7
|
+
};
|
|
8
|
+
variable: {
|
|
9
|
+
required: "node" | "name";
|
|
10
|
+
optional: never;
|
|
11
|
+
};
|
|
12
|
+
class: {
|
|
13
|
+
required: "node" | "name" | "body";
|
|
14
|
+
optional: "extends";
|
|
15
|
+
};
|
|
16
|
+
function: {
|
|
17
|
+
required: "node" | "name" | "body";
|
|
18
|
+
optional: never;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
type NodeKind = letant.Head<keyof QueryConfig> | "parameter";
|
|
22
|
+
type Node = letant.Node<NodeKind>;
|
|
23
|
+
type Descriptor = letant.Plugin.Descriptor<QueryConfig, Node>;
|
|
24
|
+
|
|
25
|
+
declare const descriptor: Descriptor;
|
|
26
|
+
|
|
27
|
+
export { descriptor as default, descriptor };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
default: () => index_default,
|
|
34
|
+
descriptor: () => descriptor
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/query.ts
|
|
39
|
+
var import_query = require("letant/query");
|
|
40
|
+
var import_tree_sitter_python = __toESM(require("tree-sitter-python"));
|
|
41
|
+
|
|
42
|
+
// src/queries/binding/module.scm
|
|
43
|
+
var module_default = "(import_statement name: (dotted_name) @source @name) (import_statement name: (aliased_import name: (dotted_name) @source alias: (identifier) @alias)) (import_from_statement module_name: [ (dotted_name) (relative_import) ] @source name: (dotted_name) @name) (import_from_statement module_name: [ (dotted_name) (relative_import) ] @source name: (aliased_import name: (dotted_name) @name alias: (identifier) @alias))";
|
|
44
|
+
|
|
45
|
+
// src/queries/binding/variable.scm
|
|
46
|
+
var variable_default = "(expression_statement (assignment left: [ (identifier) (pattern_list) (tuple_pattern) ] @name) ) @node (for_statement left: [ (identifier) (pattern_list) (tuple_pattern) ] @name ) @node";
|
|
47
|
+
|
|
48
|
+
// src/queries/scope/class.scm
|
|
49
|
+
var class_default = "(class_definition name: (identifier) @name superclasses: (argument_list)? @extends body: (block) @body ) @node";
|
|
50
|
+
|
|
51
|
+
// src/queries/scope/function.scm
|
|
52
|
+
var function_default = "(function_definition name: (identifier) @name body: (block) @body ) @node";
|
|
53
|
+
|
|
54
|
+
// src/queries/utility/reference.scm
|
|
55
|
+
var reference_default = "(identifier) @reference";
|
|
56
|
+
|
|
57
|
+
// src/query.ts
|
|
58
|
+
var language = import_tree_sitter_python.default;
|
|
59
|
+
var query = new import_query.QueryMap(language).set("module.binding", module_default).set("variable", variable_default).set("class", class_default).set("function", function_default);
|
|
60
|
+
var utility = new import_query.QueryMap(language).set(
|
|
61
|
+
"reference",
|
|
62
|
+
reference_default
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// src/handlers/bypass/compound.ts
|
|
66
|
+
var COMPOUND = /* @__PURE__ */ new Set([
|
|
67
|
+
"if_statement",
|
|
68
|
+
"elif_clause",
|
|
69
|
+
"else_clause",
|
|
70
|
+
"for_statement",
|
|
71
|
+
"while_statement",
|
|
72
|
+
"try_statement",
|
|
73
|
+
"except_clause",
|
|
74
|
+
"finally_clause",
|
|
75
|
+
"with_statement",
|
|
76
|
+
"match_statement",
|
|
77
|
+
"case_clause"
|
|
78
|
+
]);
|
|
79
|
+
function bypassCompound(queryKey) {
|
|
80
|
+
const blocks = (node) => node.namedChildren.flatMap((child) => {
|
|
81
|
+
if (child.type === "block") return [child];
|
|
82
|
+
if (COMPOUND.has(child.type)) return blocks(child);
|
|
83
|
+
return [];
|
|
84
|
+
});
|
|
85
|
+
const run = (node) => {
|
|
86
|
+
const matches = [];
|
|
87
|
+
for (const child of node.namedChildren) {
|
|
88
|
+
if (child.type === "decorated_definition") {
|
|
89
|
+
const definition = child.childForFieldName("definition");
|
|
90
|
+
if (definition) {
|
|
91
|
+
matches.push(
|
|
92
|
+
...query.match(queryKey, definition, { maxStartDepth: 0 })
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (!COMPOUND.has(child.type)) continue;
|
|
98
|
+
for (const block of blocks(child)) {
|
|
99
|
+
matches.push(...query.match(queryKey, block, { maxStartDepth: 1 }));
|
|
100
|
+
matches.push(...run(block));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return matches;
|
|
104
|
+
};
|
|
105
|
+
return run;
|
|
106
|
+
}
|
|
107
|
+
var compound_default = bypassCompound;
|
|
108
|
+
|
|
109
|
+
// src/capture.ts
|
|
110
|
+
var captureConfig = {
|
|
111
|
+
"module.binding": {
|
|
112
|
+
bypass: compound_default("module.binding")
|
|
113
|
+
},
|
|
114
|
+
variable: {
|
|
115
|
+
bypass: compound_default("variable")
|
|
116
|
+
},
|
|
117
|
+
class: {
|
|
118
|
+
bypass: compound_default("class")
|
|
119
|
+
},
|
|
120
|
+
function: {
|
|
121
|
+
bypass: compound_default("function")
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// src/handlers/binding/module.ts
|
|
126
|
+
var import_utils = require("letant/utils");
|
|
127
|
+
var import_utils2 = require("letant/utils");
|
|
128
|
+
|
|
129
|
+
// src/handlers/utility/module-path.ts
|
|
130
|
+
function toModulePath(source) {
|
|
131
|
+
if (!source.startsWith(".")) return source;
|
|
132
|
+
const dots = /^\.+/.exec(source)[0].length;
|
|
133
|
+
const rest = source.slice(dots).replace(/\./g, "/");
|
|
134
|
+
const prefix = dots === 1 ? "./" : "../".repeat(dots - 1);
|
|
135
|
+
return rest ? prefix + rest : prefix;
|
|
136
|
+
}
|
|
137
|
+
var module_path_default = toModulePath;
|
|
138
|
+
|
|
139
|
+
// src/handlers/binding/module.ts
|
|
140
|
+
var moduleBindingHandler = (captures, parent) => {
|
|
141
|
+
const result = (0, import_utils2.createConvertResult)();
|
|
142
|
+
for (const c of captures) {
|
|
143
|
+
const { source, name, alias } = c;
|
|
144
|
+
const plain = !!name && !alias && source.text === name.text;
|
|
145
|
+
const representative = alias?.text ?? (plain ? source.text.split(".")[0] : name?.text);
|
|
146
|
+
if (!representative) continue;
|
|
147
|
+
let modulePath = module_path_default(plain ? representative : source.text);
|
|
148
|
+
if (modulePath.endsWith("/") && name) {
|
|
149
|
+
modulePath += name.text;
|
|
150
|
+
}
|
|
151
|
+
result.nodes.push({
|
|
152
|
+
path: (0, import_utils2.createChildPath)(parent, representative),
|
|
153
|
+
type: "binding",
|
|
154
|
+
kind: "module",
|
|
155
|
+
at: (0, import_utils.NodeSource)(modulePath),
|
|
156
|
+
props: alias ? { alias_of: (name ?? source).text } : void 0
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
};
|
|
161
|
+
var module_default2 = moduleBindingHandler;
|
|
162
|
+
|
|
163
|
+
// src/handlers/binding/variable.ts
|
|
164
|
+
var import_utils3 = require("letant/utils");
|
|
165
|
+
|
|
166
|
+
// src/handlers/utility/pattern.ts
|
|
167
|
+
var dispatcher = {
|
|
168
|
+
// terminate condition of recursion
|
|
169
|
+
identifier: (node) => [{ name: node.text, node }],
|
|
170
|
+
// recurse over single element
|
|
171
|
+
list_splat_pattern: (node) => flatPattern(node.firstNamedChild),
|
|
172
|
+
// recurse over multiple elements
|
|
173
|
+
pattern_list: (node) => node.namedChildren.flatMap((c) => flatPattern(c)),
|
|
174
|
+
tuple_pattern: (node) => node.namedChildren.flatMap((c) => flatPattern(c)),
|
|
175
|
+
list_pattern: (node) => node.namedChildren.flatMap((c) => flatPattern(c))
|
|
176
|
+
};
|
|
177
|
+
function flatPattern(node) {
|
|
178
|
+
if (!dispatcher[node.type]) {
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
return dispatcher[node.type](node);
|
|
182
|
+
}
|
|
183
|
+
var pattern_default = flatPattern;
|
|
184
|
+
|
|
185
|
+
// src/handlers/binding/variable.ts
|
|
186
|
+
var variableHandler = (captures, parent) => {
|
|
187
|
+
const result = (0, import_utils3.createConvertResult)();
|
|
188
|
+
for (const c of captures) {
|
|
189
|
+
const { node, name } = c;
|
|
190
|
+
for (const { name: nm, node: n } of pattern_default(name)) {
|
|
191
|
+
const path = (0, import_utils3.createChildPath)(parent, nm);
|
|
192
|
+
result.nodes.push({
|
|
193
|
+
path,
|
|
194
|
+
type: "binding",
|
|
195
|
+
kind: "variable",
|
|
196
|
+
at: (0, import_utils3.getRange)(name.type === "identifier" ? node : n)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
};
|
|
202
|
+
var variable_default2 = variableHandler;
|
|
203
|
+
|
|
204
|
+
// src/handlers/scope/class.ts
|
|
205
|
+
var import_utils4 = require("letant/utils");
|
|
206
|
+
var classHandler = (captures, parent, { capture, convert }) => {
|
|
207
|
+
const result = (0, import_utils4.createConvertResult)();
|
|
208
|
+
for (const c of captures) {
|
|
209
|
+
const { node, name, extends: ext, body } = c;
|
|
210
|
+
const path = (0, import_utils4.createChildPath)(parent, name.text);
|
|
211
|
+
result.nodes.push({
|
|
212
|
+
path,
|
|
213
|
+
type: "scope",
|
|
214
|
+
kind: "class",
|
|
215
|
+
at: (0, import_utils4.getRange)(node),
|
|
216
|
+
blockStartIndex: body.startIndex,
|
|
217
|
+
props: {
|
|
218
|
+
extends: ext?.text
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
result.push(convert(capture(body), path));
|
|
222
|
+
}
|
|
223
|
+
return result;
|
|
224
|
+
};
|
|
225
|
+
var class_default2 = classHandler;
|
|
226
|
+
|
|
227
|
+
// src/handlers/scope/function.ts
|
|
228
|
+
var import_utils5 = require("letant/utils");
|
|
229
|
+
|
|
230
|
+
// src/handlers/utility/parameter.ts
|
|
231
|
+
function flatParameters(parameters) {
|
|
232
|
+
const result = [];
|
|
233
|
+
for (const child of parameters.namedChildren) {
|
|
234
|
+
switch (child.type) {
|
|
235
|
+
case "identifier":
|
|
236
|
+
result.push({ name: child.text, node: child, has_default: false });
|
|
237
|
+
break;
|
|
238
|
+
case "typed_parameter": {
|
|
239
|
+
const inner = child.firstNamedChild;
|
|
240
|
+
if (inner?.type === "identifier") {
|
|
241
|
+
result.push({ name: inner.text, node: child, has_default: false });
|
|
242
|
+
}
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case "default_parameter":
|
|
246
|
+
case "typed_default_parameter": {
|
|
247
|
+
const name = child.childForFieldName("name");
|
|
248
|
+
if (name?.type === "identifier") {
|
|
249
|
+
result.push({ name: name.text, node: child, has_default: true });
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case "list_splat_pattern":
|
|
254
|
+
case "dictionary_splat_pattern": {
|
|
255
|
+
const inner = child.firstNamedChild;
|
|
256
|
+
if (inner?.type === "identifier") {
|
|
257
|
+
result.push({ name: inner.text, node: child, has_default: false });
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
default:
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
var parameter_default = flatParameters;
|
|
268
|
+
|
|
269
|
+
// src/handlers/scope/function.ts
|
|
270
|
+
var functionHandler = (captures, parent, { capture, convert }) => {
|
|
271
|
+
const result = (0, import_utils5.createConvertResult)();
|
|
272
|
+
for (const c of captures) {
|
|
273
|
+
const { node, name, body } = c;
|
|
274
|
+
const path = (0, import_utils5.createChildPath)(parent, name.text);
|
|
275
|
+
result.nodes.push({
|
|
276
|
+
path,
|
|
277
|
+
type: "scope",
|
|
278
|
+
kind: "function",
|
|
279
|
+
at: (0, import_utils5.getRange)(node),
|
|
280
|
+
blockStartIndex: body.startIndex,
|
|
281
|
+
props: {
|
|
282
|
+
is_async: node.children.some((child) => child.type === "async")
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
const parameters = node.childForFieldName("parameters");
|
|
286
|
+
if (parameters) {
|
|
287
|
+
for (const { name: nm, node: n, has_default } of parameter_default(
|
|
288
|
+
parameters
|
|
289
|
+
)) {
|
|
290
|
+
result.nodes.push({
|
|
291
|
+
path: (0, import_utils5.createChildPath)(path, nm),
|
|
292
|
+
type: "binding",
|
|
293
|
+
kind: "parameter",
|
|
294
|
+
at: (0, import_utils5.getRange)(n),
|
|
295
|
+
props: { has_default }
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
result.push(convert(capture(body), path));
|
|
300
|
+
}
|
|
301
|
+
return result;
|
|
302
|
+
};
|
|
303
|
+
var function_default2 = functionHandler;
|
|
304
|
+
|
|
305
|
+
// src/convert.ts
|
|
306
|
+
var convertConfig = {
|
|
307
|
+
// binding
|
|
308
|
+
"module.binding": module_default2,
|
|
309
|
+
variable: variable_default2,
|
|
310
|
+
// scope
|
|
311
|
+
class: class_default2,
|
|
312
|
+
function: function_default2
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// src/handlers/utility/reference.ts
|
|
316
|
+
function referenceHandler(node) {
|
|
317
|
+
const captured = utility.get("reference").captures(node, { startIndex: node.startIndex, endIndex: node.endIndex }).flatMap((c) => c.node);
|
|
318
|
+
return captured;
|
|
319
|
+
}
|
|
320
|
+
var reference_default2 = referenceHandler;
|
|
321
|
+
|
|
322
|
+
// src/index.ts
|
|
323
|
+
var descriptor = {
|
|
324
|
+
language,
|
|
325
|
+
extensions: [".py", "/__init__.py"],
|
|
326
|
+
query,
|
|
327
|
+
captureConfig,
|
|
328
|
+
convertConfig,
|
|
329
|
+
references: reference_default2
|
|
330
|
+
};
|
|
331
|
+
var index_default = descriptor;
|
|
332
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
333
|
+
0 && (module.exports = {
|
|
334
|
+
descriptor
|
|
335
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// src/query.ts
|
|
2
|
+
import { QueryMap } from "letant/query";
|
|
3
|
+
import Python from "tree-sitter-python";
|
|
4
|
+
|
|
5
|
+
// src/queries/binding/module.scm
|
|
6
|
+
var module_default = "(import_statement name: (dotted_name) @source @name) (import_statement name: (aliased_import name: (dotted_name) @source alias: (identifier) @alias)) (import_from_statement module_name: [ (dotted_name) (relative_import) ] @source name: (dotted_name) @name) (import_from_statement module_name: [ (dotted_name) (relative_import) ] @source name: (aliased_import name: (dotted_name) @name alias: (identifier) @alias))";
|
|
7
|
+
|
|
8
|
+
// src/queries/binding/variable.scm
|
|
9
|
+
var variable_default = "(expression_statement (assignment left: [ (identifier) (pattern_list) (tuple_pattern) ] @name) ) @node (for_statement left: [ (identifier) (pattern_list) (tuple_pattern) ] @name ) @node";
|
|
10
|
+
|
|
11
|
+
// src/queries/scope/class.scm
|
|
12
|
+
var class_default = "(class_definition name: (identifier) @name superclasses: (argument_list)? @extends body: (block) @body ) @node";
|
|
13
|
+
|
|
14
|
+
// src/queries/scope/function.scm
|
|
15
|
+
var function_default = "(function_definition name: (identifier) @name body: (block) @body ) @node";
|
|
16
|
+
|
|
17
|
+
// src/queries/utility/reference.scm
|
|
18
|
+
var reference_default = "(identifier) @reference";
|
|
19
|
+
|
|
20
|
+
// src/query.ts
|
|
21
|
+
var language = Python;
|
|
22
|
+
var query = new QueryMap(language).set("module.binding", module_default).set("variable", variable_default).set("class", class_default).set("function", function_default);
|
|
23
|
+
var utility = new QueryMap(language).set(
|
|
24
|
+
"reference",
|
|
25
|
+
reference_default
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// src/handlers/bypass/compound.ts
|
|
29
|
+
var COMPOUND = /* @__PURE__ */ new Set([
|
|
30
|
+
"if_statement",
|
|
31
|
+
"elif_clause",
|
|
32
|
+
"else_clause",
|
|
33
|
+
"for_statement",
|
|
34
|
+
"while_statement",
|
|
35
|
+
"try_statement",
|
|
36
|
+
"except_clause",
|
|
37
|
+
"finally_clause",
|
|
38
|
+
"with_statement",
|
|
39
|
+
"match_statement",
|
|
40
|
+
"case_clause"
|
|
41
|
+
]);
|
|
42
|
+
function bypassCompound(queryKey) {
|
|
43
|
+
const blocks = (node) => node.namedChildren.flatMap((child) => {
|
|
44
|
+
if (child.type === "block") return [child];
|
|
45
|
+
if (COMPOUND.has(child.type)) return blocks(child);
|
|
46
|
+
return [];
|
|
47
|
+
});
|
|
48
|
+
const run = (node) => {
|
|
49
|
+
const matches = [];
|
|
50
|
+
for (const child of node.namedChildren) {
|
|
51
|
+
if (child.type === "decorated_definition") {
|
|
52
|
+
const definition = child.childForFieldName("definition");
|
|
53
|
+
if (definition) {
|
|
54
|
+
matches.push(
|
|
55
|
+
...query.match(queryKey, definition, { maxStartDepth: 0 })
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!COMPOUND.has(child.type)) continue;
|
|
61
|
+
for (const block of blocks(child)) {
|
|
62
|
+
matches.push(...query.match(queryKey, block, { maxStartDepth: 1 }));
|
|
63
|
+
matches.push(...run(block));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return matches;
|
|
67
|
+
};
|
|
68
|
+
return run;
|
|
69
|
+
}
|
|
70
|
+
var compound_default = bypassCompound;
|
|
71
|
+
|
|
72
|
+
// src/capture.ts
|
|
73
|
+
var captureConfig = {
|
|
74
|
+
"module.binding": {
|
|
75
|
+
bypass: compound_default("module.binding")
|
|
76
|
+
},
|
|
77
|
+
variable: {
|
|
78
|
+
bypass: compound_default("variable")
|
|
79
|
+
},
|
|
80
|
+
class: {
|
|
81
|
+
bypass: compound_default("class")
|
|
82
|
+
},
|
|
83
|
+
function: {
|
|
84
|
+
bypass: compound_default("function")
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// src/handlers/binding/module.ts
|
|
89
|
+
import { NodeSource } from "letant/utils";
|
|
90
|
+
import { createChildPath, createConvertResult } from "letant/utils";
|
|
91
|
+
|
|
92
|
+
// src/handlers/utility/module-path.ts
|
|
93
|
+
function toModulePath(source) {
|
|
94
|
+
if (!source.startsWith(".")) return source;
|
|
95
|
+
const dots = /^\.+/.exec(source)[0].length;
|
|
96
|
+
const rest = source.slice(dots).replace(/\./g, "/");
|
|
97
|
+
const prefix = dots === 1 ? "./" : "../".repeat(dots - 1);
|
|
98
|
+
return rest ? prefix + rest : prefix;
|
|
99
|
+
}
|
|
100
|
+
var module_path_default = toModulePath;
|
|
101
|
+
|
|
102
|
+
// src/handlers/binding/module.ts
|
|
103
|
+
var moduleBindingHandler = (captures, parent) => {
|
|
104
|
+
const result = createConvertResult();
|
|
105
|
+
for (const c of captures) {
|
|
106
|
+
const { source, name, alias } = c;
|
|
107
|
+
const plain = !!name && !alias && source.text === name.text;
|
|
108
|
+
const representative = alias?.text ?? (plain ? source.text.split(".")[0] : name?.text);
|
|
109
|
+
if (!representative) continue;
|
|
110
|
+
let modulePath = module_path_default(plain ? representative : source.text);
|
|
111
|
+
if (modulePath.endsWith("/") && name) {
|
|
112
|
+
modulePath += name.text;
|
|
113
|
+
}
|
|
114
|
+
result.nodes.push({
|
|
115
|
+
path: createChildPath(parent, representative),
|
|
116
|
+
type: "binding",
|
|
117
|
+
kind: "module",
|
|
118
|
+
at: NodeSource(modulePath),
|
|
119
|
+
props: alias ? { alias_of: (name ?? source).text } : void 0
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
var module_default2 = moduleBindingHandler;
|
|
125
|
+
|
|
126
|
+
// src/handlers/binding/variable.ts
|
|
127
|
+
import { createChildPath as createChildPath2, createConvertResult as createConvertResult2, getRange } from "letant/utils";
|
|
128
|
+
|
|
129
|
+
// src/handlers/utility/pattern.ts
|
|
130
|
+
var dispatcher = {
|
|
131
|
+
// terminate condition of recursion
|
|
132
|
+
identifier: (node) => [{ name: node.text, node }],
|
|
133
|
+
// recurse over single element
|
|
134
|
+
list_splat_pattern: (node) => flatPattern(node.firstNamedChild),
|
|
135
|
+
// recurse over multiple elements
|
|
136
|
+
pattern_list: (node) => node.namedChildren.flatMap((c) => flatPattern(c)),
|
|
137
|
+
tuple_pattern: (node) => node.namedChildren.flatMap((c) => flatPattern(c)),
|
|
138
|
+
list_pattern: (node) => node.namedChildren.flatMap((c) => flatPattern(c))
|
|
139
|
+
};
|
|
140
|
+
function flatPattern(node) {
|
|
141
|
+
if (!dispatcher[node.type]) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
return dispatcher[node.type](node);
|
|
145
|
+
}
|
|
146
|
+
var pattern_default = flatPattern;
|
|
147
|
+
|
|
148
|
+
// src/handlers/binding/variable.ts
|
|
149
|
+
var variableHandler = (captures, parent) => {
|
|
150
|
+
const result = createConvertResult2();
|
|
151
|
+
for (const c of captures) {
|
|
152
|
+
const { node, name } = c;
|
|
153
|
+
for (const { name: nm, node: n } of pattern_default(name)) {
|
|
154
|
+
const path = createChildPath2(parent, nm);
|
|
155
|
+
result.nodes.push({
|
|
156
|
+
path,
|
|
157
|
+
type: "binding",
|
|
158
|
+
kind: "variable",
|
|
159
|
+
at: getRange(name.type === "identifier" ? node : n)
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
};
|
|
165
|
+
var variable_default2 = variableHandler;
|
|
166
|
+
|
|
167
|
+
// src/handlers/scope/class.ts
|
|
168
|
+
import { createChildPath as createChildPath3, createConvertResult as createConvertResult3, getRange as getRange2 } from "letant/utils";
|
|
169
|
+
var classHandler = (captures, parent, { capture, convert }) => {
|
|
170
|
+
const result = createConvertResult3();
|
|
171
|
+
for (const c of captures) {
|
|
172
|
+
const { node, name, extends: ext, body } = c;
|
|
173
|
+
const path = createChildPath3(parent, name.text);
|
|
174
|
+
result.nodes.push({
|
|
175
|
+
path,
|
|
176
|
+
type: "scope",
|
|
177
|
+
kind: "class",
|
|
178
|
+
at: getRange2(node),
|
|
179
|
+
blockStartIndex: body.startIndex,
|
|
180
|
+
props: {
|
|
181
|
+
extends: ext?.text
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
result.push(convert(capture(body), path));
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
};
|
|
188
|
+
var class_default2 = classHandler;
|
|
189
|
+
|
|
190
|
+
// src/handlers/scope/function.ts
|
|
191
|
+
import { createChildPath as createChildPath4, createConvertResult as createConvertResult4, getRange as getRange3 } from "letant/utils";
|
|
192
|
+
|
|
193
|
+
// src/handlers/utility/parameter.ts
|
|
194
|
+
function flatParameters(parameters) {
|
|
195
|
+
const result = [];
|
|
196
|
+
for (const child of parameters.namedChildren) {
|
|
197
|
+
switch (child.type) {
|
|
198
|
+
case "identifier":
|
|
199
|
+
result.push({ name: child.text, node: child, has_default: false });
|
|
200
|
+
break;
|
|
201
|
+
case "typed_parameter": {
|
|
202
|
+
const inner = child.firstNamedChild;
|
|
203
|
+
if (inner?.type === "identifier") {
|
|
204
|
+
result.push({ name: inner.text, node: child, has_default: false });
|
|
205
|
+
}
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case "default_parameter":
|
|
209
|
+
case "typed_default_parameter": {
|
|
210
|
+
const name = child.childForFieldName("name");
|
|
211
|
+
if (name?.type === "identifier") {
|
|
212
|
+
result.push({ name: name.text, node: child, has_default: true });
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case "list_splat_pattern":
|
|
217
|
+
case "dictionary_splat_pattern": {
|
|
218
|
+
const inner = child.firstNamedChild;
|
|
219
|
+
if (inner?.type === "identifier") {
|
|
220
|
+
result.push({ name: inner.text, node: child, has_default: false });
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
default:
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
var parameter_default = flatParameters;
|
|
231
|
+
|
|
232
|
+
// src/handlers/scope/function.ts
|
|
233
|
+
var functionHandler = (captures, parent, { capture, convert }) => {
|
|
234
|
+
const result = createConvertResult4();
|
|
235
|
+
for (const c of captures) {
|
|
236
|
+
const { node, name, body } = c;
|
|
237
|
+
const path = createChildPath4(parent, name.text);
|
|
238
|
+
result.nodes.push({
|
|
239
|
+
path,
|
|
240
|
+
type: "scope",
|
|
241
|
+
kind: "function",
|
|
242
|
+
at: getRange3(node),
|
|
243
|
+
blockStartIndex: body.startIndex,
|
|
244
|
+
props: {
|
|
245
|
+
is_async: node.children.some((child) => child.type === "async")
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const parameters = node.childForFieldName("parameters");
|
|
249
|
+
if (parameters) {
|
|
250
|
+
for (const { name: nm, node: n, has_default } of parameter_default(
|
|
251
|
+
parameters
|
|
252
|
+
)) {
|
|
253
|
+
result.nodes.push({
|
|
254
|
+
path: createChildPath4(path, nm),
|
|
255
|
+
type: "binding",
|
|
256
|
+
kind: "parameter",
|
|
257
|
+
at: getRange3(n),
|
|
258
|
+
props: { has_default }
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
result.push(convert(capture(body), path));
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
};
|
|
266
|
+
var function_default2 = functionHandler;
|
|
267
|
+
|
|
268
|
+
// src/convert.ts
|
|
269
|
+
var convertConfig = {
|
|
270
|
+
// binding
|
|
271
|
+
"module.binding": module_default2,
|
|
272
|
+
variable: variable_default2,
|
|
273
|
+
// scope
|
|
274
|
+
class: class_default2,
|
|
275
|
+
function: function_default2
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/handlers/utility/reference.ts
|
|
279
|
+
function referenceHandler(node) {
|
|
280
|
+
const captured = utility.get("reference").captures(node, { startIndex: node.startIndex, endIndex: node.endIndex }).flatMap((c) => c.node);
|
|
281
|
+
return captured;
|
|
282
|
+
}
|
|
283
|
+
var reference_default2 = referenceHandler;
|
|
284
|
+
|
|
285
|
+
// src/index.ts
|
|
286
|
+
var descriptor = {
|
|
287
|
+
language,
|
|
288
|
+
extensions: [".py", "/__init__.py"],
|
|
289
|
+
query,
|
|
290
|
+
captureConfig,
|
|
291
|
+
convertConfig,
|
|
292
|
+
references: reference_default2
|
|
293
|
+
};
|
|
294
|
+
var index_default = descriptor;
|
|
295
|
+
export {
|
|
296
|
+
index_default as default,
|
|
297
|
+
descriptor
|
|
298
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@letant/python",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Python plugin for letant",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.mts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"keywords": [],
|
|
24
|
+
"author": "Juun",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": "^22.13.0 || >=24"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"letant": "^0.0.5",
|
|
34
|
+
"tree-sitter-python": "^0.25.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
38
|
+
"@types/node": "^26.1.1",
|
|
39
|
+
"letant": "0.0.5",
|
|
40
|
+
"tree-sitter-python": "^0.25.0",
|
|
41
|
+
"tsup": "^8.5.1",
|
|
42
|
+
"typescript": "^6.0.3"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"attw": "attw --pack --ignore-rules 'no-resolution'",
|
|
46
|
+
"attw:quiet": "attw --pack --quiet --ignore-rules 'no-resolution'",
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"check-types": "tsc -p ./tsconfig.json --noEmit",
|
|
49
|
+
"dev": "tsup --watch",
|
|
50
|
+
"dev:query": "pnpm letant query --grammar tree-sitter-python"
|
|
51
|
+
}
|
|
52
|
+
}
|