@astrojs/ts-plugin 0.2.1 → 0.4.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/.turbo/turbo-build.log +5 -2
- package/CHANGELOG.md +16 -0
- package/LICENSE +36 -0
- package/README.md +1 -1
- package/dist/astro-snapshots.js +48 -47
- package/dist/astro-sys.js +22 -35
- package/dist/astro2tsx.js +17 -41
- package/dist/index.js +38 -39
- package/dist/language-service/completions.js +42 -42
- package/dist/language-service/definition.js +22 -40
- package/dist/language-service/diagnostics.js +15 -18
- package/dist/language-service/file-references.js +52 -0
- package/dist/language-service/find-references.js +20 -38
- package/dist/language-service/implementation.js +18 -37
- package/dist/language-service/index.js +26 -42
- package/dist/language-service/line-column-offset.js +44 -0
- package/dist/language-service/rename.js +24 -37
- package/dist/logger.js +18 -5
- package/dist/module-loader.js +28 -22
- package/dist/project-astro-files.js +125 -0
- package/dist/utils.js +34 -19
- package/dist/workers/TSXService.js +39 -0
- package/dist/workers/TSXWorker.js +9 -0
- package/package.json +36 -27
- package/src/astro-snapshots.ts +270 -291
- package/src/astro-sys.ts +22 -22
- package/src/astro2tsx.ts +5 -50
- package/src/index.ts +49 -60
- package/src/language-service/completions.ts +56 -64
- package/src/language-service/definition.ts +35 -42
- package/src/language-service/diagnostics.ts +32 -33
- package/src/language-service/file-references.ts +31 -0
- package/src/language-service/find-references.ts +67 -76
- package/src/language-service/implementation.ts +27 -34
- package/src/language-service/index.ts +17 -32
- package/src/language-service/line-column-offset.ts +21 -0
- package/src/language-service/rename.ts +38 -48
- package/src/logger.ts +32 -36
- package/src/module-loader.ts +124 -124
- package/src/project-astro-files.ts +130 -0
- package/src/utils.ts +54 -45
- package/src/workers/TSXService.ts +11 -0
- package/src/workers/TSXWorker.ts +8 -0
- package/test/fixtures/MyAstroComponent.astro +5 -0
- package/test/fixtures/script.ts +9 -0
- package/test/fixtures/tsconfig.json +3 -0
- package/test/runTest.js +41 -0
- package/test/suite/extension.test.js +68 -0
- package/test/suite/index.js +38 -0
- package/test/tsconfig.json +14 -0
- package/test/utils.js +65 -0
- package/tsconfig.json +2 -1
- package/dist/source-mapper.js +0 -114
- package/src/source-mapper.ts +0 -123
package/src/module-loader.ts
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
import type ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
-
import {
|
|
3
|
-
import { AstroSnapshotManager } from './astro-snapshots.js';
|
|
2
|
+
import type { AstroSnapshotManager } from './astro-snapshots.js';
|
|
4
3
|
import { createAstroSys } from './astro-sys.js';
|
|
4
|
+
import type { Logger } from './logger.js';
|
|
5
5
|
import { ensureRealAstroFilePath, isVirtualAstroFilePath } from './utils.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Caches resolved modules.
|
|
9
9
|
*/
|
|
10
10
|
class ModuleResolutionCache {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
11
|
+
private cache = new Map<string, ts.ResolvedModule>();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Tries to get a cached module.
|
|
15
|
+
*/
|
|
16
|
+
get(moduleName: string, containingFile: string): ts.ResolvedModule | undefined {
|
|
17
|
+
return this.cache.get(this.getKey(moduleName, containingFile));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Caches resolved module, if it is not undefined.
|
|
22
|
+
*/
|
|
23
|
+
set(moduleName: string, containingFile: string, resolvedModule: ts.ResolvedModule | undefined) {
|
|
24
|
+
if (!resolvedModule) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.cache.set(this.getKey(moduleName, containingFile), resolvedModule);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Deletes module from cache. Call this if a file was deleted.
|
|
32
|
+
* @param resolvedModuleName full path of the module
|
|
33
|
+
*/
|
|
34
|
+
delete(resolvedModuleName: string): void {
|
|
35
|
+
this.cache.forEach((val, key) => {
|
|
36
|
+
if (val.resolvedFileName === resolvedModuleName) {
|
|
37
|
+
this.cache.delete(key);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private getKey(moduleName: string, containingFile: string) {
|
|
43
|
+
return containingFile + ':::' + ensureRealAstroFilePath(moduleName);
|
|
44
|
+
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -54,92 +54,92 @@ class ModuleResolutionCache {
|
|
|
54
54
|
* In order to fix this, we need to wrap typescript's module resolution and reroute all `.astro.ts` file lookups to .astro.
|
|
55
55
|
*/
|
|
56
56
|
export function patchModuleLoader(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
logger: Logger,
|
|
58
|
+
snapshotManager: AstroSnapshotManager,
|
|
59
|
+
typescript: typeof ts,
|
|
60
|
+
lsHost: ts.LanguageServiceHost,
|
|
61
|
+
project: ts.server.Project
|
|
62
62
|
): void {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
63
|
+
const astroSys = createAstroSys(logger);
|
|
64
|
+
const moduleCache = new ModuleResolutionCache();
|
|
65
|
+
const origResolveModuleNames = lsHost.resolveModuleNames?.bind(lsHost);
|
|
66
|
+
|
|
67
|
+
lsHost.resolveModuleNames = resolveModuleNames;
|
|
68
|
+
|
|
69
|
+
const origRemoveFile = project.removeFile.bind(project);
|
|
70
|
+
project.removeFile = (info, fileExists, detachFromProject) => {
|
|
71
|
+
logger.log('File is being removed. Delete from cache: ', info.fileName);
|
|
72
|
+
moduleCache.delete(info.fileName);
|
|
73
|
+
return origRemoveFile(info, fileExists, detachFromProject);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Patch readDirectory so we get completions for .astro files
|
|
77
|
+
const origReadDirectory = project.readDirectory.bind(project);
|
|
78
|
+
project.readDirectory = (path, extensions, exclude, include, depth) => {
|
|
79
|
+
const extensionsWithAstro = (extensions ?? []).concat('.astro', '.md', '.mdx');
|
|
80
|
+
return origReadDirectory(path, extensionsWithAstro, exclude, include, depth);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
function resolveModuleNames(
|
|
84
|
+
moduleNames: string[],
|
|
85
|
+
containingFile: string,
|
|
86
|
+
reusedNames: string[] | undefined,
|
|
87
|
+
redirectedReference: ts.ResolvedProjectReference | undefined,
|
|
88
|
+
compilerOptions: ts.CompilerOptions
|
|
89
|
+
): Array<ts.ResolvedModule | undefined> {
|
|
90
|
+
// logger.log('Resolving modules names for ' + containingFile);
|
|
91
|
+
|
|
92
|
+
// Try resolving all module names with the original method first.
|
|
93
|
+
// The ones that are undefined will be re-checked if they are a
|
|
94
|
+
// astro file and if so, are resolved, too. This way we can defer
|
|
95
|
+
// all module resolving logic except for astro files to TypeScript.
|
|
96
|
+
const resolved =
|
|
97
|
+
origResolveModuleNames?.(moduleNames, containingFile, reusedNames, redirectedReference, compilerOptions) ||
|
|
98
|
+
Array.from<undefined>(Array(moduleNames.length));
|
|
99
|
+
|
|
100
|
+
return resolved.map((moduleName, idx) => {
|
|
101
|
+
const fileName = moduleNames[idx];
|
|
102
|
+
if (moduleName || !ensureRealAstroFilePath(fileName).endsWith('.astro')) {
|
|
103
|
+
return moduleName;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const cachedModule = moduleCache.get(fileName, containingFile);
|
|
107
|
+
if (cachedModule) {
|
|
108
|
+
return cachedModule;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const resolvedModule = resolveModuleName(fileName, containingFile, compilerOptions);
|
|
112
|
+
moduleCache.set(fileName, containingFile, resolvedModule);
|
|
113
|
+
return resolvedModule;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function resolveModuleName(
|
|
118
|
+
name: string,
|
|
119
|
+
containingFile: string,
|
|
120
|
+
compilerOptions: ts.CompilerOptions
|
|
121
|
+
): ts.ResolvedModule | undefined {
|
|
122
|
+
const astroResolvedModule = typescript.resolveModuleName(
|
|
123
|
+
name,
|
|
124
|
+
containingFile,
|
|
125
|
+
compilerOptions,
|
|
126
|
+
astroSys
|
|
127
|
+
).resolvedModule;
|
|
128
|
+
if (!astroResolvedModule || !isVirtualAstroFilePath(astroResolvedModule.resolvedFileName)) {
|
|
129
|
+
return astroResolvedModule;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const resolvedFileName = ensureRealAstroFilePath(astroResolvedModule.resolvedFileName);
|
|
133
|
+
logger.log('Resolved', name, 'to astro file', resolvedFileName);
|
|
134
|
+
const snapshot = snapshotManager.create(resolvedFileName);
|
|
135
|
+
if (!snapshot) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const resolvedAstroModule: ts.ResolvedModuleFull = {
|
|
140
|
+
extension: typescript.Extension.Tsx,
|
|
141
|
+
resolvedFileName,
|
|
142
|
+
};
|
|
143
|
+
return resolvedAstroModule;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import type { AstroSnapshotManager } from './astro-snapshots';
|
|
3
|
+
import { getConfigPathForProject, isAstroFilePath, readProjectAstroFilesFromFs } from './utils';
|
|
4
|
+
|
|
5
|
+
export class ProjectAstroFilesManager {
|
|
6
|
+
private files = new Set<string>();
|
|
7
|
+
private directoryWatchers = new Set<ts.FileWatcher>();
|
|
8
|
+
|
|
9
|
+
private static instances = new Map<string, ProjectAstroFilesManager>();
|
|
10
|
+
|
|
11
|
+
static getInstance(projectName: string) {
|
|
12
|
+
return this.instances.get(projectName);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
private readonly typescript: typeof ts,
|
|
17
|
+
private readonly project: ts.server.Project,
|
|
18
|
+
private readonly serverHost: ts.server.ServerHost,
|
|
19
|
+
private readonly snapshotManager: AstroSnapshotManager,
|
|
20
|
+
private parsedCommandLine: ts.ParsedCommandLine
|
|
21
|
+
) {
|
|
22
|
+
this.setupWatchers();
|
|
23
|
+
this.updateProjectAstroFiles();
|
|
24
|
+
|
|
25
|
+
ProjectAstroFilesManager.instances.set(project.getProjectName(), this);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
updateProjectConfig(serviceHost: ts.LanguageServiceHost) {
|
|
29
|
+
const parsedCommandLine = serviceHost.getParsedCommandLine?.(getConfigPathForProject(this.project));
|
|
30
|
+
|
|
31
|
+
if (!parsedCommandLine) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.disposeWatchersAndFiles();
|
|
36
|
+
this.parsedCommandLine = parsedCommandLine;
|
|
37
|
+
this.setupWatchers();
|
|
38
|
+
this.updateProjectAstroFiles();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getFiles() {
|
|
42
|
+
return Array.from(this.files);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create directory watcher for include and exclude
|
|
47
|
+
* The watcher in tsserver doesn't support astro file
|
|
48
|
+
* It won't add new created astro file to root
|
|
49
|
+
*/
|
|
50
|
+
private setupWatchers() {
|
|
51
|
+
for (const directory in this.parsedCommandLine.wildcardDirectories) {
|
|
52
|
+
if (!Object.prototype.hasOwnProperty.call(this.parsedCommandLine.wildcardDirectories, directory)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const watchDirectoryFlags = this.parsedCommandLine.wildcardDirectories[directory];
|
|
57
|
+
const watcher = this.serverHost.watchDirectory(
|
|
58
|
+
directory,
|
|
59
|
+
this.watcherCallback.bind(this),
|
|
60
|
+
watchDirectoryFlags === this.typescript.WatchDirectoryFlags.Recursive,
|
|
61
|
+
this.parsedCommandLine.watchOptions
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
this.directoryWatchers.add(watcher);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private watcherCallback(fileName: string) {
|
|
69
|
+
if (!isAstroFilePath(fileName)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// We can't just add the file to the project directly, because
|
|
74
|
+
// - the casing of fileName is different
|
|
75
|
+
// - we don't know whether the file was added or deleted
|
|
76
|
+
this.updateProjectAstroFiles();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private updateProjectAstroFiles() {
|
|
80
|
+
const fileNamesAfter = readProjectAstroFilesFromFs(this.typescript, this.project, this.parsedCommandLine);
|
|
81
|
+
const removedFiles = new Set(...this.files);
|
|
82
|
+
const newFiles = fileNamesAfter.filter((fileName) => {
|
|
83
|
+
const has = this.files.has(fileName);
|
|
84
|
+
if (has) {
|
|
85
|
+
removedFiles.delete(fileName);
|
|
86
|
+
}
|
|
87
|
+
return !has;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
for (const newFile of newFiles) {
|
|
91
|
+
this.addFileToProject(newFile);
|
|
92
|
+
this.files.add(newFile);
|
|
93
|
+
}
|
|
94
|
+
for (const removedFile of removedFiles) {
|
|
95
|
+
this.removeFileFromProject(removedFile, false);
|
|
96
|
+
this.files.delete(removedFile);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private addFileToProject(newFile: string) {
|
|
101
|
+
this.snapshotManager.create(newFile);
|
|
102
|
+
const snapshot = this.project.projectService.getScriptInfo(newFile);
|
|
103
|
+
|
|
104
|
+
if (snapshot) {
|
|
105
|
+
this.project.addRoot(snapshot);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private removeFileFromProject(file: string, exists = true) {
|
|
110
|
+
const info = this.project.getScriptInfo(file);
|
|
111
|
+
|
|
112
|
+
if (info) {
|
|
113
|
+
this.project.removeFile(info, exists, true);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private disposeWatchersAndFiles() {
|
|
118
|
+
this.directoryWatchers.forEach((watcher) => watcher.close());
|
|
119
|
+
this.directoryWatchers.clear();
|
|
120
|
+
|
|
121
|
+
this.files.forEach((file) => this.removeFileFromProject(file));
|
|
122
|
+
this.files.clear();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
dispose() {
|
|
126
|
+
this.disposeWatchersAndFiles();
|
|
127
|
+
|
|
128
|
+
ProjectAstroFilesManager.instances.delete(this.project.getProjectName());
|
|
129
|
+
}
|
|
130
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -1,66 +1,75 @@
|
|
|
1
1
|
export function isAstroFilePath(filePath: string) {
|
|
2
|
-
|
|
2
|
+
return filePath.endsWith('.astro');
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function isVirtualAstroFilePath(filePath: string) {
|
|
6
|
-
|
|
6
|
+
return filePath.endsWith('.astro.ts');
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function toRealAstroFilePath(filePath: string) {
|
|
10
|
-
|
|
10
|
+
return filePath.slice(0, -'.ts'.length);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function ensureRealAstroFilePath(filePath: string) {
|
|
14
|
-
|
|
14
|
+
return isVirtualAstroFilePath(filePath) ? toRealAstroFilePath(filePath) : filePath;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function isNotNullOrUndefined<T>(val: T | undefined | null): val is T {
|
|
18
|
-
|
|
18
|
+
return val !== undefined && val !== null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
* Replace all occurrences of a string within an object with another string,
|
|
23
|
+
*/
|
|
24
|
+
export function replaceDeep<T extends Record<string, any>>(
|
|
25
|
+
obj: T,
|
|
26
|
+
searchStr: string | RegExp,
|
|
27
|
+
replacementStr: string
|
|
28
|
+
): T {
|
|
29
|
+
return _replaceDeep(obj);
|
|
30
|
+
|
|
31
|
+
function _replaceDeep(_obj: any): any {
|
|
32
|
+
if (typeof _obj === 'string') {
|
|
33
|
+
return _obj.replace(searchStr, replacementStr);
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(_obj)) {
|
|
36
|
+
return _obj.map((entry) => _replaceDeep(entry));
|
|
37
|
+
}
|
|
38
|
+
if (typeof _obj === 'object') {
|
|
39
|
+
return Object.keys(_obj).reduce((_o, key) => {
|
|
40
|
+
_o[key] = _replaceDeep(_obj[key]);
|
|
41
|
+
return _o;
|
|
42
|
+
}, {} as any);
|
|
43
|
+
}
|
|
44
|
+
return _obj;
|
|
45
|
+
}
|
|
31
46
|
}
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return !isInGeneratedCode(text, span.start, span.start + span.length);
|
|
48
|
+
export function getConfigPathForProject(project: ts.server.Project) {
|
|
49
|
+
return (
|
|
50
|
+
(project as ts.server.ConfiguredProject).canonicalConfigFilePath ??
|
|
51
|
+
(project.getCompilerOptions() as any).configFilePath
|
|
52
|
+
);
|
|
39
53
|
}
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
export function readProjectAstroFilesFromFs(
|
|
56
|
+
ts: typeof import('typescript/lib/tsserverlibrary'),
|
|
57
|
+
project: ts.server.Project,
|
|
58
|
+
parsedCommandLine: ts.ParsedCommandLine
|
|
59
|
+
) {
|
|
60
|
+
const fileSpec: TsFilesSpec = parsedCommandLine.raw;
|
|
61
|
+
const { include, exclude } = fileSpec;
|
|
62
|
+
|
|
63
|
+
if (include?.length === 0) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
_o[key] = _replaceDeep(_obj[key]);
|
|
61
|
-
return _o;
|
|
62
|
-
}, {} as any);
|
|
63
|
-
}
|
|
64
|
-
return _obj;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
+
return ts.sys
|
|
68
|
+
.readDirectory(project.getCurrentDirectory() || process.cwd(), ['.astro'], exclude, include)
|
|
69
|
+
.map(ts.server.toNormalizedPath);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface TsFilesSpec {
|
|
73
|
+
include?: readonly string[];
|
|
74
|
+
exclude?: readonly string[];
|
|
75
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TSXResult } from '@astrojs/compiler/shared/types';
|
|
2
|
+
import { createSyncFn } from 'synckit';
|
|
3
|
+
|
|
4
|
+
const convertToTSXSync = createSyncFn(require.resolve('./TSXWorker'));
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parse code by `@astrojs/compiler`
|
|
8
|
+
*/
|
|
9
|
+
export function convertToTSX(source: string, options: { sourcefile: string }): TSXResult {
|
|
10
|
+
return convertToTSXSync(source, options);
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { runAsWorker } from 'synckit';
|
|
2
|
+
|
|
3
|
+
const dynamicImport = new Function('m', 'return import(m)');
|
|
4
|
+
runAsWorker(async (source: string, options: { sourcefile: string }) => {
|
|
5
|
+
const { convertToTSX } = await dynamicImport('@astrojs/compiler');
|
|
6
|
+
const result: any = convertToTSX(source, options);
|
|
7
|
+
return result;
|
|
8
|
+
});
|
package/test/runTest.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { runTests } = require('@vscode/test-electron');
|
|
3
|
+
const { downloadDirToExecutablePath } = require('./utils');
|
|
4
|
+
const { existsSync, readdirSync } = require('fs');
|
|
5
|
+
|
|
6
|
+
async function main() {
|
|
7
|
+
try {
|
|
8
|
+
// The folder containing the Extension Manifest package.json
|
|
9
|
+
// Passed to `--extensionDevelopmentPath`
|
|
10
|
+
const extensionDevelopmentPath = path.resolve(__dirname, '../../vscode');
|
|
11
|
+
|
|
12
|
+
// The path to the extension test script
|
|
13
|
+
// Passed to --extensionTestsPath
|
|
14
|
+
const extensionTestsPath = path.resolve(__dirname, './suite/index.js');
|
|
15
|
+
|
|
16
|
+
// If there's already a downloaded version of VS Code, let's use it
|
|
17
|
+
const vscodeTestPath = path.resolve(__dirname, '../../vscode/.vscode-test');
|
|
18
|
+
let vsPath = undefined;
|
|
19
|
+
if (existsSync(vscodeTestPath)) {
|
|
20
|
+
const files = readdirSync(vscodeTestPath);
|
|
21
|
+
files.forEach((file) => {
|
|
22
|
+
if (file.startsWith('vscode-')) {
|
|
23
|
+
vsPath = downloadDirToExecutablePath(path.resolve(__dirname, '../../vscode/.vscode-test/', file));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
await runTests({
|
|
30
|
+
extensionDevelopmentPath,
|
|
31
|
+
extensionTestsPath,
|
|
32
|
+
vscodeExecutablePath: vsPath,
|
|
33
|
+
launchArgs: ['./fixtures/fixtures.code-workspace'],
|
|
34
|
+
});
|
|
35
|
+
} catch (err) {
|
|
36
|
+
console.error('Failed to run tests');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
main();
|