@@ -6,34 +6,34 @@ import { debugAssertIsNonNull } from "./utils/asserts.js";
66// are identical. Ditto `lintFile` and `lintFileWrapper`.
77let loadPlugin : typeof loadPluginWrapper | null = null ;
88let lintFile : typeof lintFileWrapper | null = null ;
9+ let createWorkspace : typeof createWorkspaceWrapper | null = null ;
10+ let destroyWorkspace : typeof destroyWorkspaceWrapper | null = null ;
911
1012/**
1113 * Load a plugin.
1214 *
13- * Lazy-loads plugins code on first call, so that overhead is skipped if user doesn't use JS plugins .
15+ * Delegates to `loadPlugin`, which was lazy-loaded by `createWorkspaceWrapper` .
1416 *
17+ * @param workspaceDir - Workspace root directory
1518 * @param path - Absolute path of plugin file
1619 * @param packageName - Optional package name from `package.json` (fallback if `plugin.meta.name` is not defined)
1720 * @returns Plugin details or error serialized to JSON string
1821 */
19- function loadPluginWrapper ( path : string , packageName : string | null ) : Promise < string > {
20- if ( loadPlugin === null ) {
21- // Use promises here instead of making `loadPluginWrapper` an async function,
22- // to avoid a micro-tick and extra wrapper `Promise` in all later calls to `loadPluginWrapper`
23- return import ( "./plugins/index.js" ) . then ( ( mod ) => {
24- ( { loadPlugin, lintFile } = mod ) ;
25- return loadPlugin ( path , packageName ) ;
26- } ) ;
27- }
22+ function loadPluginWrapper (
23+ workspaceDir : string ,
24+ path : string ,
25+ packageName : string | null ,
26+ ) : Promise < string > {
2827 debugAssertIsNonNull ( loadPlugin ) ;
29- return loadPlugin ( path , packageName ) ;
28+ return loadPlugin ( workspaceDir , path , packageName ) ;
3029}
3130
3231/**
3332 * Lint a file.
3433 *
35- * Delegates to `lintFile`, which was lazy-loaded by `loadPluginWrapper `.
34+ * Delegates to `lintFile`, which was lazy-loaded by `createWorkspaceWrapper `.
3635 *
36+ * @param workspaceDir - Directory of the workspace
3737 * @param filePath - Absolute path of file being linted
3838 * @param bufferId - ID of buffer containing file data
3939 * @param buffer - Buffer containing file data, or `null` if buffer with this ID was previously sent to JS
@@ -42,23 +42,64 @@ function loadPluginWrapper(path: string, packageName: string | null): Promise<st
4242 * @returns Diagnostics or error serialized to JSON string
4343 */
4444function lintFileWrapper (
45+ rootDir : string ,
4546 filePath : string ,
4647 bufferId : number ,
4748 buffer : Uint8Array | null ,
4849 ruleIds : number [ ] ,
4950 settingsJSON : string ,
5051) : string {
51- // `lintFileWrapper` is never called without `loadPluginWrapper ` being called first,
52+ // `lintFileWrapper` is never called without `createWorkspaceWrapper ` being called first,
5253 // so `lintFile` must be defined here
5354 debugAssertIsNonNull ( lintFile ) ;
54- return lintFile ( filePath , bufferId , buffer , ruleIds , settingsJSON ) ;
55+ return lintFile ( rootDir , filePath , bufferId , buffer , ruleIds , settingsJSON ) ;
56+ }
57+
58+ /**
59+ * Create a new workspace.
60+ *
61+ * Lazy-loads workspace code on first call, so that overhead is skipped if user doesn't use JS plugins.
62+ *
63+ * @param rootDir - Root directory of the workspace
64+ * @returns Promise that resolves when workspace is created
65+ */
66+ function createWorkspaceWrapper ( rootDir : string ) : Promise < undefined > {
67+ if ( createWorkspace === null ) {
68+ // Use promises here instead of making `createWorkspaceWrapper` an async function,
69+ // to avoid a micro-tick and extra wrapper `Promise` in all later calls to `createWorkspaceWrapper`
70+ return import ( "./plugins/index.js" ) . then ( ( mod ) => {
71+ ( { loadPlugin, lintFile, createWorkspace, destroyWorkspace } = mod ) ;
72+ return createWorkspace ( rootDir ) ;
73+ } ) ;
74+ }
75+
76+ debugAssertIsNonNull ( createWorkspace ) ;
77+ return Promise . resolve ( createWorkspace ( rootDir ) ) ;
78+ }
79+
80+ /**
81+ * Destroy a workspace.
82+ *
83+ * @param rootDir - Root directory of the workspace
84+ */
85+ function destroyWorkspaceWrapper ( rootDir : string ) : void {
86+ // `destroyWorkspaceWrapper` is never called without `createWorkspaceWrapper` being called first,
87+ // so `destroyWorkspace` must be defined here
88+ debugAssertIsNonNull ( destroyWorkspace ) ;
89+ destroyWorkspace ( rootDir ) ;
5590}
5691
5792// Get command line arguments, skipping first 2 (node binary and script path)
5893const args = process . argv . slice ( 2 ) ;
5994
60- // Call Rust, passing `loadPlugin` and `lintFile` as callbacks, and CLI arguments
61- const success = await lint ( args , loadPluginWrapper , lintFileWrapper ) ;
95+ // Call Rust, passing `loadPlugin`, `lintFile`, `createWorkspace` and `destroyWorkspace` as callbacks, and CLI arguments
96+ const success = await lint (
97+ args ,
98+ loadPluginWrapper ,
99+ lintFileWrapper ,
100+ createWorkspaceWrapper ,
101+ destroyWorkspaceWrapper ,
102+ ) ;
62103
63104// Note: It's recommended to set `process.exitCode` instead of calling `process.exit()`.
64105// `process.exit()` kills the process immediately and `stdout` may not be flushed before process dies.
0 commit comments