round-core 0.0.6 → 0.0.7
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/dist/index.d.ts +18 -3
- package/extension/.vscodeignore +5 -0
- package/extension/LICENSE +21 -0
- package/extension/cgmanifest.json +45 -0
- package/extension/extension.js +163 -0
- package/extension/images/round-config-dark.svg +10 -0
- package/extension/images/round-config-light.svg +10 -0
- package/extension/images/round-dark.svg +10 -0
- package/extension/images/round-light.svg +10 -0
- package/extension/javascript-language-configuration.json +241 -0
- package/extension/package-lock.json +97 -0
- package/extension/package.json +119 -0
- package/extension/package.nls.json +4 -0
- package/extension/round-0.1.0.vsix +0 -0
- package/extension/round-lsp/package-lock.json +185 -0
- package/extension/round-lsp/package.json +21 -0
- package/extension/round-lsp/src/round-transformer-lsp.js +248 -0
- package/extension/round-lsp/src/server.js +396 -0
- package/extension/snippets/javascript.code-snippets +266 -0
- package/extension/snippets/round.code-snippets +109 -0
- package/extension/syntaxes/JavaScript.tmLanguage.json +6001 -0
- package/extension/syntaxes/JavaScriptReact.tmLanguage.json +6066 -0
- package/extension/syntaxes/Readme.md +12 -0
- package/extension/syntaxes/Regular Expressions (JavaScript).tmLanguage +237 -0
- package/extension/syntaxes/Round.tmLanguage.json +290 -0
- package/extension/syntaxes/RoundInject.tmLanguage.json +20 -0
- package/extension/tags-language-configuration.json +152 -0
- package/extension/temp_astro/package-lock.json +912 -0
- package/extension/temp_astro/package.json +16 -0
- package/extension/types/round-core.d.ts +326 -0
- package/package.json +1 -1
- package/src/index.d.ts +18 -3
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
const {
|
|
2
|
+
createConnection,
|
|
3
|
+
TextDocuments,
|
|
4
|
+
ProposedFeatures,
|
|
5
|
+
TextDocumentSyncKind,
|
|
6
|
+
Diagnostic,
|
|
7
|
+
DiagnosticSeverity,
|
|
8
|
+
Position,
|
|
9
|
+
Range,
|
|
10
|
+
FileChangeType,
|
|
11
|
+
DidChangeWatchedFilesNotification
|
|
12
|
+
} = require('vscode-languageserver/node');
|
|
13
|
+
|
|
14
|
+
const { TextDocument } = require('vscode-languageserver-textdocument');
|
|
15
|
+
const { transformLSP } = require('./round-transformer-lsp');
|
|
16
|
+
const ts = require('typescript');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const { glob } = require('glob');
|
|
20
|
+
const { URI } = require('vscode-uri');
|
|
21
|
+
|
|
22
|
+
function normalizePath(p) {
|
|
23
|
+
if (!p) return p;
|
|
24
|
+
return path.normalize(p).replace(/\\/g, '/');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const connection = createConnection(ProposedFeatures.all);
|
|
28
|
+
const documents = new TextDocuments(TextDocument);
|
|
29
|
+
|
|
30
|
+
// Virtual document storage
|
|
31
|
+
const virtualDocs = new Map(); // roundUri -> { roundDoc, tsxText, map, version }
|
|
32
|
+
const tsFiles = new Map(); // tsxFsPath -> { text, version }
|
|
33
|
+
let workspaceRoot = null;
|
|
34
|
+
let roundRootCached = null;
|
|
35
|
+
function getRoundRoot() {
|
|
36
|
+
if (roundRootCached) return roundRootCached;
|
|
37
|
+
const localNodeModules = path.join(workspaceRoot || '', 'node_modules', 'round-core');
|
|
38
|
+
const sourceDir = path.resolve(__dirname, "../../src");
|
|
39
|
+
roundRootCached = normalizePath(fs.existsSync(localNodeModules) ? localNodeModules : sourceDir);
|
|
40
|
+
return roundRootCached;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const host = {
|
|
44
|
+
getScriptFileNames: () => {
|
|
45
|
+
const names = Array.from(tsFiles.keys());
|
|
46
|
+
const root = getRoundRoot();
|
|
47
|
+
|
|
48
|
+
// Try to find the best d.ts
|
|
49
|
+
const dtsPaths = [
|
|
50
|
+
path.join(root, "src/index.d.ts"),
|
|
51
|
+
path.join(root, "index.d.ts"),
|
|
52
|
+
path.join(root, "dist/index.d.ts")
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const dtsPath = dtsPaths.find(p => fs.existsSync(p));
|
|
56
|
+
const entryPath = dtsPath || normalizePath(path.join(root, "index.js"));
|
|
57
|
+
|
|
58
|
+
if (fs.existsSync(entryPath) && !names.includes(entryPath)) names.push(entryPath);
|
|
59
|
+
return names;
|
|
60
|
+
},
|
|
61
|
+
getScriptVersion: fileName => {
|
|
62
|
+
const normalized = normalizePath(fileName);
|
|
63
|
+
if (tsFiles.has(normalized)) return tsFiles.get(normalized).version.toString();
|
|
64
|
+
if (fs.existsSync(normalized)) {
|
|
65
|
+
try {
|
|
66
|
+
return fs.statSync(normalized).mtimeMs.toString();
|
|
67
|
+
} catch (e) {
|
|
68
|
+
return '0';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return '0';
|
|
72
|
+
},
|
|
73
|
+
getScriptSnapshot: fileName => {
|
|
74
|
+
const text = host.readFile(fileName);
|
|
75
|
+
return text ? ts.ScriptSnapshot.fromString(text) : undefined;
|
|
76
|
+
},
|
|
77
|
+
getCurrentDirectory: () => workspaceRoot || process.cwd(),
|
|
78
|
+
getCompilationSettings: () => {
|
|
79
|
+
const settings = {
|
|
80
|
+
jsx: ts.JsxEmit.React,
|
|
81
|
+
jsxFactory: 'React.createElement',
|
|
82
|
+
jsxFragmentFactory: 'React.Fragment',
|
|
83
|
+
allowJs: true,
|
|
84
|
+
target: ts.ScriptTarget.ESNext,
|
|
85
|
+
module: ts.ModuleKind.ESNext,
|
|
86
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
87
|
+
skipLibCheck: true,
|
|
88
|
+
lib: ['lib.esnext.d.ts', 'lib.dom.d.ts'],
|
|
89
|
+
baseUrl: workspaceRoot || '.',
|
|
90
|
+
paths: {}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const root = getRoundRoot();
|
|
94
|
+
const dtsPaths = [
|
|
95
|
+
path.join(root, "src/index.d.ts"),
|
|
96
|
+
path.join(root, "index.d.ts"),
|
|
97
|
+
path.join(root, "dist/index.d.ts")
|
|
98
|
+
];
|
|
99
|
+
const dtsPath = dtsPaths.find(p => fs.existsSync(p));
|
|
100
|
+
const entryPath = dtsPath || normalizePath(path.join(root, "index.js"));
|
|
101
|
+
|
|
102
|
+
settings.paths["round-core"] = [entryPath];
|
|
103
|
+
settings.paths["round-core/*"] = [path.join(root, "*")];
|
|
104
|
+
|
|
105
|
+
return settings;
|
|
106
|
+
},
|
|
107
|
+
getDefaultLibFileName: options => normalizePath(ts.getDefaultLibFilePath(options)),
|
|
108
|
+
fileExists: fileName => {
|
|
109
|
+
const normalized = normalizePath(fileName);
|
|
110
|
+
return tsFiles.has(normalized) || ts.sys.fileExists(normalized);
|
|
111
|
+
},
|
|
112
|
+
readFile: fileName => {
|
|
113
|
+
const normalized = normalizePath(fileName);
|
|
114
|
+
if (tsFiles.has(normalized)) return tsFiles.get(normalized).text;
|
|
115
|
+
if (ts.sys.fileExists(normalized)) {
|
|
116
|
+
try {
|
|
117
|
+
return ts.sys.readFile(normalized);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
},
|
|
124
|
+
readDirectory: ts.sys.readDirectory,
|
|
125
|
+
directoryExists: ts.sys.directoryExists,
|
|
126
|
+
getDirectories: ts.sys.getDirectories,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const ls = ts.createLanguageService(host, ts.createDocumentRegistry());
|
|
130
|
+
|
|
131
|
+
connection.onInitialize((params) => {
|
|
132
|
+
workspaceRoot = params.rootPath || (params.workspaceFolders?.[0]?.uri ? URI.parse(params.workspaceFolders[0].uri).fsPath : null);
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
capabilities: {
|
|
136
|
+
textDocumentSync: TextDocumentSyncKind.Full,
|
|
137
|
+
hoverProvider: true,
|
|
138
|
+
definitionProvider: true
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
connection.onInitialized(async () => {
|
|
144
|
+
if (workspaceRoot) {
|
|
145
|
+
connection.console.log(`Scanning workspace: ${workspaceRoot}`);
|
|
146
|
+
const files = await glob('**/*.round', { cwd: workspaceRoot, ignore: 'node_modules/**', absolute: true });
|
|
147
|
+
const discovered = [];
|
|
148
|
+
for (const file of files) {
|
|
149
|
+
const uri = URI.file(file).toString();
|
|
150
|
+
const content = fs.readFileSync(file, 'utf8');
|
|
151
|
+
processFile(uri, content, 0, false);
|
|
152
|
+
discovered.push(uri);
|
|
153
|
+
}
|
|
154
|
+
// Phase 2: Send diagnostics now that all files are in context
|
|
155
|
+
for (const uri of discovered) {
|
|
156
|
+
const tsxFsPath = normalizePath(URI.parse(uri + '.tsx').fsPath);
|
|
157
|
+
sendDiagnostics(uri, tsxFsPath);
|
|
158
|
+
}
|
|
159
|
+
connection.console.log(`Initialized with ${files.length} .round files`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
connection.client.register(DidChangeWatchedFilesNotification.type, {
|
|
163
|
+
watchers: [{ globPattern: '**/*.round' }]
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
function processFile(uri, text, version, send = true) {
|
|
168
|
+
try {
|
|
169
|
+
const { code, edits } = transformLSP(text, uri);
|
|
170
|
+
const tsxFsPath = normalizePath(URI.parse(uri + '.tsx').fsPath);
|
|
171
|
+
|
|
172
|
+
tsFiles.set(tsxFsPath, { text: code, version });
|
|
173
|
+
virtualDocs.set(uri, {
|
|
174
|
+
roundDoc: TextDocument.create(uri, 'round', version, text),
|
|
175
|
+
tsxText: code,
|
|
176
|
+
edits, // Store precise edits
|
|
177
|
+
version
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (send) sendDiagnostics(uri, tsxFsPath);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
// connection.console.error(`Transform failed for ${uri}: ${e.message}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
documents.onDidChangeContent(change => {
|
|
187
|
+
processFile(change.document.uri, change.document.getText(), change.document.version);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
connection.onDidChangeWatchedFiles(params => {
|
|
191
|
+
for (const change of params.changes) {
|
|
192
|
+
if (change.type === FileChangeType.Deleted) {
|
|
193
|
+
const tsxFsPath = normalizePath(URI.parse(change.uri + '.tsx').fsPath);
|
|
194
|
+
tsFiles.delete(tsxFsPath);
|
|
195
|
+
virtualDocs.delete(change.uri);
|
|
196
|
+
} else if (change.type === FileChangeType.Created || change.type === FileChangeType.Changed) {
|
|
197
|
+
const doc = documents.get(change.uri);
|
|
198
|
+
if (!doc) {
|
|
199
|
+
const fsPath = normalizePath(URI.parse(change.uri).fsPath);
|
|
200
|
+
if (fs.existsSync(fsPath)) {
|
|
201
|
+
processFile(change.uri, fs.readFileSync(fsPath, 'utf8'), Date.now());
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const VIRTUAL_IMPORT = `// @ts-nocheck
|
|
209
|
+
import { Fragment, createElement } from 'round-core';
|
|
210
|
+
const React = { createElement, Fragment };
|
|
211
|
+
|
|
212
|
+
declare global {
|
|
213
|
+
namespace JSX {
|
|
214
|
+
interface IntrinsicElements {
|
|
215
|
+
[elemName: string]: any;
|
|
216
|
+
}
|
|
217
|
+
interface ElementAttributesProperty { props: {}; }
|
|
218
|
+
type Element = any;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
`;
|
|
222
|
+
|
|
223
|
+
function sendDiagnostics(roundUri, tsxFsPath) {
|
|
224
|
+
try {
|
|
225
|
+
const vdoc = virtualDocs.get(roundUri);
|
|
226
|
+
if (!vdoc) return;
|
|
227
|
+
|
|
228
|
+
const allDiagnostics = [
|
|
229
|
+
...ls.getSyntacticDiagnostics(tsxFsPath),
|
|
230
|
+
...ls.getSemanticDiagnostics(tsxFsPath),
|
|
231
|
+
...ls.getSuggestionDiagnostics(tsxFsPath)
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
const mapped = allDiagnostics.map(diag => {
|
|
235
|
+
const range = mapTsxRangeToRound(diag.start, diag.length, vdoc);
|
|
236
|
+
if (!range) return null;
|
|
237
|
+
return {
|
|
238
|
+
severity: mapSeverity(diag.category),
|
|
239
|
+
range,
|
|
240
|
+
message: ts.flattenDiagnosticMessageText(diag.messageText, '\n'),
|
|
241
|
+
source: 'round-ts'
|
|
242
|
+
};
|
|
243
|
+
}).filter(Boolean);
|
|
244
|
+
|
|
245
|
+
connection.sendDiagnostics({ uri: roundUri, diagnostics: mapped });
|
|
246
|
+
} catch (e) {
|
|
247
|
+
connection.console.error(`Diagnostics failed for ${tsxFsPath}: ${e.message}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function toGeneratedOffset(originalOffset, edits) {
|
|
252
|
+
let current = originalOffset;
|
|
253
|
+
for (const edit of edits) {
|
|
254
|
+
if (edit.offset <= originalOffset) {
|
|
255
|
+
// If the edit is entirely before our offset, or starts at it
|
|
256
|
+
if (originalOffset >= edit.offset + edit.length) {
|
|
257
|
+
current += (edit.newLength - edit.length);
|
|
258
|
+
} else {
|
|
259
|
+
// Offset is inside the range being replaced
|
|
260
|
+
// map it to the start of the replacement
|
|
261
|
+
current += (edit.offset - originalOffset);
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return current;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function toOriginalOffset(generatedOffset, edits) {
|
|
270
|
+
let current = generatedOffset;
|
|
271
|
+
let original = generatedOffset;
|
|
272
|
+
|
|
273
|
+
// Need to work backwards through the edits to find the original location
|
|
274
|
+
// Since edits are sorted by original offset, we can simulate the transformation
|
|
275
|
+
let accum = 0;
|
|
276
|
+
for (const edit of edits) {
|
|
277
|
+
const genStart = edit.offset + accum;
|
|
278
|
+
const genEnd = genStart + edit.newLength;
|
|
279
|
+
|
|
280
|
+
if (generatedOffset < genStart) {
|
|
281
|
+
// Offset is before this edit
|
|
282
|
+
return generatedOffset - accum;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (generatedOffset >= genStart && generatedOffset < genEnd) {
|
|
286
|
+
// Offset is inside the replacement
|
|
287
|
+
return edit.offset;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
accum += (edit.newLength - edit.length);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return generatedOffset - accum;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function mapTsxRangeToRound(start, length, vdoc) {
|
|
297
|
+
const edits = vdoc.edits || [];
|
|
298
|
+
const originalStart = toOriginalOffset(start, edits);
|
|
299
|
+
const originalEnd = toOriginalOffset(start + length, edits);
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
start: vdoc.roundDoc.positionAt(originalStart),
|
|
303
|
+
end: vdoc.roundDoc.positionAt(originalEnd)
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function mapSeverity(category) {
|
|
308
|
+
switch (category) {
|
|
309
|
+
case ts.DiagnosticCategory.Error: return DiagnosticSeverity.Error;
|
|
310
|
+
case ts.DiagnosticCategory.Warning: return DiagnosticSeverity.Warning;
|
|
311
|
+
case ts.DiagnosticCategory.Message: return DiagnosticSeverity.Information;
|
|
312
|
+
case ts.DiagnosticCategory.Suggestion: return DiagnosticSeverity.Hint;
|
|
313
|
+
default: return DiagnosticSeverity.Error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
connection.onHover((params) => {
|
|
318
|
+
try {
|
|
319
|
+
const vdoc = virtualDocs.get(params.textDocument.uri);
|
|
320
|
+
if (!vdoc) return null;
|
|
321
|
+
|
|
322
|
+
const tsxFsPath = normalizePath(URI.parse(params.textDocument.uri + '.tsx').fsPath);
|
|
323
|
+
const originalOffset = vdoc.roundDoc.offsetAt(params.position);
|
|
324
|
+
const offset = toGeneratedOffset(originalOffset, vdoc.edits || []);
|
|
325
|
+
|
|
326
|
+
const info = ls.getQuickInfoAtPosition(tsxFsPath, offset);
|
|
327
|
+
if (!info) return null;
|
|
328
|
+
|
|
329
|
+
const text = ts.displayPartsToString(info.displayParts);
|
|
330
|
+
const docs = ts.displayPartsToString(info.documentation);
|
|
331
|
+
const tags = info.tags ? info.tags.map(t => `*@${t.name}* ${t.text ? ts.displayPartsToString(t.text) : ''}`).join('\n\n') : '';
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
contents: {
|
|
335
|
+
kind: 'markdown',
|
|
336
|
+
value: `\`\`\`typescript\n${text}\n\`\`\`\n${docs}${tags ? '\n\n' + tags : ''}`
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
} catch (e) {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
connection.onDefinition((params) => {
|
|
345
|
+
try {
|
|
346
|
+
const vdoc = virtualDocs.get(params.textDocument.uri);
|
|
347
|
+
if (!vdoc) return null;
|
|
348
|
+
|
|
349
|
+
const tsxFsPath = normalizePath(URI.parse(params.textDocument.uri + '.tsx').fsPath);
|
|
350
|
+
const originalOffset = vdoc.roundDoc.offsetAt(params.position);
|
|
351
|
+
const offset = toGeneratedOffset(originalOffset, vdoc.edits || []);
|
|
352
|
+
|
|
353
|
+
const defs = ls.getDefinitionAtPosition(tsxFsPath, offset);
|
|
354
|
+
if (!defs || defs.length === 0) return null;
|
|
355
|
+
|
|
356
|
+
return defs.map(def => {
|
|
357
|
+
let fsPath = normalizePath(def.fileName);
|
|
358
|
+
let start = def.textSpan.start;
|
|
359
|
+
let length = def.textSpan.length;
|
|
360
|
+
|
|
361
|
+
const isVirtual = fsPath.endsWith('.round.tsx');
|
|
362
|
+
const uri = isVirtual ? URI.file(fsPath.slice(0, -4)).toString() : URI.file(fsPath).toString();
|
|
363
|
+
|
|
364
|
+
if (isVirtual) {
|
|
365
|
+
const targetVdoc = virtualDocs.get(uri);
|
|
366
|
+
if (targetVdoc && targetVdoc.edits) {
|
|
367
|
+
start = toOriginalOffset(start, targetVdoc.edits);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const targetVdoc = virtualDocs.get(uri);
|
|
372
|
+
if (targetVdoc) {
|
|
373
|
+
return {
|
|
374
|
+
uri,
|
|
375
|
+
range: {
|
|
376
|
+
start: targetVdoc.roundDoc.positionAt(start),
|
|
377
|
+
end: targetVdoc.roundDoc.positionAt(start + length)
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
uri,
|
|
384
|
+
range: {
|
|
385
|
+
start: { line: 0, character: 0 },
|
|
386
|
+
end: { line: 0, character: 0 }
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}).filter(Boolean);
|
|
390
|
+
} catch (e) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
documents.listen(connection);
|
|
396
|
+
connection.listen();
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Constructor": {
|
|
3
|
+
"prefix": "ctor",
|
|
4
|
+
"body": [
|
|
5
|
+
"/**",
|
|
6
|
+
" *",
|
|
7
|
+
" */",
|
|
8
|
+
"constructor() {",
|
|
9
|
+
"\tsuper();",
|
|
10
|
+
"\t$0",
|
|
11
|
+
"}"
|
|
12
|
+
],
|
|
13
|
+
"description": "Constructor"
|
|
14
|
+
},
|
|
15
|
+
"Class Definition": {
|
|
16
|
+
"prefix": "class",
|
|
17
|
+
"isFileTemplate": true,
|
|
18
|
+
"body": [
|
|
19
|
+
"class ${1:name} {",
|
|
20
|
+
"\tconstructor(${2:parameters}) {",
|
|
21
|
+
"\t\t$0",
|
|
22
|
+
"\t}",
|
|
23
|
+
"}"
|
|
24
|
+
],
|
|
25
|
+
"description": "Class Definition"
|
|
26
|
+
},
|
|
27
|
+
"Method Definition": {
|
|
28
|
+
"prefix": "method",
|
|
29
|
+
"body": [
|
|
30
|
+
"/**",
|
|
31
|
+
" * ",
|
|
32
|
+
" */",
|
|
33
|
+
"${1:name}() {",
|
|
34
|
+
"\t$0",
|
|
35
|
+
"}"
|
|
36
|
+
],
|
|
37
|
+
"description": "Method Definition"
|
|
38
|
+
},
|
|
39
|
+
"Import Statement": {
|
|
40
|
+
"prefix": "import",
|
|
41
|
+
"body": [
|
|
42
|
+
"import { $0 } from \"${1:module}\";"
|
|
43
|
+
],
|
|
44
|
+
"description": "Import external module"
|
|
45
|
+
},
|
|
46
|
+
"Log to the console": {
|
|
47
|
+
"prefix": "log",
|
|
48
|
+
"body": [
|
|
49
|
+
"console.log($1);",
|
|
50
|
+
"$0"
|
|
51
|
+
],
|
|
52
|
+
"description": "Log to the console"
|
|
53
|
+
},
|
|
54
|
+
"Log warning to console": {
|
|
55
|
+
"prefix": "warn",
|
|
56
|
+
"body": [
|
|
57
|
+
"console.warn($1);",
|
|
58
|
+
"$0"
|
|
59
|
+
],
|
|
60
|
+
"description": "Log warning to the console"
|
|
61
|
+
},
|
|
62
|
+
"Log error to console": {
|
|
63
|
+
"prefix": "error",
|
|
64
|
+
"body": [
|
|
65
|
+
"console.error($1);",
|
|
66
|
+
"$0"
|
|
67
|
+
],
|
|
68
|
+
"description": "Log error to the console"
|
|
69
|
+
},
|
|
70
|
+
"Throw Exception": {
|
|
71
|
+
"prefix": "throw",
|
|
72
|
+
"body": [
|
|
73
|
+
"throw new Error(\"$1\");",
|
|
74
|
+
"$0"
|
|
75
|
+
],
|
|
76
|
+
"description": "Throw Exception"
|
|
77
|
+
},
|
|
78
|
+
"For Loop": {
|
|
79
|
+
"prefix": "for",
|
|
80
|
+
"body": [
|
|
81
|
+
"for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {",
|
|
82
|
+
"\tconst ${3:element} = ${2:array}[${1:index}];",
|
|
83
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
84
|
+
"}"
|
|
85
|
+
],
|
|
86
|
+
"description": "For Loop"
|
|
87
|
+
},
|
|
88
|
+
"For-Each Loop using =>": {
|
|
89
|
+
"prefix": "foreach =>",
|
|
90
|
+
"body": [
|
|
91
|
+
"${1:array}.forEach(${2:element} => {",
|
|
92
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
93
|
+
"});"
|
|
94
|
+
],
|
|
95
|
+
"description": "For-Each Loop using =>"
|
|
96
|
+
},
|
|
97
|
+
"For-In Loop": {
|
|
98
|
+
"prefix": "forin",
|
|
99
|
+
"body": [
|
|
100
|
+
"for (const ${1:key} in ${2:object}) {",
|
|
101
|
+
"\tif (!Object.hasOwn(${2:object}, ${1:key})) continue;",
|
|
102
|
+
"\t",
|
|
103
|
+
"\tconst ${3:element} = ${2:object}[${1:key}];",
|
|
104
|
+
"\t",
|
|
105
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
106
|
+
"}"
|
|
107
|
+
],
|
|
108
|
+
"description": "For-In Loop"
|
|
109
|
+
},
|
|
110
|
+
"For-Of Loop": {
|
|
111
|
+
"prefix": "forof",
|
|
112
|
+
"body": [
|
|
113
|
+
"for (const ${1:element} of ${2:object}) {",
|
|
114
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
115
|
+
"}"
|
|
116
|
+
],
|
|
117
|
+
"description": "For-Of Loop"
|
|
118
|
+
},
|
|
119
|
+
"For-Await-Of Loop": {
|
|
120
|
+
"prefix": "forawaitof",
|
|
121
|
+
"body": [
|
|
122
|
+
"for await (const ${1:element} of ${2:object}) {",
|
|
123
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
124
|
+
"}"
|
|
125
|
+
],
|
|
126
|
+
"description": "For-Await-Of Loop"
|
|
127
|
+
},
|
|
128
|
+
"Function Statement": {
|
|
129
|
+
"prefix": "function",
|
|
130
|
+
"body": [
|
|
131
|
+
"function ${1:name}(${2:params}) {",
|
|
132
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
133
|
+
"}"
|
|
134
|
+
],
|
|
135
|
+
"description": "Function Statement"
|
|
136
|
+
},
|
|
137
|
+
"If Statement": {
|
|
138
|
+
"prefix": "if",
|
|
139
|
+
"body": [
|
|
140
|
+
"if (${1:condition}) {",
|
|
141
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
142
|
+
"}"
|
|
143
|
+
],
|
|
144
|
+
"description": "If Statement"
|
|
145
|
+
},
|
|
146
|
+
"If-Else Statement": {
|
|
147
|
+
"prefix": "ifelse",
|
|
148
|
+
"body": [
|
|
149
|
+
"if (${1:condition}) {",
|
|
150
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
151
|
+
"} else {",
|
|
152
|
+
"\t",
|
|
153
|
+
"}"
|
|
154
|
+
],
|
|
155
|
+
"description": "If-Else Statement"
|
|
156
|
+
},
|
|
157
|
+
"New Statement": {
|
|
158
|
+
"prefix": "new",
|
|
159
|
+
"body": [
|
|
160
|
+
"const ${1:name} = new ${2:type}(${3:arguments});$0"
|
|
161
|
+
],
|
|
162
|
+
"description": "New Statement"
|
|
163
|
+
},
|
|
164
|
+
"Switch Statement": {
|
|
165
|
+
"prefix": "switch",
|
|
166
|
+
"body": [
|
|
167
|
+
"switch (${1:key}) {",
|
|
168
|
+
"\tcase ${2:value}:",
|
|
169
|
+
"\t\t$0",
|
|
170
|
+
"\t\tbreak;",
|
|
171
|
+
"",
|
|
172
|
+
"\tdefault:",
|
|
173
|
+
"\t\tbreak;",
|
|
174
|
+
"}"
|
|
175
|
+
],
|
|
176
|
+
"description": "Switch Statement"
|
|
177
|
+
},
|
|
178
|
+
"While Statement": {
|
|
179
|
+
"prefix": "while",
|
|
180
|
+
"body": [
|
|
181
|
+
"while (${1:condition}) {",
|
|
182
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
183
|
+
"}"
|
|
184
|
+
],
|
|
185
|
+
"description": "While Statement"
|
|
186
|
+
},
|
|
187
|
+
"Do-While Statement": {
|
|
188
|
+
"prefix": "dowhile",
|
|
189
|
+
"body": [
|
|
190
|
+
"do {",
|
|
191
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
192
|
+
"} while (${1:condition});"
|
|
193
|
+
],
|
|
194
|
+
"description": "Do-While Statement"
|
|
195
|
+
},
|
|
196
|
+
"Try-Catch Statement": {
|
|
197
|
+
"prefix": "trycatch",
|
|
198
|
+
"body": [
|
|
199
|
+
"try {",
|
|
200
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
201
|
+
"} catch (${1:error}) {",
|
|
202
|
+
"\t",
|
|
203
|
+
"}"
|
|
204
|
+
],
|
|
205
|
+
"description": "Try-Catch Statement"
|
|
206
|
+
},
|
|
207
|
+
"Set Timeout Function": {
|
|
208
|
+
"prefix": "settimeout",
|
|
209
|
+
"body": [
|
|
210
|
+
"setTimeout(() => {",
|
|
211
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
212
|
+
"}, ${1:timeout});"
|
|
213
|
+
],
|
|
214
|
+
"description": "Set Timeout Function"
|
|
215
|
+
},
|
|
216
|
+
"Set Interval Function": {
|
|
217
|
+
"prefix": "setinterval",
|
|
218
|
+
"body": [
|
|
219
|
+
"setInterval(() => {",
|
|
220
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
221
|
+
"}, ${1:interval});"
|
|
222
|
+
],
|
|
223
|
+
"description": "Set Interval Function"
|
|
224
|
+
},
|
|
225
|
+
"Region Start": {
|
|
226
|
+
"prefix": "#region",
|
|
227
|
+
"body": [
|
|
228
|
+
"//#region $0"
|
|
229
|
+
],
|
|
230
|
+
"description": "Folding Region Start"
|
|
231
|
+
},
|
|
232
|
+
"Region End": {
|
|
233
|
+
"prefix": "#endregion",
|
|
234
|
+
"body": [
|
|
235
|
+
"//#endregion"
|
|
236
|
+
],
|
|
237
|
+
"description": "Folding Region End"
|
|
238
|
+
},
|
|
239
|
+
"new Promise": {
|
|
240
|
+
"prefix": "newpromise",
|
|
241
|
+
"body": [
|
|
242
|
+
"new Promise((resolve, reject) => {",
|
|
243
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
244
|
+
"})"
|
|
245
|
+
],
|
|
246
|
+
"description": "Create a new Promise"
|
|
247
|
+
},
|
|
248
|
+
"Async Function Statement": {
|
|
249
|
+
"prefix": "async function",
|
|
250
|
+
"body": [
|
|
251
|
+
"async function ${1:name}(${2:params}) {",
|
|
252
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
253
|
+
"}"
|
|
254
|
+
],
|
|
255
|
+
"description": "Async Function Statement"
|
|
256
|
+
},
|
|
257
|
+
"Async Function Expression": {
|
|
258
|
+
"prefix": "async arrow function",
|
|
259
|
+
"body": [
|
|
260
|
+
"async (${1:params}) => {",
|
|
261
|
+
"\t$TM_SELECTED_TEXT$0",
|
|
262
|
+
"}"
|
|
263
|
+
],
|
|
264
|
+
"description": "Async Function Expression"
|
|
265
|
+
}
|
|
266
|
+
}
|