@volar/typescript 1.6.8 → 1.7.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.
- package/out/dtsHost.d.ts +26 -0
- package/out/dtsHost.js +190 -0
- package/out/getProgram.d.ts +1 -1
- package/out/getProgram.js +12 -10
- package/out/index.d.ts +4 -8
- package/out/index.js +18 -285
- package/out/languageService.d.ts +9 -0
- package/out/languageService.js +291 -0
- package/out/languageServiceHost.d.ts +5 -0
- package/out/languageServiceHost.js +218 -0
- package/out/sys.d.ts +7 -0
- package/out/sys.js +322 -0
- package/out/typescript/core.d.ts +83 -0
- package/out/typescript/core.js +320 -0
- package/out/typescript/corePublic.d.ts +91 -0
- package/out/typescript/corePublic.js +51 -0
- package/out/typescript/path.d.ts +112 -0
- package/out/typescript/path.js +417 -0
- package/out/typescript/types.d.ts +129 -0
- package/out/typescript/types.js +3 -0
- package/out/typescript/utilities.d.ts +7 -0
- package/out/typescript/utilities.js +250 -0
- package/package.json +6 -3
package/out/dtsHost.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FileStat, FileType } from '@volar/language-service';
|
|
2
|
+
export interface IDtsHost {
|
|
3
|
+
stat(uri: string): Promise<FileStat | undefined>;
|
|
4
|
+
readFile(fileName: string): Promise<string | undefined>;
|
|
5
|
+
readDirectory(dirName: string): Promise<[string, FileType][]>;
|
|
6
|
+
}
|
|
7
|
+
export declare function createJsDelivrDtsHost(versions?: Record<string, string>, onFetch?: (fileName: string, text: string) => void): DtsHost;
|
|
8
|
+
declare class DtsHost implements IDtsHost {
|
|
9
|
+
private fetchText;
|
|
10
|
+
private flat;
|
|
11
|
+
fetchResults: Map<string, Promise<string | undefined>>;
|
|
12
|
+
flatResults: Map<string, Promise<string[]>>;
|
|
13
|
+
constructor(fetchText: (path: string) => Promise<string | undefined>, flat: (pkg: string) => Promise<string[]>);
|
|
14
|
+
stat(fileName: string): Promise<{
|
|
15
|
+
type: number;
|
|
16
|
+
ctime: number;
|
|
17
|
+
mtime: number;
|
|
18
|
+
size: number;
|
|
19
|
+
} | undefined>;
|
|
20
|
+
readDirectory(dirName: string): Promise<[string, FileType][]>;
|
|
21
|
+
readFile(fileName: string): Promise<string | undefined>;
|
|
22
|
+
fetchFile(fileName: string): Promise<string | undefined>;
|
|
23
|
+
valid(fileName: string): Promise<boolean>;
|
|
24
|
+
}
|
|
25
|
+
export declare function getPackageNameOfDtsPath(path: string): string | undefined;
|
|
26
|
+
export {};
|
package/out/dtsHost.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPackageNameOfDtsPath = exports.createJsDelivrDtsHost = void 0;
|
|
4
|
+
function createJsDelivrDtsHost(versions = {}, onFetch) {
|
|
5
|
+
return new DtsHost(async (fileName) => {
|
|
6
|
+
const requestFileName = resolveRequestFileName(fileName);
|
|
7
|
+
const url = 'https://cdn.jsdelivr.net/npm/' + requestFileName.slice('/node_modules/'.length);
|
|
8
|
+
const text = await fetchText(url);
|
|
9
|
+
if (text !== undefined) {
|
|
10
|
+
onFetch?.(fileName, text);
|
|
11
|
+
}
|
|
12
|
+
return text;
|
|
13
|
+
}, async (pkg) => {
|
|
14
|
+
let version = versions[pkg];
|
|
15
|
+
if (!version) {
|
|
16
|
+
const data = await fetchJson(`https://data.jsdelivr.com/v1/package/resolve/npm/${pkg}@latest`);
|
|
17
|
+
if (data?.version) {
|
|
18
|
+
version = data.version;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!version) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const flat = await fetchJson(`https://data.jsdelivr.com/v1/package/npm/${pkg}@${version}/flat`);
|
|
25
|
+
if (!flat) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
return flat.files.map(file => file.name);
|
|
29
|
+
});
|
|
30
|
+
function resolveRequestFileName(fileName) {
|
|
31
|
+
for (const [key, version] of Object.entries(versions)) {
|
|
32
|
+
if (fileName.startsWith(`/node_modules/${key}/`)) {
|
|
33
|
+
fileName = fileName.replace(`/node_modules/${key}/`, `/node_modules/${key}@${version}/`);
|
|
34
|
+
return fileName;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return fileName;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.createJsDelivrDtsHost = createJsDelivrDtsHost;
|
|
41
|
+
class DtsHost {
|
|
42
|
+
constructor(fetchText, flat) {
|
|
43
|
+
this.fetchText = fetchText;
|
|
44
|
+
this.flat = flat;
|
|
45
|
+
this.fetchResults = new Map();
|
|
46
|
+
this.flatResults = new Map();
|
|
47
|
+
}
|
|
48
|
+
async stat(fileName) {
|
|
49
|
+
if (!await this.valid(fileName)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const pkgName = getPackageNameOfDtsPath(fileName);
|
|
53
|
+
if (!pkgName) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (!this.flatResults.has(pkgName)) {
|
|
57
|
+
this.flatResults.set(pkgName, this.flat(pkgName));
|
|
58
|
+
}
|
|
59
|
+
const flat = await this.flatResults.get(pkgName);
|
|
60
|
+
const filePath = fileName.slice(`/node_modules/${pkgName}`.length);
|
|
61
|
+
if (flat.includes(filePath)) {
|
|
62
|
+
return {
|
|
63
|
+
type: 1,
|
|
64
|
+
ctime: -1,
|
|
65
|
+
mtime: -1,
|
|
66
|
+
size: -1,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
else if (flat.some(f => f.startsWith(filePath + '/'))) {
|
|
70
|
+
return {
|
|
71
|
+
type: 2,
|
|
72
|
+
ctime: -1,
|
|
73
|
+
mtime: -1,
|
|
74
|
+
size: -1,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async readDirectory(dirName) {
|
|
79
|
+
if (!await this.valid(dirName)) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const pkgName = getPackageNameOfDtsPath(dirName);
|
|
83
|
+
if (!pkgName) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
if (!this.flatResults.has(pkgName)) {
|
|
87
|
+
this.flatResults.set(pkgName, this.flat(pkgName));
|
|
88
|
+
}
|
|
89
|
+
const flat = await this.flatResults.get(pkgName);
|
|
90
|
+
const dirPath = dirName.slice(`/node_modules/${pkgName}`.length);
|
|
91
|
+
const files = flat
|
|
92
|
+
.filter(f => f.substring(0, f.lastIndexOf('/')) === dirPath)
|
|
93
|
+
.map(f => f.slice(dirPath.length + 1));
|
|
94
|
+
const dirs = flat
|
|
95
|
+
.filter(f => f.startsWith(dirPath + '/') && f.substring(dirPath.length + 1).split('/').length >= 2)
|
|
96
|
+
.map(f => f.slice(dirPath.length + 1).split('/')[0]);
|
|
97
|
+
return [
|
|
98
|
+
...files.map(f => [f, 1]),
|
|
99
|
+
...[...new Set(dirs)].map(f => [f, 2]),
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
async readFile(fileName) {
|
|
103
|
+
if (!await this.valid(fileName)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (!this.fetchResults.has(fileName)) {
|
|
107
|
+
this.fetchResults.set(fileName, this.fetchFile(fileName));
|
|
108
|
+
}
|
|
109
|
+
return await this.fetchResults.get(fileName);
|
|
110
|
+
}
|
|
111
|
+
async fetchFile(fileName) {
|
|
112
|
+
const pkgName = getPackageNameOfDtsPath(fileName);
|
|
113
|
+
if (!pkgName) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
if ((await this.stat(fileName))?.type !== 1) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return await this.fetchText(fileName);
|
|
120
|
+
}
|
|
121
|
+
async valid(fileName) {
|
|
122
|
+
const pkgName = getPackageNameOfDtsPath(fileName);
|
|
123
|
+
if (!pkgName) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
if (pkgName.indexOf('.') >= 0 || pkgName.endsWith('/node_modules')) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// hard code for known invalid package
|
|
130
|
+
if (pkgName.startsWith('@typescript/') || pkgName.startsWith('@types/typescript__')) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
// don't check @types if original package already having types
|
|
134
|
+
if (pkgName.startsWith('@types/')) {
|
|
135
|
+
let originalPkgName = pkgName.slice('@types/'.length);
|
|
136
|
+
if (originalPkgName.indexOf('__') >= 0) {
|
|
137
|
+
originalPkgName = '@' + originalPkgName.replace('__', '/');
|
|
138
|
+
}
|
|
139
|
+
const packageJson = await this.readFile(`/node_modules/${originalPkgName}/package.json`);
|
|
140
|
+
if (packageJson) {
|
|
141
|
+
const packageJsonObj = JSON.parse(packageJson);
|
|
142
|
+
if (packageJsonObj.types || packageJsonObj.typings) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
const indexDts = await this.stat(`/node_modules/${originalPkgName}/index.d.ts`);
|
|
146
|
+
if (indexDts?.type === 1) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function fetchText(url) {
|
|
155
|
+
try {
|
|
156
|
+
const res = await fetch(url);
|
|
157
|
+
if (res.status === 200) {
|
|
158
|
+
return await res.text();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// ignore
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function fetchJson(url) {
|
|
166
|
+
try {
|
|
167
|
+
const res = await fetch(url);
|
|
168
|
+
if (res.status === 200) {
|
|
169
|
+
return await res.json();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// ignore
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function getPackageNameOfDtsPath(path) {
|
|
177
|
+
if (!path.startsWith('/node_modules/')) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
let pkgName = path.split('/')[2];
|
|
181
|
+
if (pkgName.startsWith('@')) {
|
|
182
|
+
if (path.split('/').length < 4) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
pkgName += '/' + path.split('/')[3];
|
|
186
|
+
}
|
|
187
|
+
return pkgName;
|
|
188
|
+
}
|
|
189
|
+
exports.getPackageNameOfDtsPath = getPackageNameOfDtsPath;
|
|
190
|
+
//# sourceMappingURL=dtsHost.js.map
|
package/out/getProgram.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
2
|
import type * as embedded from '@volar/language-core';
|
|
3
|
-
export declare function getProgram(ts: typeof import('typescript/lib/tsserverlibrary'), core: embedded.LanguageContext, ls: ts.LanguageService): any;
|
|
3
|
+
export declare function getProgram(ts: typeof import('typescript/lib/tsserverlibrary'), core: embedded.LanguageContext, ls: ts.LanguageService, lsHost: ts.LanguageServiceHost): any;
|
package/out/getProgram.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getProgram = void 0;
|
|
4
|
-
function getProgram(ts, core, ls) {
|
|
4
|
+
function getProgram(ts, core, ls, lsHost) {
|
|
5
5
|
const proxy = {
|
|
6
6
|
getRootFileNames,
|
|
7
7
|
emit,
|
|
@@ -34,7 +34,7 @@ function getProgram(ts, core, ls) {
|
|
|
34
34
|
return ls.getProgram();
|
|
35
35
|
}
|
|
36
36
|
function getRootFileNames() {
|
|
37
|
-
return getProgram().getRootFileNames().filter(fileName =>
|
|
37
|
+
return getProgram().getRootFileNames().filter(fileName => lsHost.fileExists?.(fileName));
|
|
38
38
|
}
|
|
39
39
|
// for vue-tsc --noEmit --watch
|
|
40
40
|
function getBindAndCheckDiagnostics(sourceFile, cancellationToken) {
|
|
@@ -63,7 +63,7 @@ function getProgram(ts, core, ls) {
|
|
|
63
63
|
return transformDiagnostics(getProgram().getGlobalDiagnostics(cancellationToken) ?? []);
|
|
64
64
|
}
|
|
65
65
|
function emit(targetSourceFile, _writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) {
|
|
66
|
-
const scriptResult = getProgram().emit(targetSourceFile, (
|
|
66
|
+
const scriptResult = getProgram().emit(targetSourceFile, (lsHost.writeFile ?? ts.sys.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers);
|
|
67
67
|
return {
|
|
68
68
|
emitSkipped: scriptResult.emitSkipped,
|
|
69
69
|
emittedFiles: scriptResult.emittedFiles,
|
|
@@ -79,16 +79,18 @@ function getProgram(ts, core, ls) {
|
|
|
79
79
|
&& diagnostic.length !== undefined) {
|
|
80
80
|
const [virtualFile, source] = core.virtualFiles.getVirtualFile(diagnostic.file.fileName);
|
|
81
81
|
if (virtualFile && source) {
|
|
82
|
-
if (
|
|
82
|
+
if (lsHost.fileExists?.(source.fileName) === false)
|
|
83
83
|
continue;
|
|
84
|
-
for (const [
|
|
85
|
-
if (
|
|
84
|
+
for (const [_, [sourceSnapshot, map]] of core.virtualFiles.getMaps(virtualFile)) {
|
|
85
|
+
if (sourceSnapshot !== source.snapshot)
|
|
86
86
|
continue;
|
|
87
87
|
for (const start of map.toSourceOffsets(diagnostic.start)) {
|
|
88
|
-
|
|
88
|
+
const reportStart = typeof start[1].data.diagnostic === 'object' ? typeof start[1].data.diagnostic.shouldReport() : !!start[1].data.diagnostic;
|
|
89
|
+
if (!reportStart)
|
|
89
90
|
continue;
|
|
90
91
|
for (const end of map.toSourceOffsets(diagnostic.start + diagnostic.length, true)) {
|
|
91
|
-
|
|
92
|
+
const reportEnd = typeof end[1].data.diagnostic === 'object' ? typeof end[1].data.diagnostic.shouldReport() : !!end[1].data.diagnostic;
|
|
93
|
+
if (!reportEnd)
|
|
92
94
|
continue;
|
|
93
95
|
onMapping(diagnostic, source.fileName, start[0], end[0], source.snapshot.getText(0, source.snapshot.getLength()));
|
|
94
96
|
break;
|
|
@@ -98,7 +100,7 @@ function getProgram(ts, core, ls) {
|
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
else {
|
|
101
|
-
if (
|
|
103
|
+
if (lsHost.fileExists?.(diagnostic.file.fileName) === false)
|
|
102
104
|
continue;
|
|
103
105
|
onMapping(diagnostic, diagnostic.file.fileName, diagnostic.start, diagnostic.start + diagnostic.length, diagnostic.file.text);
|
|
104
106
|
}
|
|
@@ -114,7 +116,7 @@ function getProgram(ts, core, ls) {
|
|
|
114
116
|
: undefined;
|
|
115
117
|
if (!file) {
|
|
116
118
|
if (docText === undefined) {
|
|
117
|
-
const snapshot =
|
|
119
|
+
const snapshot = lsHost.getScriptSnapshot(fileName);
|
|
118
120
|
if (snapshot) {
|
|
119
121
|
docText = snapshot.getText(0, snapshot.getLength());
|
|
120
122
|
}
|
package/out/index.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
languageService: ts.LanguageService;
|
|
6
|
-
context: embedded.LanguageContext;
|
|
7
|
-
};
|
|
8
|
-
} & ts.LanguageService;
|
|
1
|
+
export * from './languageService';
|
|
2
|
+
export * from './languageServiceHost';
|
|
3
|
+
export * from './sys';
|
|
4
|
+
export * from './dtsHost';
|
package/out/index.js
CHANGED
|
@@ -1,288 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const core = embedded.createLanguageContext({ typescript: ts }, host, mods);
|
|
8
|
-
if (!ts) {
|
|
9
|
-
throw new Error('TypeScript module not provided.');
|
|
10
|
-
}
|
|
11
|
-
const ls = ts.createLanguageService(core.typescript.languageServiceHost);
|
|
12
|
-
return new Proxy({
|
|
13
|
-
organizeImports,
|
|
14
|
-
// only support for .ts for now, not support for .vue
|
|
15
|
-
getDefinitionAtPosition,
|
|
16
|
-
getDefinitionAndBoundSpan,
|
|
17
|
-
getTypeDefinitionAtPosition,
|
|
18
|
-
getImplementationAtPosition,
|
|
19
|
-
findRenameLocations,
|
|
20
|
-
getReferencesAtPosition,
|
|
21
|
-
findReferences,
|
|
22
|
-
// TODO: now is handled by vue server
|
|
23
|
-
// prepareCallHierarchy: tsLanguageService.rawLs.prepareCallHierarchy,
|
|
24
|
-
// provideCallHierarchyIncomingCalls: tsLanguageService.rawLs.provideCallHierarchyIncomingCalls,
|
|
25
|
-
// provideCallHierarchyOutgoingCalls: tsLanguageService.rawLs.provideCallHierarchyOutgoingCalls,
|
|
26
|
-
// getEditsForFileRename: tsLanguageService.rawLs.getEditsForFileRename,
|
|
27
|
-
// TODO
|
|
28
|
-
// getCodeFixesAtPosition: tsLanguageService.rawLs.getCodeFixesAtPosition,
|
|
29
|
-
// getCombinedCodeFix: tsLanguageService.rawLs.getCombinedCodeFix,
|
|
30
|
-
// applyCodeActionCommand: tsLanguageService.rawLs.applyCodeActionCommand,
|
|
31
|
-
// getApplicableRefactors: tsLanguageService.rawLs.getApplicableRefactors,
|
|
32
|
-
// getEditsForRefactor: tsLanguageService.rawLs.getEditsForRefactor,
|
|
33
|
-
getProgram: () => (0, getProgram_1.getProgram)(ts, core, ls),
|
|
34
|
-
__internal__: {
|
|
35
|
-
context: core,
|
|
36
|
-
languageService: ls,
|
|
37
|
-
},
|
|
38
|
-
}, {
|
|
39
|
-
get: (target, property) => {
|
|
40
|
-
if (property in target) {
|
|
41
|
-
return target[property];
|
|
42
|
-
}
|
|
43
|
-
return ls[property];
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
// apis
|
|
47
|
-
function organizeImports(args, formatOptions, preferences) {
|
|
48
|
-
let edits = [];
|
|
49
|
-
const file = core.virtualFiles.getSource(args.fileName)?.root;
|
|
50
|
-
if (file) {
|
|
51
|
-
embedded.forEachEmbeddedFile(file, embeddedFile => {
|
|
52
|
-
if (embeddedFile.kind === embedded.FileKind.TypeScriptHostFile && embeddedFile.capabilities.codeAction) {
|
|
53
|
-
edits = edits.concat(ls.organizeImports({
|
|
54
|
-
...args,
|
|
55
|
-
fileName: embeddedFile.fileName,
|
|
56
|
-
}, formatOptions, preferences));
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
return ls.organizeImports(args, formatOptions, preferences);
|
|
62
|
-
}
|
|
63
|
-
return edits.map(transformFileTextChanges).filter(notEmpty);
|
|
64
|
-
}
|
|
65
|
-
function getReferencesAtPosition(fileName, position) {
|
|
66
|
-
return findLocations(fileName, position, 'references');
|
|
67
|
-
}
|
|
68
|
-
function getDefinitionAtPosition(fileName, position) {
|
|
69
|
-
return findLocations(fileName, position, 'definition');
|
|
70
|
-
}
|
|
71
|
-
function getTypeDefinitionAtPosition(fileName, position) {
|
|
72
|
-
return findLocations(fileName, position, 'typeDefinition');
|
|
73
|
-
}
|
|
74
|
-
function getImplementationAtPosition(fileName, position) {
|
|
75
|
-
return findLocations(fileName, position, 'implementation');
|
|
76
|
-
}
|
|
77
|
-
function findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename) {
|
|
78
|
-
return findLocations(fileName, position, 'rename', findInStrings, findInComments, providePrefixAndSuffixTextForRename);
|
|
79
|
-
}
|
|
80
|
-
function findLocations(fileName, position, mode, findInStrings = false, findInComments = false, providePrefixAndSuffixTextForRename) {
|
|
81
|
-
const loopChecker = new Set();
|
|
82
|
-
let symbols = [];
|
|
83
|
-
withMirrors(fileName, position);
|
|
84
|
-
return symbols.map(s => transformDocumentSpanLike(s)).filter(notEmpty);
|
|
85
|
-
function withMirrors(fileName, position) {
|
|
86
|
-
if (loopChecker.has(fileName + ':' + position))
|
|
87
|
-
return;
|
|
88
|
-
loopChecker.add(fileName + ':' + position);
|
|
89
|
-
const _symbols = mode === 'definition' ? ls.getDefinitionAtPosition(fileName, position)
|
|
90
|
-
: mode === 'typeDefinition' ? ls.getTypeDefinitionAtPosition(fileName, position)
|
|
91
|
-
: mode === 'references' ? ls.getReferencesAtPosition(fileName, position)
|
|
92
|
-
: mode === 'implementation' ? ls.getImplementationAtPosition(fileName, position)
|
|
93
|
-
: mode === 'rename' ? ls.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename)
|
|
94
|
-
: undefined;
|
|
95
|
-
if (!_symbols)
|
|
96
|
-
return;
|
|
97
|
-
symbols = symbols.concat(_symbols);
|
|
98
|
-
for (const ref of _symbols) {
|
|
99
|
-
loopChecker.add(ref.fileName + ':' + ref.textSpan.start);
|
|
100
|
-
const [virtualFile] = core.virtualFiles.getVirtualFile(ref.fileName);
|
|
101
|
-
if (!virtualFile)
|
|
102
|
-
continue;
|
|
103
|
-
const mirrorMap = core.virtualFiles.getMirrorMap(virtualFile);
|
|
104
|
-
if (!mirrorMap)
|
|
105
|
-
continue;
|
|
106
|
-
for (const [mirrorOffset, data] of mirrorMap.findMirrorOffsets(ref.textSpan.start)) {
|
|
107
|
-
if ((mode === 'definition' || mode === 'typeDefinition' || mode === 'implementation') && !data.definition)
|
|
108
|
-
continue;
|
|
109
|
-
if ((mode === 'references') && !data.references)
|
|
110
|
-
continue;
|
|
111
|
-
if ((mode === 'rename') && !data.rename)
|
|
112
|
-
continue;
|
|
113
|
-
if (loopChecker.has(ref.fileName + ':' + mirrorOffset))
|
|
114
|
-
continue;
|
|
115
|
-
withMirrors(ref.fileName, mirrorOffset);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function getDefinitionAndBoundSpan(fileName, position) {
|
|
121
|
-
const loopChecker = new Set();
|
|
122
|
-
let textSpan;
|
|
123
|
-
let symbols = [];
|
|
124
|
-
withMirrors(fileName, position);
|
|
125
|
-
if (!textSpan)
|
|
126
|
-
return;
|
|
127
|
-
return {
|
|
128
|
-
textSpan: textSpan,
|
|
129
|
-
definitions: symbols?.map(s => transformDocumentSpanLike(s)).filter(notEmpty),
|
|
130
|
-
};
|
|
131
|
-
function withMirrors(fileName, position) {
|
|
132
|
-
if (loopChecker.has(fileName + ':' + position))
|
|
133
|
-
return;
|
|
134
|
-
loopChecker.add(fileName + ':' + position);
|
|
135
|
-
const _symbols = ls.getDefinitionAndBoundSpan(fileName, position);
|
|
136
|
-
if (!_symbols)
|
|
137
|
-
return;
|
|
138
|
-
if (!textSpan) {
|
|
139
|
-
textSpan = _symbols.textSpan;
|
|
140
|
-
}
|
|
141
|
-
if (!_symbols.definitions)
|
|
142
|
-
return;
|
|
143
|
-
symbols = symbols.concat(_symbols.definitions);
|
|
144
|
-
for (const ref of _symbols.definitions) {
|
|
145
|
-
loopChecker.add(ref.fileName + ':' + ref.textSpan.start);
|
|
146
|
-
const [virtualFile] = core.virtualFiles.getVirtualFile(ref.fileName);
|
|
147
|
-
if (!virtualFile)
|
|
148
|
-
continue;
|
|
149
|
-
const mirrorMap = core.virtualFiles.getMirrorMap(virtualFile);
|
|
150
|
-
if (!mirrorMap)
|
|
151
|
-
continue;
|
|
152
|
-
for (const [mirrorOffset, data] of mirrorMap.findMirrorOffsets(ref.textSpan.start)) {
|
|
153
|
-
if (!data.definition)
|
|
154
|
-
continue;
|
|
155
|
-
if (loopChecker.has(ref.fileName + ':' + mirrorOffset))
|
|
156
|
-
continue;
|
|
157
|
-
withMirrors(ref.fileName, mirrorOffset);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function findReferences(fileName, position) {
|
|
163
|
-
const loopChecker = new Set();
|
|
164
|
-
let symbols = [];
|
|
165
|
-
withMirrors(fileName, position);
|
|
166
|
-
return symbols.map(s => transformReferencedSymbol(s)).filter(notEmpty);
|
|
167
|
-
function withMirrors(fileName, position) {
|
|
168
|
-
if (loopChecker.has(fileName + ':' + position))
|
|
169
|
-
return;
|
|
170
|
-
loopChecker.add(fileName + ':' + position);
|
|
171
|
-
const _symbols = ls.findReferences(fileName, position);
|
|
172
|
-
if (!_symbols)
|
|
173
|
-
return;
|
|
174
|
-
symbols = symbols.concat(_symbols);
|
|
175
|
-
for (const symbol of _symbols) {
|
|
176
|
-
for (const ref of symbol.references) {
|
|
177
|
-
loopChecker.add(ref.fileName + ':' + ref.textSpan.start);
|
|
178
|
-
const [virtualFile] = core.virtualFiles.getVirtualFile(ref.fileName);
|
|
179
|
-
if (!virtualFile)
|
|
180
|
-
continue;
|
|
181
|
-
const mirrorMap = core.virtualFiles.getMirrorMap(virtualFile);
|
|
182
|
-
if (!mirrorMap)
|
|
183
|
-
continue;
|
|
184
|
-
for (const [mirrorOffset, data] of mirrorMap.findMirrorOffsets(ref.textSpan.start)) {
|
|
185
|
-
if (!data.references)
|
|
186
|
-
continue;
|
|
187
|
-
if (loopChecker.has(ref.fileName + ':' + mirrorOffset))
|
|
188
|
-
continue;
|
|
189
|
-
withMirrors(ref.fileName, mirrorOffset);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// transforms
|
|
196
|
-
function transformFileTextChanges(changes) {
|
|
197
|
-
const [_, source] = core.virtualFiles.getVirtualFile(changes.fileName);
|
|
198
|
-
if (source) {
|
|
199
|
-
return {
|
|
200
|
-
...changes,
|
|
201
|
-
fileName: source.fileName,
|
|
202
|
-
textChanges: changes.textChanges.map(c => {
|
|
203
|
-
const span = transformSpan(changes.fileName, c.span);
|
|
204
|
-
if (span) {
|
|
205
|
-
return {
|
|
206
|
-
...c,
|
|
207
|
-
span: span.textSpan,
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
}).filter(notEmpty),
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
return changes;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
function transformReferencedSymbol(symbol) {
|
|
218
|
-
const definition = transformDocumentSpanLike(symbol.definition);
|
|
219
|
-
const references = symbol.references.map(r => transformDocumentSpanLike(r)).filter(notEmpty);
|
|
220
|
-
if (definition) {
|
|
221
|
-
return {
|
|
222
|
-
definition,
|
|
223
|
-
references,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
else if (references.length) { // TODO: remove patching
|
|
227
|
-
return {
|
|
228
|
-
definition: {
|
|
229
|
-
...symbol.definition,
|
|
230
|
-
fileName: references[0].fileName,
|
|
231
|
-
textSpan: references[0].textSpan,
|
|
232
|
-
},
|
|
233
|
-
references,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
function transformDocumentSpanLike(documentSpan) {
|
|
238
|
-
const textSpan = transformSpan(documentSpan.fileName, documentSpan.textSpan);
|
|
239
|
-
if (!textSpan)
|
|
240
|
-
return;
|
|
241
|
-
const contextSpan = transformSpan(documentSpan.fileName, documentSpan.contextSpan);
|
|
242
|
-
const originalTextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalTextSpan);
|
|
243
|
-
const originalContextSpan = transformSpan(documentSpan.originalFileName, documentSpan.originalContextSpan);
|
|
244
|
-
return {
|
|
245
|
-
...documentSpan,
|
|
246
|
-
fileName: textSpan.fileName,
|
|
247
|
-
textSpan: textSpan.textSpan,
|
|
248
|
-
contextSpan: contextSpan?.textSpan,
|
|
249
|
-
originalFileName: originalTextSpan?.fileName,
|
|
250
|
-
originalTextSpan: originalTextSpan?.textSpan,
|
|
251
|
-
originalContextSpan: originalContextSpan?.textSpan,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
function transformSpan(fileName, textSpan) {
|
|
255
|
-
if (!fileName)
|
|
256
|
-
return;
|
|
257
|
-
if (!textSpan)
|
|
258
|
-
return;
|
|
259
|
-
const [virtualFile, source] = core.virtualFiles.getVirtualFile(fileName);
|
|
260
|
-
if (virtualFile && source) {
|
|
261
|
-
for (const [sourceFileName, map] of core.virtualFiles.getMaps(virtualFile)) {
|
|
262
|
-
if (source.fileName !== sourceFileName)
|
|
263
|
-
continue;
|
|
264
|
-
const sourceLoc = map.toSourceOffset(textSpan.start);
|
|
265
|
-
if (sourceLoc) {
|
|
266
|
-
return {
|
|
267
|
-
fileName: source.fileName,
|
|
268
|
-
textSpan: {
|
|
269
|
-
start: sourceLoc[0],
|
|
270
|
-
length: textSpan.length,
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
return {
|
|
278
|
-
fileName,
|
|
279
|
-
textSpan,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
exports.createLanguageService = createLanguageService;
|
|
285
|
-
function notEmpty(value) {
|
|
286
|
-
return value !== null && value !== undefined;
|
|
287
|
-
}
|
|
17
|
+
__exportStar(require("./languageService"), exports);
|
|
18
|
+
__exportStar(require("./languageServiceHost"), exports);
|
|
19
|
+
__exportStar(require("./sys"), exports);
|
|
20
|
+
__exportStar(require("./dtsHost"), exports);
|
|
288
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LanguageContext } from '@volar/language-core';
|
|
2
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
|
+
export declare function createLanguageService(core: LanguageContext, ts: typeof import('typescript/lib/tsserverlibrary'), sys: ts.System): {
|
|
4
|
+
__internal__: {
|
|
5
|
+
languageServiceHost: ts.LanguageServiceHost;
|
|
6
|
+
languageService: ts.LanguageService;
|
|
7
|
+
context: LanguageContext;
|
|
8
|
+
};
|
|
9
|
+
} & ts.LanguageService;
|