Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/monaco-api.js
3520 views
1
"use strict";
2
var __importDefault = (this && this.__importDefault) || function (mod) {
3
return (mod && mod.__esModule) ? mod : { "default": mod };
4
};
5
Object.defineProperty(exports, "__esModule", { value: true });
6
exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0;
7
exports.run3 = run3;
8
exports.execute = execute;
9
/*---------------------------------------------------------------------------------------------
10
* Copyright (c) Microsoft Corporation. All rights reserved.
11
* Licensed under the MIT License. See License.txt in the project root for license information.
12
*--------------------------------------------------------------------------------------------*/
13
const fs_1 = __importDefault(require("fs"));
14
const path_1 = __importDefault(require("path"));
15
const fancy_log_1 = __importDefault(require("fancy-log"));
16
const ansi_colors_1 = __importDefault(require("ansi-colors"));
17
const dtsv = '3';
18
const tsfmt = require('../../tsfmt.json');
19
const SRC = path_1.default.join(__dirname, '../../src');
20
exports.RECIPE_PATH = path_1.default.join(__dirname, '../monaco/monaco.d.ts.recipe');
21
const DECLARATION_PATH = path_1.default.join(__dirname, '../../src/vs/monaco.d.ts');
22
function logErr(message, ...rest) {
23
(0, fancy_log_1.default)(ansi_colors_1.default.yellow(`[monaco.d.ts]`), message, ...rest);
24
}
25
function isDeclaration(ts, a) {
26
return (a.kind === ts.SyntaxKind.InterfaceDeclaration
27
|| a.kind === ts.SyntaxKind.EnumDeclaration
28
|| a.kind === ts.SyntaxKind.ClassDeclaration
29
|| a.kind === ts.SyntaxKind.TypeAliasDeclaration
30
|| a.kind === ts.SyntaxKind.FunctionDeclaration
31
|| a.kind === ts.SyntaxKind.ModuleDeclaration);
32
}
33
function visitTopLevelDeclarations(ts, sourceFile, visitor) {
34
let stop = false;
35
const visit = (node) => {
36
if (stop) {
37
return;
38
}
39
switch (node.kind) {
40
case ts.SyntaxKind.InterfaceDeclaration:
41
case ts.SyntaxKind.EnumDeclaration:
42
case ts.SyntaxKind.ClassDeclaration:
43
case ts.SyntaxKind.VariableStatement:
44
case ts.SyntaxKind.TypeAliasDeclaration:
45
case ts.SyntaxKind.FunctionDeclaration:
46
case ts.SyntaxKind.ModuleDeclaration:
47
stop = visitor(node);
48
}
49
if (stop) {
50
return;
51
}
52
ts.forEachChild(node, visit);
53
};
54
visit(sourceFile);
55
}
56
function getAllTopLevelDeclarations(ts, sourceFile) {
57
const all = [];
58
visitTopLevelDeclarations(ts, sourceFile, (node) => {
59
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
60
const interfaceDeclaration = node;
61
const triviaStart = interfaceDeclaration.pos;
62
const triviaEnd = interfaceDeclaration.name.pos;
63
const triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd });
64
if (triviaText.indexOf('@internal') === -1) {
65
all.push(node);
66
}
67
}
68
else {
69
const nodeText = getNodeText(sourceFile, node);
70
if (nodeText.indexOf('@internal') === -1) {
71
all.push(node);
72
}
73
}
74
return false /*continue*/;
75
});
76
return all;
77
}
78
function getTopLevelDeclaration(ts, sourceFile, typeName) {
79
let result = null;
80
visitTopLevelDeclarations(ts, sourceFile, (node) => {
81
if (isDeclaration(ts, node) && node.name) {
82
if (node.name.text === typeName) {
83
result = node;
84
return true /*stop*/;
85
}
86
return false /*continue*/;
87
}
88
// node is ts.VariableStatement
89
if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) {
90
result = node;
91
return true /*stop*/;
92
}
93
return false /*continue*/;
94
});
95
return result;
96
}
97
function getNodeText(sourceFile, node) {
98
return sourceFile.getFullText().substring(node.pos, node.end);
99
}
100
function hasModifier(modifiers, kind) {
101
if (modifiers) {
102
for (let i = 0; i < modifiers.length; i++) {
103
const mod = modifiers[i];
104
if (mod.kind === kind) {
105
return true;
106
}
107
}
108
}
109
return false;
110
}
111
function isStatic(ts, member) {
112
if (ts.canHaveModifiers(member)) {
113
return hasModifier(ts.getModifiers(member), ts.SyntaxKind.StaticKeyword);
114
}
115
return false;
116
}
117
function isDefaultExport(ts, declaration) {
118
return (hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword)
119
&& hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword));
120
}
121
function getMassagedTopLevelDeclarationText(ts, sourceFile, declaration, importName, usage, enums) {
122
let result = getNodeText(sourceFile, declaration);
123
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
124
const interfaceDeclaration = declaration;
125
const staticTypeName = (isDefaultExport(ts, interfaceDeclaration)
126
? `${importName}.default`
127
: `${importName}.${declaration.name.text}`);
128
let instanceTypeName = staticTypeName;
129
const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0);
130
if (typeParametersCnt > 0) {
131
const arr = [];
132
for (let i = 0; i < typeParametersCnt; i++) {
133
arr.push('any');
134
}
135
instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`;
136
}
137
const members = interfaceDeclaration.members;
138
members.forEach((member) => {
139
try {
140
const memberText = getNodeText(sourceFile, member);
141
if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) {
142
result = result.replace(memberText, '');
143
}
144
else {
145
const memberName = member.name.text;
146
const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`);
147
if (isStatic(ts, member)) {
148
usage.push(`a = ${staticTypeName}${memberAccess};`);
149
}
150
else {
151
usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`);
152
}
153
}
154
}
155
catch (err) {
156
// life..
157
}
158
});
159
}
160
result = result.replace(/export default /g, 'export ');
161
result = result.replace(/export declare /g, 'export ');
162
result = result.replace(/declare /g, '');
163
const lines = result.split(/\r\n|\r|\n/);
164
for (let i = 0; i < lines.length; i++) {
165
if (/\s*\*/.test(lines[i])) {
166
// very likely a comment
167
continue;
168
}
169
lines[i] = lines[i].replace(/"/g, '\'');
170
}
171
result = lines.join('\n');
172
if (declaration.kind === ts.SyntaxKind.EnumDeclaration) {
173
result = result.replace(/const enum/, 'enum');
174
enums.push({
175
enumName: declaration.name.getText(sourceFile),
176
text: result
177
});
178
}
179
return result;
180
}
181
function format(ts, text, endl) {
182
const REALLY_FORMAT = false;
183
text = preformat(text, endl);
184
if (!REALLY_FORMAT) {
185
return text;
186
}
187
// Parse the source text
188
const sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
189
// Get the formatting edits on the input sources
190
const edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt);
191
// Apply the edits on the input code
192
return applyEdits(text, edits);
193
function countParensCurly(text) {
194
let cnt = 0;
195
for (let i = 0; i < text.length; i++) {
196
if (text.charAt(i) === '(' || text.charAt(i) === '{') {
197
cnt++;
198
}
199
if (text.charAt(i) === ')' || text.charAt(i) === '}') {
200
cnt--;
201
}
202
}
203
return cnt;
204
}
205
function repeatStr(s, cnt) {
206
let r = '';
207
for (let i = 0; i < cnt; i++) {
208
r += s;
209
}
210
return r;
211
}
212
function preformat(text, endl) {
213
const lines = text.split(endl);
214
let inComment = false;
215
let inCommentDeltaIndent = 0;
216
let indent = 0;
217
for (let i = 0; i < lines.length; i++) {
218
let line = lines[i].replace(/\s$/, '');
219
let repeat = false;
220
let lineIndent = 0;
221
do {
222
repeat = false;
223
if (line.substring(0, 4) === ' ') {
224
line = line.substring(4);
225
lineIndent++;
226
repeat = true;
227
}
228
if (line.charAt(0) === '\t') {
229
line = line.substring(1);
230
lineIndent++;
231
repeat = true;
232
}
233
} while (repeat);
234
if (line.length === 0) {
235
continue;
236
}
237
if (inComment) {
238
if (/\*\//.test(line)) {
239
inComment = false;
240
}
241
lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line;
242
continue;
243
}
244
if (/\/\*/.test(line)) {
245
inComment = true;
246
inCommentDeltaIndent = indent - lineIndent;
247
lines[i] = repeatStr('\t', indent) + line;
248
continue;
249
}
250
const cnt = countParensCurly(line);
251
let shouldUnindentAfter = false;
252
let shouldUnindentBefore = false;
253
if (cnt < 0) {
254
if (/[({]/.test(line)) {
255
shouldUnindentAfter = true;
256
}
257
else {
258
shouldUnindentBefore = true;
259
}
260
}
261
else if (cnt === 0) {
262
shouldUnindentBefore = /^\}/.test(line);
263
}
264
let shouldIndentAfter = false;
265
if (cnt > 0) {
266
shouldIndentAfter = true;
267
}
268
else if (cnt === 0) {
269
shouldIndentAfter = /{$/.test(line);
270
}
271
if (shouldUnindentBefore) {
272
indent--;
273
}
274
lines[i] = repeatStr('\t', indent) + line;
275
if (shouldUnindentAfter) {
276
indent--;
277
}
278
if (shouldIndentAfter) {
279
indent++;
280
}
281
}
282
return lines.join(endl);
283
}
284
function getRuleProvider(options) {
285
// Share this between multiple formatters using the same options.
286
// This represents the bulk of the space the formatter uses.
287
return ts.formatting.getFormatContext(options);
288
}
289
function applyEdits(text, edits) {
290
// Apply edits in reverse on the existing text
291
let result = text;
292
for (let i = edits.length - 1; i >= 0; i--) {
293
const change = edits[i];
294
const head = result.slice(0, change.span.start);
295
const tail = result.slice(change.span.start + change.span.length);
296
result = head + change.newText + tail;
297
}
298
return result;
299
}
300
}
301
function createReplacerFromDirectives(directives) {
302
return (str) => {
303
for (let i = 0; i < directives.length; i++) {
304
str = str.replace(directives[i][0], directives[i][1]);
305
}
306
return str;
307
};
308
}
309
function createReplacer(data) {
310
data = data || '';
311
const rawDirectives = data.split(';');
312
const directives = [];
313
rawDirectives.forEach((rawDirective) => {
314
if (rawDirective.length === 0) {
315
return;
316
}
317
const pieces = rawDirective.split('=>');
318
let findStr = pieces[0];
319
const replaceStr = pieces[1];
320
findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
321
findStr = '\\b' + findStr + '\\b';
322
directives.push([new RegExp(findStr, 'g'), replaceStr]);
323
});
324
return createReplacerFromDirectives(directives);
325
}
326
function generateDeclarationFile(ts, recipe, sourceFileGetter) {
327
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
328
const lines = recipe.split(endl);
329
const result = [];
330
let usageCounter = 0;
331
const usageImports = [];
332
const usage = [];
333
let failed = false;
334
usage.push(`var a: any;`);
335
usage.push(`var b: any;`);
336
const generateUsageImport = (moduleId) => {
337
const importName = 'm' + (++usageCounter);
338
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
339
return importName;
340
};
341
const enums = [];
342
let version = null;
343
lines.forEach(line => {
344
if (failed) {
345
return;
346
}
347
const m0 = line.match(/^\/\/dtsv=(\d+)$/);
348
if (m0) {
349
version = m0[1];
350
}
351
const m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
352
if (m1) {
353
const moduleId = m1[1];
354
const sourceFile = sourceFileGetter(moduleId);
355
if (!sourceFile) {
356
logErr(`While handling ${line}`);
357
logErr(`Cannot find ${moduleId}`);
358
failed = true;
359
return;
360
}
361
const importName = generateUsageImport(moduleId);
362
const replacer = createReplacer(m1[2]);
363
const typeNames = m1[3].split(/,/);
364
typeNames.forEach((typeName) => {
365
typeName = typeName.trim();
366
if (typeName.length === 0) {
367
return;
368
}
369
const declaration = getTopLevelDeclaration(ts, sourceFile, typeName);
370
if (!declaration) {
371
logErr(`While handling ${line}`);
372
logErr(`Cannot find ${typeName}`);
373
failed = true;
374
return;
375
}
376
result.push(replacer(getMassagedTopLevelDeclarationText(ts, sourceFile, declaration, importName, usage, enums)));
377
});
378
return;
379
}
380
const m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
381
if (m2) {
382
const moduleId = m2[1];
383
const sourceFile = sourceFileGetter(moduleId);
384
if (!sourceFile) {
385
logErr(`While handling ${line}`);
386
logErr(`Cannot find ${moduleId}`);
387
failed = true;
388
return;
389
}
390
const importName = generateUsageImport(moduleId);
391
const replacer = createReplacer(m2[2]);
392
const typeNames = m2[3].split(/,/);
393
const typesToExcludeMap = {};
394
const typesToExcludeArr = [];
395
typeNames.forEach((typeName) => {
396
typeName = typeName.trim();
397
if (typeName.length === 0) {
398
return;
399
}
400
typesToExcludeMap[typeName] = true;
401
typesToExcludeArr.push(typeName);
402
});
403
getAllTopLevelDeclarations(ts, sourceFile).forEach((declaration) => {
404
if (isDeclaration(ts, declaration) && declaration.name) {
405
if (typesToExcludeMap[declaration.name.text]) {
406
return;
407
}
408
}
409
else {
410
// node is ts.VariableStatement
411
const nodeText = getNodeText(sourceFile, declaration);
412
for (let i = 0; i < typesToExcludeArr.length; i++) {
413
if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) {
414
return;
415
}
416
}
417
}
418
result.push(replacer(getMassagedTopLevelDeclarationText(ts, sourceFile, declaration, importName, usage, enums)));
419
});
420
return;
421
}
422
result.push(line);
423
});
424
if (failed) {
425
return null;
426
}
427
if (version !== dtsv) {
428
if (!version) {
429
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
430
}
431
else {
432
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
433
}
434
return null;
435
}
436
let resultTxt = result.join(endl);
437
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
438
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
439
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
440
resultTxt = format(ts, resultTxt, endl);
441
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
442
enums.sort((e1, e2) => {
443
if (e1.enumName < e2.enumName) {
444
return -1;
445
}
446
if (e1.enumName > e2.enumName) {
447
return 1;
448
}
449
return 0;
450
});
451
let resultEnums = [
452
'/*---------------------------------------------------------------------------------------------',
453
' * Copyright (c) Microsoft Corporation. All rights reserved.',
454
' * Licensed under the MIT License. See License.txt in the project root for license information.',
455
' *--------------------------------------------------------------------------------------------*/',
456
'',
457
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
458
''
459
].concat(enums.map(e => e.text)).join(endl);
460
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
461
resultEnums = format(ts, resultEnums, endl);
462
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
463
return {
464
result: resultTxt,
465
usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`,
466
enums: resultEnums
467
};
468
}
469
function _run(ts, sourceFileGetter) {
470
const recipe = fs_1.default.readFileSync(exports.RECIPE_PATH).toString();
471
const t = generateDeclarationFile(ts, recipe, sourceFileGetter);
472
if (!t) {
473
return null;
474
}
475
const result = t.result;
476
const usageContent = t.usageContent;
477
const enums = t.enums;
478
const currentContent = fs_1.default.readFileSync(DECLARATION_PATH).toString();
479
const one = currentContent.replace(/\r\n/gm, '\n');
480
const other = result.replace(/\r\n/gm, '\n');
481
const isTheSame = (one === other);
482
return {
483
content: result,
484
usageContent: usageContent,
485
enums: enums,
486
filePath: DECLARATION_PATH,
487
isTheSame
488
};
489
}
490
class FSProvider {
491
existsSync(filePath) {
492
return fs_1.default.existsSync(filePath);
493
}
494
statSync(filePath) {
495
return fs_1.default.statSync(filePath);
496
}
497
readFileSync(_moduleId, filePath) {
498
return fs_1.default.readFileSync(filePath);
499
}
500
}
501
exports.FSProvider = FSProvider;
502
class CacheEntry {
503
sourceFile;
504
mtime;
505
constructor(sourceFile, mtime) {
506
this.sourceFile = sourceFile;
507
this.mtime = mtime;
508
}
509
}
510
class DeclarationResolver {
511
_fsProvider;
512
ts;
513
_sourceFileCache;
514
constructor(_fsProvider) {
515
this._fsProvider = _fsProvider;
516
this.ts = require('typescript');
517
this._sourceFileCache = Object.create(null);
518
}
519
invalidateCache(moduleId) {
520
this._sourceFileCache[moduleId] = null;
521
}
522
getDeclarationSourceFile(moduleId) {
523
if (this._sourceFileCache[moduleId]) {
524
// Since we cannot trust file watching to invalidate the cache, check also the mtime
525
const fileName = this._getFileName(moduleId);
526
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
527
if (this._sourceFileCache[moduleId].mtime !== mtime) {
528
this._sourceFileCache[moduleId] = null;
529
}
530
}
531
if (!this._sourceFileCache[moduleId]) {
532
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
533
}
534
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null;
535
}
536
_getFileName(moduleId) {
537
if (/\.d\.ts$/.test(moduleId)) {
538
return path_1.default.join(SRC, moduleId);
539
}
540
return path_1.default.join(SRC, `${moduleId}.ts`);
541
}
542
_getDeclarationSourceFile(moduleId) {
543
const fileName = this._getFileName(moduleId);
544
if (!this._fsProvider.existsSync(fileName)) {
545
return null;
546
}
547
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
548
if (/\.d\.ts$/.test(moduleId)) {
549
// const mtime = this._fsProvider.statFileSync()
550
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
551
return new CacheEntry(this.ts.createSourceFile(fileName, fileContents, this.ts.ScriptTarget.ES5), mtime);
552
}
553
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
554
const fileMap = {
555
'file.ts': fileContents
556
};
557
const service = this.ts.createLanguageService(new TypeScriptLanguageServiceHost(this.ts, {}, fileMap, {}));
558
const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text;
559
return new CacheEntry(this.ts.createSourceFile(fileName, text, this.ts.ScriptTarget.ES5), mtime);
560
}
561
}
562
exports.DeclarationResolver = DeclarationResolver;
563
function run3(resolver) {
564
const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId);
565
return _run(resolver.ts, sourceFileGetter);
566
}
567
class TypeScriptLanguageServiceHost {
568
_ts;
569
_libs;
570
_files;
571
_compilerOptions;
572
constructor(ts, libs, files, compilerOptions) {
573
this._ts = ts;
574
this._libs = libs;
575
this._files = files;
576
this._compilerOptions = compilerOptions;
577
}
578
// --- language service host ---------------
579
getCompilationSettings() {
580
return this._compilerOptions;
581
}
582
getScriptFileNames() {
583
return ([]
584
.concat(Object.keys(this._libs))
585
.concat(Object.keys(this._files)));
586
}
587
getScriptVersion(_fileName) {
588
return '1';
589
}
590
getProjectVersion() {
591
return '1';
592
}
593
getScriptSnapshot(fileName) {
594
if (this._files.hasOwnProperty(fileName)) {
595
return this._ts.ScriptSnapshot.fromString(this._files[fileName]);
596
}
597
else if (this._libs.hasOwnProperty(fileName)) {
598
return this._ts.ScriptSnapshot.fromString(this._libs[fileName]);
599
}
600
else {
601
return this._ts.ScriptSnapshot.fromString('');
602
}
603
}
604
getScriptKind(_fileName) {
605
return this._ts.ScriptKind.TS;
606
}
607
getCurrentDirectory() {
608
return '';
609
}
610
getDefaultLibFileName(_options) {
611
return 'defaultLib:es5';
612
}
613
isDefaultLibFileName(fileName) {
614
return fileName === this.getDefaultLibFileName(this._compilerOptions);
615
}
616
readFile(path, _encoding) {
617
return this._files[path] || this._libs[path];
618
}
619
fileExists(path) {
620
return path in this._files || path in this._libs;
621
}
622
}
623
function execute() {
624
const r = run3(new DeclarationResolver(new FSProvider()));
625
if (!r) {
626
throw new Error(`monaco.d.ts generation error - Cannot continue`);
627
}
628
return r;
629
}
630
//# sourceMappingURL=monaco-api.js.map
631