vzcode 0.81.0 → 0.83.0

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.
@@ -1,322 +0,0 @@
1
- import * as tsvfs from '@typescript/vfs';
2
- import ts from 'typescript';
3
- import { File, Files, VZCodeContent } from '../../types';
4
- import {
5
- AutocompleteRequest,
6
- AutocompleteResponse,
7
- LinterRequest,
8
- LinterResponse,
9
- } from './requestTypes';
10
-
11
- let env: tsvfs.VirtualTypeScriptEnvironment = null;
12
-
13
- const debug = false;
14
-
15
- // replace .js or .jsx with .ts or .tsx,
16
- // to support TypeScript completions on non-TS files.
17
- const getTSFileName = (fileName: string) => {
18
- if (fileName.endsWith('.js')) {
19
- return fileName.replace('.js', '.tsx');
20
- }
21
- if (fileName.endsWith('.jsx')) {
22
- return fileName.replace('.jsx', '.tsx');
23
- }
24
- return fileName;
25
- };
26
-
27
- // Returns true if the file name ends with `.ts` or `.tsx`.
28
- const isTS = (fileName: string) => {
29
- return (
30
- fileName.endsWith('.ts') || fileName.endsWith('.tsx')
31
- );
32
- };
33
-
34
- // This is a place for things we only do _once_.
35
- const initializeFileSystem = async () => {
36
- if (debug) {
37
- console.log('initializeFileSystem');
38
- }
39
- const compilerOptions: ts.CompilerOptions = {
40
- lib: ['dom', 'esnext'],
41
-
42
- // Disable warnings around "Any type".
43
- noImplicitAny: false,
44
-
45
- // Disable warnings around "Implicit any in parameter".
46
- noImplicitThis: false,
47
-
48
- // Allow JavaScript files to be processed
49
- allowJs: true,
50
-
51
- // Disable type checking for JavaScript files
52
- // checkJs: false,
53
-
54
- // Skip type checking of declaration files
55
- skipLibCheck: true,
56
-
57
- // Support React JSX
58
- jsx: ts.JsxEmit.React,
59
- };
60
-
61
- // `true` breaks in a Web Worker because
62
- // this uses `localStorage` under the hood,
63
- // which is not available in a Web Worker.
64
- const cache = false;
65
-
66
- const fsMap = await tsvfs.createDefaultMapFromCDN(
67
- compilerOptions,
68
- ts.version,
69
- cache,
70
- ts,
71
- );
72
- const sys: ts.System = tsvfs.createSystem(fsMap);
73
-
74
- // We'll add files to this later.
75
- const rootFiles = [];
76
-
77
- env = tsvfs.createVirtualTypeScriptEnvironment(
78
- sys,
79
- rootFiles,
80
- ts,
81
- compilerOptions,
82
- );
83
-
84
- if (debug) {
85
- console.log('initializeFileSystem done');
86
- }
87
- };
88
-
89
- const setFile = (tsFileName: string, text: string) => {
90
- const existingFile = env.getSourceFile(tsFileName);
91
- if (existingFile === undefined) {
92
- env.createFile(tsFileName, text);
93
- } else {
94
- env.updateFile(tsFileName, text);
95
- }
96
- };
97
-
98
- // Inspired by: https://stackblitz.com/edit/codemirror-6-typescript?file=client%2Findex.ts%3AL44-L44
99
- const convertToCodeMirrorDiagnostic = (
100
- tsErrors: ts.Diagnostic[],
101
- ) => {
102
- return tsErrors.map((tsError: ts.Diagnostic) => ({
103
- from: tsError.start,
104
- to: tsError.start + tsError.length,
105
- severity: 'error',
106
- message:
107
- typeof tsError.messageText === 'string'
108
- ? tsError.messageText
109
- : tsError.messageText.messageText,
110
- }));
111
- };
112
-
113
- // This is a promise that resolves when the file system is initialized.
114
- let fileSystemInitializationPromise = null;
115
- async function ensureFileSystemInitialized() {
116
- if (!fileSystemInitializationPromise) {
117
- fileSystemInitializationPromise =
118
- initializeFileSystem();
119
- }
120
- await fileSystemInitializationPromise;
121
- }
122
-
123
- onmessage = async ({ data }) => {
124
- if (debug) {
125
- console.log('message received');
126
- }
127
-
128
- // Ensure the file system is initialized.
129
- await ensureFileSystemInitialized();
130
-
131
- // Sanity check - should never happen.
132
- if (env === null) {
133
- throw new Error('File system not initialized');
134
- }
135
-
136
- // Handle the update-content event, which
137
- // updates the files as they change.
138
- // This handles the cases where:
139
- // * The file system is populated for the first time.
140
- // * Files are edited by remote users.
141
- if (data.event === 'update-content') {
142
- if (debug) {
143
- console.log('update-content message received');
144
- }
145
- // Unpack the files
146
- const content: VZCodeContent = data.details;
147
- const files: Files = content.files;
148
-
149
- // Iterate over the files
150
- for (const fileId of Object.keys(files)) {
151
- const file: File = files[fileId];
152
- const { name, text } = file;
153
-
154
- const tsFileName = getTSFileName(name);
155
-
156
- if (!isTS(tsFileName)) {
157
- continue;
158
- }
159
-
160
- setFile(tsFileName, text);
161
- // TODO - Handle renaming files.
162
- // TODO - Handle deleting files.
163
- // TODO - Handle directories.
164
- }
165
- }
166
-
167
- if (data.event === 'autocomplete-request') {
168
- if (debug) {
169
- console.log('autocomplete-request message received');
170
- }
171
- // Should not happen.
172
- if (env === null) {
173
- console.log('env is null');
174
- return;
175
- }
176
-
177
- // Example of `data`:
178
- // {
179
- // "event": "autocomplete-request",
180
- // "pos": 8,
181
- // "location": "index.js",
182
- // "requestId": "0.9090605799171392"
183
- // }
184
-
185
- const autocompleteRequest: AutocompleteRequest = data;
186
- const { fileName, fileContent, position, requestId } =
187
- autocompleteRequest;
188
-
189
- const tsFileName = getTSFileName(fileName);
190
-
191
- let completions = null;
192
- if (isTS(tsFileName) && fileContent !== '') {
193
- // Update the file in the file system to the
194
- // absolute latest version. This is critical
195
- // for correct completions.
196
- setFile(tsFileName, fileContent);
197
-
198
- completions =
199
- env.languageService.getCompletionsAtPosition(
200
- tsFileName,
201
- position,
202
- {},
203
- );
204
- }
205
-
206
- const autocompleteResponse: AutocompleteResponse = {
207
- event: 'post-completions',
208
- completions,
209
- requestId,
210
- };
211
-
212
- postMessage(autocompleteResponse);
213
- }
214
-
215
- if (data.event === 'lint-request') {
216
- if (debug) {
217
- console.log('Lint Request');
218
- }
219
- const linterRequest: LinterRequest = data;
220
- const { fileName, fileContent, requestId } =
221
- linterRequest;
222
-
223
- const tsFileName = getTSFileName(fileName);
224
- let tsErrors = [];
225
- // Since we are also updating the server when we autocomplete we do not need to update
226
- if (isTS(tsFileName) && fileContent !== '') {
227
- setFile(tsFileName, fileContent);
228
- // Creates an array of diagnostic objects containing
229
- // both semantic and syntactic diagnostics.
230
- tsErrors = env.languageService
231
- .getSemanticDiagnostics(tsFileName)
232
- .concat(
233
- env.languageService.getSyntacticDiagnostics(
234
- tsFileName,
235
- ),
236
- );
237
-
238
- // Be less aggressive for non-TS files,
239
- // e.g. files that end in .js or .jsx.
240
- // if (!isTS(fileName)) {
241
- // This code is for errors like:
242
- // "Binding element 'data' implicitly has an 'any' type."
243
- const LINT_ERROR_CODE_ANY = 7031;
244
-
245
- // This code is for errors like:
246
- // "Parameter 'selection' implicitly has an 'any' type.""
247
- const LINT_ERROR_CODE_ANY_PARAM = 7006;
248
-
249
- // This code is for errors like:
250
- // "Cannot find module 'd3' or its corresponding type declarations."
251
- const LINT_ERROR_CODE_IMPORT = 2307;
252
-
253
- // This code is for errors like:
254
- // "Variable 'mic' implicitly has type 'any' in some locations where its type cannot be determined."
255
- const LINT_ERROR_CODE_ANY_TYPE = 7034;
256
-
257
- // "Element implicitly has an 'any' type because expression
258
- // of type '"test"' can't be used to index type '{}'."
259
- const LINT_ERROR_CODE_ANY_TYPE_KEYS = 7053;
260
-
261
- // "Property 'id' does not exist on type { ... }"
262
- // Happens on objects with dynamic keys.
263
- // Not valid in TypeScript, but common in JavaScript.
264
- const LINT_ERROR_CODE_NON_EXISTENT_PROPERTY = 2339;
265
-
266
- // "Type 'Set<unknown>' can only be iterated through when using the '--downlevelIteration'
267
- // flag or with a '--target' of 'es2015' or higher."
268
- const LINT_ERROR_CODE_ITERATED_THROUGH = 2802;
269
-
270
- // Argument of type '{ Month: string; High: number; Temp: number; Low: number; }'
271
- // is not assignable to parameter of type 'never'.
272
- const LINT_ERROR_CODE_ASSIGNABLE_TO_NEVER = 2345;
273
-
274
- if (debug) {
275
- console.log('tsErrors');
276
- console.log(tsErrors);
277
- }
278
- tsErrors = tsErrors.filter(
279
- (error: { code: number }) =>
280
- error.code !== LINT_ERROR_CODE_ANY &&
281
- error.code !== LINT_ERROR_CODE_IMPORT &&
282
- error.code !== LINT_ERROR_CODE_ANY_PARAM &&
283
- error.code !== LINT_ERROR_CODE_ANY_TYPE &&
284
- error.code !== LINT_ERROR_CODE_ANY_TYPE_KEYS &&
285
- error.code !==
286
- LINT_ERROR_CODE_NON_EXISTENT_PROPERTY &&
287
- error.code !== LINT_ERROR_CODE_ITERATED_THROUGH &&
288
- error.code !==
289
- LINT_ERROR_CODE_ASSIGNABLE_TO_NEVER,
290
- );
291
- // }
292
- tsErrors = convertToCodeMirrorDiagnostic(tsErrors);
293
- }
294
-
295
- const linterResponse: LinterResponse = {
296
- event: 'post-error-linter',
297
- tsErrors,
298
- requestId,
299
- };
300
- postMessage(linterResponse);
301
- }
302
-
303
- // Handle the transpile-request event, which
304
- // transpiles TypeScript to JavaScript.
305
- if (data.event === 'transpile-request') {
306
- const tsCode = data.tsCode;
307
-
308
- const compilerOptions = {
309
- jsx: ts.JsxEmit.React,
310
- };
311
-
312
- const jsCode = ts.transpileModule(tsCode, {
313
- compilerOptions,
314
- }).outputText;
315
-
316
- postMessage({
317
- event: 'transpile-response',
318
- jsCode,
319
- fileId: data.fileId,
320
- });
321
- }
322
- };