@typespec/compiler 0.52.0-dev.12 → 0.52.0-dev.13
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/manifest.js +2 -2
- package/dist/src/server/classify.d.ts +8 -0
- package/dist/src/server/classify.d.ts.map +1 -0
- package/dist/src/server/classify.js +310 -0
- package/dist/src/server/classify.js.map +1 -0
- package/dist/src/server/compile-service.d.ts +42 -0
- package/dist/src/server/compile-service.d.ts.map +1 -0
- package/dist/src/server/compile-service.js +163 -0
- package/dist/src/server/compile-service.js.map +1 -0
- package/dist/src/server/constants.d.ts +7 -0
- package/dist/src/server/constants.d.ts.map +1 -0
- package/dist/src/server/constants.js +13 -0
- package/dist/src/server/constants.js.map +1 -0
- package/dist/src/server/file-service.d.ts +18 -0
- package/dist/src/server/file-service.d.ts.map +1 -0
- package/dist/src/server/file-service.js +56 -0
- package/dist/src/server/file-service.js.map +1 -0
- package/dist/src/server/file-system-cache.d.ts +25 -0
- package/dist/src/server/file-system-cache.d.ts.map +1 -0
- package/dist/src/server/file-system-cache.js +27 -0
- package/dist/src/server/file-system-cache.js.map +1 -0
- package/dist/src/server/index.d.ts +2 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +2 -1
- package/dist/src/server/index.js.map +1 -1
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/server/serverlib.d.ts +1 -71
- package/dist/src/server/serverlib.d.ts.map +1 -1
- package/dist/src/server/serverlib.js +115 -622
- package/dist/src/server/serverlib.js.map +1 -1
- package/dist/src/server/types.d.ts +76 -0
- package/dist/src/server/types.d.ts.map +1 -0
- package/dist/src/server/types.js +26 -0
- package/dist/src/server/types.js.map +1 -0
- package/dist/src/server/update-manager.d.ts +19 -0
- package/dist/src/server/update-manager.d.ts.map +1 -0
- package/dist/src/server/update-manager.js +70 -0
- package/dist/src/server/update-manager.js.map +1 -0
- package/dist/src/testing/types.d.ts +2 -2
- package/dist/src/testing/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,67 +1,40 @@
|
|
|
1
1
|
import { DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, MarkupKind, Range, SemanticTokensBuilder, TextDocumentSyncKind, TextEdit, Diagnostic as VSDiagnostic, } from "vscode-languageserver/node.js";
|
|
2
|
-
import { defaultConfig, findTypeSpecConfigPath, loadTypeSpecConfigFile, } from "../config/config-loader.js";
|
|
3
|
-
import { resolveOptionsFromConfig } from "../config/config-to-options.js";
|
|
4
2
|
import { codePointBefore, isIdentifierContinue } from "../core/charcode.js";
|
|
5
|
-
import { compilerAssert, createSourceFile,
|
|
3
|
+
import { compilerAssert, createSourceFile, getSourceLocation } from "../core/diagnostics.js";
|
|
6
4
|
import { formatTypeSpec } from "../core/formatter.js";
|
|
7
5
|
import { getTypeName } from "../core/helpers/type-name-utils.js";
|
|
8
6
|
import { getNodeAtPosition, visitChildren } from "../core/parser.js";
|
|
9
|
-
import { ensureTrailingDirectorySeparator
|
|
10
|
-
import {
|
|
11
|
-
import { Token, TokenFlags, createScanner, isKeyword, isPunctuation, skipTrivia, skipWhiteSpace, } from "../core/scanner.js";
|
|
7
|
+
import { ensureTrailingDirectorySeparator } from "../core/path-utils.js";
|
|
8
|
+
import { skipTrivia, skipWhiteSpace } from "../core/scanner.js";
|
|
12
9
|
import { SyntaxKind, } from "../core/types.js";
|
|
13
|
-
import {
|
|
10
|
+
import { getNormalizedRealPath, getSourceFileKindFromExt } from "../core/util.js";
|
|
11
|
+
import { getSemanticTokens } from "./classify.js";
|
|
12
|
+
import { createCompileService } from "./compile-service.js";
|
|
14
13
|
import { resolveCompletion } from "./completion.js";
|
|
14
|
+
import { createFileService } from "./file-service.js";
|
|
15
|
+
import { createFileSystemCache } from "./file-system-cache.js";
|
|
15
16
|
import { getPositionBeforeTrivia } from "./server-utils.js";
|
|
16
17
|
import { getSymbolStructure } from "./symbol-structure.js";
|
|
17
18
|
import { getParameterDocumentation, getSymbolDetails, getTemplateParameterDocumentation, } from "./type-details.js";
|
|
18
|
-
|
|
19
|
-
(function (SemanticTokenKind) {
|
|
20
|
-
SemanticTokenKind[SemanticTokenKind["Namespace"] = 0] = "Namespace";
|
|
21
|
-
SemanticTokenKind[SemanticTokenKind["Type"] = 1] = "Type";
|
|
22
|
-
SemanticTokenKind[SemanticTokenKind["Class"] = 2] = "Class";
|
|
23
|
-
SemanticTokenKind[SemanticTokenKind["Enum"] = 3] = "Enum";
|
|
24
|
-
SemanticTokenKind[SemanticTokenKind["Interface"] = 4] = "Interface";
|
|
25
|
-
SemanticTokenKind[SemanticTokenKind["Struct"] = 5] = "Struct";
|
|
26
|
-
SemanticTokenKind[SemanticTokenKind["TypeParameter"] = 6] = "TypeParameter";
|
|
27
|
-
SemanticTokenKind[SemanticTokenKind["Parameter"] = 7] = "Parameter";
|
|
28
|
-
SemanticTokenKind[SemanticTokenKind["Variable"] = 8] = "Variable";
|
|
29
|
-
SemanticTokenKind[SemanticTokenKind["Property"] = 9] = "Property";
|
|
30
|
-
SemanticTokenKind[SemanticTokenKind["EnumMember"] = 10] = "EnumMember";
|
|
31
|
-
SemanticTokenKind[SemanticTokenKind["Event"] = 11] = "Event";
|
|
32
|
-
SemanticTokenKind[SemanticTokenKind["Function"] = 12] = "Function";
|
|
33
|
-
SemanticTokenKind[SemanticTokenKind["Method"] = 13] = "Method";
|
|
34
|
-
SemanticTokenKind[SemanticTokenKind["Macro"] = 14] = "Macro";
|
|
35
|
-
SemanticTokenKind[SemanticTokenKind["Keyword"] = 15] = "Keyword";
|
|
36
|
-
SemanticTokenKind[SemanticTokenKind["Comment"] = 16] = "Comment";
|
|
37
|
-
SemanticTokenKind[SemanticTokenKind["String"] = 17] = "String";
|
|
38
|
-
SemanticTokenKind[SemanticTokenKind["Number"] = 18] = "Number";
|
|
39
|
-
SemanticTokenKind[SemanticTokenKind["Regexp"] = 19] = "Regexp";
|
|
40
|
-
SemanticTokenKind[SemanticTokenKind["Operator"] = 20] = "Operator";
|
|
41
|
-
SemanticTokenKind[SemanticTokenKind["DocCommentTag"] = 21] = "DocCommentTag";
|
|
42
|
-
})(SemanticTokenKind || (SemanticTokenKind = {}));
|
|
43
|
-
const serverOptions = {
|
|
44
|
-
noEmit: true,
|
|
45
|
-
designTimeBuild: true,
|
|
46
|
-
parseOptions: {
|
|
47
|
-
comments: true,
|
|
48
|
-
docs: true,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
19
|
+
import { SemanticTokenKind, } from "./types.js";
|
|
51
20
|
export function createServer(host) {
|
|
52
|
-
|
|
53
|
-
// get it back. We can't convert it back because things like URL-encoding
|
|
54
|
-
// could give us back an equivalent but non-identical URL but the original
|
|
55
|
-
// URL is used as a key into the opened documents and so we must reproduce
|
|
56
|
-
// it exactly.
|
|
57
|
-
const pathToURLMap = new Map();
|
|
21
|
+
const fileService = createFileService({ serverHost: host });
|
|
58
22
|
// Cache all file I/O. Only open documents are sent over the LSP pipe. When
|
|
59
23
|
// the compiler reads a file that isn't open, we use this cache to avoid
|
|
60
24
|
// hitting the disk. Entries are invalidated when LSP client notifies us of
|
|
61
25
|
// a file change.
|
|
62
|
-
const fileSystemCache = createFileSystemCache(
|
|
26
|
+
const fileSystemCache = createFileSystemCache({
|
|
27
|
+
fileService,
|
|
28
|
+
});
|
|
63
29
|
const compilerHost = createCompilerHost();
|
|
64
|
-
const
|
|
30
|
+
const compileService = createCompileService({
|
|
31
|
+
fileService,
|
|
32
|
+
fileSystemCache,
|
|
33
|
+
compilerHost,
|
|
34
|
+
serverHost: host,
|
|
35
|
+
log,
|
|
36
|
+
});
|
|
37
|
+
compileService.on("compileEnd", (result) => reportDiagnostics(result));
|
|
65
38
|
let workspaceFolders = [];
|
|
66
39
|
let isInitialized = false;
|
|
67
40
|
let pendingMessages = [];
|
|
@@ -72,7 +45,7 @@ export function createServer(host) {
|
|
|
72
45
|
get workspaceFolders() {
|
|
73
46
|
return workspaceFolders;
|
|
74
47
|
},
|
|
75
|
-
compile,
|
|
48
|
+
compile: compileService.compile,
|
|
76
49
|
initialize,
|
|
77
50
|
initialized,
|
|
78
51
|
workspaceFoldersChanged,
|
|
@@ -85,7 +58,7 @@ export function createServer(host) {
|
|
|
85
58
|
findDocumentHighlight,
|
|
86
59
|
prepareRename,
|
|
87
60
|
rename,
|
|
88
|
-
getSemanticTokens,
|
|
61
|
+
getSemanticTokens: getSemanticTokensForDocument,
|
|
89
62
|
buildSemanticTokens,
|
|
90
63
|
checkChange,
|
|
91
64
|
getFoldingRanges,
|
|
@@ -131,7 +104,7 @@ export function createServer(host) {
|
|
|
131
104
|
for (const w of (_b = params.workspaceFolders) !== null && _b !== void 0 ? _b : []) {
|
|
132
105
|
workspaceFolders.push({
|
|
133
106
|
...w,
|
|
134
|
-
path: ensureTrailingDirectorySeparator(await fileURLToRealPath(w.uri)),
|
|
107
|
+
path: ensureTrailingDirectorySeparator(await fileService.fileURLToRealPath(w.uri)),
|
|
135
108
|
});
|
|
136
109
|
}
|
|
137
110
|
capabilities.workspace = {
|
|
@@ -148,8 +121,9 @@ export function createServer(host) {
|
|
|
148
121
|
name: "<root>",
|
|
149
122
|
// eslint-disable-next-line deprecation/deprecation
|
|
150
123
|
uri: params.rootUri,
|
|
124
|
+
path: ensureTrailingDirectorySeparator(
|
|
151
125
|
// eslint-disable-next-line deprecation/deprecation
|
|
152
|
-
|
|
126
|
+
await fileService.fileURLToRealPath(params.rootUri)),
|
|
153
127
|
},
|
|
154
128
|
];
|
|
155
129
|
// eslint-disable-next-line deprecation/deprecation
|
|
@@ -182,7 +156,7 @@ export function createServer(host) {
|
|
|
182
156
|
for (const folder of e.added) {
|
|
183
157
|
map.set(folder.uri, {
|
|
184
158
|
...folder,
|
|
185
|
-
path: ensureTrailingDirectorySeparator(await fileURLToRealPath(folder.uri)),
|
|
159
|
+
path: ensureTrailingDirectorySeparator(await fileService.fileURLToRealPath(folder.uri)),
|
|
186
160
|
});
|
|
187
161
|
}
|
|
188
162
|
workspaceFolders = Array.from(map.values());
|
|
@@ -191,85 +165,8 @@ export function createServer(host) {
|
|
|
191
165
|
function watchedFilesChanged(params) {
|
|
192
166
|
fileSystemCache.notify(params.changes);
|
|
193
167
|
}
|
|
194
|
-
async function compile(document, callback) {
|
|
195
|
-
const path = await getPath(document);
|
|
196
|
-
const mainFile = await getMainFileForDocument(path);
|
|
197
|
-
const config = await getConfig(mainFile);
|
|
198
|
-
const [optionsFromConfig, _] = resolveOptionsFromConfig(config, { cwd: path });
|
|
199
|
-
const options = {
|
|
200
|
-
...optionsFromConfig,
|
|
201
|
-
...serverOptions,
|
|
202
|
-
};
|
|
203
|
-
if (!upToDate(document)) {
|
|
204
|
-
return undefined;
|
|
205
|
-
}
|
|
206
|
-
let program;
|
|
207
|
-
try {
|
|
208
|
-
program = await compileProgram(compilerHost, mainFile, options, oldPrograms.get(mainFile));
|
|
209
|
-
oldPrograms.set(mainFile, program);
|
|
210
|
-
if (!upToDate(document)) {
|
|
211
|
-
return undefined;
|
|
212
|
-
}
|
|
213
|
-
if (mainFile !== path && !program.sourceFiles.has(path)) {
|
|
214
|
-
// If the file that changed wasn't imported by anything from the main
|
|
215
|
-
// file, retry using the file itself as the main file.
|
|
216
|
-
program = await compileProgram(compilerHost, path, options, oldPrograms.get(path));
|
|
217
|
-
oldPrograms.set(path, program);
|
|
218
|
-
}
|
|
219
|
-
if (!upToDate(document)) {
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
if (callback) {
|
|
223
|
-
const doc = "version" in document ? document : host.getOpenDocumentByURL(document.uri);
|
|
224
|
-
compilerAssert(doc, "Failed to get document.");
|
|
225
|
-
const path = await getPath(doc);
|
|
226
|
-
const script = program.sourceFiles.get(path);
|
|
227
|
-
compilerAssert(script, "Failed to get script.");
|
|
228
|
-
return await callback(program, doc, script);
|
|
229
|
-
}
|
|
230
|
-
return program;
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
if (host.throwInternalErrors) {
|
|
234
|
-
throw err;
|
|
235
|
-
}
|
|
236
|
-
host.sendDiagnostics({
|
|
237
|
-
uri: document.uri,
|
|
238
|
-
diagnostics: [
|
|
239
|
-
{
|
|
240
|
-
severity: DiagnosticSeverity.Error,
|
|
241
|
-
range: Range.create(0, 0, 0, 0),
|
|
242
|
-
message: `Internal compiler error!\nFile issue at https://github.com/microsoft/typespec\n\n` +
|
|
243
|
-
err.stack,
|
|
244
|
-
},
|
|
245
|
-
],
|
|
246
|
-
});
|
|
247
|
-
return undefined;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
async function getConfig(mainFile) {
|
|
251
|
-
const entrypointStat = await host.compilerHost.stat(mainFile);
|
|
252
|
-
const lookupDir = entrypointStat.isDirectory() ? mainFile : getDirectoryPath(mainFile);
|
|
253
|
-
const configPath = await findTypeSpecConfigPath(compilerHost, lookupDir, true);
|
|
254
|
-
if (!configPath) {
|
|
255
|
-
return { ...defaultConfig, projectRoot: getDirectoryPath(mainFile) };
|
|
256
|
-
}
|
|
257
|
-
const cached = await fileSystemCache.get(configPath);
|
|
258
|
-
if (cached === null || cached === void 0 ? void 0 : cached.data) {
|
|
259
|
-
return cached.data;
|
|
260
|
-
}
|
|
261
|
-
const config = await loadTypeSpecConfigFile(compilerHost, configPath);
|
|
262
|
-
await fileSystemCache.setData(configPath, config);
|
|
263
|
-
return config;
|
|
264
|
-
}
|
|
265
|
-
async function getScript(document) {
|
|
266
|
-
var _a;
|
|
267
|
-
const file = await compilerHost.readFile(await getPath(document));
|
|
268
|
-
const cached = (_a = compilerHost.parseCache) === null || _a === void 0 ? void 0 : _a.get(file);
|
|
269
|
-
return cached !== null && cached !== void 0 ? cached : (await compile(document, (_, __, script) => script));
|
|
270
|
-
}
|
|
271
168
|
async function getFoldingRanges(params) {
|
|
272
|
-
const ast = await getScript(params.textDocument);
|
|
169
|
+
const ast = await compileService.getScript(params.textDocument);
|
|
273
170
|
if (!ast) {
|
|
274
171
|
return [];
|
|
275
172
|
}
|
|
@@ -323,29 +220,29 @@ export function createServer(host) {
|
|
|
323
220
|
}
|
|
324
221
|
}
|
|
325
222
|
async function getDocumentSymbols(params) {
|
|
326
|
-
const ast = await getScript(params.textDocument);
|
|
223
|
+
const ast = await compileService.getScript(params.textDocument);
|
|
327
224
|
if (!ast) {
|
|
328
225
|
return [];
|
|
329
226
|
}
|
|
330
227
|
return getSymbolStructure(ast);
|
|
331
228
|
}
|
|
332
229
|
async function findDocumentHighlight(params) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
230
|
+
const result = await compileService.compile(params.textDocument);
|
|
231
|
+
if (result === undefined) {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const { program, document, script } = result;
|
|
235
|
+
const identifiers = findReferenceIdentifiers(program, script, document.offsetAt(params.position), [script]);
|
|
236
|
+
return identifiers.map((identifier) => ({
|
|
237
|
+
range: getRange(identifier, script.file),
|
|
238
|
+
kind: DocumentHighlightKind.Read,
|
|
239
|
+
}));
|
|
342
240
|
}
|
|
343
241
|
async function checkChange(change) {
|
|
242
|
+
compileService.notifyChange(change.document);
|
|
243
|
+
}
|
|
244
|
+
async function reportDiagnostics({ program, document }) {
|
|
344
245
|
var _a, _b, _c;
|
|
345
|
-
const program = await compile(change.document);
|
|
346
|
-
if (!program) {
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
246
|
// Group diagnostics by file.
|
|
350
247
|
//
|
|
351
248
|
// Initialize diagnostics for all source files in program to empty array
|
|
@@ -353,7 +250,7 @@ export function createServer(host) {
|
|
|
353
250
|
// stale diagnostics from a previous run will stick around in the IDE.
|
|
354
251
|
//
|
|
355
252
|
const diagnosticMap = new Map();
|
|
356
|
-
diagnosticMap.set(
|
|
253
|
+
diagnosticMap.set(document, []);
|
|
357
254
|
for (const each of program.sourceFiles.values()) {
|
|
358
255
|
const document = (_a = each.file) === null || _a === void 0 ? void 0 : _a.document;
|
|
359
256
|
if (document) {
|
|
@@ -361,10 +258,10 @@ export function createServer(host) {
|
|
|
361
258
|
}
|
|
362
259
|
}
|
|
363
260
|
for (const each of program.diagnostics) {
|
|
364
|
-
let
|
|
261
|
+
let diagDocument;
|
|
365
262
|
const location = getSourceLocation(each.target, { locateId: true });
|
|
366
263
|
if (location === null || location === void 0 ? void 0 : location.file) {
|
|
367
|
-
|
|
264
|
+
diagDocument = location.file.document;
|
|
368
265
|
}
|
|
369
266
|
else {
|
|
370
267
|
// https://github.com/microsoft/language-server-protocol/issues/256
|
|
@@ -372,20 +269,20 @@ export function createServer(host) {
|
|
|
372
269
|
// LSP does not currently allow sending a diagnostic with no location so
|
|
373
270
|
// we report diagnostics with no location on the document that changed to
|
|
374
271
|
// trigger.
|
|
375
|
-
|
|
272
|
+
diagDocument = document;
|
|
376
273
|
}
|
|
377
|
-
if (!
|
|
274
|
+
if (!diagDocument || !fileService.upToDate(diagDocument)) {
|
|
378
275
|
continue;
|
|
379
276
|
}
|
|
380
|
-
const start =
|
|
381
|
-
const end =
|
|
277
|
+
const start = diagDocument.positionAt((_b = location === null || location === void 0 ? void 0 : location.pos) !== null && _b !== void 0 ? _b : 0);
|
|
278
|
+
const end = diagDocument.positionAt((_c = location === null || location === void 0 ? void 0 : location.end) !== null && _c !== void 0 ? _c : 0);
|
|
382
279
|
const range = Range.create(start, end);
|
|
383
280
|
const severity = convertSeverity(each.severity);
|
|
384
281
|
const diagnostic = VSDiagnostic.create(range, each.message, severity, each.code, "TypeSpec");
|
|
385
282
|
if (each.code === "deprecated") {
|
|
386
283
|
diagnostic.tags = [DiagnosticTag.Deprecated];
|
|
387
284
|
}
|
|
388
|
-
const diagnostics = diagnosticMap.get(
|
|
285
|
+
const diagnostics = diagnosticMap.get(diagDocument);
|
|
389
286
|
compilerAssert(diagnostics, "Diagnostic reported against a source file that was not added to the program.");
|
|
390
287
|
diagnostics.push(diagnostic);
|
|
391
288
|
}
|
|
@@ -394,40 +291,42 @@ export function createServer(host) {
|
|
|
394
291
|
}
|
|
395
292
|
}
|
|
396
293
|
async function getHover(params) {
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
});
|
|
294
|
+
const result = await compileService.compile(params.textDocument);
|
|
295
|
+
if (result === undefined) {
|
|
296
|
+
return { contents: [] };
|
|
297
|
+
}
|
|
298
|
+
const { program, document, script } = result;
|
|
299
|
+
const id = getNodeAtPosition(script, document.offsetAt(params.position));
|
|
300
|
+
const sym = (id === null || id === void 0 ? void 0 : id.kind) === SyntaxKind.Identifier ? program.checker.resolveIdentifier(id) : undefined;
|
|
405
301
|
const markdown = {
|
|
406
302
|
kind: MarkupKind.Markdown,
|
|
407
|
-
value:
|
|
303
|
+
value: sym ? getSymbolDetails(program, sym) : "",
|
|
408
304
|
};
|
|
409
305
|
return {
|
|
410
306
|
contents: markdown,
|
|
411
307
|
};
|
|
412
308
|
}
|
|
413
309
|
async function getSignatureHelp(params) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
310
|
+
const result = await compileService.compile(params.textDocument);
|
|
311
|
+
if (result === undefined) {
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
const { script, document, program } = result;
|
|
315
|
+
const data = getSignatureHelpNodeAtPosition(script, document.offsetAt(params.position));
|
|
316
|
+
if (data === undefined) {
|
|
317
|
+
return undefined;
|
|
318
|
+
}
|
|
319
|
+
const { node, argumentIndex } = data;
|
|
320
|
+
switch (node.kind) {
|
|
321
|
+
case SyntaxKind.TypeReference:
|
|
322
|
+
return getSignatureHelpForTemplate(program, node, argumentIndex);
|
|
323
|
+
case SyntaxKind.DecoratorExpression:
|
|
324
|
+
case SyntaxKind.AugmentDecoratorStatement:
|
|
325
|
+
return getSignatureHelpForDecorator(program, node, argumentIndex);
|
|
326
|
+
default:
|
|
327
|
+
const _assertNever = node;
|
|
328
|
+
compilerAssert(false, "Unreachable");
|
|
329
|
+
}
|
|
431
330
|
}
|
|
432
331
|
function getSignatureHelpForTemplate(program, node, argumentIndex) {
|
|
433
332
|
const sym = program.checker.resolveIdentifier(node.target.kind === SyntaxKind.MemberExpression ? node.target.id : node.target);
|
|
@@ -551,10 +450,12 @@ export function createServer(host) {
|
|
|
551
450
|
return TextEdit.replace(Range.create(pos0, pos1), newText);
|
|
552
451
|
}
|
|
553
452
|
async function gotoDefinition(params) {
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
return
|
|
557
|
-
}
|
|
453
|
+
const result = await compileService.compile(params.textDocument);
|
|
454
|
+
if (result === undefined) {
|
|
455
|
+
return [];
|
|
456
|
+
}
|
|
457
|
+
const id = getNodeAtPosition(result.script, result.document.offsetAt(params.position));
|
|
458
|
+
const sym = (id === null || id === void 0 ? void 0 : id.kind) === SyntaxKind.Identifier ? result.program.checker.resolveIdentifier(id) : undefined;
|
|
558
459
|
return getLocations(sym === null || sym === void 0 ? void 0 : sym.declarations);
|
|
559
460
|
}
|
|
560
461
|
async function complete(params) {
|
|
@@ -562,32 +463,41 @@ export function createServer(host) {
|
|
|
562
463
|
isIncomplete: false,
|
|
563
464
|
items: [],
|
|
564
465
|
};
|
|
565
|
-
await compile(params.textDocument
|
|
566
|
-
|
|
466
|
+
const result = await compileService.compile(params.textDocument);
|
|
467
|
+
if (result) {
|
|
468
|
+
const { script, document, program } = result;
|
|
469
|
+
const node = getCompletionNodeAtPosition(script, document.offsetAt(params.position));
|
|
567
470
|
await resolveCompletion({
|
|
568
471
|
program,
|
|
569
|
-
file,
|
|
472
|
+
file: script,
|
|
570
473
|
completions,
|
|
571
474
|
params,
|
|
572
475
|
}, node);
|
|
573
|
-
}
|
|
476
|
+
}
|
|
574
477
|
return completions;
|
|
575
478
|
}
|
|
576
479
|
async function findReferences(params) {
|
|
577
|
-
const
|
|
480
|
+
const result = await compileService.compile(params.textDocument);
|
|
481
|
+
if (result === undefined) {
|
|
482
|
+
return [];
|
|
483
|
+
}
|
|
484
|
+
const identifiers = findReferenceIdentifiers(result.program, result.script, result.document.offsetAt(params.position));
|
|
578
485
|
return getLocations(identifiers);
|
|
579
486
|
}
|
|
580
487
|
async function prepareRename(params) {
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
return
|
|
585
|
-
}
|
|
488
|
+
var _a;
|
|
489
|
+
const result = await compileService.compile(params.textDocument);
|
|
490
|
+
if (result === undefined) {
|
|
491
|
+
return undefined;
|
|
492
|
+
}
|
|
493
|
+
const id = getNodeAtPosition(result.script, result.document.offsetAt(params.position));
|
|
494
|
+
return (id === null || id === void 0 ? void 0 : id.kind) === SyntaxKind.Identifier ? (_a = getLocation(id)) === null || _a === void 0 ? void 0 : _a.range : undefined;
|
|
586
495
|
}
|
|
587
496
|
async function rename(params) {
|
|
588
497
|
const changes = {};
|
|
589
|
-
await compile(params.textDocument
|
|
590
|
-
|
|
498
|
+
const result = await compileService.compile(params.textDocument);
|
|
499
|
+
if (result) {
|
|
500
|
+
const identifiers = findReferenceIdentifiers(result.program, result.script, result.document.offsetAt(params.position));
|
|
591
501
|
for (const id of identifiers) {
|
|
592
502
|
const location = getLocation(id);
|
|
593
503
|
if (!location) {
|
|
@@ -601,7 +511,7 @@ export function createServer(host) {
|
|
|
601
511
|
changes[location.uri] = [change];
|
|
602
512
|
}
|
|
603
513
|
}
|
|
604
|
-
}
|
|
514
|
+
}
|
|
605
515
|
return { changes };
|
|
606
516
|
}
|
|
607
517
|
function findReferenceIdentifiers(program, file, pos, searchFiles = program.sourceFiles.values()) {
|
|
@@ -627,317 +537,17 @@ export function createServer(host) {
|
|
|
627
537
|
}
|
|
628
538
|
return references;
|
|
629
539
|
}
|
|
630
|
-
async function
|
|
631
|
-
const
|
|
632
|
-
const defer = -2;
|
|
633
|
-
const ast = await getScript(params.textDocument);
|
|
540
|
+
async function getSemanticTokensForDocument(params) {
|
|
541
|
+
const ast = await compileService.getScript(params.textDocument);
|
|
634
542
|
if (!ast) {
|
|
635
543
|
return [];
|
|
636
544
|
}
|
|
637
|
-
|
|
638
|
-
const tokens = mapTokens();
|
|
639
|
-
classifyNode(ast);
|
|
640
|
-
return Array.from(tokens.values()).filter((t) => t.kind !== undefined);
|
|
641
|
-
function mapTokens() {
|
|
642
|
-
const tokens = new Map();
|
|
643
|
-
const scanner = createScanner(file, () => { });
|
|
644
|
-
const templateStack = [];
|
|
645
|
-
while (scanner.scan() !== Token.EndOfFile) {
|
|
646
|
-
if (scanner.tokenFlags & TokenFlags.DocComment) {
|
|
647
|
-
classifyDocComment({ pos: scanner.tokenPosition, end: scanner.position });
|
|
648
|
-
}
|
|
649
|
-
else {
|
|
650
|
-
handleToken(scanner.token, scanner.tokenFlags, {
|
|
651
|
-
pos: scanner.tokenPosition,
|
|
652
|
-
end: scanner.position,
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
return tokens;
|
|
657
|
-
function classifyDocComment(range) {
|
|
658
|
-
scanner.scanRange(range, () => {
|
|
659
|
-
while (scanner.scanDoc() !== Token.EndOfFile) {
|
|
660
|
-
const kind = classifyDocToken(scanner.token);
|
|
661
|
-
if (kind === ignore) {
|
|
662
|
-
continue;
|
|
663
|
-
}
|
|
664
|
-
tokens.set(scanner.tokenPosition, {
|
|
665
|
-
kind: kind === defer ? undefined : kind,
|
|
666
|
-
pos: scanner.tokenPosition,
|
|
667
|
-
end: scanner.position,
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
function handleToken(token, tokenFlags, range) {
|
|
673
|
-
switch (token) {
|
|
674
|
-
case Token.StringTemplateHead:
|
|
675
|
-
templateStack.push([token, tokenFlags]);
|
|
676
|
-
classifyStringTemplate(token, range);
|
|
677
|
-
break;
|
|
678
|
-
case Token.OpenBrace:
|
|
679
|
-
// If we don't have anything on the template stack,
|
|
680
|
-
// then we aren't trying to keep track of a previously scanned template head.
|
|
681
|
-
if (templateStack.length > 0) {
|
|
682
|
-
templateStack.push([token, tokenFlags]);
|
|
683
|
-
}
|
|
684
|
-
handleSimpleToken(token, range);
|
|
685
|
-
break;
|
|
686
|
-
case Token.CloseBrace:
|
|
687
|
-
// If we don't have anything on the template stack,
|
|
688
|
-
// then we aren't trying to keep track of a previously scanned template head.
|
|
689
|
-
if (templateStack.length > 0) {
|
|
690
|
-
const [lastToken, lastTokenFlags] = templateStack[templateStack.length - 1];
|
|
691
|
-
if (lastToken === Token.StringTemplateHead) {
|
|
692
|
-
token = scanner.reScanStringTemplate(lastTokenFlags);
|
|
693
|
-
// Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
|
|
694
|
-
if (token === Token.StringTemplateTail) {
|
|
695
|
-
templateStack.pop();
|
|
696
|
-
classifyStringTemplate(token, {
|
|
697
|
-
pos: scanner.tokenPosition,
|
|
698
|
-
end: scanner.position,
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
else {
|
|
702
|
-
compilerAssert(token === Token.StringTemplateMiddle, "Should have been a template middle.");
|
|
703
|
-
classifyStringTemplate(token, {
|
|
704
|
-
pos: scanner.tokenPosition,
|
|
705
|
-
end: scanner.position,
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
compilerAssert(lastToken === Token.OpenBrace, "Should have been an open brace");
|
|
711
|
-
templateStack.pop();
|
|
712
|
-
}
|
|
713
|
-
break;
|
|
714
|
-
}
|
|
715
|
-
handleSimpleToken(token, range);
|
|
716
|
-
break;
|
|
717
|
-
default:
|
|
718
|
-
handleSimpleToken(token, range);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
function handleSimpleToken(token, range) {
|
|
722
|
-
const kind = classifyToken(scanner.token);
|
|
723
|
-
if (kind === ignore) {
|
|
724
|
-
return;
|
|
725
|
-
}
|
|
726
|
-
tokens.set(range.pos, {
|
|
727
|
-
kind: kind === defer ? undefined : kind,
|
|
728
|
-
...range,
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
function classifyStringTemplate(token, range) {
|
|
732
|
-
const stringStart = token === Token.StringTemplateHead ? range.pos : range.pos + 1;
|
|
733
|
-
const stringEnd = token === Token.StringTemplateTail ? range.end : range.end - 2;
|
|
734
|
-
if (stringStart !== range.pos) {
|
|
735
|
-
tokens.set(range.pos, {
|
|
736
|
-
kind: SemanticTokenKind.Operator,
|
|
737
|
-
pos: range.pos,
|
|
738
|
-
end: stringStart,
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
tokens.set(stringStart, {
|
|
742
|
-
kind: SemanticTokenKind.String,
|
|
743
|
-
pos: stringStart,
|
|
744
|
-
end: stringEnd,
|
|
745
|
-
});
|
|
746
|
-
if (stringEnd !== range.end) {
|
|
747
|
-
tokens.set(stringEnd, {
|
|
748
|
-
kind: SemanticTokenKind.Operator,
|
|
749
|
-
pos: stringEnd,
|
|
750
|
-
end: range.end,
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
function classifyToken(token) {
|
|
756
|
-
switch (token) {
|
|
757
|
-
case Token.Identifier:
|
|
758
|
-
return defer;
|
|
759
|
-
case Token.StringLiteral:
|
|
760
|
-
return SemanticTokenKind.String;
|
|
761
|
-
case Token.NumericLiteral:
|
|
762
|
-
return SemanticTokenKind.Number;
|
|
763
|
-
case Token.MultiLineComment:
|
|
764
|
-
case Token.SingleLineComment:
|
|
765
|
-
return SemanticTokenKind.Comment;
|
|
766
|
-
default:
|
|
767
|
-
if (isKeyword(token)) {
|
|
768
|
-
return SemanticTokenKind.Keyword;
|
|
769
|
-
}
|
|
770
|
-
if (isPunctuation(token)) {
|
|
771
|
-
return SemanticTokenKind.Operator;
|
|
772
|
-
}
|
|
773
|
-
return ignore;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
/** Classify tokens when scanning doc comment. */
|
|
777
|
-
function classifyDocToken(token) {
|
|
778
|
-
switch (token) {
|
|
779
|
-
case Token.NewLine:
|
|
780
|
-
case Token.Whitespace:
|
|
781
|
-
return ignore;
|
|
782
|
-
case Token.DocText:
|
|
783
|
-
case Token.Star:
|
|
784
|
-
case Token.Identifier:
|
|
785
|
-
return SemanticTokenKind.Comment;
|
|
786
|
-
case Token.At:
|
|
787
|
-
return defer;
|
|
788
|
-
default:
|
|
789
|
-
return ignore;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
function classifyNode(node) {
|
|
793
|
-
switch (node.kind) {
|
|
794
|
-
case SyntaxKind.DirectiveExpression:
|
|
795
|
-
classify(node.target, SemanticTokenKind.Keyword);
|
|
796
|
-
break;
|
|
797
|
-
case SyntaxKind.TemplateParameterDeclaration:
|
|
798
|
-
classify(node.id, SemanticTokenKind.TypeParameter);
|
|
799
|
-
break;
|
|
800
|
-
case SyntaxKind.ModelProperty:
|
|
801
|
-
case SyntaxKind.UnionVariant:
|
|
802
|
-
if (node.id) {
|
|
803
|
-
classify(node.id, SemanticTokenKind.Property);
|
|
804
|
-
}
|
|
805
|
-
break;
|
|
806
|
-
case SyntaxKind.AliasStatement:
|
|
807
|
-
classify(node.id, SemanticTokenKind.Struct);
|
|
808
|
-
break;
|
|
809
|
-
case SyntaxKind.ModelStatement:
|
|
810
|
-
classify(node.id, SemanticTokenKind.Struct);
|
|
811
|
-
break;
|
|
812
|
-
case SyntaxKind.ScalarStatement:
|
|
813
|
-
classify(node.id, SemanticTokenKind.Type);
|
|
814
|
-
break;
|
|
815
|
-
case SyntaxKind.EnumStatement:
|
|
816
|
-
classify(node.id, SemanticTokenKind.Enum);
|
|
817
|
-
break;
|
|
818
|
-
case SyntaxKind.EnumMember:
|
|
819
|
-
classify(node.id, SemanticTokenKind.EnumMember);
|
|
820
|
-
break;
|
|
821
|
-
case SyntaxKind.NamespaceStatement:
|
|
822
|
-
classify(node.id, SemanticTokenKind.Namespace);
|
|
823
|
-
break;
|
|
824
|
-
case SyntaxKind.InterfaceStatement:
|
|
825
|
-
classify(node.id, SemanticTokenKind.Interface);
|
|
826
|
-
break;
|
|
827
|
-
case SyntaxKind.OperationStatement:
|
|
828
|
-
classify(node.id, SemanticTokenKind.Function);
|
|
829
|
-
break;
|
|
830
|
-
case SyntaxKind.DecoratorDeclarationStatement:
|
|
831
|
-
classify(node.id, SemanticTokenKind.Function);
|
|
832
|
-
break;
|
|
833
|
-
case SyntaxKind.FunctionDeclarationStatement:
|
|
834
|
-
classify(node.id, SemanticTokenKind.Function);
|
|
835
|
-
break;
|
|
836
|
-
case SyntaxKind.FunctionParameter:
|
|
837
|
-
classify(node.id, SemanticTokenKind.Parameter);
|
|
838
|
-
break;
|
|
839
|
-
case SyntaxKind.AugmentDecoratorStatement:
|
|
840
|
-
classifyReference(node.targetType, SemanticTokenKind.Type);
|
|
841
|
-
classifyReference(node.target, SemanticTokenKind.Macro);
|
|
842
|
-
break;
|
|
843
|
-
case SyntaxKind.DecoratorExpression:
|
|
844
|
-
classifyReference(node.target, SemanticTokenKind.Macro);
|
|
845
|
-
break;
|
|
846
|
-
case SyntaxKind.TypeReference:
|
|
847
|
-
classifyReference(node.target);
|
|
848
|
-
break;
|
|
849
|
-
case SyntaxKind.MemberExpression:
|
|
850
|
-
classifyReference(node);
|
|
851
|
-
break;
|
|
852
|
-
case SyntaxKind.ProjectionStatement:
|
|
853
|
-
classifyReference(node.selector);
|
|
854
|
-
classify(node.id, SemanticTokenKind.Variable);
|
|
855
|
-
break;
|
|
856
|
-
case SyntaxKind.Projection:
|
|
857
|
-
classify(node.directionId, SemanticTokenKind.Keyword);
|
|
858
|
-
for (const modifierId of node.modifierIds) {
|
|
859
|
-
classify(modifierId, SemanticTokenKind.Keyword);
|
|
860
|
-
}
|
|
861
|
-
break;
|
|
862
|
-
case SyntaxKind.ProjectionParameterDeclaration:
|
|
863
|
-
classifyReference(node.id, SemanticTokenKind.Parameter);
|
|
864
|
-
break;
|
|
865
|
-
case SyntaxKind.ProjectionCallExpression:
|
|
866
|
-
classifyReference(node.target, SemanticTokenKind.Function);
|
|
867
|
-
for (const arg of node.arguments) {
|
|
868
|
-
classifyReference(arg);
|
|
869
|
-
}
|
|
870
|
-
break;
|
|
871
|
-
case SyntaxKind.ProjectionMemberExpression:
|
|
872
|
-
classifyReference(node.id);
|
|
873
|
-
break;
|
|
874
|
-
case SyntaxKind.DocParamTag:
|
|
875
|
-
case SyntaxKind.DocTemplateTag:
|
|
876
|
-
classifyDocTag(node.tagName, SemanticTokenKind.DocCommentTag);
|
|
877
|
-
classifyOverride(node.paramName, SemanticTokenKind.Variable);
|
|
878
|
-
break;
|
|
879
|
-
case SyntaxKind.DocReturnsTag:
|
|
880
|
-
classifyDocTag(node.tagName, SemanticTokenKind.DocCommentTag);
|
|
881
|
-
break;
|
|
882
|
-
case SyntaxKind.DocUnknownTag:
|
|
883
|
-
classifyDocTag(node.tagName, SemanticTokenKind.Macro);
|
|
884
|
-
break;
|
|
885
|
-
case SyntaxKind.TemplateArgument:
|
|
886
|
-
if (node.name)
|
|
887
|
-
classify(node.name, SemanticTokenKind.TypeParameter);
|
|
888
|
-
break;
|
|
889
|
-
default:
|
|
890
|
-
break;
|
|
891
|
-
}
|
|
892
|
-
visitChildren(node, classifyNode);
|
|
893
|
-
}
|
|
894
|
-
function classifyDocTag(node, kind) {
|
|
895
|
-
classifyOverride(node, kind);
|
|
896
|
-
const token = tokens.get(node.pos - 1); // Get the `@` token
|
|
897
|
-
if (token) {
|
|
898
|
-
token.kind = kind;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
function classify(node, kind) {
|
|
902
|
-
const token = tokens.get(node.pos);
|
|
903
|
-
if (token && token.kind === undefined) {
|
|
904
|
-
token.kind = kind;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
function classifyOverride(node, kind) {
|
|
908
|
-
const token = tokens.get(node.pos);
|
|
909
|
-
if (token) {
|
|
910
|
-
token.kind = kind;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
function classifyReference(node, kind = SemanticTokenKind.Type) {
|
|
914
|
-
switch (node.kind) {
|
|
915
|
-
case SyntaxKind.MemberExpression:
|
|
916
|
-
classifyIdentifier(node.base, SemanticTokenKind.Namespace);
|
|
917
|
-
classifyIdentifier(node.id, kind);
|
|
918
|
-
break;
|
|
919
|
-
case SyntaxKind.ProjectionMemberExpression:
|
|
920
|
-
classifyReference(node.base, SemanticTokenKind.Namespace);
|
|
921
|
-
classifyIdentifier(node.id, kind);
|
|
922
|
-
break;
|
|
923
|
-
case SyntaxKind.TypeReference:
|
|
924
|
-
classifyIdentifier(node.target, kind);
|
|
925
|
-
break;
|
|
926
|
-
case SyntaxKind.Identifier:
|
|
927
|
-
classify(node, kind);
|
|
928
|
-
break;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
function classifyIdentifier(node, kind) {
|
|
932
|
-
if (node.kind === SyntaxKind.Identifier) {
|
|
933
|
-
classify(node, kind);
|
|
934
|
-
}
|
|
935
|
-
}
|
|
545
|
+
return getSemanticTokens(ast);
|
|
936
546
|
}
|
|
937
547
|
async function buildSemanticTokens(params) {
|
|
938
548
|
const builder = new SemanticTokensBuilder();
|
|
939
|
-
const tokens = await
|
|
940
|
-
const file = await compilerHost.readFile(await getPath(params.textDocument));
|
|
549
|
+
const tokens = await getSemanticTokensForDocument(params);
|
|
550
|
+
const file = await compilerHost.readFile(await fileService.getPath(params.textDocument));
|
|
941
551
|
const starts = file.getLineStarts();
|
|
942
552
|
for (const token of tokens) {
|
|
943
553
|
const start = file.getLineAndCharacterOfPosition(token.pos);
|
|
@@ -965,7 +575,7 @@ export function createServer(host) {
|
|
|
965
575
|
return undefined;
|
|
966
576
|
}
|
|
967
577
|
return {
|
|
968
|
-
uri: getURL(location.file.path),
|
|
578
|
+
uri: fileService.getURL(location.file.path),
|
|
969
579
|
range: getRange(location, location.file),
|
|
970
580
|
};
|
|
971
581
|
}
|
|
@@ -1004,123 +614,6 @@ export function createServer(host) {
|
|
|
1004
614
|
diagnostics,
|
|
1005
615
|
});
|
|
1006
616
|
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Determine if the given document is the latest version.
|
|
1009
|
-
*
|
|
1010
|
-
* A document can become out-of-date if a change comes in during an async
|
|
1011
|
-
* operation.
|
|
1012
|
-
*/
|
|
1013
|
-
function upToDate(document) {
|
|
1014
|
-
var _a;
|
|
1015
|
-
if (!("version" in document)) {
|
|
1016
|
-
return true;
|
|
1017
|
-
}
|
|
1018
|
-
return document.version === ((_a = host.getOpenDocumentByURL(document.uri)) === null || _a === void 0 ? void 0 : _a.version);
|
|
1019
|
-
}
|
|
1020
|
-
/**
|
|
1021
|
-
* Infer the appropriate entry point (a.k.a. "main file") for analyzing a
|
|
1022
|
-
* change to the file at the given path. This is necessary because different
|
|
1023
|
-
* results can be obtained from compiling the same file with different entry
|
|
1024
|
-
* points.
|
|
1025
|
-
*
|
|
1026
|
-
* Walk directory structure upwards looking for package.json with tspMain or
|
|
1027
|
-
* main.tsp file. Stop search when reaching a workspace root. If a root is
|
|
1028
|
-
* reached without finding an entry point, use the given path as its own
|
|
1029
|
-
* entry point.
|
|
1030
|
-
*
|
|
1031
|
-
* Untitled documents are always treated as their own entry points as they
|
|
1032
|
-
* do not exist in a directory that could pull them in via another entry
|
|
1033
|
-
* point.
|
|
1034
|
-
*/
|
|
1035
|
-
async function getMainFileForDocument(path) {
|
|
1036
|
-
if (path.startsWith("untitled:")) {
|
|
1037
|
-
return path;
|
|
1038
|
-
}
|
|
1039
|
-
let dir = getDirectoryPath(path);
|
|
1040
|
-
const options = { allowFileNotFound: true };
|
|
1041
|
-
while (true) {
|
|
1042
|
-
let mainFile = "main.tsp";
|
|
1043
|
-
let pkg;
|
|
1044
|
-
const pkgPath = joinPaths(dir, "package.json");
|
|
1045
|
-
const cached = await fileSystemCache.get(pkgPath);
|
|
1046
|
-
if (cached === null || cached === void 0 ? void 0 : cached.data) {
|
|
1047
|
-
pkg = cached.data;
|
|
1048
|
-
}
|
|
1049
|
-
else {
|
|
1050
|
-
[pkg] = await loadFile(compilerHost, pkgPath, JSON.parse, logMainFileSearchDiagnostic, options);
|
|
1051
|
-
await fileSystemCache.setData(pkgPath, pkg !== null && pkg !== void 0 ? pkg : {});
|
|
1052
|
-
}
|
|
1053
|
-
const tspMain = resolveTspMain(pkg);
|
|
1054
|
-
if (typeof tspMain === "string") {
|
|
1055
|
-
mainFile = tspMain;
|
|
1056
|
-
}
|
|
1057
|
-
const candidate = joinPaths(dir, mainFile);
|
|
1058
|
-
const stat = await doIO(() => compilerHost.stat(candidate), candidate, logMainFileSearchDiagnostic, options);
|
|
1059
|
-
if (stat === null || stat === void 0 ? void 0 : stat.isFile()) {
|
|
1060
|
-
return candidate;
|
|
1061
|
-
}
|
|
1062
|
-
const parentDir = getDirectoryPath(dir);
|
|
1063
|
-
if (parentDir === dir) {
|
|
1064
|
-
break;
|
|
1065
|
-
}
|
|
1066
|
-
dir = parentDir;
|
|
1067
|
-
}
|
|
1068
|
-
return path;
|
|
1069
|
-
function logMainFileSearchDiagnostic(diagnostic) {
|
|
1070
|
-
log(`Unexpected diagnostic while looking for main file of ${path}`, formatDiagnostic(diagnostic));
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
async function getPath(document) {
|
|
1074
|
-
if (isUntitled(document.uri)) {
|
|
1075
|
-
return document.uri;
|
|
1076
|
-
}
|
|
1077
|
-
const path = await fileURLToRealPath(document.uri);
|
|
1078
|
-
pathToURLMap.set(path, document.uri);
|
|
1079
|
-
return path;
|
|
1080
|
-
}
|
|
1081
|
-
function getURL(path) {
|
|
1082
|
-
var _a;
|
|
1083
|
-
if (isUntitled(path)) {
|
|
1084
|
-
return path;
|
|
1085
|
-
}
|
|
1086
|
-
return (_a = pathToURLMap.get(path)) !== null && _a !== void 0 ? _a : compilerHost.pathToFileURL(path);
|
|
1087
|
-
}
|
|
1088
|
-
function isUntitled(pathOrUrl) {
|
|
1089
|
-
return pathOrUrl.startsWith("untitled:");
|
|
1090
|
-
}
|
|
1091
|
-
function getOpenDocument(path) {
|
|
1092
|
-
const url = getURL(path);
|
|
1093
|
-
return url ? host.getOpenDocumentByURL(url) : undefined;
|
|
1094
|
-
}
|
|
1095
|
-
async function fileURLToRealPath(url) {
|
|
1096
|
-
return getNormalizedRealPath(compilerHost, compilerHost.fileURLToPath(url));
|
|
1097
|
-
}
|
|
1098
|
-
function createFileSystemCache() {
|
|
1099
|
-
const cache = new Map();
|
|
1100
|
-
let changes = [];
|
|
1101
|
-
return {
|
|
1102
|
-
async get(path) {
|
|
1103
|
-
for (const change of changes) {
|
|
1104
|
-
const path = await fileURLToRealPath(change.uri);
|
|
1105
|
-
cache.delete(path);
|
|
1106
|
-
}
|
|
1107
|
-
changes = [];
|
|
1108
|
-
return cache.get(path);
|
|
1109
|
-
},
|
|
1110
|
-
set(path, entry) {
|
|
1111
|
-
cache.set(path, entry);
|
|
1112
|
-
},
|
|
1113
|
-
async setData(path, data) {
|
|
1114
|
-
const entry = await this.get(path);
|
|
1115
|
-
if (entry) {
|
|
1116
|
-
entry.data = data;
|
|
1117
|
-
}
|
|
1118
|
-
},
|
|
1119
|
-
notify(changes) {
|
|
1120
|
-
changes.push(...changes);
|
|
1121
|
-
},
|
|
1122
|
-
};
|
|
1123
|
-
}
|
|
1124
617
|
function createCompilerHost() {
|
|
1125
618
|
const base = host.compilerHost;
|
|
1126
619
|
return {
|
|
@@ -1131,7 +624,7 @@ export function createServer(host) {
|
|
|
1131
624
|
getSourceFileKind,
|
|
1132
625
|
};
|
|
1133
626
|
async function readFile(path) {
|
|
1134
|
-
const document = getOpenDocument(path);
|
|
627
|
+
const document = fileService.getOpenDocument(path);
|
|
1135
628
|
const cached = await fileSystemCache.get(path);
|
|
1136
629
|
// Try cache
|
|
1137
630
|
if (cached && (!document || document.version === cached.version)) {
|
|
@@ -1165,7 +658,7 @@ export function createServer(host) {
|
|
|
1165
658
|
var _a;
|
|
1166
659
|
// if we have an open document for the path or a cache entry, then we know
|
|
1167
660
|
// it's a file and not a directory and needn't hit the disk.
|
|
1168
|
-
if (getOpenDocument(path) || ((_a = (await fileSystemCache.get(path))) === null || _a === void 0 ? void 0 : _a.type) === "file") {
|
|
661
|
+
if (fileService.getOpenDocument(path) || ((_a = (await fileSystemCache.get(path))) === null || _a === void 0 ? void 0 : _a.type) === "file") {
|
|
1169
662
|
return {
|
|
1170
663
|
isFile() {
|
|
1171
664
|
return true;
|
|
@@ -1178,7 +671,7 @@ export function createServer(host) {
|
|
|
1178
671
|
return await base.stat(path);
|
|
1179
672
|
}
|
|
1180
673
|
function getSourceFileKind(path) {
|
|
1181
|
-
const document = getOpenDocument(path);
|
|
674
|
+
const document = fileService.getOpenDocument(path);
|
|
1182
675
|
if ((document === null || document === void 0 ? void 0 : document.languageId) === "typespec") {
|
|
1183
676
|
return "typespec";
|
|
1184
677
|
}
|