@pcbjs/ts-plugin 0.0.0 → 0.0.1-next.9029beb783788cfbb471cc9d57e1b47864c6eaa6
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/dist/index.cjs +771 -0
- package/package.json +33 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yuxuan Zhang
|
|
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/dist/index.cjs
ADDED
|
@@ -0,0 +1,771 @@
|
|
|
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 __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
|
|
32
|
+
// scripts/ts-shim.cjs
|
|
33
|
+
var require_ts_shim = __commonJS({
|
|
34
|
+
"scripts/ts-shim.cjs"(exports2, module2) {
|
|
35
|
+
"use strict";
|
|
36
|
+
var ts2;
|
|
37
|
+
module2.exports = new Proxy({}, { get: (_, k) => k === "__bind" ? (t) => {
|
|
38
|
+
ts2 = t;
|
|
39
|
+
} : ts2?.[k] });
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// ../compile/dist/scope.js
|
|
44
|
+
var import_node_fs = require("node:fs");
|
|
45
|
+
var import_node_path = require("node:path");
|
|
46
|
+
var import_typescript = __toESM(require_ts_shim(), 1);
|
|
47
|
+
var ScopeError = class extends Error {
|
|
48
|
+
file;
|
|
49
|
+
pos;
|
|
50
|
+
constructor(message, file, pos) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.file = file;
|
|
53
|
+
this.pos = pos;
|
|
54
|
+
this.name = "ScopeError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var EXTS = [".ts", ".tsx", ".mts", ".js", ".jsx", ".mjs"];
|
|
58
|
+
var isFile = (f) => {
|
|
59
|
+
try {
|
|
60
|
+
return (0, import_node_fs.statSync)(f).isFile();
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var resolveFile = (spec, from) => {
|
|
66
|
+
if (!spec.startsWith(".") && !spec.startsWith("/"))
|
|
67
|
+
return null;
|
|
68
|
+
const base = (0, import_node_path.resolve)((0, import_node_path.dirname)(from), spec);
|
|
69
|
+
const ext = (0, import_node_path.extname)(base);
|
|
70
|
+
const stem = [".js", ".jsx", ".mjs"].includes(ext) ? base.slice(0, -ext.length) : null;
|
|
71
|
+
const tries = [...EXTS.includes(ext) ? [base] : [], ...EXTS.map((x) => base + x), ...stem ? EXTS.map((x) => stem + x) : [], ...EXTS.map((x) => (0, import_node_path.resolve)(base, "index" + x))];
|
|
72
|
+
const file = tries.find(isFile);
|
|
73
|
+
return file && (0, import_node_fs.existsSync)(file) ? { file, source: (0, import_node_fs.readFileSync)(file, "utf8") } : null;
|
|
74
|
+
};
|
|
75
|
+
var kindOf = (file) => /\.[jt]sx$/.test(file) ? import_typescript.default.ScriptKind.TSX : /\.[cm]?js$/.test(file) ? import_typescript.default.ScriptKind.JS : import_typescript.default.ScriptKind.TS;
|
|
76
|
+
var parse = (file, source) => import_typescript.default.createSourceFile(file, source, import_typescript.default.ScriptTarget.Latest, true, kindOf(file));
|
|
77
|
+
var has = (n, k) => !!import_typescript.default.canHaveModifiers(n) && !!import_typescript.default.getModifiers(n)?.some((m) => m.kind === k);
|
|
78
|
+
function bindingNames(name, out2 = []) {
|
|
79
|
+
if (import_typescript.default.isIdentifier(name))
|
|
80
|
+
out2.push(name.text);
|
|
81
|
+
else
|
|
82
|
+
for (const e of name.elements)
|
|
83
|
+
if (!import_typescript.default.isOmittedExpression(e))
|
|
84
|
+
bindingNames(e.name, out2);
|
|
85
|
+
return out2;
|
|
86
|
+
}
|
|
87
|
+
function moduleExports(mod, resolveModule = resolveFile, seen = /* @__PURE__ */ new Set()) {
|
|
88
|
+
const out2 = /* @__PURE__ */ new Set();
|
|
89
|
+
if (seen.has(mod.file))
|
|
90
|
+
return out2;
|
|
91
|
+
seen.add(mod.file);
|
|
92
|
+
const sf = parse(mod.file, mod.source);
|
|
93
|
+
const types = /* @__PURE__ */ new Set(), values = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const st of sf.statements) {
|
|
95
|
+
if (import_typescript.default.isInterfaceDeclaration(st) || import_typescript.default.isTypeAliasDeclaration(st))
|
|
96
|
+
types.add(st.name.text);
|
|
97
|
+
else if (import_typescript.default.isVariableStatement(st))
|
|
98
|
+
for (const d of st.declarationList.declarations)
|
|
99
|
+
bindingNames(d.name).forEach((n) => values.add(n));
|
|
100
|
+
else if ((import_typescript.default.isFunctionDeclaration(st) || import_typescript.default.isClassDeclaration(st) || import_typescript.default.isEnumDeclaration(st) || import_typescript.default.isModuleDeclaration(st)) && st.name && import_typescript.default.isIdentifier(st.name))
|
|
101
|
+
values.add(st.name.text);
|
|
102
|
+
else if (import_typescript.default.isImportDeclaration(st) && st.importClause && !st.importClause.isTypeOnly) {
|
|
103
|
+
const c = st.importClause;
|
|
104
|
+
if (c.name)
|
|
105
|
+
values.add(c.name.text);
|
|
106
|
+
if (c.namedBindings && import_typescript.default.isNamespaceImport(c.namedBindings))
|
|
107
|
+
values.add(c.namedBindings.name.text);
|
|
108
|
+
else if (c.namedBindings) {
|
|
109
|
+
for (const e of c.namedBindings.elements)
|
|
110
|
+
if (!e.isTypeOnly)
|
|
111
|
+
values.add(e.name.text);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (const st of sf.statements) {
|
|
116
|
+
if (import_typescript.default.isExportDeclaration(st)) {
|
|
117
|
+
if (st.isTypeOnly)
|
|
118
|
+
continue;
|
|
119
|
+
const spec = st.moduleSpecifier && import_typescript.default.isStringLiteral(st.moduleSpecifier) ? st.moduleSpecifier.text : void 0;
|
|
120
|
+
if (!st.exportClause) {
|
|
121
|
+
const m = spec !== void 0 ? resolveModule(spec, mod.file) : null;
|
|
122
|
+
if (m)
|
|
123
|
+
for (const n of moduleExports(m, resolveModule, seen))
|
|
124
|
+
out2.add(n);
|
|
125
|
+
} else if (import_typescript.default.isNamespaceExport(st.exportClause))
|
|
126
|
+
out2.add(st.exportClause.name.text);
|
|
127
|
+
else
|
|
128
|
+
for (const e of st.exportClause.elements) {
|
|
129
|
+
const local = (e.propertyName ?? e.name).text;
|
|
130
|
+
if (!e.isTypeOnly && (spec !== void 0 || !types.has(local) || values.has(local)))
|
|
131
|
+
out2.add(e.name.text);
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (!has(st, import_typescript.default.SyntaxKind.ExportKeyword) || has(st, import_typescript.default.SyntaxKind.DefaultKeyword))
|
|
136
|
+
continue;
|
|
137
|
+
if (import_typescript.default.isVariableStatement(st))
|
|
138
|
+
for (const d of st.declarationList.declarations)
|
|
139
|
+
bindingNames(d.name).forEach((n) => out2.add(n));
|
|
140
|
+
else if ((import_typescript.default.isFunctionDeclaration(st) || import_typescript.default.isClassDeclaration(st) || import_typescript.default.isEnumDeclaration(st) || import_typescript.default.isModuleDeclaration(st) || import_typescript.default.isImportEqualsDeclaration(st)) && st.name && import_typescript.default.isIdentifier(st.name))
|
|
141
|
+
out2.add(st.name.text);
|
|
142
|
+
}
|
|
143
|
+
out2.delete("default");
|
|
144
|
+
return out2;
|
|
145
|
+
}
|
|
146
|
+
var GLOBALS = /* @__PURE__ */ new Set([...Object.getOwnPropertyNames(globalThis), "globalThis", "undefined", "arguments", "require", "module", "exports", "__dirname", "__filename", "window", "document", "self", "navigator", "location"]);
|
|
147
|
+
var Scope = class {
|
|
148
|
+
parent;
|
|
149
|
+
names = /* @__PURE__ */ new Set();
|
|
150
|
+
fn;
|
|
151
|
+
constructor(parent, fn = false) {
|
|
152
|
+
this.parent = parent;
|
|
153
|
+
this.fn = fn || !parent ? this : parent.fn;
|
|
154
|
+
}
|
|
155
|
+
has(n) {
|
|
156
|
+
return this.names.has(n) || !!this.parent?.has(n);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
function freeNames(sf) {
|
|
160
|
+
const refs = [];
|
|
161
|
+
const root = new Scope(null);
|
|
162
|
+
const declare = (name, s) => bindingNames(name).forEach((n) => s.names.add(n));
|
|
163
|
+
const binding = (name, s) => {
|
|
164
|
+
if (import_typescript.default.isIdentifier(name))
|
|
165
|
+
return;
|
|
166
|
+
for (const e of name.elements) {
|
|
167
|
+
if (import_typescript.default.isOmittedExpression(e))
|
|
168
|
+
continue;
|
|
169
|
+
if (e.propertyName && import_typescript.default.isComputedPropertyName(e.propertyName))
|
|
170
|
+
visit(e.propertyName.expression, s);
|
|
171
|
+
if (e.initializer)
|
|
172
|
+
visit(e.initializer, s);
|
|
173
|
+
binding(e.name, s);
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const typeRefs = (n, s) => {
|
|
177
|
+
if (import_typescript.default.isTypeQueryNode(n)) {
|
|
178
|
+
let e = n.exprName;
|
|
179
|
+
while (import_typescript.default.isQualifiedName(e))
|
|
180
|
+
e = e.left;
|
|
181
|
+
refs.push([e.text, s]);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
import_typescript.default.forEachChild(n, (c) => typeRefs(c, s));
|
|
185
|
+
};
|
|
186
|
+
const fnLike = (n, s) => {
|
|
187
|
+
const f = new Scope(s, true);
|
|
188
|
+
if (import_typescript.default.isFunctionExpression(n) && n.name)
|
|
189
|
+
f.names.add(n.name.text);
|
|
190
|
+
if (!import_typescript.default.isArrowFunction(n))
|
|
191
|
+
f.names.add("arguments");
|
|
192
|
+
if (n.name && import_typescript.default.isComputedPropertyName(n.name))
|
|
193
|
+
visit(n.name.expression, s);
|
|
194
|
+
for (const p of n.parameters) {
|
|
195
|
+
declare(p.name, f);
|
|
196
|
+
binding(p.name, f);
|
|
197
|
+
if (p.type)
|
|
198
|
+
typeRefs(p.type, f);
|
|
199
|
+
if (p.initializer)
|
|
200
|
+
visit(p.initializer, f);
|
|
201
|
+
p.modifiers?.forEach((m) => visit(m, f));
|
|
202
|
+
}
|
|
203
|
+
if (n.type)
|
|
204
|
+
typeRefs(n.type, f);
|
|
205
|
+
const body = n.body;
|
|
206
|
+
if (body && import_typescript.default.isBlock(body))
|
|
207
|
+
body.statements.forEach((st) => visit(st, f));
|
|
208
|
+
else if (body)
|
|
209
|
+
visit(body, f);
|
|
210
|
+
};
|
|
211
|
+
const klass = (n, s) => {
|
|
212
|
+
const c = new Scope(s);
|
|
213
|
+
if (n.name)
|
|
214
|
+
c.names.add(n.name.text);
|
|
215
|
+
n.modifiers?.forEach((m) => visit(m, s));
|
|
216
|
+
for (const h of n.heritageClauses ?? [])
|
|
217
|
+
if (h.token === import_typescript.default.SyntaxKind.ExtendsKeyword)
|
|
218
|
+
h.types.forEach((t) => visit(t.expression, s));
|
|
219
|
+
for (const m of n.members) {
|
|
220
|
+
if (m.name && import_typescript.default.isComputedPropertyName(m.name))
|
|
221
|
+
visit(m.name.expression, c);
|
|
222
|
+
if (import_typescript.default.isPropertyDeclaration(m) && m.initializer)
|
|
223
|
+
visit(m.initializer, c);
|
|
224
|
+
else if (import_typescript.default.isFunctionLike(m))
|
|
225
|
+
fnLike(m, c);
|
|
226
|
+
else if (import_typescript.default.isClassStaticBlockDeclaration(m))
|
|
227
|
+
visit(m.body, c);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const visit = (n, s) => {
|
|
231
|
+
if (import_typescript.default.isIdentifier(n)) {
|
|
232
|
+
refs.push([n.text, s]);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (import_typescript.default.isExpressionWithTypeArguments(n))
|
|
236
|
+
return visit(n.expression, s);
|
|
237
|
+
if (import_typescript.default.isTypeNode(n))
|
|
238
|
+
return typeRefs(n, s);
|
|
239
|
+
switch (n.kind) {
|
|
240
|
+
case import_typescript.default.SyntaxKind.ImportDeclaration: {
|
|
241
|
+
const c = n.importClause;
|
|
242
|
+
if (c?.name)
|
|
243
|
+
root.names.add(c.name.text);
|
|
244
|
+
if (c?.namedBindings)
|
|
245
|
+
import_typescript.default.isNamespaceImport(c.namedBindings) ? root.names.add(c.namedBindings.name.text) : c.namedBindings.elements.forEach((e) => root.names.add(e.name.text));
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
case import_typescript.default.SyntaxKind.ImportEqualsDeclaration:
|
|
249
|
+
s.names.add(n.name.text);
|
|
250
|
+
return;
|
|
251
|
+
case import_typescript.default.SyntaxKind.ExportDeclaration: {
|
|
252
|
+
const e = n;
|
|
253
|
+
if (!e.moduleSpecifier && !e.isTypeOnly && e.exportClause && import_typescript.default.isNamedExports(e.exportClause)) {
|
|
254
|
+
for (const x of e.exportClause.elements)
|
|
255
|
+
if (!x.isTypeOnly)
|
|
256
|
+
refs.push([(x.propertyName ?? x.name).text, s]);
|
|
257
|
+
}
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
case import_typescript.default.SyntaxKind.InterfaceDeclaration:
|
|
261
|
+
case import_typescript.default.SyntaxKind.TypeAliasDeclaration:
|
|
262
|
+
return typeRefs(n, s);
|
|
263
|
+
case import_typescript.default.SyntaxKind.TypeParameter:
|
|
264
|
+
case import_typescript.default.SyntaxKind.BreakStatement:
|
|
265
|
+
case import_typescript.default.SyntaxKind.ContinueStatement:
|
|
266
|
+
case import_typescript.default.SyntaxKind.MetaProperty:
|
|
267
|
+
case import_typescript.default.SyntaxKind.JsxClosingElement:
|
|
268
|
+
case import_typescript.default.SyntaxKind.JsxNamespacedName:
|
|
269
|
+
return;
|
|
270
|
+
case import_typescript.default.SyntaxKind.EnumDeclaration:
|
|
271
|
+
s.names.add(n.name.text);
|
|
272
|
+
return;
|
|
273
|
+
case import_typescript.default.SyntaxKind.ModuleDeclaration: {
|
|
274
|
+
const m = n;
|
|
275
|
+
if (import_typescript.default.isIdentifier(m.name))
|
|
276
|
+
s.names.add(m.name.text);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
case import_typescript.default.SyntaxKind.VariableDeclarationList: {
|
|
280
|
+
const l = n;
|
|
281
|
+
const target = l.flags & (import_typescript.default.NodeFlags.Let | import_typescript.default.NodeFlags.Const | import_typescript.default.NodeFlags.Using) ? s : s.fn;
|
|
282
|
+
for (const d of l.declarations) {
|
|
283
|
+
declare(d.name, target);
|
|
284
|
+
binding(d.name, s);
|
|
285
|
+
if (d.type)
|
|
286
|
+
typeRefs(d.type, s);
|
|
287
|
+
if (d.initializer)
|
|
288
|
+
visit(d.initializer, s);
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
case import_typescript.default.SyntaxKind.FunctionDeclaration: {
|
|
293
|
+
const f = n;
|
|
294
|
+
if (f.name)
|
|
295
|
+
s.names.add(f.name.text);
|
|
296
|
+
return fnLike(f, s);
|
|
297
|
+
}
|
|
298
|
+
case import_typescript.default.SyntaxKind.ClassDeclaration: {
|
|
299
|
+
const c = n;
|
|
300
|
+
if (c.name)
|
|
301
|
+
s.names.add(c.name.text);
|
|
302
|
+
return klass(c, s);
|
|
303
|
+
}
|
|
304
|
+
case import_typescript.default.SyntaxKind.ClassExpression:
|
|
305
|
+
return klass(n, s);
|
|
306
|
+
case import_typescript.default.SyntaxKind.FunctionExpression:
|
|
307
|
+
case import_typescript.default.SyntaxKind.ArrowFunction:
|
|
308
|
+
case import_typescript.default.SyntaxKind.MethodDeclaration:
|
|
309
|
+
case import_typescript.default.SyntaxKind.GetAccessor:
|
|
310
|
+
case import_typescript.default.SyntaxKind.SetAccessor:
|
|
311
|
+
case import_typescript.default.SyntaxKind.Constructor:
|
|
312
|
+
return fnLike(n, s);
|
|
313
|
+
case import_typescript.default.SyntaxKind.Block:
|
|
314
|
+
case import_typescript.default.SyntaxKind.CaseBlock:
|
|
315
|
+
case import_typescript.default.SyntaxKind.ForStatement:
|
|
316
|
+
case import_typescript.default.SyntaxKind.ForInStatement:
|
|
317
|
+
case import_typescript.default.SyntaxKind.ForOfStatement: {
|
|
318
|
+
const b = new Scope(s);
|
|
319
|
+
import_typescript.default.forEachChild(n, (c) => visit(c, b));
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
case import_typescript.default.SyntaxKind.CatchClause: {
|
|
323
|
+
const c = n, b = new Scope(s);
|
|
324
|
+
if (c.variableDeclaration) {
|
|
325
|
+
declare(c.variableDeclaration.name, b);
|
|
326
|
+
binding(c.variableDeclaration.name, b);
|
|
327
|
+
}
|
|
328
|
+
c.block.statements.forEach((st) => visit(st, b));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
case import_typescript.default.SyntaxKind.PropertyAccessExpression:
|
|
332
|
+
return visit(n.expression, s);
|
|
333
|
+
case import_typescript.default.SyntaxKind.PropertyAssignment: {
|
|
334
|
+
const p = n;
|
|
335
|
+
if (import_typescript.default.isComputedPropertyName(p.name))
|
|
336
|
+
visit(p.name.expression, s);
|
|
337
|
+
return visit(p.initializer, s);
|
|
338
|
+
}
|
|
339
|
+
case import_typescript.default.SyntaxKind.ShorthandPropertyAssignment: {
|
|
340
|
+
const p = n;
|
|
341
|
+
refs.push([p.name.text, s]);
|
|
342
|
+
if (p.objectAssignmentInitializer)
|
|
343
|
+
visit(p.objectAssignmentInitializer, s);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
case import_typescript.default.SyntaxKind.LabeledStatement:
|
|
347
|
+
return visit(n.statement, s);
|
|
348
|
+
case import_typescript.default.SyntaxKind.JsxAttribute: {
|
|
349
|
+
const a = n;
|
|
350
|
+
if (a.initializer)
|
|
351
|
+
visit(a.initializer, s);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
case import_typescript.default.SyntaxKind.JsxOpeningElement:
|
|
355
|
+
case import_typescript.default.SyntaxKind.JsxSelfClosingElement: {
|
|
356
|
+
const e = n;
|
|
357
|
+
if (!import_typescript.default.isIdentifier(e.tagName) || !/^[a-z]/.test(e.tagName.text))
|
|
358
|
+
visit(e.tagName, s);
|
|
359
|
+
return visit(e.attributes, s);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
import_typescript.default.forEachChild(n, (c) => visit(c, s));
|
|
363
|
+
};
|
|
364
|
+
sf.statements.forEach((st) => visit(st, root));
|
|
365
|
+
const out2 = [];
|
|
366
|
+
for (const [n, s] of refs)
|
|
367
|
+
if (!s.has(n) && !GLOBALS.has(n) && !out2.includes(n))
|
|
368
|
+
out2.push(n);
|
|
369
|
+
return out2;
|
|
370
|
+
}
|
|
371
|
+
function schematicImports(sf) {
|
|
372
|
+
const ns = /* @__PURE__ */ new Map();
|
|
373
|
+
for (const st of sf.statements) {
|
|
374
|
+
const b = import_typescript.default.isImportDeclaration(st) && !st.importClause?.isTypeOnly ? st.importClause?.namedBindings : void 0;
|
|
375
|
+
if (b && import_typescript.default.isNamespaceImport(b))
|
|
376
|
+
ns.set(b.name.text, st);
|
|
377
|
+
}
|
|
378
|
+
const out2 = [];
|
|
379
|
+
if (!ns.size)
|
|
380
|
+
return out2;
|
|
381
|
+
const visit = (n) => {
|
|
382
|
+
if (import_typescript.default.isJsxAttribute(n) && import_typescript.default.isIdentifier(n.name) && n.name.text === "schematic" && n.initializer && import_typescript.default.isJsxExpression(n.initializer)) {
|
|
383
|
+
const e = n.initializer.expression;
|
|
384
|
+
const d = e && import_typescript.default.isIdentifier(e) ? ns.get(e.text) : void 0;
|
|
385
|
+
if (d && !out2.some((o) => o.ns === e.text))
|
|
386
|
+
out2.push({ ns: e.text, decl: d, attr: n });
|
|
387
|
+
}
|
|
388
|
+
import_typescript.default.forEachChild(n, visit);
|
|
389
|
+
};
|
|
390
|
+
visit(sf);
|
|
391
|
+
return out2;
|
|
392
|
+
}
|
|
393
|
+
function scopeInject(source, resolveModule = resolveFile, file = "design.tsx") {
|
|
394
|
+
if (!source.includes("schematic"))
|
|
395
|
+
return null;
|
|
396
|
+
const sf = parse(file, source);
|
|
397
|
+
const found = schematicImports(sf);
|
|
398
|
+
if (!found.length)
|
|
399
|
+
return null;
|
|
400
|
+
if (found.length > 1) {
|
|
401
|
+
const at2 = found[1].attr.getStart(sf), { line } = sf.getLineAndCharacterOfPosition(at2);
|
|
402
|
+
throw new ScopeError(`${file}:${line + 1}: <PCB schematic> takes the namespaces ${found.map((f) => f.ns).join(" and ")} in one file; put each board with its own schematic module in a file of its own`, file, at2);
|
|
403
|
+
}
|
|
404
|
+
const { ns, decl } = found[0];
|
|
405
|
+
const mod = resolveModule(decl.moduleSpecifier.text, file);
|
|
406
|
+
if (!mod)
|
|
407
|
+
return null;
|
|
408
|
+
const exported = moduleExports(mod, resolveModule);
|
|
409
|
+
const names = freeNames(sf).filter((n) => exported.has(n)).sort();
|
|
410
|
+
if (!names.length)
|
|
411
|
+
return null;
|
|
412
|
+
const at = decl.getEnd(), text = `;const {${names.join(",")}}=${ns};`;
|
|
413
|
+
return { code: source.slice(0, at) + text + source.slice(at), at, text, ns, module: mod.file, names };
|
|
414
|
+
}
|
|
415
|
+
var toSource = (inj, pos) => !inj || pos <= inj.at ? pos : pos < inj.at + inj.text.length ? inj.at : pos - inj.text.length;
|
|
416
|
+
var toInjected = (inj, pos) => !inj || pos < inj.at ? pos : pos + inj.text.length;
|
|
417
|
+
|
|
418
|
+
// src/map.ts
|
|
419
|
+
var DROP = /* @__PURE__ */ Symbol("drop");
|
|
420
|
+
function inside(inj, start, length) {
|
|
421
|
+
if (!inj) return false;
|
|
422
|
+
const end = inj.at + inj.text.length;
|
|
423
|
+
return length ? start >= inj.at && start + length <= end : start > inj.at && start < end;
|
|
424
|
+
}
|
|
425
|
+
var into = (inj, pos) => toInjected(inj, pos);
|
|
426
|
+
var intoEnd = (inj, pos) => inj && pos <= inj.at ? pos : toInjected(inj, pos);
|
|
427
|
+
var out = (inj, pos) => toSource(inj, pos);
|
|
428
|
+
function outSpan(inj, s) {
|
|
429
|
+
if (!inj) return s;
|
|
430
|
+
if (inside(inj, s.start, s.length)) return null;
|
|
431
|
+
const start = out(inj, s.start);
|
|
432
|
+
return { start, length: out(inj, s.start + s.length) - start };
|
|
433
|
+
}
|
|
434
|
+
var intoSpan = (inj, s) => {
|
|
435
|
+
const start = into(inj, s.start);
|
|
436
|
+
return { start, length: intoEnd(inj, s.start + s.length) - start };
|
|
437
|
+
};
|
|
438
|
+
var isSpan = (v) => typeof v.start === "number" && typeof v.length === "number" && Object.keys(v).length === 2;
|
|
439
|
+
var OWN = /* @__PURE__ */ new Set(["textSpan", "span", "triggerSpan", "nameSpan", "selectionSpan"]);
|
|
440
|
+
function outResult(v, file, injOf) {
|
|
441
|
+
if (Array.isArray(v)) return v.map((x) => outResult(x, file, injOf)).filter((x) => x !== DROP);
|
|
442
|
+
if (!v || typeof v !== "object") return v;
|
|
443
|
+
const proto = Object.getPrototypeOf(v);
|
|
444
|
+
if (proto !== Object.prototype && proto !== null) return v;
|
|
445
|
+
if (typeof v.fileName === "string") file = v.fileName;
|
|
446
|
+
const inj = file ? injOf(file) : null;
|
|
447
|
+
if (isSpan(v)) return outSpan(inj, v) ?? DROP;
|
|
448
|
+
const o = { ...v };
|
|
449
|
+
for (const k of Object.keys(o)) {
|
|
450
|
+
const x = o[k];
|
|
451
|
+
if (typeof x === "number" && (k === "position" || k === "renameLocation")) {
|
|
452
|
+
const at = k === "renameLocation" && typeof o.renameFilename === "string" ? injOf(o.renameFilename) : inj;
|
|
453
|
+
if (k === "position" && inside(at, x, 0)) return DROP;
|
|
454
|
+
o[k] = out(at, x);
|
|
455
|
+
} else if (x && typeof x === "object") {
|
|
456
|
+
const m = outResult(x, file, injOf);
|
|
457
|
+
if (m !== DROP) o[k] = m;
|
|
458
|
+
else if (OWN.has(k)) return DROP;
|
|
459
|
+
else delete o[k];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return o;
|
|
463
|
+
}
|
|
464
|
+
function lineStarts(text) {
|
|
465
|
+
const out2 = [0];
|
|
466
|
+
for (let i = 0; i < text.length; i++) {
|
|
467
|
+
const c = text.charCodeAt(i);
|
|
468
|
+
if (c === 13 && text.charCodeAt(i + 1) === 10) i++;
|
|
469
|
+
if (c === 10 || c === 13 || c === 8232 || c === 8233) out2.push(i + 1);
|
|
470
|
+
}
|
|
471
|
+
return out2;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/index.ts
|
|
475
|
+
var CONFIGS = ["pcb.config", "pcbjs.config"].flatMap((n) => ["ts", "mts", "js", "mjs"].map((x) => `${n}.${x}`));
|
|
476
|
+
var WRAPPED = /* @__PURE__ */ Symbol.for("pcbjs.ts-plugin");
|
|
477
|
+
var CANNOT_FIND = /* @__PURE__ */ new Set([2304, 2552]);
|
|
478
|
+
var SCOPE_ERROR = 99001;
|
|
479
|
+
var AT_POS = [
|
|
480
|
+
"getCompletionEntrySymbol",
|
|
481
|
+
"getQuickInfoAtPosition",
|
|
482
|
+
"getTypeDefinitionAtPosition",
|
|
483
|
+
"getImplementationAtPosition",
|
|
484
|
+
"getDocumentHighlights",
|
|
485
|
+
"getRenameInfo",
|
|
486
|
+
"getSignatureHelpItems",
|
|
487
|
+
"getSmartSelectionRange",
|
|
488
|
+
"getBraceMatchingAtPosition",
|
|
489
|
+
"getIndentationAtPosition",
|
|
490
|
+
"getFormattingEditsAfterKeystroke",
|
|
491
|
+
"isValidBraceCompletionAtPosition",
|
|
492
|
+
"getJsxClosingTagAtPosition",
|
|
493
|
+
"getLinkedEditingRangeAtPosition",
|
|
494
|
+
"getSpanOfEnclosingComment",
|
|
495
|
+
"getDocCommentTemplateAtPosition",
|
|
496
|
+
"prepareCallHierarchy",
|
|
497
|
+
"provideCallHierarchyIncomingCalls",
|
|
498
|
+
"provideCallHierarchyOutgoingCalls",
|
|
499
|
+
"getBreakpointStatementAtPosition"
|
|
500
|
+
];
|
|
501
|
+
var AT_RANGE = ["getNameOrDottedNameSpan", "getCodeFixesAtPosition", "getFormattingEditsForRange"];
|
|
502
|
+
var AT_SPAN = ["provideInlayHints", "getSemanticClassifications", "getSyntacticClassifications"];
|
|
503
|
+
var AT_TEXT_RANGE = ["toggleLineComment", "toggleMultilineComment", "commentSelection", "uncommentSelection"];
|
|
504
|
+
var ENCODED = ["getEncodedSemanticClassifications", "getEncodedSyntacticClassifications"];
|
|
505
|
+
var RESULT_ONLY = [
|
|
506
|
+
"getOutliningSpans",
|
|
507
|
+
"getNavigationBarItems",
|
|
508
|
+
"getNavigationTree",
|
|
509
|
+
"getFormattingEditsForDocument",
|
|
510
|
+
"organizeImports",
|
|
511
|
+
"getEditsForFileRename",
|
|
512
|
+
"getCombinedCodeFix",
|
|
513
|
+
"getNavigateToItems",
|
|
514
|
+
"getFileReferences",
|
|
515
|
+
"getTodoComments"
|
|
516
|
+
];
|
|
517
|
+
var DIAGNOSTICS = ["getSyntacticDiagnostics", "getSemanticDiagnostics", "getSuggestionDiagnostics"];
|
|
518
|
+
function init({ typescript: ts2 }) {
|
|
519
|
+
;
|
|
520
|
+
require_ts_shim().__bind?.(ts2);
|
|
521
|
+
function create(info) {
|
|
522
|
+
const host = info.languageServiceHost;
|
|
523
|
+
const ls = info.languageService;
|
|
524
|
+
if (host[WRAPPED]) return ls;
|
|
525
|
+
host[WRAPPED] = true;
|
|
526
|
+
const log = (m) => info.project?.projectService?.logger?.info(`[pcbjs] ${m}`);
|
|
527
|
+
const snap0 = host.getScriptSnapshot.bind(host);
|
|
528
|
+
const ver0 = host.getScriptVersion.bind(host);
|
|
529
|
+
const exists = (f) => host.fileExists?.(f) ?? ts2.sys.fileExists(f);
|
|
530
|
+
const read = (f) => {
|
|
531
|
+
const s = snap0(f);
|
|
532
|
+
return s ? s.getText(0, s.getLength()) : host.readFile?.(f) ?? ts2.sys.readFile(f);
|
|
533
|
+
};
|
|
534
|
+
const modHost = {
|
|
535
|
+
fileExists: exists,
|
|
536
|
+
readFile: (f) => host.readFile?.(f) ?? ts2.sys.readFile(f),
|
|
537
|
+
directoryExists: (d) => host.directoryExists?.(d) ?? ts2.sys.directoryExists(d),
|
|
538
|
+
realpath: host.realpath?.bind(host) ?? ts2.sys.realpath,
|
|
539
|
+
getCurrentDirectory: () => host.getCurrentDirectory(),
|
|
540
|
+
getDirectories: (d) => host.getDirectories?.(d) ?? ts2.sys.getDirectories(d)
|
|
541
|
+
};
|
|
542
|
+
const projects = /* @__PURE__ */ new Map();
|
|
543
|
+
const inProject = (dir) => {
|
|
544
|
+
let hit = projects.get(dir);
|
|
545
|
+
if (hit !== void 0) return hit;
|
|
546
|
+
const up = dir.replace(/\/[^/]*$/, "");
|
|
547
|
+
hit = !/\/node_modules(\/|$)/.test(dir) && (CONFIGS.some((c) => exists(`${dir}/${c}`)) || up !== dir && up !== "" && inProject(up));
|
|
548
|
+
projects.set(dir, hit);
|
|
549
|
+
return hit;
|
|
550
|
+
};
|
|
551
|
+
const wanted = (f) => f.endsWith(".tsx") && inProject(f.replace(/\/[^/]*$/, ""));
|
|
552
|
+
const resolver = (deps, seen) => (s, from) => {
|
|
553
|
+
seen?.(s, from);
|
|
554
|
+
const r = ts2.resolveModuleName(s, from, host.getCompilationSettings(), modHost, host.getModuleResolutionCache?.()).resolvedModule;
|
|
555
|
+
if (!r || r.isExternalLibraryImport) return null;
|
|
556
|
+
const text = read(r.resolvedFileName);
|
|
557
|
+
if (text === void 0) return null;
|
|
558
|
+
deps.push(r.resolvedFileName);
|
|
559
|
+
return { file: r.resolvedFileName, source: text };
|
|
560
|
+
};
|
|
561
|
+
const cache = /* @__PURE__ */ new Map();
|
|
562
|
+
const fresh = (e, version) => e && e.version === version && e.deps.every(([d, v]) => ver0(d) === v);
|
|
563
|
+
function entry(file) {
|
|
564
|
+
if (!wanted(file)) return void 0;
|
|
565
|
+
const version = ver0(file);
|
|
566
|
+
const old = cache.get(file);
|
|
567
|
+
if (fresh(old, version)) return old;
|
|
568
|
+
const source = read(file);
|
|
569
|
+
if (source === void 0) return void 0;
|
|
570
|
+
const deps = [];
|
|
571
|
+
let spec;
|
|
572
|
+
const resolveModule = resolver(deps, (s, from) => {
|
|
573
|
+
if (from === file) spec ??= s;
|
|
574
|
+
});
|
|
575
|
+
const e = { key: "", version, deps: [], inj: null, source };
|
|
576
|
+
try {
|
|
577
|
+
e.inj = scopeInject(source, resolveModule, file);
|
|
578
|
+
} catch (err) {
|
|
579
|
+
if (err instanceof ScopeError) e.error = err;
|
|
580
|
+
else log(`scope of ${file}: ${err.message}`);
|
|
581
|
+
}
|
|
582
|
+
e.spec = spec;
|
|
583
|
+
e.deps = deps.map((d) => [d, ver0(d)]);
|
|
584
|
+
e.key = e.deps.length ? `${version}|${e.deps.map((d) => d[1]).join("|")}` : version;
|
|
585
|
+
if (e.inj) e.snap = ts2.ScriptSnapshot.fromString(e.inj.code);
|
|
586
|
+
cache.set(file, e);
|
|
587
|
+
return e;
|
|
588
|
+
}
|
|
589
|
+
const injOf = (f) => entry(f)?.inj;
|
|
590
|
+
host.getScriptVersion = (f) => entry(f)?.key ?? ver0(f);
|
|
591
|
+
host.getScriptSnapshot = (f) => entry(f)?.snap ?? snap0(f);
|
|
592
|
+
const result = (v, file) => {
|
|
593
|
+
if (![...cache.values()].some((e) => e.inj)) return v;
|
|
594
|
+
const m = outResult(v, file, injOf);
|
|
595
|
+
return m === DROP ? void 0 : m;
|
|
596
|
+
};
|
|
597
|
+
const insideOf = (d) => inside(injOf(d.fileName), d.textSpan.start, d.textSpan.length);
|
|
598
|
+
const viaExport = (defs) => defs?.flatMap((d) => insideOf(d) ? (ls.getDefinitionAtPosition(d.fileName, d.textSpan.start) ?? []).filter((x) => !insideOf(x)) : [d]);
|
|
599
|
+
function scopedUses(first, at) {
|
|
600
|
+
const hit = first.find(insideOf);
|
|
601
|
+
if (!hit) return void 0;
|
|
602
|
+
const all = [...first];
|
|
603
|
+
for (const d of viaExport(ls.getDefinitionAtPosition(hit.fileName, hit.textSpan.start)) ?? []) {
|
|
604
|
+
for (const l of at(d.fileName, d.textSpan.start) ?? []) {
|
|
605
|
+
all.push(l);
|
|
606
|
+
if (insideOf(l) && l !== hit) all.push(...at(l.fileName, l.textSpan.start) ?? []);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const seen = /* @__PURE__ */ new Set();
|
|
610
|
+
return all.filter((l) => !insideOf(l) && !seen.has(`${l.fileName}:${l.textSpan.start}`) && !!seen.add(`${l.fileName}:${l.textSpan.start}`));
|
|
611
|
+
}
|
|
612
|
+
function useSite(file, e, name) {
|
|
613
|
+
const sf = ls.getProgram()?.getSourceFile(file);
|
|
614
|
+
const inj = e.inj;
|
|
615
|
+
if (!sf || !inj) return void 0;
|
|
616
|
+
let found;
|
|
617
|
+
const visit = (n) => {
|
|
618
|
+
if (found !== void 0) return;
|
|
619
|
+
if (ts2.isIdentifier(n) && n.text === name && !inside(inj, n.getStart(sf), name.length)) {
|
|
620
|
+
const p2 = n.parent;
|
|
621
|
+
const member = ts2.isPropertyAccessExpression(p2) && p2.name === n || ts2.isPropertyAssignment(p2) && p2.name === n || ts2.isJsxAttribute(p2) && p2.name === n;
|
|
622
|
+
if (!member) found = out(inj, n.getStart(sf));
|
|
623
|
+
}
|
|
624
|
+
ts2.forEachChild(n, visit);
|
|
625
|
+
};
|
|
626
|
+
visit(sf);
|
|
627
|
+
return found;
|
|
628
|
+
}
|
|
629
|
+
const specAt = (e) => {
|
|
630
|
+
const i = e.spec === void 0 ? -1 : e.source.lastIndexOf(e.spec, e.inj?.at ?? e.source.length);
|
|
631
|
+
return i < 0 ? { start: 0, length: 0 } : { start: i, length: e.spec.length };
|
|
632
|
+
};
|
|
633
|
+
function view(sf, e) {
|
|
634
|
+
return e.view ??= Object.create(sf, { text: { value: e.source }, lineMap: { value: lineStarts(e.source) } });
|
|
635
|
+
}
|
|
636
|
+
function outDiag(d) {
|
|
637
|
+
const e = d.file && entry(d.file.fileName);
|
|
638
|
+
if (!e || d.start === void 0 || !e.inj && e.spec === void 0) return d;
|
|
639
|
+
const inj = e.inj;
|
|
640
|
+
const len = d.length ?? 0;
|
|
641
|
+
let messageText = d.messageText;
|
|
642
|
+
let span;
|
|
643
|
+
if (inside(inj, d.start, len)) {
|
|
644
|
+
const name = /^[A-Za-z_$][\w$]*/.exec(inj.code.slice(d.start))?.[0];
|
|
645
|
+
const use = name === void 0 ? void 0 : useSite(d.file.fileName, e, name);
|
|
646
|
+
span = use === void 0 ? specAt(e) : { start: use, length: name.length };
|
|
647
|
+
if (name) messageText = `${name} is not exported by ${e.spec}`;
|
|
648
|
+
} else {
|
|
649
|
+
span = outSpan(inj, { start: d.start, length: len });
|
|
650
|
+
if (e.spec !== void 0 && CANNOT_FIND.has(d.code)) {
|
|
651
|
+
const name = e.source.slice(span.start, span.start + span.length);
|
|
652
|
+
const flat = ts2.flattenDiagnosticMessageText(d.messageText, "\n");
|
|
653
|
+
const hint = /Did you mean .*$/.exec(flat)?.[0];
|
|
654
|
+
messageText = `${name} is not exported by ${e.spec}${hint ? `. ${hint}` : ""}`;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const related = "relatedInformation" in d && d.relatedInformation ? { relatedInformation: d.relatedInformation.map(outDiag).filter((r) => !!r) } : {};
|
|
658
|
+
return { ...d, ...related, file: e.inj ? view(d.file, e) : d.file, start: span.start, length: span.length, messageText };
|
|
659
|
+
}
|
|
660
|
+
const scopeError = (file) => {
|
|
661
|
+
const e = entry(file);
|
|
662
|
+
if (!e?.error) return [];
|
|
663
|
+
const sf = ls.getProgram()?.getSourceFile(file);
|
|
664
|
+
return [{ category: ts2.DiagnosticCategory.Error, code: SCOPE_ERROR, source: "pcbjs", file: sf && view(sf, e), start: e.error.pos, length: 1, messageText: e.error.message }];
|
|
665
|
+
};
|
|
666
|
+
const p = /* @__PURE__ */ Object.create(null);
|
|
667
|
+
for (const k of Object.keys(ls)) {
|
|
668
|
+
const f = ls[k];
|
|
669
|
+
p[k] = typeof f === "function" ? f.bind(ls) : f;
|
|
670
|
+
}
|
|
671
|
+
const fn = ls;
|
|
672
|
+
for (const k of AT_POS) p[k] = (file, pos, ...rest) => result(fn[k](file, into(injOf(file), pos), ...rest), file);
|
|
673
|
+
for (const k of AT_RANGE) p[k] = (file, start, end, ...rest) => {
|
|
674
|
+
const inj = injOf(file);
|
|
675
|
+
return result(fn[k](file, into(inj, start), intoEnd(inj, end), ...rest), file);
|
|
676
|
+
};
|
|
677
|
+
for (const k of AT_SPAN) p[k] = (file, span, ...rest) => result(fn[k](file, intoSpan(injOf(file), span), ...rest), file);
|
|
678
|
+
for (const k of AT_TEXT_RANGE) p[k] = (file, r, ...rest) => {
|
|
679
|
+
const inj = injOf(file);
|
|
680
|
+
return result(fn[k](file, { pos: into(inj, r.pos), end: intoEnd(inj, r.end) }, ...rest), file);
|
|
681
|
+
};
|
|
682
|
+
for (const k of RESULT_ONLY) p[k] = (...a) => result(fn[k](...a), typeof a[0] === "string" ? a[0] : void 0);
|
|
683
|
+
for (const k of ENCODED) p[k] = (file, span, ...rest) => {
|
|
684
|
+
const inj = injOf(file);
|
|
685
|
+
const c = fn[k](file, intoSpan(inj, span), ...rest);
|
|
686
|
+
if (!inj) return c;
|
|
687
|
+
const spans = [];
|
|
688
|
+
for (let i = 0; i < c.spans.length; i += 3) {
|
|
689
|
+
const s = outSpan(inj, { start: c.spans[i], length: c.spans[i + 1] });
|
|
690
|
+
if (s) spans.push(s.start, s.length, c.spans[i + 2]);
|
|
691
|
+
}
|
|
692
|
+
return { ...c, spans };
|
|
693
|
+
};
|
|
694
|
+
for (const k of DIAGNOSTICS) p[k] = (file) => {
|
|
695
|
+
const ds = fn[k](file).map(outDiag).filter((d) => !!d);
|
|
696
|
+
return k === "getSemanticDiagnostics" ? [...scopeError(file), ...ds] : ds;
|
|
697
|
+
};
|
|
698
|
+
const posOrRange = (inj, r) => typeof r === "number" ? into(inj, r) : { pos: into(inj, r.pos), end: intoEnd(inj, r.end) };
|
|
699
|
+
p.getApplicableRefactors = (file, r, ...rest) => result(fn.getApplicableRefactors(file, posOrRange(injOf(file), r), ...rest), file);
|
|
700
|
+
p.getMoveToRefactoringFileSuggestions = (file, r, ...rest) => result(fn.getMoveToRefactoringFileSuggestions(file, posOrRange(injOf(file), r), ...rest), file);
|
|
701
|
+
p.getEditsForRefactor = (file, fmt, r, ...rest) => result(fn.getEditsForRefactor(file, fmt, posOrRange(injOf(file), r), ...rest), file);
|
|
702
|
+
const exportsOf = (file, e) => {
|
|
703
|
+
if (e.exports) return e.exports;
|
|
704
|
+
const res = resolver([]);
|
|
705
|
+
const mod = e.spec === void 0 ? null : res(e.spec, file);
|
|
706
|
+
return e.exports = mod ? [...moduleExports(mod, res)].sort() : [];
|
|
707
|
+
};
|
|
708
|
+
function exportName(file, name) {
|
|
709
|
+
const program = ls.getProgram();
|
|
710
|
+
const sf = program?.getSourceFile(file);
|
|
711
|
+
if (!program || !sf) return void 0;
|
|
712
|
+
const checker = program.getTypeChecker();
|
|
713
|
+
for (const st of sf.statements) {
|
|
714
|
+
if (!ts2.isImportDeclaration(st) || !st.importClause?.namedBindings || !ts2.isNamespaceImport(st.importClause.namedBindings)) continue;
|
|
715
|
+
const mod = checker.getSymbolAtLocation(st.moduleSpecifier);
|
|
716
|
+
let sym = mod && checker.getExportsOfModule(mod).find((x) => x.name === name);
|
|
717
|
+
if (sym && sym.flags & ts2.SymbolFlags.Alias) sym = checker.getAliasedSymbol(sym);
|
|
718
|
+
const decl = sym?.declarations?.[0];
|
|
719
|
+
const id = decl && ts2.getNameOfDeclaration(decl);
|
|
720
|
+
if (id && decl) return { fileName: decl.getSourceFile().fileName, pos: id.getStart() };
|
|
721
|
+
}
|
|
722
|
+
return void 0;
|
|
723
|
+
}
|
|
724
|
+
p.getCompletionsAtPosition = (file, pos, ...rest) => {
|
|
725
|
+
const r = result(fn.getCompletionsAtPosition(file, into(injOf(file), pos), ...rest), file);
|
|
726
|
+
const e = entry(file);
|
|
727
|
+
if (!r || !e?.spec || !r.isGlobalCompletion) return r;
|
|
728
|
+
const have = new Set(r.entries.map((x) => x.name));
|
|
729
|
+
const more = exportsOf(file, e).filter((n) => !have.has(n)).map((name) => ({ name, kind: ts2.ScriptElementKind.constElement, kindModifiers: "", sortText: "11" }));
|
|
730
|
+
return { ...r, entries: [...r.entries, ...more] };
|
|
731
|
+
};
|
|
732
|
+
p.getCompletionEntryDetails = (file, pos, name, ...rest) => {
|
|
733
|
+
const d = fn.getCompletionEntryDetails(file, into(injOf(file), pos), name, ...rest);
|
|
734
|
+
if (d) return result(d, file);
|
|
735
|
+
const e = entry(file);
|
|
736
|
+
const at = e?.spec !== void 0 && exportsOf(file, e).includes(name) ? exportName(file, name) : void 0;
|
|
737
|
+
const qi = at && ls.getQuickInfoAtPosition(at.fileName, at.pos);
|
|
738
|
+
return qi && { name, kind: qi.kind, kindModifiers: qi.kindModifiers, displayParts: qi.displayParts ?? [], documentation: qi.documentation, tags: qi.tags };
|
|
739
|
+
};
|
|
740
|
+
p.getDefinitionAtPosition = (file, pos) => result(viaExport(ls.getDefinitionAtPosition(file, into(injOf(file), pos))), file);
|
|
741
|
+
p.getDefinitionAndBoundSpan = (file, pos) => {
|
|
742
|
+
const r = ls.getDefinitionAndBoundSpan(file, into(injOf(file), pos));
|
|
743
|
+
return r && result({ ...r, definitions: viaExport(r.definitions) }, file);
|
|
744
|
+
};
|
|
745
|
+
p.getReferencesAtPosition = (file, pos) => {
|
|
746
|
+
const at = (f, q) => ls.getReferencesAtPosition(f, q);
|
|
747
|
+
const first = at(file, into(injOf(file), pos));
|
|
748
|
+
return result(first && (scopedUses(first, at) ?? first), file);
|
|
749
|
+
};
|
|
750
|
+
p.findReferences = (file, pos) => {
|
|
751
|
+
const syms = ls.findReferences(file, into(injOf(file), pos));
|
|
752
|
+
const refs = syms?.flatMap((s) => s.references);
|
|
753
|
+
const uses = refs && scopedUses(refs, (f, q) => ls.getReferencesAtPosition(f, q));
|
|
754
|
+
if (!syms || !uses) return result(syms, file);
|
|
755
|
+
const def = viaExport(syms.map((s) => s.definition).filter((d) => insideOf(d)))?.[0];
|
|
756
|
+
const owner = def && ls.findReferences(def.fileName, def.textSpan.start)?.[0]?.definition;
|
|
757
|
+
return result([{ definition: owner ?? syms[0].definition, references: uses }], file);
|
|
758
|
+
};
|
|
759
|
+
p.findRenameLocations = (file, pos, ...rest) => {
|
|
760
|
+
const at = (f, q) => fn.findRenameLocations(f, q, ...rest);
|
|
761
|
+
const first = at(file, into(injOf(file), pos));
|
|
762
|
+
const uses = first && scopedUses(first, at);
|
|
763
|
+
if (!uses) return result(first, file);
|
|
764
|
+
return result(uses.map(({ prefixText, suffixText, ...l }) => injOf(l.fileName) ? l : { ...l, prefixText, suffixText }), file);
|
|
765
|
+
};
|
|
766
|
+
log(`schematic scope on for ${info.project?.getProjectName?.() ?? "a project"}`);
|
|
767
|
+
return p;
|
|
768
|
+
}
|
|
769
|
+
return { create };
|
|
770
|
+
}
|
|
771
|
+
module.exports = init;
|
package/package.json
CHANGED
|
@@ -1,15 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pcbjs/ts-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1-next.9029beb783788cfbb471cc9d57e1b47864c6eaa6",
|
|
4
4
|
"description": "A TypeScript language service plugin: in a file that passes a schematic module to <PCB schematic={sch}>, every export of that module is in scope by its bare name in the editor, with full types.",
|
|
5
|
+
"type": "commonjs",
|
|
5
6
|
"license": "MIT",
|
|
7
|
+
"homepage": "https://pcbjs.dev",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/pcbjs/pcbjs/issues"
|
|
10
|
+
},
|
|
6
11
|
"repository": {
|
|
7
12
|
"type": "git",
|
|
8
13
|
"url": "git+https://github.com/pcbjs/pcbjs.git",
|
|
9
14
|
"directory": "packages/ts-plugin"
|
|
10
15
|
},
|
|
11
|
-
"
|
|
16
|
+
"main": "./dist/index.cjs",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json --noEmit && node scripts/bundle.mjs",
|
|
28
|
+
"test": "npm run build && node --test \"tests/**/*.test.mjs\"",
|
|
29
|
+
"prepack": "npm run build && node ../../scripts/pack-files.mjs pre",
|
|
30
|
+
"postpack": "node ../../scripts/pack-files.mjs post"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@pcbjs/compile": "0.0.1-next.9029beb783788cfbb471cc9d57e1b47864c6eaa6",
|
|
34
|
+
"@types/node": "^24.0.0",
|
|
35
|
+
"esbuild": "^0.28.0",
|
|
36
|
+
"typescript": "~5.9.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
12
41
|
"publishConfig": {
|
|
13
|
-
"access": "public"
|
|
42
|
+
"access": "public",
|
|
43
|
+
"provenance": true
|
|
14
44
|
}
|
|
15
45
|
}
|