@@ -6,34 +6,42 @@ 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 *
1315 * Lazy-loads plugins code on first call, so that overhead is skipped if user doesn't use JS plugins.
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 > {
22+ function loadPluginWrapper (
23+ workspaceDir : string ,
24+ path : string ,
25+ packageName : string | null ,
26+ ) : Promise < string > {
2027 if ( loadPlugin === null ) {
2128 // Use promises here instead of making `loadPluginWrapper` an async function,
2229 // to avoid a micro-tick and extra wrapper `Promise` in all later calls to `loadPluginWrapper`
2330 return import ( "./plugins/index.js" ) . then ( ( mod ) => {
24- ( { loadPlugin, lintFile } = mod ) ;
25- return loadPlugin ( path , packageName ) ;
31+ ( { loadPlugin, lintFile, createWorkspace , destroyWorkspace } = mod ) ;
32+ return loadPlugin ( workspaceDir , path , packageName ) ;
2633 } ) ;
2734 }
2835 debugAssertIsNonNull ( loadPlugin ) ;
29- return loadPlugin ( path , packageName ) ;
36+ return loadPlugin ( workspaceDir , path , packageName ) ;
3037}
3138
3239/**
3340 * Lint a file.
3441 *
3542 * Delegates to `lintFile`, which was lazy-loaded by `loadPluginWrapper`.
3643 *
44+ * @param workspaceDir - Directory of the workspace
3745 * @param filePath - Absolute path of file being linted
3846 * @param bufferId - ID of buffer containing file data
3947 * @param buffer - Buffer containing file data, or `null` if buffer with this ID was previously sent to JS
@@ -42,6 +50,7 @@ function loadPluginWrapper(path: string, packageName: string | null): Promise<st
4250 * @returns Diagnostics or error serialized to JSON string
4351 */
4452function lintFileWrapper (
53+ rootDir : string ,
4554 filePath : string ,
4655 bufferId : number ,
4756 buffer : Uint8Array | null ,
@@ -51,14 +60,54 @@ function lintFileWrapper(
5160 // `lintFileWrapper` is never called without `loadPluginWrapper` being called first,
5261 // so `lintFile` must be defined here
5362 debugAssertIsNonNull ( lintFile ) ;
54- return lintFile ( filePath , bufferId , buffer , ruleIds , settingsJSON ) ;
63+ return lintFile ( rootDir , filePath , bufferId , buffer , ruleIds , settingsJSON ) ;
64+ }
65+
66+ /**
67+ * Create a new workspace.
68+ *
69+ * Delegates to `createWorkspace`, which was lazy-loaded by `createWorkspaceWrapper`.
70+ *
71+ * @param rootDir - Root directory of the workspace
72+ * @returns Promise that resolves when workspace is created
73+ */
74+ function createWorkspaceWrapper ( rootDir : string ) : Promise < undefined > {
75+ if ( createWorkspace === null ) {
76+ // Use promises here instead of making `createWorkspaceWrapper` an async function,
77+ // to avoid a micro-tick and extra wrapper `Promise` in all later calls to `createWorkspaceWrapper`
78+ return import ( "./plugins/index.js" ) . then ( ( mod ) => {
79+ ( { loadPlugin, lintFile, createWorkspace, destroyWorkspace } = mod ) ;
80+ return createWorkspace ( rootDir ) ;
81+ } ) ;
82+ }
83+
84+ debugAssertIsNonNull ( createWorkspace ) ;
85+ return Promise . resolve ( createWorkspace ( rootDir ) ) ;
86+ }
87+
88+ /**
89+ * Destroy a workspace.
90+ *
91+ * @param rootDir - Root directory of the workspace
92+ */
93+ function destroyWorkspaceWrapper ( rootDir : string ) : void {
94+ // `destroyWorkspaceWrapper` is never called without `createWorkspaceWrapper` being called first,
95+ // so `destroyWorkspace` must be defined here
96+ debugAssertIsNonNull ( destroyWorkspace ) ;
97+ destroyWorkspace ( rootDir ) ;
5598}
5699
57100// Get command line arguments, skipping first 2 (node binary and script path)
58101const args = process . argv . slice ( 2 ) ;
59102
60- // Call Rust, passing `loadPlugin` and `lintFile` as callbacks, and CLI arguments
61- const success = await lint ( args , loadPluginWrapper , lintFileWrapper ) ;
103+ // Call Rust, passing `loadPlugin`, `lintFile`, and `clearLoadedPlugin` as callbacks, and CLI arguments
104+ const success = await lint (
105+ args ,
106+ loadPluginWrapper ,
107+ lintFileWrapper ,
108+ createWorkspaceWrapper ,
109+ destroyWorkspaceWrapper ,
110+ ) ;
62111
63112// Note: It's recommended to set `process.exitCode` instead of calling `process.exit()`.
64113// `process.exit()` kills the process immediately and `stdout` may not be flushed before process dies.
0 commit comments