Skip to content

Commit 05c5be7

Browse files
committed
extract loadLibrary
1 parent d16e306 commit 05c5be7

File tree

4 files changed

+232
-16
lines changed

4 files changed

+232
-16
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
const path = require('path');
7+
const fs = require('fs');
8+
const child_process = require('child_process');
9+
10+
const generatedNote = `//
11+
// **NOTE**: Do not edit directly! This file is generated using \`npm run import-typescript\`
12+
//
13+
`;
14+
15+
const TYPESCRIPT_LIB_SOURCE = path.join(__dirname, '../../node_modules/typescript/lib');
16+
const TYPESCRIPT_LIB_DESTINATION = path.join(__dirname, '../server/build');
17+
18+
(function () {
19+
try {
20+
fs.statSync(TYPESCRIPT_LIB_DESTINATION);
21+
} catch (err) {
22+
fs.mkdirSync(TYPESCRIPT_LIB_DESTINATION);
23+
}
24+
importLibs('es6');
25+
})();
26+
27+
28+
function importLibs(startLib) {
29+
function getFileName(name) {
30+
return (name === '' ? 'lib.d.ts' : `lib.${name}.d.ts`);
31+
}
32+
function getVariableName(name) {
33+
return (name === '' ? 'lib_dts' : `lib_${name.replace(/\./g, '_')}_dts`);
34+
}
35+
function readLibFile(name) {
36+
var srcPath = path.join(TYPESCRIPT_LIB_SOURCE, getFileName(name));
37+
return fs.readFileSync(srcPath).toString();
38+
}
39+
40+
var queue = [];
41+
var in_queue = {};
42+
43+
var enqueue = function (name) {
44+
if (in_queue[name]) {
45+
return;
46+
}
47+
in_queue[name] = true;
48+
queue.push(name);
49+
};
50+
51+
enqueue(startLib);
52+
53+
var result = [];
54+
while (queue.length > 0) {
55+
var name = queue.shift();
56+
var contents = readLibFile(name);
57+
var lines = contents.split(/\r\n|\r|\n/);
58+
59+
var output = '';
60+
var writeOutput = function (text) {
61+
if (output.length === 0) {
62+
output = text;
63+
} else {
64+
output += ` + ${text}`;
65+
}
66+
};
67+
var outputLines = [];
68+
var flushOutputLines = function () {
69+
writeOutput(`"${escapeText(outputLines.join('\n'))}"`);
70+
outputLines = [];
71+
};
72+
var deps = [];
73+
for (let i = 0; i < lines.length; i++) {
74+
let m = lines[i].match(/\/\/\/\s*<reference\s*lib="([^"]+)"/);
75+
if (m) {
76+
flushOutputLines();
77+
writeOutput(getVariableName(m[1]));
78+
deps.push(getVariableName(m[1]));
79+
enqueue(m[1]);
80+
continue;
81+
}
82+
outputLines.push(lines[i]);
83+
}
84+
flushOutputLines();
85+
86+
result.push({
87+
name: getVariableName(name),
88+
deps: deps,
89+
output: output
90+
});
91+
}
92+
93+
var strResult = `/*---------------------------------------------------------------------------------------------
94+
* Copyright (c) Microsoft Corporation. All rights reserved.
95+
* Licensed under the MIT License. See License.txt in the project root for license information.
96+
*--------------------------------------------------------------------------------------------*/
97+
${generatedNote}`;
98+
// Do a topological sort
99+
while (result.length > 0) {
100+
for (let i = result.length - 1; i >= 0; i--) {
101+
if (result[i].deps.length === 0) {
102+
// emit this node
103+
strResult += `\nexport const ${result[i].name}: string = ${result[i].output};\n`;
104+
105+
// mark dep as resolved
106+
for (let j = 0; j < result.length; j++) {
107+
for (let k = 0; k < result[j].deps.length; k++) {
108+
if (result[j].deps[k] === result[i].name) {
109+
result[j].deps.splice(k, 1);
110+
break;
111+
}
112+
}
113+
}
114+
115+
// remove from result
116+
result.splice(i, 1);
117+
break;
118+
}
119+
}
120+
}
121+
122+
var dstPath = path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts');
123+
fs.writeFileSync(dstPath, strResult);
124+
}
125+
126+
/**
127+
* Escape text such that it can be used in a javascript string enclosed by double quotes (")
128+
*/
129+
function escapeText(text) {
130+
// See http://www.javascriptkit.com/jsref/escapesequence.shtml
131+
var _backspace = '\b'.charCodeAt(0);
132+
var _formFeed = '\f'.charCodeAt(0);
133+
var _newLine = '\n'.charCodeAt(0);
134+
var _nullChar = 0;
135+
var _carriageReturn = '\r'.charCodeAt(0);
136+
var _tab = '\t'.charCodeAt(0);
137+
var _verticalTab = '\v'.charCodeAt(0);
138+
var _backslash = '\\'.charCodeAt(0);
139+
var _doubleQuote = '"'.charCodeAt(0);
140+
141+
var startPos = 0, chrCode, replaceWith = null, resultPieces = [];
142+
143+
for (var i = 0, len = text.length; i < len; i++) {
144+
chrCode = text.charCodeAt(i);
145+
switch (chrCode) {
146+
case _backspace:
147+
replaceWith = '\\b';
148+
break;
149+
case _formFeed:
150+
replaceWith = '\\f';
151+
break;
152+
case _newLine:
153+
replaceWith = '\\n';
154+
break;
155+
case _nullChar:
156+
replaceWith = '\\0';
157+
break;
158+
case _carriageReturn:
159+
replaceWith = '\\r';
160+
break;
161+
case _tab:
162+
replaceWith = '\\t';
163+
break;
164+
case _verticalTab:
165+
replaceWith = '\\v';
166+
break;
167+
case _backslash:
168+
replaceWith = '\\\\';
169+
break;
170+
case _doubleQuote:
171+
replaceWith = '\\"';
172+
break;
173+
}
174+
if (replaceWith !== null) {
175+
resultPieces.push(text.substring(startPos, i));
176+
resultPieces.push(replaceWith);
177+
startPos = i + 1;
178+
replaceWith = null;
179+
}
180+
}
181+
resultPieces.push(text.substring(startPos, len));
182+
return resultPieces.join('');
183+
}

extensions/html-language-features/server/extension-browser.webpack.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,13 @@ const serverConfig = withDefaults({
3232
});
3333
serverConfig.module.rules[0].use.shift(); // remove nls loader
3434
serverConfig.module.noParse = /typescript\/lib\/typescript\.js/;
35+
serverConfig.module.rules.push({
36+
test: /javascriptLibs.ts$/,
37+
use: [
38+
{
39+
loader: path.resolve(__dirname, 'build', 'javaScriptLibraryLoader.js')
40+
}
41+
]
42+
});
3543

3644
module.exports = serverConfig;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { join, basename, dirname } from 'path';
7+
import { readFileSync } from 'fs';
8+
9+
const contents: { [name: string]: string } = {};
10+
11+
const serverFolder = basename(__dirname) === 'dist' ? dirname(__dirname) : dirname(dirname(__dirname));
12+
const TYPESCRIPT_LIB_SOURCE = join(serverFolder, '../../node_modules/typescript/lib');
13+
const JQUERY_PATH = join(serverFolder, 'lib/jquery.d.ts');
14+
15+
export function loadLibrary(name: string) {
16+
let content = contents[name];
17+
if (typeof content !== 'string') {
18+
let libPath;
19+
if (name === 'jquery') {
20+
libPath = JQUERY_PATH;
21+
} else {
22+
libPath = join(TYPESCRIPT_LIB_SOURCE, name); // from source
23+
}
24+
try {
25+
content = readFileSync(libPath).toString();
26+
} catch (e) {
27+
console.log(`Unable to load library ${name} at ${libPath}: ${e.message}`);
28+
content = '';
29+
}
30+
contents[name] = content;
31+
}
32+
return content;
33+
}

extensions/html-language-features/server/src/modes/javascriptMode.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,20 @@ import {
1010
DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions, FoldingRange, FoldingRangeKind, SelectionRange,
1111
LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext
1212
} from './languageModes';
13-
import { getWordAtText, startsWith, isWhitespaceOnly, repeat } from '../utils/strings';
13+
import { getWordAtText, isWhitespaceOnly, repeat } from '../utils/strings';
1414
import { HTMLDocumentRegions } from './embeddedSupport';
1515

1616
import * as ts from 'typescript';
1717
import { getSemanticTokens, getSemanticTokenLegend } from './javascriptSemanticTokens';
18-
import { joinPath } from '../requests';
19-
18+
import { loadLibrary } from './javascriptLibs';
2019

2120
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
2221

23-
let jquery_d_ts = joinPath(__dirname, '../lib/jquery.d.ts'); // when packaged
24-
if (!ts.sys.fileExists(jquery_d_ts)) {
25-
jquery_d_ts = joinPath(__dirname, '../../lib/jquery.d.ts'); // from source
26-
}
27-
2822
export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>, languageId: 'javascript' | 'typescript', workspace: Workspace): LanguageMode {
2923
let jsDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument(languageId));
3024

3125
const workingFile = languageId === 'javascript' ? 'vscode://javascript/1.js' : 'vscode://javascript/2.ts'; // the same 'file' is used for all contents
26+
const jQueryFile = 'jquery';
3227

3328
let compilerOptions: ts.CompilerOptions = { allowNonTsExtensions: true, allowJs: true, lib: ['lib.es6.d.ts'], target: ts.ScriptTarget.Latest, moduleResolution: ts.ModuleResolutionKind.Classic, experimentalDecorators: false };
3429
let currentTextDocument: TextDocument;
@@ -41,7 +36,7 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
4136
}
4237
const host: ts.LanguageServiceHost = {
4338
getCompilationSettings: () => compilerOptions,
44-
getScriptFileNames: () => [workingFile, jquery_d_ts],
39+
getScriptFileNames: () => [workingFile, jQueryFile],
4540
getScriptKind: (fileName) => fileName.substr(fileName.length - 2) === 'ts' ? ts.ScriptKind.TS : ts.ScriptKind.JS,
4641
getScriptVersion: (fileName: string) => {
4742
if (fileName === workingFile) {
@@ -51,12 +46,10 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
5146
},
5247
getScriptSnapshot: (fileName: string) => {
5348
let text = '';
54-
if (startsWith(fileName, 'vscode:')) {
55-
if (fileName === workingFile) {
56-
text = currentTextDocument.getText();
57-
}
49+
if (fileName === workingFile) {
50+
text = currentTextDocument.getText();
5851
} else {
59-
text = ts.sys.readFile(fileName) || '';
52+
text = loadLibrary(fileName);
6053
}
6154
return {
6255
getText: (start, end) => text.substring(start, end),
@@ -65,8 +58,7 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
6558
};
6659
},
6760
getCurrentDirectory: () => '',
68-
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
69-
61+
getDefaultLibFileName: (_options: ts.CompilerOptions) => 'es6'
7062
};
7163
let jsLanguageService = ts.createLanguageService(host);
7264

0 commit comments

Comments
 (0)